func main() { var testnet bool if len(os.Args) != 2 { fmt.Println("Specify one P2KH bitcoin address to see it's P2SH-P2WPKH deposit address") fmt.Println("WARNING: Make sure the input address comes from an uncompressed key!!!!!") return } aa, er := btc.NewAddrFromString(os.Args[1]) if er != nil { println(er.Error()) return } if btc.AddrVerPubkey(false) == aa.Version { } else if btc.AddrVerPubkey(true) == aa.Version { testnet = true } else { fmt.Println("This does nto seem to be P2KH type address") return } h160 := btc.Rimp160AfterSha256(append([]byte{0, 20}, aa.Hash160[:]...)) aa = btc.NewAddrFromHash160(h160[:], btc.AddrVerScript(testnet)) fmt.Println(aa.String()) }
// version byte for P2KH addresses func ver_pubkey() byte { if litecoin { return ltc.AddrVerPubkey(testnet) } else { return btc.AddrVerPubkey(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 GetAllUnspent(aa *btc.BtcAddr) (thisbal chain.AllUnspentTx) { var rec *OneAllAddrBal if aa.Version == btc.AddrVerPubkey(common.Testnet) { rec = AllBalancesP2KH[aa.Hash160] } else if aa.Version == btc.AddrVerScript(common.Testnet) { rec = AllBalancesP2SH[aa.Hash160] } else { return } if rec != nil { for _, v := range rec.Unsp { if qr, vout := v.GetRec(); qr != nil { if oo := qr.Outs[vout]; oo != nil { unsp := &chain.OneUnspentTx{TxPrevOut: btc.TxPrevOut{Hash: qr.TxID, Vout: vout}, Value: oo.Value, MinedAt: qr.InBlock, Coinbase: qr.Coinbase, BtcAddr: aa} if int(vout+1) < len(qr.Outs) { var msg []byte if qr.Outs[vout+1] != nil && len(qr.Outs[vout+1].PKScr) > 1 && qr.Outs[vout+1].PKScr[0] == 0x6a { msg = qr.Outs[vout+1].PKScr[1:] } else if int(vout+1) != len(qr.Outs) && qr.Outs[len(qr.Outs)-1] != nil && len(qr.Outs[len(qr.Outs)-1].PKScr) > 1 && qr.Outs[len(qr.Outs)-1].PKScr[0] == 0x6a { msg = qr.Outs[len(qr.Outs)-1].PKScr[1:] } if msg != nil { _, unsp.Message, _, _ = btc.GetOpcode(msg) } } thisbal = append(thisbal, unsp) } } } } return }
func main() { var testnet bool if len(os.Args) < 3 { fmt.Println("Specify secret, public_key and optionaly number of addresses you want.") fmt.Println("Use a negative value for number of addresses, to work with Testnet addresses.") return } public_key, er := hex.DecodeString(os.Args[2]) if er != nil { println("Error parsing public_key:", er.Error()) os.Exit(1) } if len(public_key) == 33 && (public_key[0] == 2 || public_key[0] == 3) { fmt.Println("Compressed") } else if len(public_key) == 65 && (public_key[0] == 4) { fmt.Println("Uncompressed") } else { println("Incorrect public key") } secret, er := hex.DecodeString(os.Args[1]) if er != nil { println("Error parsing secret:", er.Error()) os.Exit(1) } n := int64(25) if len(os.Args) > 3 { n, er = strconv.ParseInt(os.Args[3], 10, 32) if er != nil { println("Error parsing number of keys value:", er.Error()) os.Exit(1) } if n == 0 { return } if n < 0 { n = -n testnet = true } } fmt.Println("# Type-2") fmt.Println("#", hex.EncodeToString(public_key)) fmt.Println("#", hex.EncodeToString(secret)) for i := 1; i <= int(n); i++ { fmt.Println(btc.NewAddrFromPubkey(public_key, btc.AddrVerPubkey(testnet)).String(), "TypB", i) if i >= int(n) { break } public_key = btc.DeriveNextPublic(public_key, secret) } }
func listarmkeys(p string) { if p != "seed" { if len(wallet.StealthSecrets) > 0 { fmt.Println("Persistent secret scan keys:") for i := range wallet.StealthSecrets { pk := btc.PublicFromPrivate(wallet.StealthSecrets[i], true) fmt.Print(" #", i, " ", hex.EncodeToString(pk)) if p == "addr" { fmt.Print(" ", btc.NewAddrFromPubkey(pk, btc.AddrVerPubkey(common.Testnet)).String()) } fmt.Println() } } else { fmt.Println("You have no persistent secret scan keys") } } if p != "file" { if len(wallet.ArmedStealthSecrets) > 0 { fmt.Println("Volatile secret scan keys:") for i := range wallet.ArmedStealthSecrets { pk := btc.PublicFromPrivate(wallet.ArmedStealthSecrets[i], true) fmt.Print(" #", i, " ", hex.EncodeToString(pk)) if p == "addr" { fmt.Print(" ", btc.NewAddrFromPubkey(pk, btc.AddrVerPubkey(common.Testnet)).String()) } if p == "save" { fn := common.GocoinHomeDir + "wallet/stealth/" + hex.EncodeToString(pk) if fi, er := os.Stat(fn); er == nil && fi.Size() >= 32 { fmt.Print(" already on disk") } else { ioutil.WriteFile(fn, wallet.ArmedStealthSecrets[i], 0600) fmt.Print(" saved") } sys.ClearBuffer(wallet.ArmedStealthSecrets[i]) } fmt.Println() } } else { fmt.Println("You have no volatile secret scan keys") } } if p == "save" { wallet.ArmedStealthSecrets = nil wallet.FetchStealthKeys() } }
func main() { if len(os.Args) < 3 { fmt.Println("Specify secret and public_key to get the next Type-2 deterministic address") fmt.Println("Add -t as the third argument to work with Testnet addresses.") return } public_key, er := hex.DecodeString(os.Args[2]) if er != nil { println("Error parsing public_key:", er.Error()) os.Exit(1) } if len(public_key) == 33 && (public_key[0] == 2 || public_key[0] == 3) { fmt.Println("Compressed") } else if len(public_key) == 65 && (public_key[0] == 4) { fmt.Println("Uncompressed") } else { println("Incorrect public key") } secret, er := hex.DecodeString(os.Args[1]) if er != nil { println("Error parsing secret:", er.Error()) os.Exit(1) } testnet := len(os.Args) > 3 && os.Args[3] == "-t" // Old address public_key = btc.DeriveNextPublic(public_key, secret) // New address fmt.Println(btc.NewAddrFromPubkey(public_key, btc.AddrVerPubkey(testnet)).String()) // New key fmt.Println(hex.EncodeToString(public_key)) }
// It is assumed that you call this function only after rec.IsStealthIdx() was true func CheckStealthRec(db *qdb.DB, k qdb.KeyType, rec *chain.OneWalkRecord, addr *btc.BtcAddr, d []byte, inbrowse bool) (fl uint32, uo *chain.OneUnspentTx) { sth_scr := rec.Script() sa := addr.StealthAddr if sa.CheckNonce(sth_scr[3:]) { vo := rec.VOut() // get the spending output var spend_v []byte if inbrowse { spend_v = db.GetNoMutex(qdb.KeyType(uint64(k) ^ uint64(vo) ^ uint64(vo+1))) } else { spend_v = db.Get(qdb.KeyType(uint64(k) ^ uint64(vo) ^ uint64(vo+1))) } if spend_v != nil { rec = chain.NewWalkRecord(spend_v) if rec.IsP2KH() { var h160 [20]byte c := btc.StealthDH(sth_scr[7:40], d) spen_exp := btc.DeriveNextPublic(sa.SpendKeys[0][:], c) btc.RimpHash(spen_exp, h160[:]) if bytes.Equal(rec.Script()[3:23], h160[:]) { adr := btc.NewAddrFromHash160(h160[:], btc.AddrVerPubkey(common.CFG.Testnet)) uo = rec.ToUnspent(adr) adr.StealthAddr = sa adr.Extra = addr.Extra uo.StealthC = c } } else { fl = chain.WALK_NOMORE } } else { fl = chain.WALK_NOMORE } } return }
func list_unspent(addr string) { fmt.Println("Checking unspent coins for addr", addr) defer func() { // in case if ad.OutScript() would panic if r := recover(); r != nil { err := r.(error) fmt.Println("main panic recovered:", err.Error()) } }() var ad *btc.BtcAddr var e error ad, e = btc.NewAddrFromString(addr) if e != nil { println(e.Error()) return } sa := ad.StealthAddr var walk chain.FunctionWalkUnspent var unsp chain.AllUnspentTx if sa == nil { exp_scr := ad.OutScript() walk = func(tx *chain.QdbRec) { for idx, rec := range tx.Outs { if rec != nil && bytes.Equal(rec.PKScr, exp_scr) { unsp = append(unsp, tx.ToUnspent(uint32(idx), ad)) } } } } else { var c, spen_exp []byte var rec, out *chain.QdbTxOut var h160 [20]byte wallet.FetchStealthKeys() d := wallet.FindStealthSecret(sa) if d == nil { fmt.Println("No matching secret found in your wallet/stealth folder") return } walk = func(tx *chain.QdbRec) { for i := 0; i < len(tx.Outs)-1; i++ { if rec = tx.Outs[i]; rec == nil { continue } if out = tx.Outs[i+1]; out == nil { continue } if !rec.IsStealthIdx() || !out.IsP2KH() || !ad.StealthAddr.CheckNonce(rec.PKScr[3:40]) { continue } c = btc.StealthDH(rec.PKScr[7:40], 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(i + 1) 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.Extra uo.StealthC = c unsp = append(unsp, uo) } } } } common.BlockChain.Unspent.BrowseUTXO(false, walk) sort.Sort(unsp) var sum uint64 for i := range unsp { if len(unsp) < 200 { fmt.Println(unsp[i].String()) } sum += unsp[i].Value } fmt.Printf("Total %.8f unspent BTC in %d outputs at address %s\n", float64(sum)/1e8, len(unsp), ad.String()) }
func do_scan_stealth(p string, ignore_prefix bool) { ad, _ := btc.NewAddrFromString(p) if ad == nil { fmt.Println("Specify base58 encoded bitcoin address") return } sa := ad.StealthAddr if sa == nil { fmt.Println("Specify base58 encoded stealth address") return } if sa.Version != btc.StealthAddressVersion(common.Testnet) { fmt.Println("Incorrect version of the stealth address") return } if len(sa.SpendKeys) != 1 { fmt.Println("Currently only single spend keys are supported. This address has", len(sa.SpendKeys)) return } //fmt.Println("scankey", hex.EncodeToString(sa.ScanKey[:])) if ignore_prefix { sa.Prefix = []byte{0} fmt.Println("Ignoring Prefix inside the address") } else if len(sa.Prefix) == 0 { fmt.Println("Prefix not present in the address") } else { fmt.Println("Prefix", sa.Prefix[0], hex.EncodeToString(sa.Prefix[1:])) } wallet.FetchStealthKeys() d := wallet.FindStealthSecret(sa) if d == nil { fmt.Println("No matching secret found in your wallet/stealth folder") return } var unsp chain.AllUnspentTx var c, spen_exp []byte var rec, out *chain.QdbTxOut var h160 [20]byte common.BlockChain.Unspent.BrowseUTXO(true, func(tx *chain.QdbRec) { for i := 0; i < len(tx.Outs)-1; i++ { if rec = tx.Outs[i]; rec == nil { continue } if out = tx.Outs[i+1]; out == nil { continue } if !rec.IsStealthIdx() || !out.IsP2KH() || !ad.StealthAddr.CheckNonce(rec.PKScr[3:40]) { continue } c = btc.StealthDH(rec.PKScr[7:40], 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(i + 1) 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.Extra uo.StealthC = c unsp = append(unsp, uo) } } }) sort.Sort(unsp) os.RemoveAll("balance") os.MkdirAll("balance/", 0770) utxt, _ := os.Create("balance/unspent.txt") fmt.Print(wallet.DumpBalance(unsp, utxt, true, false)) }
func json_balance(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } if r.Method != "POST" { return } summary := len(r.Form["summary"]) > 0 inp, er := ioutil.ReadAll(r.Body) if er != nil { println(er.Error()) return } var addrs []string er = json.Unmarshal(inp, &addrs) if er != nil { println(er.Error()) return } type OneOut struct { TxId string Vout uint32 Value uint64 Height uint32 Coinbase bool Message string Addr string } type OneOuts struct { Value uint64 OutCnt int SegWitCnt int SegWitAddr string Outs []OneOut } out := make(map[string]*OneOuts) lck := new(usif.OneLock) lck.In.Add(1) lck.Out.Add(1) usif.LocksChan <- lck lck.In.Wait() for _, a := range addrs { aa, e := btc.NewAddrFromString(a) if e != nil { continue } unsp := wallet.GetAllUnspent(aa) newrec := new(OneOuts) if len(unsp) > 0 { newrec.OutCnt = len(unsp) for _, u := range unsp { newrec.Value += u.Value if !summary { newrec.Outs = append(newrec.Outs, OneOut{ TxId: btc.NewUint256(u.TxPrevOut.Hash[:]).String(), Vout: u.Vout, Value: u.Value, Height: u.MinedAt, Coinbase: u.Coinbase, Message: html.EscapeString(string(u.Message)), Addr: a}) } } } out[aa.String()] = newrec /* Segwit P2WPKH: */ if aa.Version == btc.AddrVerPubkey(common.Testnet) { // SegWit if applicable h160 := btc.Rimp160AfterSha256(append([]byte{0, 20}, aa.Hash160[:]...)) aa = btc.NewAddrFromHash160(h160[:], btc.AddrVerScript(common.Testnet)) newrec.SegWitAddr = aa.String() unsp = wallet.GetAllUnspent(aa) if len(unsp) > 0 { newrec.OutCnt += len(unsp) newrec.SegWitCnt = len(unsp) as := aa.String() for _, u := range unsp { newrec.Value += u.Value if !summary { newrec.Outs = append(newrec.Outs, OneOut{ TxId: btc.NewUint256(u.TxPrevOut.Hash[:]).String(), Vout: u.Vout, Value: u.Value, Height: u.MinedAt, Coinbase: u.Coinbase, Message: html.EscapeString(string(u.Message)), Addr: as}) } } } } } lck.Out.Done() bx, er := json.Marshal(out) if er == nil { w.Header()["Content-Type"] = []string{"application/json"} w.Write(bx) } else { println(er.Error()) } }
func dl_balance(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } if r.Method != "POST" { return } var addrs []string var labels []string if len(r.Form["addrcnt"]) != 1 { println("no addrcnt") return } addrcnt, _ := strconv.ParseUint(r.Form["addrcnt"][0], 10, 32) for i := 0; i < int(addrcnt); i++ { is := fmt.Sprint(i) if len(r.Form["addr"+is]) == 1 { addrs = append(addrs, r.Form["addr"+is][0]) if len(r.Form["label"+is]) == 1 { labels = append(labels, r.Form["label"+is][0]) } else { labels = append(labels, "") } } } type one_unsp_rec struct { btc.TxPrevOut Value uint64 Addr string MinedAt uint32 Coinbase bool } var thisbal chain.AllUnspentTx lck := new(usif.OneLock) lck.In.Add(1) lck.Out.Add(1) usif.LocksChan <- lck lck.In.Wait() for idx, a := range addrs { aa, e := btc.NewAddrFromString(a) aa.Extra.Label = labels[idx] if e == nil { newrecs := wallet.GetAllUnspent(aa) if len(newrecs) > 0 { thisbal = append(thisbal, newrecs...) } /* Segwit P2WPKH: */ if aa.Version == btc.AddrVerPubkey(common.Testnet) { // SegWit if applicable h160 := btc.Rimp160AfterSha256(append([]byte{0, 20}, aa.Hash160[:]...)) aa = btc.NewAddrFromHash160(h160[:], btc.AddrVerScript(common.Testnet)) newrecs = wallet.GetAllUnspent(aa) if len(newrecs) > 0 { thisbal = append(thisbal, newrecs...) } } } } lck.Out.Done() buf := new(bytes.Buffer) zi := zip.NewWriter(buf) was_tx := make(map[[32]byte]bool) sort.Sort(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()) } zi.Close() w.Header()["Content-Type"] = []string{"application/zip"} w.Write(buf.Bytes()) }
// 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 }
func update_balance() { var tofetch_stealh []*btc.BtcAddr var tofetch_secrets [][]byte tofetch_regular := make(map[uint64]*btc.BtcAddr) MyBalance = nil for _, v := range CachedAddrs { v.InWallet = false } FetchStealthKeys() for i := range MyWallet.Addrs { if rec, pres := CachedAddrs[MyWallet.Addrs[i].Hash160]; pres { rec.InWallet = true cu := CacheUnspent[rec.CacheIndex] cu.BtcAddr = MyWallet.Addrs[i] for j := range cu.AllUnspentTx { // update BtcAddr in each of AllUnspentTx to reflect the latest label cu.AllUnspentTx[j].BtcAddr = MyWallet.Addrs[i] } MyBalance = append(MyBalance, CacheUnspent[rec.CacheIndex].AllUnspentTx...) } else { add_it := true // Add a new address to the balance cache if MyWallet.Addrs[i].StealthAddr == nil { tofetch_regular[MyWallet.Addrs[i].AIdx()] = MyWallet.Addrs[i] } else { sa := MyWallet.Addrs[i].StealthAddr if ssecret := FindStealthSecret(sa); ssecret != nil { tofetch_stealh = append(tofetch_stealh, MyWallet.Addrs[i]) tofetch_secrets = append(tofetch_secrets, ssecret) var rec stealthCacheRec rec.addr = MyWallet.Addrs[i] copy(rec.d[:], ssecret) copy(rec.h160[:], MyWallet.Addrs[i].Hash160[:]) StealthAdCache = append(StealthAdCache, rec) } else { if MyWallet.Addrs[i].Extra.Wallet != AddrBookFileName { fmt.Println("No matching secret for", sa.String()) } add_it = false } } if add_it { CachedAddrs[MyWallet.Addrs[i].Hash160] = &OneCachedAddrBalance{InWallet: true, CacheIndex: uint(len(CacheUnspent))} CacheUnspent = append(CacheUnspent, &OneCachedUnspent{BtcAddr: MyWallet.Addrs[i]}) } } } if len(tofetch_regular) > 0 || len(tofetch_stealh) > 0 { fmt.Println("Fetching a new blance for", len(tofetch_regular), "regular and", len(tofetch_stealh), "stealth addresses") // There are new addresses which we have not monitored yet var new_addrs chain.AllUnspentTx var c, spen_exp []byte var out *chain.QdbTxOut var h160 [20]byte common.BlockChain.Unspent.BrowseUTXO(true, func(tx *chain.QdbRec) { for idx, rec := range tx.Outs { if rec == nil { continue } if rec.IsP2KH() { if ad, ok := tofetch_regular[binary.LittleEndian.Uint64(rec.PKScr[3:3+8])]; ok { new_addrs = append(new_addrs, tx.ToUnspent(uint32(idx), ad)) } } else if rec.IsP2SH() { if ad, ok := tofetch_regular[binary.LittleEndian.Uint64(rec.PKScr[2:2+8])]; ok { new_addrs = append(new_addrs, tx.ToUnspent(uint32(idx), ad)) } } else if idx < len(tx.Outs)-1 { // check for stealth if out = tx.Outs[idx+1]; out == nil { continue } if !rec.IsStealthIdx() || !out.IsP2KH() { continue } stealth_check: for _, ad := range tofetch_stealh { if sa := ad.StealthAddr; sa.CheckNonce(rec.PKScr[3:40]) { for _, d := range tofetch_secrets { c = btc.StealthDH(rec.PKScr[7:40], 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 + 1) 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.Extra uo.StealthC = c new_addrs = append(new_addrs, uo) break stealth_check } } } } } } }) for i := range new_addrs { poi := new_addrs[i].TxPrevOut.UIdx() if _, ok := CacheUnspentIdx[poi]; ok { fmt.Println(new_addrs[i].TxPrevOut.String(), "- already on the list") continue } var rec *OneCachedAddrBalance if new_addrs[i].BtcAddr.StealthAddr != nil { var h160 [20]byte copy(h160[:], new_addrs[i].BtcAddr.StealthAddr.Hash160()) rec = CachedAddrs[h160] } else { rec = CachedAddrs[new_addrs[i].BtcAddr.Hash160] } if rec == nil { println("Hash160 not in CachedAddrs for", new_addrs[i].BtcAddr.String()) continue } rec.Value += new_addrs[i].Value CacheUnspent[rec.CacheIndex].AllUnspentTx = append(CacheUnspent[rec.CacheIndex].AllUnspentTx, new_addrs[i]) CacheUnspentIdx[new_addrs[i].TxPrevOut.UIdx()] = &OneCachedUnspentIdx{Index: rec.CacheIndex, Record: new_addrs[i]} } MyBalance = append(MyBalance, new_addrs...) } sort_and_sum() }
func AddrVerPubkey(testnet bool) byte { if !testnet { return LTC_ADDR_VERSION } return btc.AddrVerPubkey(testnet) }
/* { "address" : "2NAHUDSC1EmbTBwQQp4VQ2FNzWDqHtmk1i6", "redeemScript" : "512102cdc4fff0ad031ea5f2d0d4337e2bf976b84334f8f80b08fe3f69886d58bc5a8a2102ebf54926d3edaae51bde71f2976948559a8d43fce52f5e7ed9ed85dbaa449d7f52ae" } */ func main() { var testnet bool if len(os.Args) < 3 { fmt.Println("Specify one integer and at least one public key.") fmt.Println("For Testent, make the integer negative.") return } cnt, er := strconv.ParseInt(os.Args[1], 10, 32) if er != nil { println("Count value:", er.Error()) return } if cnt < 0 { testnet = true cnt = -cnt } if cnt < 1 || cnt > 16 { println("The integer (required number of keys) must be between 1 and 16") return } buf := new(bytes.Buffer) buf.WriteByte(byte(0x50 + cnt)) fmt.Println("Trying to prepare multisig address for", cnt, "out of", len(os.Args)-2, "public keys ...") var pkeys byte var ads string for i := 2; i < len(os.Args); i++ { if pkeys == 16 { println("Oh, give me a break. You don't need more than 16 public keys - stopping here!") break } d, er := hex.DecodeString(os.Args[i]) if er != nil { println("pubkey", i, er.Error()) } _, er = btc.NewPublicKey(d) if er != nil { println("pubkey", i, er.Error()) return } pkeys++ buf.WriteByte(byte(len(d))) buf.Write(d) if ads != "" { ads += ", " } ads += "\"" + btc.NewAddrFromPubkey(d, btc.AddrVerPubkey(testnet)).String() + "\"" } buf.WriteByte(0x50 + pkeys) buf.WriteByte(0xae) p2sh := buf.Bytes() addr := btc.NewAddrFromPubkey(p2sh, btc.AddrVerScript(testnet)) rec := "{\n" rec += fmt.Sprintf("\t\"multiAddress\" : \"%s\",\n", addr.String()) rec += fmt.Sprintf("\t\"scriptPubKey\" : \"a914%s87\",\n", hex.EncodeToString(addr.Hash160[:])) rec += fmt.Sprintf("\t\"keysRequired\" : %d,\n", cnt) rec += fmt.Sprintf("\t\"keysProvided\" : %d,\n", pkeys) rec += fmt.Sprintf("\t\"redeemScript\" : \"%s\",\n", hex.EncodeToString(p2sh)) rec += fmt.Sprintf("\t\"listOfAddres\" : [%s]\n", ads) rec += "}\n" fname := addr.String() + ".json" ioutil.WriteFile(fname, []byte(rec), 0666) fmt.Println("The address record stored in", fname) }