github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/lib/utxo/unspent_recu.go (about) 1 package utxo 2 3 import ( 4 "github.com/piotrnar/gocoin/lib/btc" 5 ) 6 7 /* 8 These are functions for dealing with uncompressed UTXO records 9 */ 10 11 func FullUtxoRecU(dat []byte) *UtxoRec { 12 var key UtxoKeyType 13 copy(key[:], dat[:UtxoIdxLen]) 14 return NewUtxoRec(key, dat[UtxoIdxLen:]) 15 } 16 17 func NewUtxoRecStaticU(key UtxoKeyType, dat []byte) *UtxoRec { 18 var off, n, i, rec_idx int 19 var u64, idx uint64 20 21 off = 32 - UtxoIdxLen 22 copy(sta_rec.TxID[:UtxoIdxLen], key[:]) 23 copy(sta_rec.TxID[UtxoIdxLen:], dat[:off]) 24 25 u64, n = btc.VULe(dat[off:]) 26 off += n 27 sta_rec.InBlock = uint32(u64) 28 29 u64, n = btc.VULe(dat[off:]) 30 off += n 31 32 sta_rec.Coinbase = (u64 & 1) != 0 33 u64 >>= 1 34 if len(rec_outs) < int(u64) { 35 rec_outs = make([]*UtxoTxOut, u64) 36 rec_pool = make([]UtxoTxOut, u64) 37 } 38 sta_rec.Outs = rec_outs[:u64] 39 for i := range sta_rec.Outs { 40 sta_rec.Outs[i] = nil 41 } 42 43 for off < len(dat) { 44 idx, n = btc.VULe(dat[off:]) 45 off += n 46 47 sta_rec.Outs[idx] = &rec_pool[rec_idx] 48 rec_idx++ 49 50 u64, n = btc.VULe(dat[off:]) 51 off += n 52 sta_rec.Outs[idx].Value = uint64(u64) 53 54 i, n = btc.VLen(dat[off:]) 55 off += n 56 57 sta_rec.Outs[idx].PKScr = dat[off : off+i] 58 off += i 59 } 60 61 return &sta_rec 62 } 63 64 func NewUtxoRecU(key UtxoKeyType, dat []byte) *UtxoRec { 65 var off, n, i int 66 var u64, idx uint64 67 var rec UtxoRec 68 69 off = 32 - UtxoIdxLen 70 copy(rec.TxID[:UtxoIdxLen], key[:]) 71 copy(rec.TxID[UtxoIdxLen:], dat[:off]) 72 73 u64, n = btc.VULe(dat[off:]) 74 off += n 75 rec.InBlock = uint32(u64) 76 77 u64, n = btc.VULe(dat[off:]) 78 off += n 79 80 rec.Coinbase = (u64 & 1) != 0 81 rec.Outs = make([]*UtxoTxOut, u64>>1) 82 83 for off < len(dat) { 84 idx, n = btc.VULe(dat[off:]) 85 off += n 86 rec.Outs[idx] = new(UtxoTxOut) 87 88 u64, n = btc.VULe(dat[off:]) 89 off += n 90 rec.Outs[idx].Value = uint64(u64) 91 92 i, n = btc.VLen(dat[off:]) 93 off += n 94 95 rec.Outs[idx].PKScr = dat[off : off+i] 96 off += i 97 } 98 return &rec 99 } 100 101 func OneUtxoRecU(key UtxoKeyType, dat []byte, vout uint32) *btc.TxOut { 102 var off, n, i int 103 var u64, idx uint64 104 var res btc.TxOut 105 106 off = 32 - UtxoIdxLen 107 108 u64, n = btc.VULe(dat[off:]) 109 off += n 110 res.BlockHeight = uint32(u64) 111 112 u64, n = btc.VULe(dat[off:]) 113 off += n 114 115 res.VoutCount = uint32(u64 >> 1) 116 if res.VoutCount <= vout { 117 return nil 118 } 119 res.WasCoinbase = (u64 & 1) != 0 120 121 for off < len(dat) { 122 idx, n = btc.VULe(dat[off:]) 123 if uint32(idx) > vout { 124 return nil 125 } 126 off += n 127 128 u64, n = btc.VULe(dat[off:]) 129 off += n 130 131 i, n = btc.VLen(dat[off:]) 132 off += n 133 134 if uint32(idx) == vout { 135 res.Value = uint64(u64) 136 res.Pk_script = dat[off : off+i] 137 return &res 138 } 139 off += i 140 } 141 return nil 142 } 143 144 // Serialize() returns UTXO-heap pointer to the freshly allocated serialized record. 145 // rec - UTXO record to serialize 146 // full - to have entire 256 bits of TxID at the beginning of the record. 147 // use_buf - the data will be serialized into this memory. if nil, it will be allocated by Memory_Malloc(). 148 func SerializeU(rec *UtxoRec, full bool, use_buf []byte) (buf []byte) { 149 var le, of int 150 var any_out bool 151 152 outcnt := uint64(len(rec.Outs) << 1) 153 if rec.Coinbase { 154 outcnt |= 1 155 } 156 157 if full { 158 le = 32 159 } else { 160 le = 32 - UtxoIdxLen 161 } 162 163 le += btc.VLenSize(uint64(rec.InBlock)) // block length 164 le += btc.VLenSize(outcnt) // out count 165 166 for i, r := range rec.Outs { 167 if rec.Outs[i] != nil { 168 le += btc.VLenSize(uint64(i)) 169 le += btc.VLenSize(r.Value) 170 le += btc.VLenSize(uint64(len(r.PKScr))) 171 le += len(r.PKScr) 172 any_out = true 173 } 174 } 175 if !any_out { 176 return 177 } 178 179 if use_buf == nil { 180 buf = Memory_Malloc(le) 181 } else { 182 buf = use_buf[:le] 183 } 184 if full { 185 copy(buf[:32], rec.TxID[:]) 186 of = 32 187 } else { 188 of = 32 - UtxoIdxLen 189 copy(buf[:of], rec.TxID[UtxoIdxLen:]) 190 } 191 192 of += btc.PutULe(buf[of:], uint64(rec.InBlock)) 193 of += btc.PutULe(buf[of:], outcnt) 194 for i, r := range rec.Outs { 195 if rec.Outs[i] != nil { 196 of += btc.PutULe(buf[of:], uint64(i)) 197 of += btc.PutULe(buf[of:], r.Value) 198 of += btc.PutULe(buf[of:], uint64(len(r.PKScr))) 199 copy(buf[of:], r.PKScr) 200 of += len(r.PKScr) 201 } 202 } 203 return 204 }