github.com/klaytn/klaytn@v1.12.1/blockchain/chain_makers.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2015 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from core/chain_makers.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package blockchain 22 23 import ( 24 "fmt" 25 "math/big" 26 27 "github.com/klaytn/klaytn/blockchain/state" 28 "github.com/klaytn/klaytn/blockchain/types" 29 "github.com/klaytn/klaytn/blockchain/vm" 30 "github.com/klaytn/klaytn/common" 31 "github.com/klaytn/klaytn/consensus" 32 "github.com/klaytn/klaytn/consensus/misc" 33 "github.com/klaytn/klaytn/params" 34 "github.com/klaytn/klaytn/storage/database" 35 "github.com/klaytn/klaytn/storage/statedb" 36 ) 37 38 // BlockGen creates blocks for testing. 39 // See GenerateChain for a detailed explanation. 40 type BlockGen struct { 41 i int 42 parent *types.Block 43 chain []*types.Block 44 chainReader consensus.ChainReader 45 header *types.Header 46 statedb *state.StateDB 47 48 txs []*types.Transaction 49 receipts []*types.Receipt 50 51 config *params.ChainConfig 52 engine consensus.Engine 53 } 54 55 // SetRewardbase sets the rewardbase field of the generated block. 56 func (b *BlockGen) SetRewardbase(addr common.Address) { 57 b.header.Rewardbase = addr 58 } 59 60 // SetExtra sets the extra data field of the generated block. 61 func (b *BlockGen) SetExtra(data []byte) { 62 b.header.Extra = data 63 } 64 65 func (b *BlockGen) SetVoteData(data []byte) { 66 b.header.Vote = data 67 } 68 69 func (b *BlockGen) SetGovData(data []byte) { 70 b.header.Governance = data 71 } 72 73 // AddTx adds a transaction to the generated block. 74 // In gxhash, arbitrary address is used as a block author's address. 75 // 76 // AddTx panics if the transaction cannot be executed. In addition to 77 // the protocol-imposed limitations (gas limit, etc.), there are some 78 // further limitations on the content of transactions that can be 79 // added. Notably, contract code relying on the BLOCKHASH instruction 80 // will panic during execution. 81 func (b *BlockGen) AddTx(tx *types.Transaction) { 82 b.AddTxWithChain(nil, tx) 83 } 84 85 // AddTxWithChain adds a transaction to the generated block. 86 // In gxhash, arbitrary address is used as a block author's address. 87 // 88 // AddTxWithChain panics if the transaction cannot be executed. In addition to 89 // the protocol-imposed limitations (gas limit, etc.), there are some 90 // further limitations on the content of transactions that can be 91 // added. If contract code relies on the BLOCKHASH instruction, 92 // the block in chain will be returned. 93 func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) { 94 b.statedb.SetTxContext(tx.Hash(), common.Hash{}, len(b.txs)) 95 receipt, _, err := bc.ApplyTransaction(b.config, ¶ms.AuthorAddressForTesting, b.statedb, b.header, tx, &b.header.GasUsed, &vm.Config{}) 96 if err != nil { 97 panic(err) 98 } 99 b.txs = append(b.txs, tx) 100 b.receipts = append(b.receipts, receipt) 101 } 102 103 // AddUncheckedTx forcefully adds a transaction to the block without any 104 // validation. 105 // 106 // AddUncheckedTx will cause consensus failures when used during real 107 // chain processing. This is best used in conjunction with raw block insertion. 108 func (b *BlockGen) AddUncheckedTx(tx *types.Transaction) { 109 b.txs = append(b.txs, tx) 110 } 111 112 // Number returns the block number of the block being generated. 113 func (b *BlockGen) Number() *big.Int { 114 return new(big.Int).Set(b.header.Number) 115 } 116 117 // AddUncheckedReceipt forcefully adds a receipts to the block without a 118 // backing transaction. 119 // 120 // AddUncheckedReceipt will cause consensus failures when used during real 121 // chain processing. This is best used in conjunction with raw block insertion. 122 func (b *BlockGen) AddUncheckedReceipt(receipt *types.Receipt) { 123 b.receipts = append(b.receipts, receipt) 124 } 125 126 // TxNonce returns the next valid transaction nonce for the 127 // account at addr. It panics if the account does not exist. 128 func (b *BlockGen) TxNonce(addr common.Address) uint64 { 129 if !b.statedb.Exist(addr) { 130 panic("account does not exist") 131 } 132 return b.statedb.GetNonce(addr) 133 } 134 135 // PrevBlock returns a previously generated block by number. It panics if 136 // num is greater or equal to the number of the block being generated. 137 // For index -1, PrevBlock returns the parent block given to GenerateChain. 138 func (b *BlockGen) PrevBlock(index int) *types.Block { 139 if index >= b.i { 140 panic("block index out of range") 141 } 142 if index == -1 { 143 return b.parent 144 } 145 return b.chain[index] 146 } 147 148 // OffsetTime modifies the time instance of a block, implicitly changing its 149 // associated blockscore. It's useful to test scenarios where forking is not 150 // tied to chain length directly. 151 func (b *BlockGen) OffsetTime(seconds int64) { 152 b.header.Time.Add(b.header.Time, new(big.Int).SetInt64(seconds)) 153 if b.header.Time.Cmp(b.parent.Header().Time) <= 0 { 154 panic("block time out of range") 155 } 156 b.header.BlockScore = b.engine.CalcBlockScore(b.chainReader, b.header.Time.Uint64(), b.parent.Header()) 157 } 158 159 // GenerateChain creates a chain of n blocks. The first block's 160 // parent will be the provided parent. db is used to store 161 // intermediate states and should contain the parent's state trie. 162 // 163 // The generator function is called with a new block generator for 164 // every block. Any transactions added to the generator 165 // become part of the block. If gen is nil, the blocks will be empty. 166 // 167 // Blocks created by GenerateChain do not contain valid proof of work 168 // values. Inserting them into BlockChain requires use of FakePow or 169 // a similar non-validating proof of work implementation. 170 func GenerateChain(config *params.ChainConfig, parent *types.Block, engine consensus.Engine, db database.DBManager, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) { 171 if config == nil { 172 config = params.TestChainConfig 173 } 174 blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n) 175 genblock := func(i int, parent *types.Block, stateDB *state.StateDB) (*types.Block, types.Receipts) { 176 // TODO(karalabe): This is needed for clique, which depends on multiple blocks. 177 // It's nonetheless ugly to spin up a blockchain here. Get rid of this somehow. 178 cacheConfig := &CacheConfig{ 179 ArchiveMode: false, 180 CacheSize: 512, 181 BlockInterval: DefaultBlockInterval, 182 TriesInMemory: DefaultTriesInMemory, 183 TrieNodeCacheConfig: statedb.GetEmptyTrieNodeCacheConfig(), 184 SnapshotCacheSize: 512, 185 SnapshotAsyncGen: true, 186 } 187 blockchain, _ := NewBlockChain(db, cacheConfig, config, engine, vm.Config{}) 188 defer blockchain.Stop() 189 190 b := &BlockGen{i: i, parent: parent, chain: blocks, chainReader: blockchain, statedb: stateDB, config: config, engine: engine} 191 b.header = makeHeader(b.chainReader, parent, stateDB, b.engine) 192 193 // Execute any user modifications to the block and finalize it 194 if gen != nil { 195 gen(i, b) 196 } 197 198 if b.engine != nil { 199 block, err := b.engine.Finalize(b.chainReader, b.header, stateDB, b.txs, b.receipts) 200 if err != nil { 201 panic(fmt.Sprintf("block finalize error: %v", err)) 202 } 203 // Write state changes to db 204 root, err := stateDB.Commit(true) 205 if err != nil { 206 panic(fmt.Sprintf("state write error: %v", err)) 207 } 208 if err := stateDB.Database().TrieDB().Commit(root, false, block.NumberU64()); err != nil { 209 panic(fmt.Sprintf("trie write error: %v", err)) 210 } 211 return block, b.receipts 212 } 213 return nil, nil 214 } 215 for i := 0; i < n; i++ { 216 statedb, err := state.New(parent.Root(), state.NewDatabase(db), nil, nil) 217 if err != nil { 218 panic(err) 219 } 220 block, receipt := genblock(i, parent, statedb) 221 blocks[i] = block 222 receipts[i] = receipt 223 parent = block 224 } 225 return blocks, receipts 226 } 227 228 func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.StateDB, engine consensus.Engine) *types.Header { 229 var time *big.Int 230 if parent.Time() == nil { 231 time = big.NewInt(10) 232 } else { 233 time = new(big.Int).Add(parent.Time(), big.NewInt(10)) // block time is fixed at 10 seconds 234 } 235 236 header := &types.Header{ 237 Root: state.IntermediateRoot(true), 238 ParentHash: parent.Hash(), 239 BlockScore: engine.CalcBlockScore(chain, time.Uint64(), &types.Header{ 240 Number: parent.Number(), 241 Time: new(big.Int).Sub(time, big.NewInt(10)), 242 BlockScore: parent.BlockScore(), 243 }), 244 Number: new(big.Int).Add(parent.Number(), common.Big1), 245 Time: time, 246 } 247 if chain.Config().IsMagmaForkEnabled(header.Number) { 248 header.BaseFee = misc.NextMagmaBlockBaseFee(parent.Header(), chain.Config().Governance.KIP71) 249 } 250 return header 251 } 252 253 // MakeHeaderChain creates a deterministic chain of headers rooted at parent. 254 func MakeHeaderChain(parent *types.Header, n int, engine consensus.Engine, db database.DBManager, seed int) []*types.Header { 255 blocks := MakeBlockChain(types.NewBlockWithHeader(parent), n, engine, db, seed) 256 headers := make([]*types.Header, len(blocks)) 257 for i, block := range blocks { 258 headers[i] = block.Header() 259 } 260 return headers 261 } 262 263 // MakeBlockChain creates a deterministic chain of blocks rooted at parent. 264 func MakeBlockChain(parent *types.Block, n int, engine consensus.Engine, db database.DBManager, seed int) []*types.Block { 265 blocks, _ := GenerateChain(params.TestChainConfig, parent, engine, db, n, func(i int, b *BlockGen) { 266 b.SetRewardbase(common.Address{0: byte(seed), 19: byte(i)}) 267 }) 268 return blocks 269 } 270 271 type fakeChainReader struct { 272 config *params.ChainConfig 273 genesis *types.Block 274 } 275 276 // Config returns the chain configuration. 277 func (cr *fakeChainReader) Config() *params.ChainConfig { 278 return cr.config 279 } 280 281 func (cr *fakeChainReader) CurrentHeader() *types.Header { return nil } 282 func (cr *fakeChainReader) GetHeaderByNumber(number uint64) *types.Header { return nil } 283 func (cr *fakeChainReader) GetHeaderByHash(hash common.Hash) *types.Header { return nil } 284 func (cr *fakeChainReader) GetHeader(hash common.Hash, number uint64) *types.Header { return nil } 285 func (cr *fakeChainReader) GetBlock(hash common.Hash, number uint64) *types.Block { return nil }