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>")) 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, true) 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>")) }
// 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 }
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 }
func main() { fmt.Println("Gocoin FetchBal version", lib.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) } } }
// 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 }