github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/integration/makegenesis/genesis.go (about) 1 package makegenesis 2 3 import ( 4 "bytes" 5 "errors" 6 "io" 7 "math/big" 8 9 "github.com/unicornultrafoundation/go-u2u/common" 10 "github.com/unicornultrafoundation/go-u2u/core/state" 11 "github.com/unicornultrafoundation/go-u2u/core/types" 12 "github.com/unicornultrafoundation/go-u2u/rlp" 13 14 "github.com/unicornultrafoundation/go-helios/hash" 15 "github.com/unicornultrafoundation/go-helios/u2udb" 16 "github.com/unicornultrafoundation/go-u2u/evmcore" 17 "github.com/unicornultrafoundation/go-u2u/gossip/blockproc" 18 "github.com/unicornultrafoundation/go-u2u/gossip/blockproc/drivermodule" 19 "github.com/unicornultrafoundation/go-u2u/gossip/blockproc/eventmodule" 20 "github.com/unicornultrafoundation/go-u2u/gossip/blockproc/evmmodule" 21 "github.com/unicornultrafoundation/go-u2u/gossip/blockproc/sealmodule" 22 "github.com/unicornultrafoundation/go-u2u/gossip/evmstore" 23 "github.com/unicornultrafoundation/go-u2u/native" 24 "github.com/unicornultrafoundation/go-u2u/native/iblockproc" 25 "github.com/unicornultrafoundation/go-u2u/native/ibr" 26 "github.com/unicornultrafoundation/go-u2u/native/ier" 27 "github.com/unicornultrafoundation/go-u2u/u2u" 28 "github.com/unicornultrafoundation/go-u2u/u2u/genesis" 29 "github.com/unicornultrafoundation/go-u2u/u2u/genesisstore" 30 "github.com/unicornultrafoundation/go-u2u/utils/iodb" 31 ) 32 33 type GenesisBuilder struct { 34 dbs u2udb.DBProducer 35 36 tmpEvmStore *evmstore.Store 37 tmpStateDB *state.StateDB 38 39 totalSupply *big.Int 40 41 blocks []ibr.LlrIdxFullBlockRecord 42 epochs []ier.LlrIdxFullEpochRecord 43 currentEpoch ier.LlrIdxFullEpochRecord 44 } 45 46 type BlockProc struct { 47 SealerModule blockproc.SealerModule 48 TxListenerModule blockproc.TxListenerModule 49 PreTxTransactor blockproc.TxTransactor 50 PostTxTransactor blockproc.TxTransactor 51 EventsModule blockproc.ConfirmedEventsModule 52 EVMModule blockproc.EVM 53 } 54 55 func DefaultBlockProc() BlockProc { 56 return BlockProc{ 57 SealerModule: sealmodule.New(), 58 TxListenerModule: drivermodule.NewDriverTxListenerModule(), 59 PreTxTransactor: drivermodule.NewDriverTxPreTransactor(), 60 PostTxTransactor: drivermodule.NewDriverTxTransactor(), 61 EventsModule: eventmodule.New(), 62 EVMModule: evmmodule.New(), 63 } 64 } 65 66 func (b *GenesisBuilder) GetStateDB() *state.StateDB { 67 if b.tmpStateDB == nil { 68 tmpEvmStore := evmstore.NewStore(b.dbs, evmstore.LiteStoreConfig()) 69 b.tmpStateDB, _ = tmpEvmStore.StateDB(hash.Zero) 70 } 71 return b.tmpStateDB 72 } 73 74 func (b *GenesisBuilder) AddBalance(acc common.Address, balance *big.Int) { 75 b.tmpStateDB.AddBalance(acc, balance) 76 b.totalSupply.Add(b.totalSupply, balance) 77 } 78 79 func (b *GenesisBuilder) SetCode(acc common.Address, code []byte) { 80 b.tmpStateDB.SetCode(acc, code) 81 } 82 83 func (b *GenesisBuilder) SetNonce(acc common.Address, nonce uint64) { 84 b.tmpStateDB.SetNonce(acc, nonce) 85 } 86 87 func (b *GenesisBuilder) SetStorage(acc common.Address, key, val common.Hash) { 88 b.tmpStateDB.SetState(acc, key, val) 89 } 90 91 func (b *GenesisBuilder) AddBlock(br ibr.LlrIdxFullBlockRecord) { 92 b.blocks = append(b.blocks, br) 93 } 94 95 func (b *GenesisBuilder) AddEpoch(er ier.LlrIdxFullEpochRecord) { 96 b.epochs = append(b.epochs, er) 97 } 98 99 func (b *GenesisBuilder) SetCurrentEpoch(er ier.LlrIdxFullEpochRecord) { 100 b.currentEpoch = er 101 } 102 103 func (b *GenesisBuilder) TotalSupply() *big.Int { 104 return b.totalSupply 105 } 106 107 func (b *GenesisBuilder) CurrentHash() hash.Hash { 108 er := b.epochs[len(b.epochs)-1] 109 return er.Hash() 110 } 111 112 func NewGenesisBuilder(dbs u2udb.DBProducer) *GenesisBuilder { 113 tmpEvmStore := evmstore.NewStore(dbs, evmstore.LiteStoreConfig()) 114 statedb, _ := tmpEvmStore.StateDB(hash.Zero) 115 return &GenesisBuilder{ 116 dbs: dbs, 117 tmpEvmStore: tmpEvmStore, 118 tmpStateDB: statedb, 119 totalSupply: new(big.Int), 120 } 121 } 122 123 type dummyHeaderReturner struct { 124 } 125 126 func (d dummyHeaderReturner) GetHeader(common.Hash, uint64) *evmcore.EvmHeader { 127 return &evmcore.EvmHeader{} 128 } 129 130 func (b *GenesisBuilder) ExecuteGenesisTxs(blockProc BlockProc, genesisTxs types.Transactions) error { 131 bs, es := b.currentEpoch.BlockState.Copy(), b.currentEpoch.EpochState.Copy() 132 133 blockCtx := iblockproc.BlockCtx{ 134 Idx: bs.LastBlock.Idx + 1, 135 Time: bs.LastBlock.Time + 1, 136 Atropos: hash.Event{}, 137 } 138 139 sealer := blockProc.SealerModule.Start(blockCtx, bs, es) 140 sealing := true 141 txListener := blockProc.TxListenerModule.Start(blockCtx, bs, es, b.tmpStateDB) 142 evmProcessor := blockProc.EVMModule.Start(blockCtx, b.tmpStateDB, dummyHeaderReturner{}, func(l *types.Log) { 143 txListener.OnNewLog(l) 144 }, es.Rules, es.Rules.EvmChainConfig([]u2u.UpgradeHeight{ 145 { 146 Upgrades: es.Rules.Upgrades, 147 Height: 0, 148 }, 149 })) 150 151 // Execute genesis transactions 152 evmProcessor.Execute(genesisTxs) 153 bs = txListener.Finalize() 154 155 // Execute pre-internal transactions 156 preInternalTxs := blockProc.PreTxTransactor.PopInternalTxs(blockCtx, bs, es, sealing, b.tmpStateDB) 157 evmProcessor.Execute(preInternalTxs) 158 bs = txListener.Finalize() 159 160 // Seal epoch if requested 161 if sealing { 162 sealer.Update(bs, es) 163 bs, es = sealer.SealEpoch() 164 txListener.Update(bs, es) 165 } 166 167 // Execute post-internal transactions 168 internalTxs := blockProc.PostTxTransactor.PopInternalTxs(blockCtx, bs, es, sealing, b.tmpStateDB) 169 evmProcessor.Execute(internalTxs) 170 171 evmBlock, skippedTxs, receipts := evmProcessor.Finalize() 172 for _, r := range receipts { 173 if r.Status == 0 { 174 return errors.New("genesis transaction reverted") 175 } 176 } 177 if len(skippedTxs) != 0 { 178 return errors.New("genesis transaction is skipped") 179 } 180 bs = txListener.Finalize() 181 bs.FinalizedStateRoot = hash.Hash(evmBlock.Root) 182 183 bs.LastBlock = blockCtx 184 185 prettyHash := func(root hash.Hash) hash.Event { 186 e := native.MutableEventPayload{} 187 // for nice-looking ID 188 e.SetEpoch(es.Epoch) 189 e.SetLamport(1) 190 // actual data hashed 191 e.SetExtra(root[:]) 192 193 return e.Build().ID() 194 } 195 receiptsStorage := make([]*types.ReceiptForStorage, len(receipts)) 196 for i, r := range receipts { 197 receiptsStorage[i] = (*types.ReceiptForStorage)(r) 198 } 199 // add block 200 b.blocks = append(b.blocks, ibr.LlrIdxFullBlockRecord{ 201 LlrFullBlockRecord: ibr.LlrFullBlockRecord{ 202 Atropos: prettyHash(bs.FinalizedStateRoot), 203 Root: bs.FinalizedStateRoot, 204 Txs: evmBlock.Transactions, 205 Receipts: receiptsStorage, 206 Time: blockCtx.Time, 207 GasUsed: evmBlock.GasUsed, 208 }, 209 Idx: blockCtx.Idx, 210 }) 211 // add epoch 212 b.currentEpoch = ier.LlrIdxFullEpochRecord{ 213 LlrFullEpochRecord: ier.LlrFullEpochRecord{ 214 BlockState: bs, 215 EpochState: es, 216 }, 217 Idx: es.Epoch, 218 } 219 b.epochs = append(b.epochs, b.currentEpoch) 220 221 return b.tmpEvmStore.Commit(bs.LastBlock.Idx, bs.FinalizedStateRoot, true) 222 } 223 224 type memFile struct { 225 *bytes.Buffer 226 } 227 228 func (f *memFile) Close() error { 229 *f = memFile{} 230 return nil 231 } 232 233 func (b *GenesisBuilder) Build(head genesis.Header) *genesisstore.Store { 234 return genesisstore.NewStore(func(name string) (io.Reader, error) { 235 buf := &memFile{bytes.NewBuffer(nil)} 236 if name == genesisstore.BlocksSection(0) { 237 for i := len(b.blocks) - 1; i >= 0; i-- { 238 _ = rlp.Encode(buf, b.blocks[i]) 239 } 240 return buf, nil 241 } 242 if name == genesisstore.EpochsSection(0) { 243 for i := len(b.epochs) - 1; i >= 0; i-- { 244 _ = rlp.Encode(buf, b.epochs[i]) 245 } 246 return buf, nil 247 } 248 if name == genesisstore.EvmSection(0) { 249 it := b.tmpEvmStore.EvmDb.NewIterator(nil, nil) 250 defer it.Release() 251 _ = iodb.Write(buf, it) 252 } 253 if buf.Len() == 0 { 254 return nil, errors.New("not found") 255 } 256 return buf, nil 257 }, head, func() error { 258 *b = GenesisBuilder{} 259 return nil 260 }) 261 }