github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/wallet/unspent.go (about) 1 package main 2 3 import ( 4 "bufio" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "strconv" 9 "strings" 10 11 "github.com/piotrnar/gocoin/lib/btc" 12 ) 13 14 type unspRec struct { 15 btc.TxPrevOut 16 label string 17 key *btc.PrivateAddr 18 spent bool 19 } 20 21 var ( 22 // set in load_balance(): 23 unspentOuts []*unspRec 24 ) 25 26 func (u *unspRec) String() string { 27 return fmt.Sprint(u.TxPrevOut.String(), " ", u.label) 28 } 29 30 func NewUnspRec(l []byte) (uns *unspRec) { 31 if len(l) < 65 || l[64] != '-' { 32 return nil 33 } 34 35 txid := btc.NewUint256FromString(string(l[:64])) 36 if txid == nil { 37 return nil 38 } 39 40 rst := strings.SplitN(string(l[65:]), " ", 2) 41 vout, e := strconv.ParseUint(rst[0], 10, 32) 42 if e != nil { 43 return nil 44 } 45 46 uns = new(unspRec) 47 uns.TxPrevOut.Hash = txid.Hash 48 uns.TxPrevOut.Vout = uint32(vout) 49 if len(rst) > 1 { 50 uns.label = rst[1] 51 } 52 53 return 54 } 55 56 // load_balance loads the content of the "balance/" folder. 57 func load_balance() error { 58 f, e := os.Open("balance/unspent.txt") 59 if e != nil { 60 return e 61 } 62 rd := bufio.NewReader(f) 63 for { 64 l, _, e := rd.ReadLine() 65 if len(l) == 0 && e != nil { 66 break 67 } 68 if uns := NewUnspRec(l); uns != nil { 69 if uns.key == nil { 70 uns.key = pkscr_to_key(getUO(&uns.TxPrevOut).Pk_script) 71 } 72 unspentOuts = append(unspentOuts, uns) 73 } else { 74 println("ERROR in unspent.txt: ", string(l)) 75 } 76 } 77 f.Close() 78 return nil 79 } 80 81 func show_balance() { 82 var totBtc, msBtc, knownInputs, unknownInputs, multisigInputs uint64 83 for i := range unspentOuts { 84 uo := getUO(&unspentOuts[i].TxPrevOut) 85 86 if unspentOuts[i].key != nil { 87 totBtc += uo.Value 88 knownInputs++ 89 continue 90 } 91 92 if btc.IsP2SH(uo.Pk_script) { 93 msBtc += uo.Value 94 multisigInputs++ 95 continue 96 } 97 98 unknownInputs++ 99 if *verbose { 100 fmt.Println("WARNING: Don't know how to sign", unspentOuts[i].TxPrevOut.String()) 101 } 102 } 103 fmt.Printf("You have %.8f BTC in %d keyhash outputs\n", float64(totBtc)/1e8, knownInputs) 104 if multisigInputs > 0 { 105 fmt.Printf("There is %.8f BTC in %d multisig outputs\n", float64(msBtc)/1e8, multisigInputs) 106 } 107 if unknownInputs > 0 { 108 fmt.Println("WARNING:", unknownInputs, "unspendable inputs (-v to print them).") 109 } 110 } 111 112 // apply_to_balance applies the changes to the balance folder. 113 func apply_to_balance(tx *btc.Tx) { 114 f, _ := os.Create("balance/unspent.txt") 115 if f != nil { 116 // append new outputs at the end of unspentOuts 117 ioutil.WriteFile("balance/"+tx.Hash.String()+".tx", tx.Serialize(), 0600) 118 119 fmt.Println("Adding", len(tx.TxOut), "new output(s) to the balance/ folder...") 120 for out := range tx.TxOut { 121 if k := pkscr_to_key(tx.TxOut[out].Pk_script); k != nil { 122 uns := new(unspRec) 123 uns.key = k 124 uns.TxPrevOut.Hash = tx.Hash.Hash 125 uns.TxPrevOut.Vout = uint32(out) 126 uns.label = fmt.Sprint("# ", btc.UintToBtc(tx.TxOut[out].Value), " BTC @ ", k.BtcAddr.String()) 127 unspentOuts = append(unspentOuts, uns) 128 } 129 } 130 131 for j := range unspentOuts { 132 if !unspentOuts[j].spent { 133 fmt.Fprintln(f, unspentOuts[j].String()) 134 } 135 } 136 f.Close() 137 } else { 138 println("ERROR: Cannot create balance/unspent.txt") 139 } 140 }