github.com/aergoio/aergo@v1.3.1/chain/stubchain.go (about) 1 package chain 2 3 import ( 4 "bytes" 5 "errors" 6 "math/big" 7 "time" 8 9 "github.com/aergoio/aergo/message" 10 "github.com/aergoio/aergo/types" 11 ) 12 13 //StubSyncer receive Syncer, P2P, Chain Service actor message 14 type StubBlockChain struct { 15 Best int 16 Hashes []([]byte) 17 Blocks []*types.Block 18 19 BestBlock *types.Block 20 } 21 22 var ( 23 ErrNotExistHash = errors.New("not exist hash") 24 ErrNotExistBlock = errors.New("not exist block of the hash") 25 ) 26 27 func NewStubBlockChain(size int) *StubBlockChain { 28 if size < 10000 { 29 size = 10000 30 } 31 32 tchain := &StubBlockChain{Best: -1} 33 34 tchain.Hashes = make([][]byte, size+1) 35 tchain.Blocks = make([]*types.Block, size+1) 36 37 return tchain 38 } 39 40 func (tchain *StubBlockChain) GenAddBlock() { 41 var prevBlockRootHash []byte 42 if tchain.BestBlock != nil { 43 prevBlockRootHash = tchain.BestBlock.GetHeader().BlocksRootHash 44 } 45 46 newBlock := types.NewBlock(tchain.BestBlock, prevBlockRootHash, nil, nil, nil, time.Now().UnixNano()) 47 tchain.AddBlock(newBlock) 48 49 time.Sleep(time.Nanosecond * 3) 50 } 51 52 func (tchain *StubBlockChain) AddBlock(newBlock *types.Block) error { 53 if newBlock.BlockNo() != uint64(tchain.Best+1) { 54 return ErrBlockOrphan 55 } 56 tchain.Best += 1 57 tchain.Hashes[tchain.Best] = newBlock.BlockHash() 58 tchain.Blocks[tchain.Best] = newBlock 59 tchain.BestBlock = newBlock 60 61 return nil 62 } 63 64 func (tchain *StubBlockChain) GetHashes(prevInfo *types.BlockInfo, count uint64) ([]message.BlockHash, error) { 65 if tchain.Best < int(prevInfo.No+count) { 66 return nil, ErrNotExistHash 67 } 68 69 start := prevInfo.No + 1 70 resHashes := tchain.Hashes[start : start+count] 71 72 blkHashes := make([]message.BlockHash, 0) 73 for _, hash := range resHashes { 74 blkHashes = append(blkHashes, hash) 75 } 76 77 return blkHashes, nil 78 } 79 80 func (tchain *StubBlockChain) GetBlockInfo(no uint64) *types.BlockInfo { 81 return &types.BlockInfo{tchain.Hashes[no], no} 82 } 83 84 func (tchain *StubBlockChain) GetBlockByNo(no uint64) *types.Block { 85 return tchain.Blocks[no] 86 } 87 88 func (tchain *StubBlockChain) GetBlocks(hashes []message.BlockHash) ([]*types.Block, error) { 89 startNo := -1 90 91 for i, block := range tchain.Blocks { 92 if bytes.Equal(block.GetHash(), hashes[0]) { 93 startNo = i 94 break 95 } 96 } 97 98 if startNo == -1 { 99 return nil, ErrNotExistBlock 100 } 101 102 resultBlocks := make([]*types.Block, 0) 103 i := startNo 104 for _, hash := range hashes { 105 if !bytes.Equal(tchain.Blocks[i].GetHash(), hash) { 106 return nil, ErrNotExistBlock 107 } 108 109 resultBlocks = append(resultBlocks, tchain.Blocks[i]) 110 i++ 111 } 112 113 return resultBlocks, nil 114 } 115 116 func (tchain *StubBlockChain) GetGenesisInfo() *types.Genesis { 117 // Not implemented. It should be implemented later if any test is related 118 // to genesis info. 119 return nil 120 } 121 122 func (tchain *StubBlockChain) GetConsensusInfo() string { 123 return "" 124 } 125 126 func (tchain *StubBlockChain) GetChainStats() string { 127 return "" 128 } 129 130 func (tchain *StubBlockChain) GetSystemValue(key types.SystemValue) (*big.Int, error) { 131 return nil, nil 132 } 133 134 func (tchain *StubBlockChain) GetEnterpriseConfig(key string) (*types.EnterpriseConfig, error) { 135 return nil, nil 136 } 137 138 func (tchain *StubBlockChain) GetBestBlock() (*types.Block, error) { 139 return tchain.BestBlock, nil 140 } 141 142 func (tchain *StubBlockChain) GetBlock(blockHash []byte) (*types.Block, error) { 143 for _, block := range tchain.Blocks { 144 if bytes.Equal(block.GetHash(), blockHash) { 145 return block, nil 146 break 147 } 148 } 149 150 return nil, ErrNotExistBlock 151 } 152 153 func (tchain *StubBlockChain) GetHashByNo(blockNo types.BlockNo) ([]byte, error) { 154 if uint64(len(tchain.Hashes)) <= blockNo { 155 return nil, ErrNotExistHash 156 } 157 158 return tchain.Hashes[blockNo], nil 159 } 160 161 //TODO refactoring with getAnchorsNew() 162 func (tchain *StubBlockChain) GetAnchors() (ChainAnchor, types.BlockNo, error) { 163 //from top : 8 * 32 = 256 164 anchors := make(ChainAnchor, 0) 165 cnt := MaxAnchors 166 logger.Debug().Msg("get anchors") 167 168 bestBlock, _ := tchain.GetBestBlock() 169 blkNo := bestBlock.BlockNo() 170 var lastNo types.BlockNo 171 LOOP: 172 for i := 0; i < cnt; i++ { 173 blockHash, err := tchain.GetHashByNo(blkNo) 174 if err != nil { 175 logger.Info().Msg("assertion - hash get failed") 176 // assertion! 177 return nil, 0, err 178 } 179 180 anchors = append(anchors, blockHash) 181 lastNo = blkNo 182 183 logger.Debug().Uint64("no", blkNo).Msg("anchor added") 184 185 switch { 186 case blkNo == 0: 187 break LOOP 188 case blkNo < Skip: 189 blkNo = 0 190 default: 191 blkNo -= Skip 192 } 193 } 194 195 return anchors, lastNo, nil 196 } 197 198 func (tchain *StubBlockChain) GetAncestorWithHashes(hashes [][]byte) *types.BlockInfo { 199 for _, hash := range hashes { 200 for j, chainHash := range tchain.Hashes { 201 if bytes.Equal(hash, chainHash) { 202 return &types.BlockInfo{Hash: chainHash, No: uint64(j)} 203 } 204 } 205 } 206 207 return nil 208 } 209 210 func (tchain *StubBlockChain) Rollback(ancestor *types.BlockInfo) { 211 prevBest := tchain.Best 212 tchain.Best = int(ancestor.No) 213 tchain.BestBlock = tchain.Blocks[tchain.Best] 214 215 logger.Debug().Int("prev", prevBest).Int("Best", tchain.Best).Msg("test local chain is rollbacked") 216 } 217 218 func InitStubBlockChain(prefixChain []*types.Block, genCount int) *StubBlockChain { 219 newChain := NewStubBlockChain(genCount + len(prefixChain) + 1) 220 221 //load initial Blocks 222 for _, block := range prefixChain { 223 newChain.AddBlock(block) 224 } 225 226 for i := 0; i < genCount; i++ { 227 newChain.GenAddBlock() 228 } 229 230 return newChain 231 }