github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/lib/chain/chain_load.go (about)

     1  package chain
     2  
     3  import (
     4  	"errors"
     5  	"github.com/piotrnar/gocoin/lib/btc"
     6  )
     7  
     8  
     9  func nextBlock(ch *Chain, hash, header []byte, height, blen, txs uint32) {
    10  	bh := btc.NewUint256(hash[:])
    11  	if _, ok := ch.BlockIndex[bh.BIdx()]; ok {
    12  		println("nextBlock:", bh.String(), "- already in")
    13  		return
    14  	}
    15  	v := new(BlockTreeNode)
    16  	v.BlockHash = bh
    17  	v.Height = height
    18  	v.BlockSize = blen
    19  	v.TxCount = txs
    20  	copy(v.BlockHeader[:], header)
    21  	ch.BlockIndex[v.BlockHash.BIdx()] = v
    22  }
    23  
    24  
    25  // loadBlockIndex loads the block index from the disk.
    26  func (ch *Chain)loadBlockIndex() {
    27  	ch.BlockIndex = make(map[[btc.Uint256IdxLen]byte]*BlockTreeNode, BlockMapInitLen)
    28  	ch.BlockTreeRoot = new(BlockTreeNode)
    29  	ch.BlockTreeRoot.BlockHash = ch.Genesis
    30  	ch.RebuildGenesisHeader()
    31  	ch.BlockIndex[ch.Genesis.BIdx()] = ch.BlockTreeRoot
    32  
    33  
    34  	ch.Blocks.LoadBlockIndex(ch, nextBlock)
    35  	tlb := ch.Unspent.LastBlockHash
    36  	//println("Building tree from", len(ch.BlockIndex), "nodes")
    37  	for k, v := range ch.BlockIndex {
    38  		if AbortNow {
    39  			return
    40  		}
    41  		if v==ch.BlockTreeRoot {
    42  			// skip root block (should be only one)
    43  			continue
    44  		}
    45  
    46  		par, ok := ch.BlockIndex[btc.NewUint256(v.BlockHeader[4:36]).BIdx()]
    47  		if !ok {
    48  			println("ERROR: Block", v.Height, v.BlockHash.String(), "has no Parent")
    49  			println("...", btc.NewUint256(v.BlockHeader[4:36]).String(), "- removing it from blocksDB")
    50  			delete(ch.BlockIndex, k)
    51  			continue
    52  		}
    53  		v.Parent = par
    54  		v.Parent.addChild(v)
    55  	}
    56  	if tlb == nil {
    57  		//println("No last block - full rescan will be needed")
    58  		ch.SetLast(ch.BlockTreeRoot)
    59  		return
    60  	} else {
    61  		//println("Last Block Hash:", btc.NewUint256(tlb).String())
    62  		last, ok := ch.BlockIndex[btc.NewUint256(tlb).BIdx()]
    63  		if !ok {
    64  			panic("Last Block Hash not found")
    65  		}
    66  		ch.SetLast(last)
    67  	}
    68  }
    69  
    70  func (ch *Chain) GetRawTx(BlockHeight uint32, txid *btc.Uint256) (data []byte, er error) {
    71  	// Find the block with the indicated Height in the main tree
    72  	ch.BlockIndexAccess.Lock()
    73  	n := ch.LastBlock()
    74  	if n.Height < BlockHeight {
    75  		println(n.Height, BlockHeight)
    76  		ch.BlockIndexAccess.Unlock()
    77  		er = errors.New("GetRawTx: block height too big")
    78  		return
    79  	}
    80  	for n.Height > BlockHeight {
    81  		n = n.Parent
    82  	}
    83  	ch.BlockIndexAccess.Unlock()
    84  
    85  	bd, _, e := ch.Blocks.BlockGet(n.BlockHash)
    86  	if e != nil {
    87  		er = errors.New("GetRawTx: block not in the database")
    88  		return
    89  	}
    90  
    91  	bl, e := btc.NewBlock(bd)
    92  	if e != nil {
    93  		er = errors.New("GetRawTx: NewBlock failed")
    94  		return
    95  	}
    96  
    97  	e = bl.BuildTxList()
    98  	if e != nil {
    99  		er = errors.New("GetRawTx: BuildTxList failed")
   100  		return
   101  	}
   102  
   103  	// Find the transaction we need and store it in the file
   104  	for i := range bl.Txs {
   105  		if bl.Txs[i].Hash.Equal(txid) {
   106  			data = bl.Txs[i].Raw
   107  			return
   108  		}
   109  	}
   110  	er = errors.New("GetRawTx: BuildTxList failed")
   111  	return
   112  }