diff --git a/core/types/block.go b/core/types/block.go index 92f75c64cba2..aedb34824d69 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -18,7 +18,6 @@ package types import ( - "bytes" "encoding/binary" "fmt" "io" @@ -27,6 +26,7 @@ import ( "sync/atomic" "time" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" @@ -466,34 +466,43 @@ func HeaderParentHashFromRLP(header []byte) common.Hash { return common.BytesToHash(parentHash) } -// CHANGE(taiko): calc withdrawals root by hashing deposits with keccak256. +var ( + ethDepositsType, _ = abi.NewType("tuple[]", "[]TaikoData.EthDeposit", []abi.ArgumentMarshaling{ + {Name: "recipient", Type: "address"}, + {Name: "amount", Type: "uint96"}, + {Name: "id", Type: "uint64"}, + }) + ethDepositsArgs = abi.Arguments{{Name: "EthDeposit", Type: ethDepositsType}} +) + +type ethDeposit struct { + Recipient common.Address + Amount *big.Int + Id uint64 +} + +// CHANGE(taiko): calc withdrawals root by abi.encode deposits with keccak256. // Golang equivalent to this solidity function: -// function hashDeposits(TaikoData.EthDeposit[] memory deposits) internal pure returns (bytes32) { -// bytes memory buffer; // -// for (uint256 i = 0; i < deposits.length; i++) { -// buffer = abi.encodePacked(buffer, deposits[i].recipient, deposits[i].amount); -// } -// -// return keccak256(buffer); -// } +// function hashEthDeposits(TaikoData.EthDeposit[] memory deposits) internal pure returns (bytes32) { +// return keccak256(abi.encode(deposits)); +// } func CalcWithdrawalsRootTaiko(withdrawals []*Withdrawal) common.Hash { - // only process withdrawals/deposits of 8 minimum + // only process withdrawals/deposits of `TaikoConfig.minEthDepositsPerBlock` minimum. if len(withdrawals) == 0 { - return EmptyCodeHash // a known keccak256 hash of the empty payload bytes. + return common.HexToHash("0x569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd") // a known keccak256 hash of zero withdrawal. } - var b []byte - + var deposits []ethDeposit for _, withdrawal := range withdrawals { - // uint96 solidity type needs us to make 12 length byte slice and put - // the uint64 into the last 8 bytes. solidity is also bigendian by - // default so we need to be specific. - amountBytes := make([]byte, 12) - binary.BigEndian.PutUint64(amountBytes[4:], withdrawal.Amount) - - b = bytes.Join([][]byte{b, withdrawal.Address.Bytes(), amountBytes}, nil) + deposits = append(deposits, ethDeposit{ + Recipient: withdrawal.Address, + Amount: new(big.Int).SetUint64(withdrawal.Amount), + Id: withdrawal.Index, + }) } + b, _ := ethDepositsArgs.Pack(deposits) + return crypto.Keccak256Hash(b) } diff --git a/core/types/block_test.go b/core/types/block_test.go index c6d525ad4e4b..c196b487d06d 100644 --- a/core/types/block_test.go +++ b/core/types/block_test.go @@ -344,8 +344,8 @@ func TestRlpDecodeParentHash(t *testing.T) { } } -// change(TAIKO): test -func Test_CalcWithdrawalsRootTaiko(t *testing.T) { +// CHANGE(taiko): test `CalcWithdrawalsRootTaiko` +func TestCalcWithdrawalsRootTaiko(t *testing.T) { tests := []struct { name string withdrawals []*Withdrawal @@ -354,7 +354,7 @@ func Test_CalcWithdrawalsRootTaiko(t *testing.T) { { "empty", nil, - EmptyCodeHash, + common.HexToHash("0x569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd"), }, { "withWithdrawals", @@ -362,37 +362,45 @@ func Test_CalcWithdrawalsRootTaiko(t *testing.T) { { Address: common.HexToAddress("0xa9bcF99f5eb19277f48b71F9b14f5960AEA58a89"), Amount: 1000000000000000000, + Index: 0, }, { Address: common.HexToAddress("0x200708D76eB1B69761c23821809d53F65049939e"), Amount: 2000000000000000000, + Index: 1, }, { Address: common.HexToAddress("0x300C9b60E19634e12FC6D68B7FEa7bFB26c2E419"), Amount: 3000000000000000000, + Index: 2, }, { Address: common.HexToAddress("0x400147C0Eb43D8D71b2B03037bB7B31f8f78EF5F"), Amount: 4000000000000000000, + Index: 3, }, { Address: common.HexToAddress("0x50081b12838240B1bA02b3177153Bca678a86078"), Amount: 5000000000000000000, + Index: 4, }, { Address: common.HexToAddress("0x430c9b60e19634e12FC6d68B7fEa7bFB26c2e419"), Amount: 6000000000000000000, + Index: 5, }, { Address: common.HexToAddress("0x520147C0eB43d8D71b2b03037bB7b31f8F78EF5f"), Amount: 7000000000000000000, + Index: 6, }, { Address: common.HexToAddress("0x61081B12838240B1Ba02b3177153BcA678a86078"), Amount: 8000000000000000000, + Index: 7, }, }, - common.HexToHash("0x8117066d69ff650d78f0d7383a10cc802c2b8c0eedd932d70994252e2438c636"), + common.HexToHash("0x60386add6a400d9b23968e1239bd600d22d2eea4709246895c0e5d8f5ae49dc3"), }, }