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  }