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 }