diff --git a/jsonrpc/eth_endpoint.go b/jsonrpc/eth_endpoint.go index d08f54ee5d..95d7a0dcba 100644 --- a/jsonrpc/eth_endpoint.go +++ b/jsonrpc/eth_endpoint.go @@ -732,6 +732,13 @@ func (e *Eth) GetProverData(block BlockNumberOrHash) (interface{}, error) { return nil, err } + // Get the previous block header + var previousBlockNumber = BlockNumber(header.Number) - 1 + previousHeader, err := GetHeaderFromBlockNumberOrHash(BlockNumberOrHash{BlockNumber: &previousBlockNumber}, e.store) + if err != nil { + return nil, err + } + fullBlock, valid := e.store.GetBlockByHash(header.Hash, true) if !valid { return nil, fmt.Errorf("failed to get block by hash %s", header.Hash) @@ -743,7 +750,7 @@ func (e *Eth) GetProverData(block BlockNumberOrHash) (interface{}, error) { return nil, err } - // Trace the block + // Configure the tracer tracer, _, err := NewTracer(&TraceConfig{ EnableMemory: true, EnableReturnData: true, @@ -774,8 +781,9 @@ func (e *Eth) GetProverData(block BlockNumberOrHash) (interface{}, error) { for _, accountStr := range accountsStr { accountAddress := types.StringToAddress(accountStr) - // Get the full account nonce, balance, state root and code hash - acc, err := e.store.GetAccount(header.StateRoot, accountAddress) + // Get the full account nonce, balance, state root and code hash of the state before this + // block is executed + acc, err := e.store.GetAccount(previousHeader.StateRoot, accountAddress) if err != nil { return nil, err } @@ -788,7 +796,7 @@ func (e *Eth) GetProverData(block BlockNumberOrHash) (interface{}, error) { } } - // Get storage data for all accounts from this block + // Lear of the storage changes in this block storages := make([]prover.Storage, 0) storageChanges, err := prover.ParseTraceForStorageChanges(tracesJSON) @@ -796,13 +804,15 @@ func (e *Eth) GetProverData(block BlockNumberOrHash) (interface{}, error) { return nil, err } + // Get the starting state storage merkle proof for each account and each slot + // that will be changed in this block execution for account, accountData := range accounts { if accountData.CodeHash != EmptyCodeHash { storageUpdates := make([]prover.StorageUpdate, 0) - // Account has code + // Account is smart contract (has code) for _, storageChange := range storageChanges[account] { - storageMerkleProof, err := e.store.GetStorageProof(header.StateRoot, + storageMerkleProof, err := e.store.GetStorageProof(previousHeader.StateRoot, types.StringToAddress(account), storageChange.Slot) if err != nil { return nil, err @@ -814,7 +824,6 @@ func (e *Eth) GetProverData(block BlockNumberOrHash) (interface{}, error) { } storageUpdates = append(storageUpdates, prover.StorageUpdate{ - Value: storageChange.Value.String(), Slot: storageChange.Slot.String(), MerkleProof: ss, }) @@ -828,8 +837,12 @@ func (e *Eth) GetProverData(block BlockNumberOrHash) (interface{}, error) { } } - // All transactions in the block - transactions := fullBlock.Transactions + // All transactions in this block + + transactions := make([]string, 0) + for _, transaction := range fullBlock.Transactions { + transactions = append(transactions, hex.EncodeToHex(transaction.MarshalRLP())) + } // Receipts from this block receipts, err := e.store.GetReceiptsByHash(header.Hash) @@ -842,7 +855,7 @@ func (e *Eth) GetProverData(block BlockNumberOrHash) (interface{}, error) { for account, accountData := range accounts { if accountData.CodeHash != EmptyCodeHash { - contractCode, err := e.store.GetCode(header.StateRoot, types.StringToAddress(account)) + contractCode, err := e.store.GetCode(previousHeader.StateRoot, types.StringToAddress(account)) if err != nil { return nil, err } @@ -854,9 +867,29 @@ func (e *Eth) GetProverData(block BlockNumberOrHash) (interface{}, error) { state := make([]prover.ProverAccountProof, 0) + // If there are no transactions in the block, add dummy account so that root storage data is provided + if len(accounts) == 0 { + zeroAccount := "0x0000000000000000000000000000000000000000" + zeroAccountData, err := e.store.GetAccount(previousHeader.StateRoot, types.StringToAddress(zeroAccount)) + if err != nil { + accounts[zeroAccount] = &prover.ProverAccount{ + Nonce: 0, + Balance: big.NewInt(0), + Root: types.Hash{}.String(), + CodeHash: types.Hash{}.String(), + } + } else { + accounts[zeroAccount] = &prover.ProverAccount{ + Nonce: zeroAccountData.Nonce, + Balance: zeroAccountData.Balance, + Root: zeroAccountData.Root.String(), + CodeHash: hex.EncodeToHex(zeroAccountData.CodeHash), + } + } + } // Get state Merkle proofs for all accounts for account := range accounts { - accountProof, err := e.store.GetAccountProof(header.StateRoot, types.StringToAddress(account)) + accountProof, err := e.store.GetAccountProof(previousHeader.StateRoot, types.StringToAddress(account)) if err != nil { return nil, err } @@ -872,13 +905,20 @@ func (e *Eth) GetProverData(block BlockNumberOrHash) (interface{}, error) { }) } + chainId, err := e.ChainId() + if err != nil { + return nil, err + } + return &prover.ProverData{ - BlockHeader: *header, - Accounts: accounts, - Storage: storages, - Transactions: transactions, - Receipts: receipts, - ContractCodes: contractCodes, - State: state, + ChainId: chainId, + BlockHeader: *header, + PreviousBlockHeader: *previousHeader, + Accounts: accounts, + PreviousStorage: storages, + Transactions: transactions, + Receipts: receipts, + ContractCodes: contractCodes, + PreviousState: state, }, nil } diff --git a/prover/prover.go b/prover/prover.go index 0aac644ec1..78cf83f885 100644 --- a/prover/prover.go +++ b/prover/prover.go @@ -11,7 +11,6 @@ import ( type StorageUpdate struct { Slot string - Value string MerkleProof []string } @@ -34,13 +33,15 @@ type ProverAccountProof struct { } type ProverData struct { - BlockHeader types.Header - Accounts interface{} - Storage interface{} - Transactions interface{} - Receipts interface{} - ContractCodes interface{} - State interface{} + ChainId interface{} + BlockHeader types.Header + PreviousBlockHeader types.Header + Accounts interface{} + PreviousStorage interface{} + Transactions interface{} + Receipts interface{} + ContractCodes interface{} + PreviousState interface{} } func ParseBlockAccounts(block *types.Block) ([]string, error) {