// apply the chnages to the balance folder func apply_to_balance(tx *btc.Tx) { f, _ := os.Create("balance/unspent.txt") if f != nil { // append new outputs at the end of unspentOuts ioutil.WriteFile("balance/"+tx.Hash.String()+".tx", tx.Serialize(), 0600) fmt.Println("Adding", len(tx.TxOut), "new output(s) to the balance/ folder...") for out := range tx.TxOut { if k := pkscr_to_key(tx.TxOut[out].Pk_script); k != nil { uns := new(unspRec) uns.key = k uns.TxPrevOut.Hash = tx.Hash.Hash uns.TxPrevOut.Vout = uint32(out) uns.label = fmt.Sprint("# ", btc.UintToBtc(tx.TxOut[out].Value), " BTC @ ", k.BtcAddr.String()) //stealth bool TODO: maybe we can fix it... unspentOuts = append(unspentOuts, uns) } } for j := range unspentOuts { if !unspentOuts[j].spent { fmt.Fprintln(f, unspentOuts[j].String()) } } f.Close() } else { println("ERROR: Cannot create balance/unspent.txt") } }
func write_tx_file(tx *btc.Tx) { signedrawtx := tx.Serialize() tx.Hash = btc.NewSha2Hash(signedrawtx) hs := tx.Hash.String() fmt.Println("TxID", hs) f, _ := os.Create(hs[:8] + ".txt") if f != nil { f.Write([]byte(hex.EncodeToString(signedrawtx))) f.Close() fmt.Println("Transaction data stored in", hs[:8]+".txt") } }
func consensus_verify_script(pkScr []byte, i int, tx *btc.Tx, ver_flags uint32) bool { txTo := tx.Serialize() var pkscr_ptr, pkscr_len uintptr // default to 0/null if pkScr != nil { pkscr_ptr = uintptr(unsafe.Pointer(&pkScr[0])) pkscr_len = uintptr(len(pkScr)) } r1, _, _ := syscall.Syscall9(bitcoinconsensus_verify_script.Addr(), 7, pkscr_ptr, pkscr_len, uintptr(unsafe.Pointer(&txTo[0])), uintptr(len(txTo)), uintptr(i), uintptr(ver_flags), 0, 0, 0) return r1 == 1 }
func mk_out_tx(sig_scr, pk_scr []byte) (output_tx *btc.Tx) { // We build input_tx only to calculate it's hash for output_tx input_tx := new(btc.Tx) input_tx.Version = 1 input_tx.TxIn = []*btc.TxIn{&btc.TxIn{Input: btc.TxPrevOut{Vout: 0xffffffff}, ScriptSig: []byte{0, 0}, Sequence: 0xffffffff}} input_tx.TxOut = []*btc.TxOut{&btc.TxOut{Pk_script: pk_scr}} // Lock_time = 0 output_tx = new(btc.Tx) output_tx.Version = 1 output_tx.TxIn = []*btc.TxIn{&btc.TxIn{Input: btc.TxPrevOut{Hash: btc.Sha2Sum(input_tx.Serialize()), Vout: 0}, ScriptSig: sig_scr, Sequence: 0xffffffff}} output_tx.TxOut = []*btc.TxOut{&btc.TxOut{}} // Lock_time = 0 return }
func write_tx_file(tx *btc.Tx) { var signedrawtx []byte if tx.SegWit != nil { signedrawtx = tx.SerializeNew() } else { signedrawtx = tx.Serialize() } tx.SetHash(signedrawtx) hs := tx.Hash.String() fmt.Println("TxID", hs) f, _ := os.Create(hs[:8] + ".txt") if f != nil { f.Write([]byte(hex.EncodeToString(signedrawtx))) f.Close() fmt.Println("Transaction data stored in", hs[:8]+".txt") } }
// return miner ID of the given coinbase transaction func TxMiner(cbtx *btc.Tx) (string, int) { txdat := cbtx.Serialize() for i, m := range MinerIds { if bytes.Equal(m.Tag, []byte("_p2pool_")) { // P2Pool if len(cbtx.TxOut) > 10 && bytes.Equal(cbtx.TxOut[len(cbtx.TxOut)-1].Pk_script[:2], []byte{0x6A, 0x28}) { return m.Name, i } } else if bytes.Contains(txdat, m.Tag) { return m.Name, i } } adr := btc.NewAddrFromPkScript(cbtx.TxOut[0].Pk_script, Testnet) if adr != nil { return adr.String(), -1 } return "", -1 }
func mk_spend_tx(input_tx *btc.Tx, sig_scr []byte, witness [][]byte) (output_tx *btc.Tx) { output_tx = new(btc.Tx) output_tx.Version = 1 output_tx.TxIn = []*btc.TxIn{&btc.TxIn{Input: btc.TxPrevOut{Hash: btc.Sha2Sum(input_tx.Serialize()), Vout: 0}, ScriptSig: sig_scr, Sequence: 0xffffffff}} output_tx.TxOut = []*btc.TxOut{&btc.TxOut{Value: input_tx.TxOut[0].Value}} // Lock_time = 0 if len(witness) > 0 { output_tx.SegWit = make([][][]byte, 1) output_tx.SegWit[0] = witness if DBG_SCR { println("tx has", len(witness), "ws") for xx := range witness { println("", xx, hex.EncodeToString(witness[xx])) } } } output_tx.SetHash(output_tx.Serialize()) return }
func check_consensus(pkScr []byte, amount uint64, i int, tx *btc.Tx, ver_flags uint32, result bool) { var tmp []byte if len(pkScr) != 0 { tmp = make([]byte, len(pkScr)) copy(tmp, pkScr) } tx_raw := tx.Raw if tx_raw == nil { tx_raw = tx.Serialize() } go func(pkScr []byte, txTo []byte, i int, ver_flags uint32, result bool) { var pkscr_ptr, pkscr_len uintptr // default to 0/null if pkScr != nil { pkscr_ptr = uintptr(unsafe.Pointer(&pkScr[0])) pkscr_len = uintptr(len(pkScr)) } r1, _, _ := syscall.Syscall9(bitcoinconsensus_verify_script_with_amount.Addr(), 8, pkscr_ptr, pkscr_len, uintptr(amount), uintptr(unsafe.Pointer(&txTo[0])), uintptr(len(txTo)), uintptr(i), uintptr(ver_flags), 0, 0) res := r1 == 1 atomic.AddUint64(&ConsensusChecks, 1) if !result { atomic.AddUint64(&ConsensusExpErr, 1) } if res != result { atomic.AddUint64(&ConsensusErrors, 1) common.CountSafe("TxConsensusERR") mut.Lock() println("Compare to consensus failed!") println("Gocoin:", result, " ConsLIB:", res) println("pkScr", hex.EncodeToString(pkScr)) println("txTo", hex.EncodeToString(txTo)) println("amount:", amount, " input_idx:", i, " ver_flags:", ver_flags) println() mut.Unlock() } }(tmp, tx_raw, i, ver_flags, result) }
// apply the chnages to the balance folder func apply_to_balance(tx *btc.Tx) { fmt.Println("Applying the transaction to the balance/ folder...") f, _ := os.Create("balance/unspent.txt") if f != nil { for j := 0; j < len(unspentOuts); j++ { if j > len(tx.TxIn) { fmt.Fprintln(f, unspentOuts[j], unspentOutsLabel[j]) } } if *verbose { fmt.Println(len(tx.TxIn), "spent output(s) removed from 'balance/unspent.txt'") } var addback int for out := range tx.TxOut { for j := range publ_addrs { if publ_addrs[j].Owns(tx.TxOut[out].Pk_script) { fmt.Fprintf(f, "%s-%03d # %.8f / %s\n", tx.Hash.String(), out, float64(tx.TxOut[out].Value)/1e8, publ_addrs[j].String()) addback++ } } } f.Close() if addback > 0 { f, _ = os.Create("balance/" + tx.Hash.String() + ".tx") if f != nil { f.Write(tx.Serialize()) f.Close() } if *verbose { fmt.Println(addback, "new output(s) appended to 'balance/unspent.txt'") } } } }
func dl_payment(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } var err string if len(r.Form["outcnt"]) == 1 { var thisbal chain.AllUnspentTx var pay_cmd string var totalinput, spentsofar uint64 var change_addr *btc.BtcAddr tx := new(btc.Tx) tx.Version = 1 tx.Lock_time = 0 seq, er := strconv.ParseInt(r.Form["tx_seq"][0], 10, 64) if er != nil || seq < -2 || seq > 0xffffffff { err = "Incorrect Sequence value: " + r.Form["tx_seq"][0] goto error } outcnt, _ := strconv.ParseUint(r.Form["outcnt"][0], 10, 32) lck := new(usif.OneLock) lck.In.Add(1) lck.Out.Add(1) usif.LocksChan <- lck lck.In.Wait() defer lck.Out.Done() for i := 1; i <= int(outcnt); i++ { is := fmt.Sprint(i) if len(r.Form["txout"+is]) == 1 && r.Form["txout"+is][0] == "on" { hash := btc.NewUint256FromString(r.Form["txid"+is][0]) if hash != nil { vout, er := strconv.ParseUint(r.Form["txvout"+is][0], 10, 32) if er == nil { var po = btc.TxPrevOut{Hash: hash.Hash, Vout: uint32(vout)} if res, er := common.BlockChain.Unspent.UnspentGet(&po); er == nil { addr := btc.NewAddrFromPkScript(res.Pk_script, common.Testnet) unsp := &chain.OneUnspentTx{TxPrevOut: po, Value: res.Value, MinedAt: res.BlockHeight, Coinbase: res.WasCoinbase, BtcAddr: addr} thisbal = append(thisbal, unsp) // Add the input to our tx tin := new(btc.TxIn) tin.Input = po tin.Sequence = uint32(seq) tx.TxIn = append(tx.TxIn, tin) // Add the value to total input value totalinput += res.Value // If no change specified, use the first input addr as it if change_addr == nil { change_addr = addr } } } } } } if change_addr == nil { // There werte no inputs return } //wallet.BalanceMutex.Lock() //wallet.BalanceMutex.Unlock() for i := 1; ; i++ { adridx := fmt.Sprint("adr", i) btcidx := fmt.Sprint("btc", i) if len(r.Form[adridx]) != 1 || len(r.Form[btcidx]) != 1 { break } if len(r.Form[adridx][0]) > 1 { addr, er := btc.NewAddrFromString(r.Form[adridx][0]) if er == nil { am, er := btc.StringToSatoshis(r.Form[btcidx][0]) if er == nil && am > 0 { if pay_cmd == "" { pay_cmd = "wallet -useallinputs -send " } else { pay_cmd += "," } pay_cmd += addr.Enc58str + "=" + btc.UintToBtc(am) outs, er := btc.NewSpendOutputs(addr, am, common.CFG.Testnet) if er != nil { err = er.Error() goto error } tx.TxOut = append(tx.TxOut, outs...) spentsofar += am } else { err = "Incorrect amount (" + r.Form[btcidx][0] + ") for Output #" + fmt.Sprint(i) goto error } } else { err = "Incorrect address (" + r.Form[adridx][0] + ") for Output #" + fmt.Sprint(i) goto error } } } if pay_cmd == "" { err = "No inputs selected" goto error } pay_cmd += fmt.Sprint(" -seq ", seq) am, er := btc.StringToSatoshis(r.Form["txfee"][0]) if er != nil { err = "Incorrect fee value: " + r.Form["txfee"][0] goto error } pay_cmd += " -fee " + r.Form["txfee"][0] spentsofar += am if len(r.Form["change"][0]) > 1 { addr, er := btc.NewAddrFromString(r.Form["change"][0]) if er != nil { err = "Incorrect change address: " + r.Form["change"][0] goto error } change_addr = addr } pay_cmd += " -change " + change_addr.String() if totalinput > spentsofar { // Add change output outs, er := btc.NewSpendOutputs(change_addr, totalinput-spentsofar, common.CFG.Testnet) if er != nil { err = er.Error() goto error } tx.TxOut = append(tx.TxOut, outs...) } buf := new(bytes.Buffer) zi := zip.NewWriter(buf) was_tx := make(map[[32]byte]bool, len(thisbal)) for i := range thisbal { if was_tx[thisbal[i].TxPrevOut.Hash] { continue } was_tx[thisbal[i].TxPrevOut.Hash] = true txid := btc.NewUint256(thisbal[i].TxPrevOut.Hash[:]) fz, _ := zi.Create("balance/" + txid.String() + ".tx") if dat, er := common.BlockChain.GetRawTx(thisbal[i].MinedAt, txid); er == nil { fz.Write(dat) } else { println(er.Error()) } } fz, _ := zi.Create("balance/unspent.txt") for i := range thisbal { fmt.Fprintln(fz, thisbal[i].UnspentTextLine()) } if pay_cmd != "" { fz, _ = zi.Create(common.CFG.WebUI.PayCommandName) fz.Write([]byte(pay_cmd)) } // Non-multisig transaction ... fz, _ = zi.Create("tx2sign.txt") fz.Write([]byte(hex.EncodeToString(tx.Serialize()))) zi.Close() w.Header()["Content-Type"] = []string{"application/zip"} w.Write(buf.Bytes()) return } else { err = "Bad request" } error: s := load_template("send_error.html") write_html_head(w, r) s = strings.Replace(s, "<!--ERROR_MSG-->", err, 1) w.Write([]byte(s)) write_html_tail(w) }
func dl_payment(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } var err string if len(r.Form["outcnt"]) == 1 { var thisbal chain.AllUnspentTx var pay_cmd string var totalinput, spentsofar uint64 var change_addr *btc.BtcAddr var multisig_input []*wallet.MultisigAddr addrs_to_msign := make(map[string]bool) tx := new(btc.Tx) tx.Version = 1 tx.Lock_time = 0 outcnt, _ := strconv.ParseUint(r.Form["outcnt"][0], 10, 32) wallet.BalanceMutex.Lock() for i := 1; i <= int(outcnt); i++ { is := fmt.Sprint(i) if len(r.Form["txout"+is]) == 1 && r.Form["txout"+is][0] == "on" { hash := btc.NewUint256FromString(r.Form["txid"+is][0]) if hash != nil { vout, er := strconv.ParseUint(r.Form["txvout"+is][0], 10, 32) if er == nil { var po = btc.TxPrevOut{Hash: hash.Hash, Vout: uint32(vout)} for j := range wallet.MyBalance { if wallet.MyBalance[j].TxPrevOut == po { thisbal = append(thisbal, wallet.MyBalance[j]) // Add the input to our tx tin := new(btc.TxIn) tin.Input = wallet.MyBalance[j].TxPrevOut tin.Sequence = 0xffffffff tx.TxIn = append(tx.TxIn, tin) // Add new multisig address description _, msi := wallet.IsMultisig(wallet.MyBalance[j].BtcAddr) multisig_input = append(multisig_input, msi) if msi != nil { for ai := range msi.ListOfAddres { addrs_to_msign[msi.ListOfAddres[ai]] = true } } // Add the value to total input value totalinput += wallet.MyBalance[j].Value // If no change specified, use the first input addr as it if change_addr == nil { change_addr = wallet.MyBalance[j].BtcAddr } } } } } } } wallet.BalanceMutex.Unlock() for i := 1; ; i++ { adridx := fmt.Sprint("adr", i) btcidx := fmt.Sprint("btc", i) if len(r.Form[adridx]) != 1 || len(r.Form[btcidx]) != 1 { break } if len(r.Form[adridx][0]) > 1 { addr, er := btc.NewAddrFromString(r.Form[adridx][0]) if er == nil { am, er := btc.StringToSatoshis(r.Form[btcidx][0]) if er == nil && am > 0 { if pay_cmd == "" { pay_cmd = "wallet -useallinputs -send " } else { pay_cmd += "," } pay_cmd += addr.Enc58str + "=" + btc.UintToBtc(am) outs, er := btc.NewSpendOutputs(addr, am, common.CFG.Testnet) if er != nil { err = er.Error() goto error } tx.TxOut = append(tx.TxOut, outs...) spentsofar += am } else { err = "Incorrect amount (" + r.Form[btcidx][0] + ") for Output #" + fmt.Sprint(i) goto error } } else { err = "Incorrect address (" + r.Form[adridx][0] + ") for Output #" + fmt.Sprint(i) goto error } } } if pay_cmd == "" { err = "No inputs selected" goto error } am, er := btc.StringToSatoshis(r.Form["txfee"][0]) if er != nil { err = "Incorrect fee value: " + r.Form["txfee"][0] goto error } pay_cmd += " -fee " + r.Form["txfee"][0] spentsofar += am if len(r.Form["change"][0]) > 1 { addr, er := btc.NewAddrFromString(r.Form["change"][0]) if er != nil { err = "Incorrect change address: " + r.Form["change"][0] goto error } change_addr = addr } pay_cmd += " -change " + change_addr.String() if totalinput > spentsofar { // Add change output outs, er := btc.NewSpendOutputs(change_addr, totalinput-spentsofar, common.CFG.Testnet) if er != nil { err = er.Error() goto error } tx.TxOut = append(tx.TxOut, outs...) } buf := new(bytes.Buffer) zi := zip.NewWriter(buf) was_tx := make(map[[32]byte]bool, len(thisbal)) for i := range thisbal { if was_tx[thisbal[i].TxPrevOut.Hash] { continue } was_tx[thisbal[i].TxPrevOut.Hash] = true txid := btc.NewUint256(thisbal[i].TxPrevOut.Hash[:]) fz, _ := zi.Create("balance/" + txid.String() + ".tx") wallet.GetRawTransaction(thisbal[i].MinedAt, txid, fz) } fz, _ := zi.Create("balance/unspent.txt") for i := range thisbal { fmt.Fprintln(fz, thisbal[i].UnspentTextLine()) } if len(addrs_to_msign) > 0 { // Multisig (or mixed) transaction ... for i := range multisig_input { if multisig_input[i] == nil { continue } d, er := hex.DecodeString(multisig_input[i].RedeemScript) if er != nil { println("ERROR parsing hex RedeemScript:", er.Error()) continue } ms, er := btc.NewMultiSigFromP2SH(d) if er != nil { println("ERROR parsing bin RedeemScript:", er.Error()) continue } tx.TxIn[i].ScriptSig = ms.Bytes() } fz, _ = zi.Create("multi_" + common.CFG.PayCommandName) fmt.Fprintln(fz, "wallet -raw tx2sign.txt") for k, _ := range addrs_to_msign { fmt.Fprintln(fz, "wallet -msign", k, "-raw ...") } } else { if pay_cmd != "" { fz, _ = zi.Create(common.CFG.PayCommandName) fz.Write([]byte(pay_cmd)) } } // Non-multisig transaction ... fz, _ = zi.Create("tx2sign.txt") fz.Write([]byte(hex.EncodeToString(tx.Serialize()))) zi.Close() w.Header()["Content-Type"] = []string{"application/zip"} w.Write(buf.Bytes()) return } else { err = "Bad request" } error: s := load_template("send_error.html") write_html_head(w, r) s = strings.Replace(s, "<!--ERROR_MSG-->", err, 1) w.Write([]byte(s)) write_html_tail(w) }
// Download (and re-assemble) raw transaction from blockexplorer.com func GetTxFromExplorer(txid *btc.Uint256) ([]byte, []byte) { url := "http://blockexplorer.com/rawtx/" + txid.String() r, er := http.Get(url) if er == nil && r.StatusCode == 200 { defer r.Body.Close() c, _ := ioutil.ReadAll(r.Body) var txx onetx er = json.Unmarshal(c[:], &txx) if er == nil { // This part looks weird, but this is how I solved seq=FFFFFFFF, if the field not present: for i := range txx.In { txx.In[i].Sequence = 0xffffffff } json.Unmarshal(c[:], &txx) // ... end of the weird solution tx := new(btc.Tx) tx.Version = txx.Ver tx.TxIn = make([]*btc.TxIn, len(txx.In)) for i := range txx.In { tx.TxIn[i] = new(btc.TxIn) tx.TxIn[i].Input.Hash = btc.NewUint256FromString(txx.In[i].Prev_out.Hash).Hash tx.TxIn[i].Input.Vout = txx.In[i].Prev_out.N if txx.In[i].Prev_out.N == 0xffffffff && txx.In[i].Prev_out.Hash == "0000000000000000000000000000000000000000000000000000000000000000" { tx.TxIn[i].ScriptSig, _ = hex.DecodeString(txx.In[i].Coinbase) } else { tx.TxIn[i].ScriptSig, _ = btc.DecodeScript(txx.In[i].ScriptSig) } tx.TxIn[i].Sequence = txx.In[i].Sequence } tx.TxOut = make([]*btc.TxOut, len(txx.Out)) for i := range txx.Out { am, er := btc.StringToSatoshis(txx.Out[i].Value) if er != nil { fmt.Println("Incorrect BTC amount", txx.Out[i].Value, er.Error()) return nil, nil } tx.TxOut[i] = new(btc.TxOut) tx.TxOut[i].Value = am tx.TxOut[i].Pk_script, _ = btc.DecodeScript(txx.Out[i].ScriptPubKey) } tx.Lock_time = txx.Lock_time rawtx := tx.Serialize() if txx.Size != uint(len(rawtx)) { fmt.Printf("Transaction size mismatch: %d expexted, %d decoded\n", txx.Size, len(rawtx)) return nil, rawtx } curid := btc.NewSha2Hash(rawtx) if !curid.Equal(txid) { fmt.Println("The downloaded transaction does not match its ID.", txid.String()) return nil, rawtx } return rawtx, rawtx } else { fmt.Println("json.Unmarshal:", er.Error()) } } else { if er != nil { fmt.Println("http.Get:", er.Error()) } else { fmt.Println("StatusCode=", r.StatusCode) } } return nil, nil }