github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/state/genesis.go (about) 1 package state 2 3 import ( 4 "context" 5 "fmt" 6 "math/big" 7 8 "github.com/0xPolygon/supernets2-node/encoding" 9 "github.com/0xPolygon/supernets2-node/hex" 10 "github.com/0xPolygon/supernets2-node/log" 11 "github.com/0xPolygon/supernets2-node/merkletree" 12 "github.com/ethereum/go-ethereum/common" 13 "github.com/ethereum/go-ethereum/core/types" 14 "github.com/ethereum/go-ethereum/trie" 15 "github.com/jackc/pgx/v4" 16 ) 17 18 // Genesis contains the information to populate state on creation 19 type Genesis struct { 20 // GenesisBlockNum is the block number where the polygonZKEVM smc was deployed 21 GenesisBlockNum uint64 22 Root common.Hash 23 GenesisActions []*GenesisAction 24 } 25 26 // GenesisAction represents one of the values set on the SMT during genesis. 27 type GenesisAction struct { 28 Address string `json:"address"` 29 Type int `json:"type"` 30 StoragePosition string `json:"storagePosition"` 31 Bytecode string `json:"bytecode"` 32 Key string `json:"key"` 33 Value string `json:"value"` 34 Root string `json:"root"` 35 } 36 37 // SetGenesis populates state with genesis information 38 func (s *State) SetGenesis(ctx context.Context, block Block, genesis Genesis, dbTx pgx.Tx) ([]byte, error) { 39 var ( 40 root common.Hash 41 newRoot []byte 42 err error 43 ) 44 if dbTx == nil { 45 return newRoot, ErrDBTxNil 46 } 47 if s.tree == nil { 48 return newRoot, ErrStateTreeNil 49 } 50 51 for _, action := range genesis.GenesisActions { 52 address := common.HexToAddress(action.Address) 53 switch action.Type { 54 case int(merkletree.LeafTypeBalance): 55 balance, err := encoding.DecodeBigIntHexOrDecimal(action.Value) 56 if err != nil { 57 return newRoot, err 58 } 59 newRoot, _, err = s.tree.SetBalance(ctx, address, balance, newRoot) 60 if err != nil { 61 return newRoot, err 62 } 63 case int(merkletree.LeafTypeNonce): 64 nonce, err := encoding.DecodeBigIntHexOrDecimal(action.Value) 65 if err != nil { 66 return newRoot, err 67 } 68 newRoot, _, err = s.tree.SetNonce(ctx, address, nonce, newRoot) 69 if err != nil { 70 return newRoot, err 71 } 72 case int(merkletree.LeafTypeCode): 73 code, err := hex.DecodeHex(action.Bytecode) 74 if err != nil { 75 return newRoot, fmt.Errorf("could not decode SC bytecode for address %q: %v", address, err) 76 } 77 newRoot, _, err = s.tree.SetCode(ctx, address, code, newRoot) 78 if err != nil { 79 return newRoot, err 80 } 81 case int(merkletree.LeafTypeStorage): 82 // Parse position and value 83 positionBI, err := encoding.DecodeBigIntHexOrDecimal(action.StoragePosition) 84 if err != nil { 85 return newRoot, err 86 } 87 valueBI, err := encoding.DecodeBigIntHexOrDecimal(action.Value) 88 if err != nil { 89 return newRoot, err 90 } 91 // Store 92 newRoot, _, err = s.tree.SetStorageAt(ctx, address, positionBI, valueBI, newRoot) 93 if err != nil { 94 return newRoot, err 95 } 96 case int(merkletree.LeafTypeSCLength): 97 log.Debug("Skipped genesis action of type merkletree.LeafTypeSCLength, these actions will be handled as part of merkletree.LeafTypeCode actions") 98 default: 99 return newRoot, fmt.Errorf("unknown genesis action type %q", action.Type) 100 } 101 } 102 103 root.SetBytes(newRoot) 104 105 // flush state db 106 err = s.tree.Flush(ctx) 107 if err != nil { 108 log.Errorf("error flushing state tree after genesis: %v", err) 109 return newRoot, err 110 } 111 112 // store L1 block related to genesis batch 113 err = s.AddBlock(ctx, &block, dbTx) 114 if err != nil { 115 return newRoot, err 116 } 117 118 // store genesis batch 119 batch := Batch{ 120 BatchNumber: 0, 121 Coinbase: ZeroAddress, 122 BatchL2Data: nil, 123 StateRoot: root, 124 LocalExitRoot: ZeroHash, 125 Timestamp: block.ReceivedAt, 126 Transactions: []types.Transaction{}, 127 GlobalExitRoot: ZeroHash, 128 ForcedBatchNum: nil, 129 } 130 131 err = s.storeGenesisBatch(ctx, batch, dbTx) 132 if err != nil { 133 return newRoot, err 134 } 135 136 // mark the genesis batch as virtualized 137 virtualBatch := &VirtualBatch{ 138 BatchNumber: batch.BatchNumber, 139 TxHash: ZeroHash, 140 Coinbase: ZeroAddress, 141 BlockNumber: block.BlockNumber, 142 } 143 err = s.AddVirtualBatch(ctx, virtualBatch, dbTx) 144 if err != nil { 145 return newRoot, err 146 } 147 148 // mark the genesis batch as verified/consolidated 149 verifiedBatch := &VerifiedBatch{ 150 BatchNumber: batch.BatchNumber, 151 TxHash: ZeroHash, 152 Aggregator: ZeroAddress, 153 BlockNumber: block.BlockNumber, 154 } 155 err = s.AddVerifiedBatch(ctx, verifiedBatch, dbTx) 156 if err != nil { 157 return newRoot, err 158 } 159 160 // store L2 genesis block 161 header := &types.Header{ 162 Number: big.NewInt(0), 163 ParentHash: ZeroHash, 164 Coinbase: ZeroAddress, 165 Root: root, 166 Time: uint64(block.ReceivedAt.Unix()), 167 } 168 rootHex := root.Hex() 169 log.Info("Genesis root ", rootHex) 170 171 receipts := []*types.Receipt{} 172 l2Block := types.NewBlock(header, []*types.Transaction{}, []*types.Header{}, receipts, &trie.StackTrie{}) 173 l2Block.ReceivedAt = block.ReceivedAt 174 175 return newRoot, s.AddL2Block(ctx, batch.BatchNumber, l2Block, receipts, dbTx) 176 }