Skip to content

Commit

Permalink
Merge branch 'master' into test_empty_cli
Browse files Browse the repository at this point in the history
  • Loading branch information
amsanghi authored Oct 11, 2023
2 parents 30f7d2c + 3fbf2e8 commit 1f24115
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 44 deletions.
66 changes: 45 additions & 21 deletions arbnode/batch_poster.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,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
Expand Down Expand Up @@ -258,6 +260,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
Expand All @@ -272,25 +284,20 @@ 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
}
return b, nil
}

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.
Expand All @@ -312,7 +319,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{
Expand All @@ -328,26 +335,32 @@ 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))
} {
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))
}

if (opts.GasRefunderAddr != common.Address{}) {
l = append(l, types.AccessTuple{
Address: opts.GasRefunderAddr,
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".
common.Hash(arbutil.StorageSlotAddress(opts.SequencerInboxAddr.Bytes(), []byte{1})),
// 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.StorageSlotAddress(opts.DataPosterAddr.Bytes(), []byte{2})),
common.Hash(arbutil.PaddedKeccak256(opts.DataPosterAddr.Bytes(), []byte{2})),
},
})
}
Expand Down Expand Up @@ -992,7 +1005,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
}
Expand Down
7 changes: 2 additions & 5 deletions arbnode/dataposter/data_poster.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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 {
Expand Down
24 changes: 17 additions & 7 deletions arbutil/hash.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
package arbutil

import (
"math/big"

"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 {
A := big.NewInt(0).SetBytes(a)
B := big.NewInt(0).SetBytes(b)
return common.BytesToHash((A.Add(A, B)).Bytes()).Bytes()
}
36 changes: 35 additions & 1 deletion arbutil/hash_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/google/go-cmp/cmp"
)

func TestSlotAddress(t *testing.T) {
Expand Down Expand Up @@ -39,11 +40,44 @@ 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)
}
})
}

}

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)
}
})
}
}
2 changes: 1 addition & 1 deletion staker/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -750,7 +750,7 @@ func (v *BlockValidator) iterativeValidationProgress(ctx context.Context, ignore
} else if reorg != nil {
err := v.Reorg(ctx, *reorg)
if err != nil {
log.Error("error trying to rorg validation", "pos", *reorg-1, "err", err)
log.Error("error trying to reorg validation", "pos", *reorg-1, "err", err)
v.possiblyFatal(err)
}
}
Expand Down
6 changes: 3 additions & 3 deletions staker/validatorwallet/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion staker/validatorwallet/eoa.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
12 changes: 7 additions & 5 deletions system_tests/seqinbox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 1f24115

Please sign in to comment.