From 2361166cb519e9e19781ba4df572bac81f504f66 Mon Sep 17 00:00:00 2001 From: ramtinms Date: Tue, 12 Mar 2024 12:23:20 -0700 Subject: [PATCH 1/5] populate receipt root --- fvm/evm/handler/handler.go | 7 +++++-- fvm/evm/types/block.go | 20 +++++++++++++++++--- fvm/evm/types/result.go | 4 ++-- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/fvm/evm/handler/handler.go b/fvm/evm/handler/handler.go index 859b376630c..ad158f9e7b9 100644 --- a/fvm/evm/handler/handler.go +++ b/fvm/evm/handler/handler.go @@ -191,7 +191,8 @@ func (h *ContractHandler) run( bp.AppendTxHash(res.TxHash) - // TODO: in the future we might update the receipt hash here + // Populate receipt root + bp.PopulateReceiptRoot([]types.Result{*res}) blockHash, err := bp.Hash() if err != nil { @@ -307,7 +308,9 @@ func (h *ContractHandler) executeAndHandleCall( } bp.AppendTxHash(res.TxHash) - // TODO: in the future we might update the receipt hash here + + // Populate receipt root + bp.PopulateReceiptRoot([]types.Result{*res}) if totalSupplyDiff != nil { if deductSupplyDiff { diff --git a/fvm/evm/types/block.go b/fvm/evm/types/block.go index 067b6341221..312a107f752 100644 --- a/fvm/evm/types/block.go +++ b/fvm/evm/types/block.go @@ -6,7 +6,8 @@ import ( gethCommon "github.com/ethereum/go-ethereum/common" gethTypes "github.com/ethereum/go-ethereum/core/types" gethCrypto "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rlp" + gethRLP "github.com/ethereum/go-ethereum/rlp" + gethTrie "github.com/onflow/go-ethereum/trie" ) // Block represents a evm block. @@ -30,7 +31,7 @@ type Block struct { // ToBytes encodes the block into bytes func (b *Block) ToBytes() ([]byte, error) { - return rlp.EncodeToBytes(b) + return gethRLP.EncodeToBytes(b) } // Hash returns the hash of the block @@ -39,6 +40,19 @@ func (b *Block) Hash() (gethCommon.Hash, error) { return gethCrypto.Keccak256Hash(data), err } +func (b *Block) PopulateReceiptRoot(results []Result) { + if len(results) == 0 { + b.ReceiptRoot = gethTypes.EmptyReceiptsHash + return + } + + receipts := make(gethTypes.Receipts, len(results)) + for i, res := range results { + receipts[i] = res.Receipt() + } + b.ReceiptRoot = gethTypes.DeriveSha(receipts, gethTrie.NewStackTrie(nil)) +} + // AppendTxHash appends a transaction hash to the list of transaction hashes of the block func (b *Block) AppendTxHash(txHash gethCommon.Hash) { b.TransactionHashes = append(b.TransactionHashes, txHash) @@ -64,7 +78,7 @@ func NewBlock( // NewBlockFromBytes constructs a new block from encoded data func NewBlockFromBytes(encoded []byte) (*Block, error) { res := &Block{} - err := rlp.DecodeBytes(encoded, res) + err := gethRLP.DecodeBytes(encoded, res) return res, err } diff --git a/fvm/evm/types/result.go b/fvm/evm/types/result.go index fba874cd641..3368dab8e66 100644 --- a/fvm/evm/types/result.go +++ b/fvm/evm/types/result.go @@ -42,7 +42,7 @@ func (res *Result) VMErrorString() string { // Receipt constructs an EVM-style receipt // can be used by json-rpc and other integration to be returned. -func (res *Result) Receipt() *gethTypes.ReceiptForStorage { +func (res *Result) Receipt() *gethTypes.Receipt { receipt := &gethTypes.Receipt{ Type: res.TxType, CumulativeGasUsed: res.GasConsumed, // TODO: update to capture cumulative @@ -56,7 +56,7 @@ func (res *Result) Receipt() *gethTypes.ReceiptForStorage { } receipt.Bloom = gethTypes.CreateBloom(gethTypes.Receipts{receipt}) - return (*gethTypes.ReceiptForStorage)(receipt) + return receipt } // Status captures the status of an interaction to the emulator From b10cd07ab2c291fb980e0feb8e6f2b4d38fab9cd Mon Sep 17 00:00:00 2001 From: ramtinms Date: Tue, 12 Mar 2024 12:33:52 -0700 Subject: [PATCH 2/5] add doc --- fvm/evm/types/block.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fvm/evm/types/block.go b/fvm/evm/types/block.go index 312a107f752..5012007fdc5 100644 --- a/fvm/evm/types/block.go +++ b/fvm/evm/types/block.go @@ -23,6 +23,9 @@ type Block struct { TotalSupply *big.Int // ReceiptRoot returns the root hash of the receipts emitted in this block + // Note that this value won't be unique to each block, for example for the + // case of empty trie of receipts or a single receipt with no logs and failed state + // the same receipt root would be reported for block. ReceiptRoot gethCommon.Hash // transaction hashes From 253d03cb2c4c509820380296bf76223db6d32f9b Mon Sep 17 00:00:00 2001 From: ramtinms Date: Tue, 12 Mar 2024 14:58:03 -0700 Subject: [PATCH 3/5] hot fix --- fvm/evm/types/block.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fvm/evm/types/block.go b/fvm/evm/types/block.go index 5012007fdc5..d69691ee5a0 100644 --- a/fvm/evm/types/block.go +++ b/fvm/evm/types/block.go @@ -7,7 +7,7 @@ import ( gethTypes "github.com/ethereum/go-ethereum/core/types" gethCrypto "github.com/ethereum/go-ethereum/crypto" gethRLP "github.com/ethereum/go-ethereum/rlp" - gethTrie "github.com/onflow/go-ethereum/trie" + gethTrie "github.com/ethereum/go-ethereum/trie" ) // Block represents a evm block. From a3f78e368319e3564b84815c4c33f543d9b381ba Mon Sep 17 00:00:00 2001 From: ramtinms Date: Tue, 12 Mar 2024 15:05:09 -0700 Subject: [PATCH 4/5] add test --- fvm/evm/types/block_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fvm/evm/types/block_test.go b/fvm/evm/types/block_test.go index 848660a6513..643e87d3f66 100644 --- a/fvm/evm/types/block_test.go +++ b/fvm/evm/types/block_test.go @@ -5,6 +5,7 @@ import ( "testing" gethCommon "github.com/ethereum/go-ethereum/common" + gethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -30,4 +31,13 @@ func Test_BlockHash(t *testing.T) { // hashes should not equal if any data is changed assert.NotEqual(t, h1, h2) + + b.PopulateReceiptRoot(nil) + require.Equal(t, gethTypes.EmptyReceiptsHash, b.ReceiptRoot) + + res := Result{ + GasConsumed: 10, + } + b.PopulateReceiptRoot([]Result{res}) + require.NotEqual(t, gethTypes.EmptyReceiptsHash, b.ReceiptRoot) } From f7ed55999582bf4d99ee1cbd0a08beaa48e2dbd3 Mon Sep 17 00:00:00 2001 From: ramtinms Date: Tue, 12 Mar 2024 15:31:49 -0700 Subject: [PATCH 5/5] doc update --- fvm/evm/types/block.go | 1 + fvm/evm/types/result.go | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/fvm/evm/types/block.go b/fvm/evm/types/block.go index d69691ee5a0..9eaa5cd7ca4 100644 --- a/fvm/evm/types/block.go +++ b/fvm/evm/types/block.go @@ -43,6 +43,7 @@ func (b *Block) Hash() (gethCommon.Hash, error) { return gethCrypto.Keccak256Hash(data), err } +// PopulateReceiptRoot populates receipt root with the given results func (b *Block) PopulateReceiptRoot(results []Result) { if len(results) == 0 { b.ReceiptRoot = gethTypes.EmptyReceiptsHash diff --git a/fvm/evm/types/result.go b/fvm/evm/types/result.go index 3368dab8e66..1827e1973f0 100644 --- a/fvm/evm/types/result.go +++ b/fvm/evm/types/result.go @@ -42,6 +42,12 @@ func (res *Result) VMErrorString() string { // Receipt constructs an EVM-style receipt // can be used by json-rpc and other integration to be returned. +// +// This is method is also used to construct block receipt root hash +// which requires the return receipt satisfy RLP encoding and cover these feilds +// Type (txType), PostState or Status, CumulativeGasUsed, Logs and Logs Bloom +// and for each log, Address, Topics, Data (consensus fields) +// During execution we also do fill in BlockNumber, TxIndex, Index (event index) func (res *Result) Receipt() *gethTypes.Receipt { receipt := &gethTypes.Receipt{ Type: res.TxType,