From 4278196f3b0f66b1bbce6da92f6f725bc7bf3599 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 9 Oct 2023 16:07:47 +0200 Subject: [PATCH 1/3] Add access list entries for dynamic storage slots for bridge contract --- arbnode/batch_poster.go | 79 ++++++++++++++++++++++-------- arbnode/dataposter/data_poster.go | 7 +-- arbutil/hash.go | 31 +++++++++--- arbutil/hash_test.go | 67 ++++++++++++++++++++++++- staker/validatorwallet/contract.go | 6 +-- staker/validatorwallet/eoa.go | 2 +- system_tests/seqinbox_test.go | 12 +++-- 7 files changed, 162 insertions(+), 42 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index d0f7fdb0e7..af054e7a50 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -6,6 +6,7 @@ package arbnode import ( "bytes" "context" + "encoding/binary" "encoding/hex" "errors" "fmt" @@ -80,6 +81,8 @@ type BatchPoster struct { batchReverted atomic.Bool // indicates whether data poster batch was reverted nextRevertCheckBlock int64 // the last parent block scanned for reverting batches + + accessList func(SequencerInboxAccs, AfterDelayedMessagesRead int) types.AccessList } type l1BlockBound int @@ -253,6 +256,16 @@ func NewBatchPoster(ctx context.Context, dataPosterDB ethdb.Database, l1Reader * bridgeAddr: deployInfo.Bridge, daWriter: daWriter, redisLock: redisLock, + accessList: func(SequencerInboxAccs, AfterDelayedMessagesRead int) types.AccessList { + return AccessList(&AccessListOpts{ + SequencerInboxAddr: deployInfo.SequencerInbox, + DataPosterAddr: transactOpts.From, + BridgeAddr: deployInfo.Bridge, + GasRefunderAddr: config().gasRefunder, + SequencerInboxAccs: SequencerInboxAccs, + AfterDelayedMessagesRead: AfterDelayedMessagesRead, + }) + }, } dataPosterConfigFetcher := func() *dataposter.DataPosterConfig { return &config().DataPoster @@ -267,14 +280,7 @@ func NewBatchPoster(ctx context.Context, dataPosterDB ethdb.Database, l1Reader * Config: dataPosterConfigFetcher, MetadataRetriever: b.getBatchPosterPosition, RedisKey: "data-poster.queue", - AccessList: AccessList(&AccessListOpts{ - SequencerInboxAddr: deployInfo.SequencerInbox, - DataPosterAddr: transactOpts.From, // Same as batchposter address. - BridgeAddr: deployInfo.Bridge, - GasRefunderAddr: config().gasRefunder, - }), - }, - ) + }) if err != nil { return nil, err } @@ -282,10 +288,12 @@ func NewBatchPoster(ctx context.Context, dataPosterDB ethdb.Database, l1Reader * } type AccessListOpts struct { - SequencerInboxAddr common.Address - BridgeAddr common.Address - DataPosterAddr common.Address - GasRefunderAddr common.Address + SequencerInboxAddr common.Address + BridgeAddr common.Address + DataPosterAddr common.Address + GasRefunderAddr common.Address + SequencerInboxAccs int + AfterDelayedMessagesRead int } // AccessList returns access list (contracts, storage slots) for batchposter. @@ -307,7 +315,7 @@ func AccessList(opts *AccessListOpts) types.AccessList { // of "eip1967.proxy.implementation" subtracted by 1. common.HexToHash("0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"), // isBatchPoster[batchPosterAddr]; for mainnnet it's: "0xa10aa54071443520884ed767b0684edf43acec528b7da83ab38ce60126562660". - common.Hash(arbutil.StorageSlotAddress(opts.DataPosterAddr.Bytes(), []byte{3})), + common.Hash(arbutil.PaddedKeccak256(opts.DataPosterAddr.Bytes(), []byte{3})), }, }, types.AccessTuple{ @@ -323,16 +331,28 @@ func AccessList(opts *AccessListOpts) types.AccessList { // IMPLEMENTATION_SLOT from OpenZeppelin, keccak-256 hash // of "eip1967.proxy.implementation" subtracted by 1. common.HexToHash("0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"), - // TODO: add dynamic storage slots for: - // - sequencerInboxAccs[sequencerInboxAccs.length - 1]; - // - sequencerInboxAccs.push(...); - // - delayedInboxAccs[afterDelayedMessagesRead - 1]; // These below may change when transaction is actually executed: // - delayedInboxAccs[delayedInboxAccs.length - 1] // - delayedInboxAccs.push(...); }, }, } + + for _, v := range []struct{ slotIdx, val int }{ + {7, opts.SequencerInboxAccs - 1}, // - sequencerInboxAccs[sequencerInboxAccs.length - 1]; (keccak256(7, sequencerInboxAccs.length - 1)) + {7, opts.SequencerInboxAccs}, // - sequencerInboxAccs.push(...); (keccak256(7, sequencerInboxAccs.length)) + {6, opts.AfterDelayedMessagesRead - 1}, // - delayedInboxAccs[afterDelayedMessagesRead - 1]; (keccak256(6, afterDelayedMessagesRead - 1)) + } { + + sia, err := intToBytes(v.val) + if err != nil { + log.Error("Error converting sequencer inbox accs to bytes", "err", err, "sequencerInboxAccs", opts.SequencerInboxAccs) + continue + } + sb := arbutil.SumBytes(arbutil.PaddedKeccak256([]byte{byte(v.slotIdx)}), sia) + l[1].StorageKeys = append(l[1].StorageKeys, common.Hash(sb)) + } + if (opts.GasRefunderAddr != common.Address{}) { l = append(l, types.AccessTuple{ Address: opts.GasRefunderAddr, @@ -340,15 +360,23 @@ func AccessList(opts *AccessListOpts) types.AccessList { common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000004"), // CommonParameters.{maxRefundeeBalance, extraGasMargin, calldataCost, maxGasTip} common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000005"), // CommonParameters.{maxGasCost, maxSingleGasUsage} // allowedContracts[msg.sender]; for mainnet it's: "0x7686888b19bb7b75e46bb1aa328b65150743f4899443d722f0adf8e252ccda41". - common.Hash(arbutil.StorageSlotAddress(opts.SequencerInboxAddr.Bytes(), []byte{1})), + common.Hash(arbutil.PaddedKeccak256(opts.SequencerInboxAddr.Bytes(), []byte{1})), // allowedRefundees[refundee]; for mainnet it's: "0xe85fd79f89ff278fc57d40aecb7947873df9f0beac531c8f71a98f630e1eab62". - common.Hash(arbutil.StorageSlotAddress(opts.DataPosterAddr.Bytes(), []byte{2})), + common.Hash(arbutil.PaddedKeccak256(opts.DataPosterAddr.Bytes(), []byte{2})), }, }) } return l } +func intToBytes(val int) ([]byte, error) { + buf := new(bytes.Buffer) + if err := binary.Write(buf, binary.BigEndian, int64(val)); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + // checkRevert checks blocks with number in range [from, to] whether they // contain reverted batch_poster transaction. // It returns true if it finds batch posting needs to halt, which is true if a batch reverts @@ -987,7 +1015,18 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) if err != nil { return false, err } - tx, err := b.dataPoster.PostTransaction(ctx, firstMsgTime, nonce, newMeta, b.seqInboxAddr, data, gasLimit, new(big.Int)) + tx, err := b.dataPoster.PostTransaction(ctx, + firstMsgTime, + nonce, + newMeta, + b.seqInboxAddr, + data, + gasLimit, + new(big.Int), + b.accessList( + int(batchPosition.NextSeqNum), + int(b.building.segments.delayedMsg)), + ) if err != nil { return false, err } diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index e49a2194ed..91bdf39d5f 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -64,7 +64,6 @@ type DataPoster struct { nonce uint64 queue QueueStorage errorCount map[uint64]int // number of consecutive intermittent errors rbf-ing or sending, per nonce - accessList types.AccessList } type AttemptLocker interface { @@ -101,7 +100,6 @@ type DataPosterOpts struct { Config ConfigFetcher MetadataRetriever func(ctx context.Context, blockNum *big.Int) ([]byte, error) RedisKey string // Redis storage key - AccessList types.AccessList } func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, error) { @@ -152,7 +150,6 @@ func NewDataPoster(ctx context.Context, opts *DataPosterOpts) (*DataPoster, erro queue: queue, redisLock: opts.RedisLock, errorCount: make(map[uint64]int), - accessList: opts.AccessList, }, nil } @@ -343,7 +340,7 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u return newFeeCap, newTipCap, nil } -func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Time, nonce uint64, meta []byte, to common.Address, calldata []byte, gasLimit uint64, value *big.Int) (*types.Transaction, error) { +func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Time, nonce uint64, meta []byte, to common.Address, calldata []byte, gasLimit uint64, value *big.Int, accessList types.AccessList) (*types.Transaction, error) { p.mutex.Lock() defer p.mutex.Unlock() @@ -372,7 +369,7 @@ func (p *DataPoster) PostTransaction(ctx context.Context, dataCreatedAt time.Tim To: &to, Value: value, Data: calldata, - AccessList: p.accessList, + AccessList: accessList, } fullTx, err := p.signer(p.sender, types.NewTx(&inner)) if err != nil { diff --git a/arbutil/hash.go b/arbutil/hash.go index 6966cc6dfe..faab6c655a 100644 --- a/arbutil/hash.go +++ b/arbutil/hash.go @@ -2,15 +2,32 @@ package arbutil import ( "github.com/ethereum/go-ethereum/common" - "golang.org/x/crypto/sha3" + "github.com/ethereum/go-ethereum/crypto" ) -// StorageSlotAddress pads each argument to 32 bytes, concatenates and returns -// keccak256 hashe of the result. -func StorageSlotAddress(args ...[]byte) []byte { - hash := sha3.NewLegacyKeccak256() +// PaddedKeccak256 pads each argument to 32 bytes, concatenates and returns +// keccak256 hash of the result. +func PaddedKeccak256(args ...[]byte) []byte { + var data []byte for _, arg := range args { - hash.Write(common.BytesToHash(arg).Bytes()) + data = append(data, common.BytesToHash(arg).Bytes()...) } - return hash.Sum(nil) + return crypto.Keccak256(data) +} + +// SumBytes sums two byte slices and returns the result. +// If the sum of bytes are over 32 bytes, it return last 32. +func SumBytes(a, b []byte) []byte { + // Normalize lengths to hash length. + a = common.BytesToHash(a).Bytes() + b = common.BytesToHash(b).Bytes() + + sum := make([]byte, common.HashLength) + c := 0 + for i := common.HashLength - 1; i >= 0; i-- { + tmp := int(a[i]) + int(b[i]) + c + sum[i] = byte(tmp & 0xFF) + c = tmp >> 8 + } + return sum } diff --git a/arbutil/hash_test.go b/arbutil/hash_test.go index 639274653f..f32a8ad6a4 100644 --- a/arbutil/hash_test.go +++ b/arbutil/hash_test.go @@ -2,9 +2,12 @@ package arbutil import ( "bytes" + "encoding/binary" + "fmt" "testing" "github.com/ethereum/go-ethereum/common" + "github.com/google/go-cmp/cmp" ) func TestSlotAddress(t *testing.T) { @@ -39,7 +42,7 @@ func TestSlotAddress(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { - got := StorageSlotAddress(tc.args...) + got := PaddedKeccak256(tc.args...) if !bytes.Equal(got, tc.want) { t.Errorf("slotAddress(%x) = %x, want %x", tc.args, got, tc.want) } @@ -47,3 +50,65 @@ func TestSlotAddress(t *testing.T) { } } + +func TestSumBytes(t *testing.T) { + for _, tc := range []struct { + desc string + a, b, want []byte + }{ + { + desc: "simple case", + a: []byte{0x0a, 0x0b}, + b: []byte{0x03, 0x04}, + want: common.HexToHash("0x0d0f").Bytes(), + }, + { + desc: "carry over last byte", + a: []byte{0x0a, 0xff}, + b: []byte{0x01}, + want: common.HexToHash("0x0b00").Bytes(), + }, + { + desc: "overflow", + a: common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").Bytes(), + b: []byte{0x01}, + want: common.HexToHash("0x00").Bytes(), + }, + } { + t.Run(tc.desc, func(t *testing.T) { + got := SumBytes(tc.a, tc.b) + if diff := cmp.Diff(got, tc.want); diff != "" { + t.Errorf("SumBytes(%x, %x) = %x want: %x", tc.a, tc.b, got, tc.want) + } + }) + } +} + +func TestBrutforce(t *testing.T) { + M := map[common.Hash]bool{ + common.HexToHash("0xa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688"): true, + common.HexToHash("0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40"): true, + common.HexToHash("0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f"): true, + common.HexToHash("0xa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689"): true, + } + + for i := 0; i < 256; i++ { + for j := 0; j < 256; j++ { + addr := SumBytes(PaddedKeccak256(intToBytes(t, i)), intToBytes(t, j)) + if M[common.BytesToHash(addr)] { + t.Errorf("anodar yes, i: %v, j: %v, \taddr: %x", i, j, addr) + } + } + + } +} + +func intToBytes(t *testing.T, val int) []byte { + t.Helper() + buf := new(bytes.Buffer) + err := binary.Write(buf, binary.BigEndian, int64(val)) + if err != nil { + fmt.Println("binary.Write failed:", err) + } + return buf.Bytes() +} diff --git a/staker/validatorwallet/contract.go b/staker/validatorwallet/contract.go index 3ade358cee..302e4fb439 100644 --- a/staker/validatorwallet/contract.go +++ b/staker/validatorwallet/contract.go @@ -177,7 +177,7 @@ func (v *Contract) executeTransaction(ctx context.Context, tx *types.Transaction if err != nil { return nil, fmt.Errorf("getting gas for tx data: %w", err) } - return v.dataPoster.PostTransaction(ctx, time.Now(), auth.Nonce.Uint64(), nil, *v.Address(), data, gas, auth.Value) + return v.dataPoster.PostTransaction(ctx, time.Now(), auth.Nonce.Uint64(), nil, *v.Address(), data, gas, auth.Value, nil) } func (v *Contract) populateWallet(ctx context.Context, createIfMissing bool) error { @@ -288,7 +288,7 @@ func (v *Contract) ExecuteTransactions(ctx context.Context, builder *txbuilder.B if err != nil { return nil, fmt.Errorf("getting gas for tx data: %w", err) } - arbTx, err := v.dataPoster.PostTransaction(ctx, time.Now(), auth.Nonce.Uint64(), nil, *v.Address(), txData, gas, auth.Value) + arbTx, err := v.dataPoster.PostTransaction(ctx, time.Now(), auth.Nonce.Uint64(), nil, *v.Address(), txData, gas, auth.Value, nil) if err != nil { return nil, err } @@ -338,7 +338,7 @@ func (v *Contract) TimeoutChallenges(ctx context.Context, challenges []uint64) ( if err != nil { return nil, fmt.Errorf("getting gas for tx data: %w", err) } - return v.dataPoster.PostTransaction(ctx, time.Now(), auth.Nonce.Uint64(), nil, *v.Address(), data, gas, auth.Value) + return v.dataPoster.PostTransaction(ctx, time.Now(), auth.Nonce.Uint64(), nil, *v.Address(), data, gas, auth.Value, nil) } // gasForTxData returns auth.GasLimit if it's nonzero, otherwise returns estimate. diff --git a/staker/validatorwallet/eoa.go b/staker/validatorwallet/eoa.go index b2c9f68b56..d86181f42f 100644 --- a/staker/validatorwallet/eoa.go +++ b/staker/validatorwallet/eoa.go @@ -95,7 +95,7 @@ func (w *EOA) postTransaction(ctx context.Context, baseTx *types.Transaction) (* return nil, err } gas := baseTx.Gas() + w.getExtraGas() - newTx, err := w.dataPoster.PostTransaction(ctx, time.Now(), nonce, nil, *baseTx.To(), baseTx.Data(), gas, baseTx.Value()) + newTx, err := w.dataPoster.PostTransaction(ctx, time.Now(), nonce, nil, *baseTx.To(), baseTx.Data(), gas, baseTx.Value(), nil) if err != nil { return nil, fmt.Errorf("post transaction: %w", err) } diff --git a/system_tests/seqinbox_test.go b/system_tests/seqinbox_test.go index c40a51a4c7..a456dc5fe9 100644 --- a/system_tests/seqinbox_test.go +++ b/system_tests/seqinbox_test.go @@ -84,7 +84,7 @@ func diffAccessList(accessed, al types.AccessList) string { for j := 0; j < len(accessed[i].StorageKeys); j++ { slot := accessed[i].StorageKeys[j] if _, ok := m[addr][slot]; !ok { - diff += fmt.Sprintf("storage slot: %q for contract: %v wasn't accessed", slot, addr) + diff += fmt.Sprintf("storage slot: %v for contract: %v wasn't accessed\n", slot, addr) } } } @@ -345,10 +345,12 @@ func testSequencerInboxReaderImpl(t *testing.T, validator bool) { t.Fatalf("Error creating access list: %v", err) } accessed := arbnode.AccessList(&arbnode.AccessListOpts{ - SequencerInboxAddr: l1Info.GetAddress("SequencerInbox"), - BridgeAddr: l1Info.GetAddress("Bridge"), - DataPosterAddr: seqOpts.From, - GasRefunderAddr: gasRefunderAddr, + SequencerInboxAddr: l1Info.GetAddress("SequencerInbox"), + BridgeAddr: l1Info.GetAddress("Bridge"), + DataPosterAddr: seqOpts.From, + GasRefunderAddr: gasRefunderAddr, + SequencerInboxAccs: len(blockStates), + AfterDelayedMessagesRead: 1, }) if diff := diffAccessList(accessed, *wantAL); diff != "" { t.Errorf("Access list mistmatch:\n%s\n", diff) From e79daea2c1115cd087638ac6f525224f2a78f7f7 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Mon, 9 Oct 2023 16:10:14 +0200 Subject: [PATCH 2/3] drop remnant from debugging --- arbnode/batch_poster.go | 2 +- arbutil/hash_test.go | 31 ------------------------------- 2 files changed, 1 insertion(+), 32 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index af054e7a50..051bac0afa 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -359,7 +359,7 @@ func AccessList(opts *AccessListOpts) types.AccessList { StorageKeys: []common.Hash{ common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000004"), // CommonParameters.{maxRefundeeBalance, extraGasMargin, calldataCost, maxGasTip} common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000005"), // CommonParameters.{maxGasCost, maxSingleGasUsage} - // allowedContracts[msg.sender]; for mainnet it's: "0x7686888b19bb7b75e46bb1aa328b65150743f4899443d722f0adf8e252ccda41". + // allowedContracts[msg.sender]; for mainnet it's: "0x7686888b19bb7b75e46bb1aa328b65150743f4899443d722f0adf8e252ccda41". common.Hash(arbutil.PaddedKeccak256(opts.SequencerInboxAddr.Bytes(), []byte{1})), // allowedRefundees[refundee]; for mainnet it's: "0xe85fd79f89ff278fc57d40aecb7947873df9f0beac531c8f71a98f630e1eab62". common.Hash(arbutil.PaddedKeccak256(opts.DataPosterAddr.Bytes(), []byte{2})), diff --git a/arbutil/hash_test.go b/arbutil/hash_test.go index f32a8ad6a4..2b93353d08 100644 --- a/arbutil/hash_test.go +++ b/arbutil/hash_test.go @@ -2,8 +2,6 @@ package arbutil import ( "bytes" - "encoding/binary" - "fmt" "testing" "github.com/ethereum/go-ethereum/common" @@ -83,32 +81,3 @@ func TestSumBytes(t *testing.T) { }) } } - -func TestBrutforce(t *testing.T) { - M := map[common.Hash]bool{ - common.HexToHash("0xa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688"): true, - common.HexToHash("0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40"): true, - common.HexToHash("0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f"): true, - common.HexToHash("0xa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c689"): true, - } - - for i := 0; i < 256; i++ { - for j := 0; j < 256; j++ { - addr := SumBytes(PaddedKeccak256(intToBytes(t, i)), intToBytes(t, j)) - if M[common.BytesToHash(addr)] { - t.Errorf("anodar yes, i: %v, j: %v, \taddr: %x", i, j, addr) - } - } - - } -} - -func intToBytes(t *testing.T, val int) []byte { - t.Helper() - buf := new(bytes.Buffer) - err := binary.Write(buf, binary.BigEndian, int64(val)) - if err != nil { - fmt.Println("binary.Write failed:", err) - } - return buf.Bytes() -} From 6b2174aca1eafb13bdea77656e32dda253b87148 Mon Sep 17 00:00:00 2001 From: Nodar Ambroladze Date: Tue, 10 Oct 2023 19:36:28 +0200 Subject: [PATCH 3/3] Use big.Int for bytes sum and int to byte conversion --- arbnode/batch_poster.go | 17 +---------------- arbutil/hash.go | 17 +++++------------ 2 files changed, 6 insertions(+), 28 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 051bac0afa..76ff8e6a50 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -6,7 +6,6 @@ package arbnode import ( "bytes" "context" - "encoding/binary" "encoding/hex" "errors" "fmt" @@ -343,13 +342,7 @@ func AccessList(opts *AccessListOpts) types.AccessList { {7, opts.SequencerInboxAccs}, // - sequencerInboxAccs.push(...); (keccak256(7, sequencerInboxAccs.length)) {6, opts.AfterDelayedMessagesRead - 1}, // - delayedInboxAccs[afterDelayedMessagesRead - 1]; (keccak256(6, afterDelayedMessagesRead - 1)) } { - - sia, err := intToBytes(v.val) - if err != nil { - log.Error("Error converting sequencer inbox accs to bytes", "err", err, "sequencerInboxAccs", opts.SequencerInboxAccs) - continue - } - sb := arbutil.SumBytes(arbutil.PaddedKeccak256([]byte{byte(v.slotIdx)}), sia) + sb := arbutil.SumBytes(arbutil.PaddedKeccak256([]byte{byte(v.slotIdx)}), big.NewInt(int64(v.val)).Bytes()) l[1].StorageKeys = append(l[1].StorageKeys, common.Hash(sb)) } @@ -369,14 +362,6 @@ func AccessList(opts *AccessListOpts) types.AccessList { return l } -func intToBytes(val int) ([]byte, error) { - buf := new(bytes.Buffer) - if err := binary.Write(buf, binary.BigEndian, int64(val)); err != nil { - return nil, err - } - return buf.Bytes(), nil -} - // checkRevert checks blocks with number in range [from, to] whether they // contain reverted batch_poster transaction. // It returns true if it finds batch posting needs to halt, which is true if a batch reverts diff --git a/arbutil/hash.go b/arbutil/hash.go index faab6c655a..c6e91c8ebf 100644 --- a/arbutil/hash.go +++ b/arbutil/hash.go @@ -1,6 +1,8 @@ package arbutil import ( + "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" ) @@ -18,16 +20,7 @@ func PaddedKeccak256(args ...[]byte) []byte { // SumBytes sums two byte slices and returns the result. // If the sum of bytes are over 32 bytes, it return last 32. func SumBytes(a, b []byte) []byte { - // Normalize lengths to hash length. - a = common.BytesToHash(a).Bytes() - b = common.BytesToHash(b).Bytes() - - sum := make([]byte, common.HashLength) - c := 0 - for i := common.HashLength - 1; i >= 0; i-- { - tmp := int(a[i]) + int(b[i]) + c - sum[i] = byte(tmp & 0xFF) - c = tmp >> 8 - } - return sum + A := big.NewInt(0).SetBytes(a) + B := big.NewInt(0).SetBytes(b) + return common.BytesToHash((A.Add(A, B)).Bytes()).Bytes() }