func DecodeTx(tx *btc.Tx) (s string, missinginp bool, totinp, totout uint64, e error) { s += fmt.Sprintln("Transaction details (for your information):") s += fmt.Sprintln(len(tx.TxIn), "Input(s):") for i := range tx.TxIn { s += fmt.Sprintf(" %3d %s", i, tx.TxIn[i].Input.String()) var po *btc.TxOut inpid := btc.NewUint256(tx.TxIn[i].Input.Hash[:]) if txinmem, ok := network.TransactionsToSend[inpid.BIdx()]; ok { s += fmt.Sprint(" mempool") if int(tx.TxIn[i].Input.Vout) >= len(txinmem.TxOut) { s += fmt.Sprintf(" - Vout TOO BIG (%d/%d)!", int(tx.TxIn[i].Input.Vout), len(txinmem.TxOut)) } else { po = txinmem.TxOut[tx.TxIn[i].Input.Vout] } } else { po, _ = common.BlockChain.Unspent.UnspentGet(&tx.TxIn[i].Input) if po != nil { s += fmt.Sprintf("%8d", po.BlockHeight) } } if po != nil { ok := script.VerifyTxScript(tx.TxIn[i].ScriptSig, po.Pk_script, i, tx, true) if !ok { s += fmt.Sprintln("\nERROR: The transacion does not have a valid signature.") e = errors.New("Invalid signature") return } totinp += po.Value ads := "???" if ad := btc.NewAddrFromPkScript(po.Pk_script, common.Testnet); ad != nil { ads = ad.String() } s += fmt.Sprintf(" %15.8f BTC @ %s\n", float64(po.Value)/1e8, ads) } else { s += fmt.Sprintln(" - UNKNOWN INPUT") missinginp = true } } s += fmt.Sprintln(len(tx.TxOut), "Output(s):") for i := range tx.TxOut { totout += tx.TxOut[i].Value adr := btc.NewAddrFromPkScript(tx.TxOut[i].Pk_script, common.Testnet) if adr != nil { s += fmt.Sprintf(" %15.8f BTC to adr %s\n", float64(tx.TxOut[i].Value)/1e8, adr.String()) } else { s += fmt.Sprintf(" %15.8f BTC to scr %s\n", float64(tx.TxOut[i].Value)/1e8, hex.EncodeToString(tx.TxOut[i].Pk_script)) } } if missinginp { s += fmt.Sprintln("WARNING: There are missing inputs and we cannot calc input BTC amount.") s += fmt.Sprintln("If there is somethign wrong with this transaction, you can loose money...") } else { s += fmt.Sprintf("All OK: %.8f BTC in -> %.8f BTC out, with %.8f BTC fee\n", float64(totinp)/1e8, float64(totout)/1e8, float64(totinp-totout)/1e8) } return }
func output_tx_xml(w http.ResponseWriter, id string) { txid := btc.NewUint256FromString(id) w.Write([]byte("<tx>")) fmt.Fprint(w, "<id>", id, "</id>") if t2s, ok := network.TransactionsToSend[txid.BIdx()]; ok { w.Write([]byte("<status>OK</status>")) w.Write([]byte(fmt.Sprint("<len>", len(t2s.Data), "</len>"))) tx := t2s.Tx w.Write([]byte("<inputs>")) for i := range tx.TxIn { w.Write([]byte("<input>")) var po *btc.TxOut inpid := btc.NewUint256(tx.TxIn[i].Input.Hash[:]) if txinmem, ok := network.TransactionsToSend[inpid.BIdx()]; ok { if int(tx.TxIn[i].Input.Vout) < len(txinmem.TxOut) { po = txinmem.TxOut[tx.TxIn[i].Input.Vout] } } else { po, _ = common.BlockChain.Unspent.UnspentGet(&tx.TxIn[i].Input) } if po != nil { ok := script.VerifyTxScript(tx.TxIn[i].ScriptSig, po.Pk_script, i, tx, script.VER_P2SH|script.VER_DERSIG) if !ok { w.Write([]byte("<status>Script FAILED</status>")) } else { w.Write([]byte("<status>OK</status>")) } fmt.Fprint(w, "<value>", po.Value, "</value>") ads := "???" if ad := btc.NewAddrFromPkScript(po.Pk_script, common.Testnet); ad != nil { ads = ad.String() } fmt.Fprint(w, "<addr>", ads, "</addr>") fmt.Fprint(w, "<block>", po.BlockHeight, "</block>") } else { w.Write([]byte("<status>UNKNOWN INPUT</status>")) } w.Write([]byte("</input>")) } w.Write([]byte("</inputs>")) w.Write([]byte("<outputs>")) for i := range tx.TxOut { w.Write([]byte("<output>")) fmt.Fprint(w, "<value>", tx.TxOut[i].Value, "</value>") adr := btc.NewAddrFromPkScript(tx.TxOut[i].Pk_script, common.Testnet) if adr != nil { fmt.Fprint(w, "<addr>", adr.String(), "</addr>") } else { fmt.Fprint(w, "<addr>", "scr:"+hex.EncodeToString(tx.TxOut[i].Pk_script), "</addr>") } w.Write([]byte("</output>")) } w.Write([]byte("</outputs>")) } else { w.Write([]byte("<status>Not found</status>")) } w.Write([]byte("</tx>")) }
func all_del_utxos(tx *chain.QdbRec, outs []bool) { var uidx [20]byte var rec *OneAllAddrBal var i int var nr OneAllAddrInp var p2kh bool nr[0] = byte(tx.TxID[31]) % chain.NumberOfUnspentSubDBs //DbIdx copy(nr[1:9], tx.TxID[:8]) //RecIdx for vout := uint32(0); vout < uint32(len(tx.Outs)); vout++ { if !outs[vout] { continue } out := tx.Outs[vout] if out == nil { continue } if out.Value < common.AllBalMinVal { continue } if p2kh = out.IsP2KH(); p2kh { copy(uidx[:], out.PKScr[3:23]) rec = AllBalancesP2KH[uidx] } else if out.IsP2SH() { copy(uidx[:], out.PKScr[2:22]) rec = AllBalancesP2SH[uidx] } else { continue } if rec == nil { println("balance rec not found for", btc.NewAddrFromPkScript(out.PKScr, common.CFG.Testnet).String()) continue } for i = 0; i < len(rec.Unsp); i++ { if bytes.Equal(rec.Unsp[i][:9], nr[:9]) && binary.LittleEndian.Uint32(rec.Unsp[i][9:13]) == vout { break } } if i == len(rec.Unsp) { println("unspent rec not found for", btc.NewAddrFromPkScript(out.PKScr, common.CFG.Testnet).String()) continue } if len(rec.Unsp) == 1 { if p2kh { delete(AllBalancesP2KH, uidx) } else { delete(AllBalancesP2SH, uidx) } } else { rec.Value -= out.Value rec.Unsp = append(rec.Unsp[:i], rec.Unsp[i+1:]...) } } }
// get BtcAddr from pk_script func addr_from_pkscr(scr []byte) *btc.BtcAddr { if litecoin { return ltc.NewAddrFromPkScript(scr, testnet) } else { return btc.NewAddrFromPkScript(scr, testnet) } }
func NewAddrFromPkScript(scr []byte, testnet bool) (ad *btc.BtcAddr) { ad = btc.NewAddrFromPkScript(scr, testnet) if ad != nil && ad.Version == btc.AddrVerPubkey(false) { ad.Version = LTC_ADDR_VERSION } return }
// This is called while accepting the block (from the chain's thread) func TxNotify(idx *btc.TxPrevOut, valpk *btc.TxOut) { var update_wallet bool BalanceMutex.Lock() if valpk != nil { // Extract hash160 from pkscript adr := btc.NewAddrFromPkScript(valpk.Pk_script, common.Testnet) if adr != nil { if rec, ok := CachedAddrs[adr.Hash160]; ok { rec.Value += valpk.Value utxo := new(chain.OneUnspentTx) utxo.TxPrevOut = *idx utxo.Value = valpk.Value utxo.MinedAt = valpk.BlockHeight utxo.BtcAddr = CacheUnspent[rec.CacheIndex].BtcAddr CacheUnspent[rec.CacheIndex].AllUnspentTx = append(CacheUnspent[rec.CacheIndex].AllUnspentTx, utxo) CacheUnspentIdx[idx.UIdx()] = &OneCachedUnspentIdx{Index: rec.CacheIndex, Record: utxo} if rec.InWallet { update_wallet = true } } } } else { ii := idx.UIdx() if ab, present := CacheUnspentIdx[ii]; present { adrec := CacheUnspent[ab.Index] //println("removing", idx.String()) rec := CachedAddrs[adrec.BtcAddr.Hash160] if rec == nil { panic("rec not found for " + adrec.BtcAddr.String()) } rec.Value -= ab.Record.Value if rec.InWallet { update_wallet = true } for j := range adrec.AllUnspentTx { if adrec.AllUnspentTx[j] == ab.Record { //println("found it at index", j) adrec.AllUnspentTx = append(adrec.AllUnspentTx[:j], adrec.AllUnspentTx[j+1:]...) break } } delete(CacheUnspentIdx, ii) } } if update_wallet { sync_wallet() } BalanceMutex.Unlock() }
func BlocksMiner(bl []byte) (string, int) { for i, m := range MinerIds { if MinedBy(bl, m.Tag) { return m.Name, i } } bt, _ := btc.NewBlock(bl) cbtx, _ := btc.NewTx(bl[bt.TxOffset:]) adr := btc.NewAddrFromPkScript(cbtx.TxOut[0].Pk_script, Testnet) if adr != nil { return adr.String(), -1 } return "", -1 }
// 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 }
// This function is only used when loading UTXO database func NewUTXO(db *qdb.DB, k qdb.KeyType, rec *chain.OneWalkRecord) uint32 { if rec.IsP2KH() || rec.IsP2SH() { if adr := btc.NewAddrFromPkScript(rec.Script(), common.Testnet); adr != nil { if crec, ok := CachedAddrs[adr.Hash160]; ok { value := rec.Value() idx := rec.TxPrevOut() crec.Value += value utxo := new(chain.OneUnspentTx) utxo.TxPrevOut = *idx utxo.Value = value utxo.MinedAt = rec.BlockHeight() utxo.BtcAddr = CacheUnspent[crec.CacheIndex].BtcAddr CacheUnspent[crec.CacheIndex].AllUnspentTx = append(CacheUnspent[crec.CacheIndex].AllUnspentTx, utxo) CacheUnspentIdx[idx.UIdx()] = &OneCachedUnspentIdx{Index: crec.CacheIndex, Record: utxo} } } } else if len(StealthAdCache) > 0 && rec.IsStealthIdx() { StealthNotify(db, k, rec) } return 0 }
// dump hashes to be signed func dump_hashes_to_sign(tx *btc.Tx) { for in := range tx.TxIn { uo := UO(unspentOuts[in]) if uo == nil { println("Unknown content of unspent input number", in) os.Exit(1) } var pubad *btc.BtcAddr if litecoin { pubad = ltc.NewAddrFromPkScript(uo.Pk_script, testnet) } else { pubad = btc.NewAddrFromPkScript(uo.Pk_script, testnet) } if pubad != nil { hash := tx.SignatureHash(uo.Pk_script, in, btc.SIGHASH_ALL) fmt.Printf("Input #%d:\n\tHash : %s\n\tAddr : %s\n", in, hex.EncodeToString(hash), pubad.String()) } else { println("Cannot decode pkscript of unspent input number", in) os.Exit(1) } } }
func main() { fmt.Println("Gocoin FetchBal version", gocoin.Version) fmt.Println("NOTE: This tool is deprecated. Use balio instead.") proxy = os.Getenv("TOR") if proxy != "" { fmt.Println("Using Tor at", proxy) http.DefaultClient.Transport = &http.Transport{Dial: dials5} } else { fmt.Println("WARNING: not using Tor (setup TOR variable, if you want)") } if len(os.Args) < 2 { print_help() return } var addrs []*btc.BtcAddr if len(os.Args) == 2 { fi, er := os.Stat(os.Args[1]) if er == nil && fi.Size() > 10 && !fi.IsDir() { wal := wallet.NewWallet(os.Args[1]) if wal != nil { fmt.Println("Found", len(wal.Addrs), "address(es) in", wal.FileName) addrs = wal.Addrs } } } if len(addrs) == 0 { for i := 1; i < len(os.Args); i++ { a, e := btc.NewAddrFromString(os.Args[i]) if e != nil { println(os.Args[i], ": ", e.Error()) return } else { addrs = append(addrs, a) } } } if len(addrs) == 0 { print_help() return } url := "http://blockchain.info/unspent?active=" for i := range addrs { if i > 0 { url += "|" } url += addrs[i].String() } var sum, outcnt uint64 r, er := http.Get(url) //println(url) if er == nil && r.StatusCode == 200 { defer r.Body.Close() c, _ := ioutil.ReadAll(r.Body) var r restype er = json.Unmarshal(c[:], &r) if er == nil { os.RemoveAll("balance/") os.Mkdir("balance/", 0700) unsp, _ := os.Create("balance/unspent.txt") for i := 0; i < len(r.Unspent_outputs); i++ { pkscr, _ := hex.DecodeString(r.Unspent_outputs[i].Script) b58adr := "???" if pkscr != nil { ba := btc.NewAddrFromPkScript(pkscr, false) if ba != nil { b58adr = ba.String() } } txidlsb, _ := hex.DecodeString(r.Unspent_outputs[i].Tx_hash) if txidlsb != nil { txid := btc.NewUint256(txidlsb) rawtx := utils.GetTxFromWeb(txid) if rawtx != nil { ioutil.WriteFile("balance/"+txid.String()+".tx", rawtx, 0666) fmt.Fprintf(unsp, "%s-%03d # %.8f @ %s, %d confs\n", txid.String(), r.Unspent_outputs[i].Tx_output_n, float64(r.Unspent_outputs[i].Value)/1e8, b58adr, r.Unspent_outputs[i].Confirmations) sum += r.Unspent_outputs[i].Value outcnt++ } else { fmt.Printf(" - cannot fetch %s-%03d\n", txid.String(), r.Unspent_outputs[i].Tx_output_n) } } } unsp.Close() if outcnt > 0 { fmt.Printf("Total %.8f BTC in %d unspent outputs.\n", float64(sum)/1e8, outcnt) fmt.Println("The data has been stored in 'balance' folder.") fmt.Println("Use it with the wallet app to spend any of it.") } else { fmt.Println("The fateched balance is empty.") } } else { fmt.Println("Unspent json.Unmarshal", er.Error()) } } else { if er != nil { fmt.Println("Unspent ", er.Error()) } else { fmt.Println("Unspent HTTP StatusCode", r.StatusCode) } } }
func output_tx_xml(w http.ResponseWriter, tx *btc.Tx) { w.Write([]byte("<input_list>")) for i := range tx.TxIn { w.Write([]byte("<input>")) w.Write([]byte("<script_sig>")) w.Write([]byte(hex.EncodeToString(tx.TxIn[i].ScriptSig))) w.Write([]byte("</script_sig>")) var po *btc.TxOut inpid := btc.NewUint256(tx.TxIn[i].Input.Hash[:]) if txinmem, ok := network.TransactionsToSend[inpid.BIdx()]; ok { if int(tx.TxIn[i].Input.Vout) < len(txinmem.TxOut) { po = txinmem.TxOut[tx.TxIn[i].Input.Vout] } } else { po, _ = common.BlockChain.Unspent.UnspentGet(&tx.TxIn[i].Input) } if po != nil { ok := script.VerifyTxScript(po.Pk_script, po.Value, i, tx, script.STANDARD_VERIFY_FLAGS) if !ok { w.Write([]byte("<status>Script FAILED</status>")) } else { w.Write([]byte("<status>OK</status>")) } fmt.Fprint(w, "<value>", po.Value, "</value>") fmt.Fprint(w, "<pkscript>", hex.EncodeToString(po.Pk_script), "</pkscript>") if ad := btc.NewAddrFromPkScript(po.Pk_script, common.Testnet); ad != nil { fmt.Fprint(w, "<addr>", ad.String(), "</addr>") } fmt.Fprint(w, "<block>", po.BlockHeight, "</block>") if btc.IsP2SH(po.Pk_script) { fmt.Fprint(w, "<input_sigops>", btc.WITNESS_SCALE_FACTOR*btc.GetP2SHSigOpCount(tx.TxIn[i].ScriptSig), "</input_sigops>") } fmt.Fprint(w, "<witness_sigops>", tx.CountWitnessSigOps(i, po.Pk_script), "</witness_sigops>") } else { w.Write([]byte("<status>UNKNOWN INPUT</status>")) } fmt.Fprint(w, "<sequence>", tx.TxIn[i].Sequence, "</sequence>") if tx.SegWit != nil { w.Write([]byte("<segwit>")) for _, wit := range tx.SegWit[i] { w.Write([]byte("<witness>")) w.Write([]byte(hex.EncodeToString(wit))) w.Write([]byte("</witness>")) } w.Write([]byte("</segwit>")) } w.Write([]byte("</input>")) } w.Write([]byte("</input_list>")) w.Write([]byte("<output_list>")) for i := range tx.TxOut { w.Write([]byte("<output>")) fmt.Fprint(w, "<value>", tx.TxOut[i].Value, "</value>") adr := btc.NewAddrFromPkScript(tx.TxOut[i].Pk_script, common.Testnet) if adr != nil { fmt.Fprint(w, "<addr>", adr.String(), "</addr>") } else { fmt.Fprint(w, "<addr>", "scr:"+hex.EncodeToString(tx.TxOut[i].Pk_script), "</addr>") } w.Write([]byte("</output>")) } w.Write([]byte("</output_list>")) }
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) }
// This function is only used when loading UTXO database func newUTXO(tx *chain.QdbRec) (update_wallet bool) { var c, spen_exp []byte var rec *chain.QdbTxOut var h160 [20]byte check_next_address: for idx, out := range tx.Outs { if out == nil { continue } // check for stealth if len(StealthAdCache) > 0 && idx > 0 { if rec = tx.Outs[idx-1]; rec == nil { goto not_stealth } if !rec.IsStealthIdx() || !out.IsP2KH() { goto not_stealth } for _, ad := range StealthAdCache { if sa := ad.addr.StealthAddr; sa.CheckNonce(rec.PKScr[3:40]) { c = btc.StealthDH(rec.PKScr[7:40], ad.d[:]) spen_exp = btc.DeriveNextPublic(sa.SpendKeys[0][:], c) btc.RimpHash(spen_exp, h160[:]) if bytes.Equal(out.PKScr[3:23], h160[:]) { uo := new(chain.OneUnspentTx) uo.TxPrevOut.Hash = tx.TxID uo.TxPrevOut.Vout = uint32(idx) uo.Value = out.Value uo.MinedAt = tx.InBlock uo.BtcAddr = btc.NewAddrFromHash160(h160[:], btc.AddrVerPubkey(common.CFG.Testnet)) uo.FixDestString() uo.BtcAddr.StealthAddr = sa uo.BtcAddr.Extra = ad.addr.Extra uo.StealthC = c carec := CachedAddrs[ad.h160] carec.Value += uo.Value CacheUnspent[carec.CacheIndex].AllUnspentTx = append(CacheUnspent[carec.CacheIndex].AllUnspentTx, uo) CacheUnspentIdx[uo.TxPrevOut.UIdx()] = &OneCachedUnspentIdx{Index: carec.CacheIndex, Record: uo} if carec.InWallet { update_wallet = true } continue check_next_address // it it was setalth, cannot be enythign else } } } } not_stealth: // Extract hash160 from pkscript adr := btc.NewAddrFromPkScript(out.PKScr, common.Testnet) if adr != nil { if carec, ok := CachedAddrs[adr.Hash160]; ok { carec.Value += out.Value utxo := new(chain.OneUnspentTx) utxo.TxPrevOut.Hash = tx.TxID utxo.TxPrevOut.Vout = uint32(idx) utxo.Value = out.Value utxo.MinedAt = tx.InBlock utxo.BtcAddr = CacheUnspent[carec.CacheIndex].BtcAddr CacheUnspent[carec.CacheIndex].AllUnspentTx = append(CacheUnspent[carec.CacheIndex].AllUnspentTx, utxo) CacheUnspentIdx[utxo.TxPrevOut.UIdx()] = &OneCachedUnspentIdx{Index: carec.CacheIndex, Record: utxo} if carec.InWallet { update_wallet = true } } } } return }
// dump raw transaction func dump_raw_tx() { tx := raw_tx_from_file(*dumptxfn) if tx == nil { fmt.Println("ERROR: Cannot decode the raw transaction") return } var unsigned int fmt.Println("ID:", tx.Hash.String()) fmt.Println("Tx Version:", tx.Version) if tx.IsCoinBase() { if len(tx.TxIn[0].ScriptSig) >= 4 && tx.TxIn[0].ScriptSig[0] == 3 { fmt.Println("Coinbase TX from block height", uint(tx.TxIn[0].ScriptSig[1])| uint(tx.TxIn[0].ScriptSig[2])<<8|uint(tx.TxIn[0].ScriptSig[3])<<16) } else { fmt.Println("Coinbase TX from an unknown block") } s := hex.EncodeToString(tx.TxIn[0].ScriptSig) for len(s) > 0 { i := len(s) if i > 64 { i = 64 } fmt.Println(" ", s[:i]) s = s[i:] } //fmt.Println() } else { fmt.Println("TX IN cnt:", len(tx.TxIn)) for i := range tx.TxIn { fmt.Printf("%4d) %s sl=%d seq=%08x\n", i, tx.TxIn[i].Input.String(), len(tx.TxIn[i].ScriptSig), tx.TxIn[i].Sequence) if len(tx.TxIn[i].ScriptSig) > 0 { if !dump_sigscript(tx.TxIn[i].ScriptSig) { unsigned++ } } else { unsigned++ } } } fmt.Println("TX OUT cnt:", len(tx.TxOut)) for i := range tx.TxOut { fmt.Printf("%4d) %20s BTC ", i, btc.UintToBtc(tx.TxOut[i].Value)) var addr *btc.BtcAddr if litecoin { addr = ltc.NewAddrFromPkScript(tx.TxOut[i].Pk_script, testnet) } else { addr = btc.NewAddrFromPkScript(tx.TxOut[i].Pk_script, testnet) } if addr != nil { if addr.Version == AddrVerScript() { fmt.Println("to scriptH", addr.String()) } else { fmt.Println("to address", addr.String()) } } else if len(tx.TxOut[i].Pk_script) == 40 && tx.TxOut[i].Pk_script[0] == 0x6a && tx.TxOut[i].Pk_script[1] == 0x26 && tx.TxOut[i].Pk_script[2] == 0x06 { fmt.Println("Stealth", hex.EncodeToString(tx.TxOut[i].Pk_script[3:7]), hex.EncodeToString(tx.TxOut[i].Pk_script[7:])) } else { if tx.TxOut[i].Value > 0 { fmt.Println("WARNING!!! These coins go to non-standard Pk_script:") } else { fmt.Println("NULL output to Pk_script:") } ss, er := btc.ScriptToText(tx.TxOut[i].Pk_script) if er == nil { for i := range ss { fmt.Println(" ", ss[i]) } } else { fmt.Println(hex.EncodeToString(tx.TxOut[i].Pk_script)) fmt.Println(er.Error()) } } } fmt.Println("Lock Time:", tx.Lock_time) if !tx.IsCoinBase() { if unsigned > 0 { fmt.Println("WARNING:", unsigned, "out of", len(tx.TxIn), "inputs are not signed or signed only patially") } else { fmt.Println("All", len(tx.TxIn), "transaction inputs seem to be signed") } } }
func all_addrs(par string) { var ptkh_outs, ptkh_vals, ptsh_outs, ptsh_vals uint64 var best SortedWalletAddrs var cnt int = 15 if par != "" { if c, e := strconv.ParseUint(par, 10, 32); e == nil { cnt = int(c) } } wallet.BalanceMutex.Lock() defer wallet.BalanceMutex.Unlock() for k, rec := range wallet.AllBalancesP2SH { ptsh_vals += rec.Value ptsh_outs += uint64(len(rec.Unsp)) if sort_by_cnt && len(rec.Unsp) >= 1000 || !sort_by_cnt && rec.Value >= 1000e8 { best = append(best, OneWalletAddrs{P2SH: true, Key: k, rec: rec}) } } for k, rec := range wallet.AllBalancesP2KH { ptkh_vals += rec.Value ptkh_outs += uint64(len(rec.Unsp)) if sort_by_cnt && len(rec.Unsp) >= 1000 || !sort_by_cnt && rec.Value >= 1000e8 { best = append(best, OneWalletAddrs{Key: k, rec: rec}) } } fmt.Println(btc.UintToBtc(ptkh_vals), "BTC in", ptkh_outs, "unspent recs from", len(wallet.AllBalancesP2KH), "P2KH addresses") fmt.Println(btc.UintToBtc(ptsh_vals), "BTC in", ptsh_outs, "unspent recs from", len(wallet.AllBalancesP2SH), "P2SH addresses") if sort_by_cnt { fmt.Println("Addrs with at least 1000 inps:", len(best)) } else { fmt.Println("Addrs with at least 1000 BTC:", len(best)) } sort.Sort(best) var pkscr_p2sk [23]byte var pkscr_p2kh [25]byte var ad *btc.BtcAddr pkscr_p2sk[0] = 0xa9 pkscr_p2sk[1] = 20 pkscr_p2sk[22] = 0x87 pkscr_p2kh[0] = 0x76 pkscr_p2kh[1] = 0xa9 pkscr_p2kh[2] = 20 pkscr_p2kh[23] = 0x88 pkscr_p2kh[24] = 0xac for i := 0; i < len(best) && i < cnt; i++ { if best[i].P2SH { copy(pkscr_p2sk[2:22], best[i].Key[:]) ad = btc.NewAddrFromPkScript(pkscr_p2sk[:], common.CFG.Testnet) } else { copy(pkscr_p2kh[3:23], best[i].Key[:]) ad = btc.NewAddrFromPkScript(pkscr_p2kh[:], common.CFG.Testnet) } fmt.Println(i+1, ad.String(), btc.UintToBtc(best[i].rec.Value), "BTC in", len(best[i].rec.Unsp), "inputs") } }