Skip to content

Commit

Permalink
Merge pull request #1630 from OffchainLabs/is-sequencer-feed
Browse files Browse the repository at this point in the history
Use sequencer inbox isSequencer to verify feed signatures
  • Loading branch information
joshuacolvin0 authored Sep 28, 2023
2 parents be635cf + 900223e commit eb54048
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 126 deletions.
4 changes: 2 additions & 2 deletions arbnode/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -641,15 +641,15 @@ func createNodeImpl(
return nil, err
}
var coordinator *SeqCoordinator
var bpVerifier *contracts.BatchPosterVerifier
var bpVerifier *contracts.AddressVerifier
if deployInfo != nil && l1client != nil {
sequencerInboxAddr := deployInfo.SequencerInbox

seqInboxCaller, err := bridgegen.NewSequencerInboxCaller(sequencerInboxAddr, l1client)
if err != nil {
return nil, err
}
bpVerifier = contracts.NewBatchPosterVerifier(seqInboxCaller)
bpVerifier = contracts.NewAddressVerifier(seqInboxCaller)
}

if config.SeqCoordinator.Enable {
Expand Down
2 changes: 1 addition & 1 deletion arbnode/seq_coordinator.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ var TestSeqCoordinatorConfig = SeqCoordinatorConfig{
Signer: signature.DefaultSignVerifyConfig,
}

func NewSeqCoordinator(dataSigner signature.DataSignerFunc, bpvalidator *contracts.BatchPosterVerifier, streamer *TransactionStreamer, sequencer *execution.Sequencer, sync *SyncMonitor, config SeqCoordinatorConfig) (*SeqCoordinator, error) {
func NewSeqCoordinator(dataSigner signature.DataSignerFunc, bpvalidator *contracts.AddressVerifier, streamer *TransactionStreamer, sequencer *execution.Sequencer, sync *SyncMonitor, config SeqCoordinatorConfig) (*SeqCoordinator, error) {
redisCoordinator, err := redisutil.NewRedisCoordinator(config.RedisUrl)
if err != nil {
return nil, err
Expand Down
4 changes: 2 additions & 2 deletions broadcastclient/broadcastclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,10 @@ func NewBroadcastClient(
txStreamer TransactionStreamerInterface,
confirmedSequencerNumberListener chan arbutil.MessageIndex,
fatalErrChan chan error,
bpVerifier contracts.BatchPosterVerifierInterface,
addrVerifier contracts.AddressVerifierInterface,
adjustCount func(int32),
) (*BroadcastClient, error) {
sigVerifier, err := signature.NewVerifier(&config().Verify, bpVerifier)
sigVerifier, err := signature.NewVerifier(&config().Verify, addrVerifier)
if err != nil {
return nil, err
}
Expand Down
6 changes: 3 additions & 3 deletions broadcastclient/broadcastclient_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,14 +200,14 @@ func (ts *dummyTransactionStreamer) AddBroadcastMessages(feedMessages []*broadca

func newTestBroadcastClient(config Config, listenerAddress net.Addr, chainId uint64, currentMessageCount arbutil.MessageIndex, txStreamer TransactionStreamerInterface, confirmedSequenceNumberListener chan arbutil.MessageIndex, feedErrChan chan error, validAddr *common.Address) (*BroadcastClient, error) {
port := listenerAddress.(*net.TCPAddr).Port
var bpv contracts.BatchPosterVerifierInterface
var av contracts.AddressVerifierInterface
if validAddr != nil {
config.Verify.AcceptSequencer = true
bpv = contracts.NewMockBatchPosterVerifier(*validAddr)
av = contracts.NewMockAddressVerifier(*validAddr)
} else {
config.Verify.AcceptSequencer = false
}
return NewBroadcastClient(func() *Config { return &config }, fmt.Sprintf("ws://127.0.0.1:%d/", port), chainId, currentMessageCount, txStreamer, confirmedSequenceNumberListener, feedErrChan, bpv, func(_ int32) {})
return NewBroadcastClient(func() *Config { return &config }, fmt.Sprintf("ws://127.0.0.1:%d/", port), chainId, currentMessageCount, txStreamer, confirmedSequenceNumberListener, feedErrChan, av, func(_ int32) {})
}

func startMakeBroadcastClient(ctx context.Context, t *testing.T, clientConfig Config, addr net.Addr, index int, expectedCount int, chainId uint64, wg *sync.WaitGroup, sequencerAddr *common.Address) {
Expand Down
4 changes: 2 additions & 2 deletions broadcastclients/broadcastclients.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func NewBroadcastClients(
txStreamer broadcastclient.TransactionStreamerInterface,
confirmedSequenceNumberListener chan arbutil.MessageIndex,
fatalErrChan chan error,
bpVerifier contracts.BatchPosterVerifierInterface,
addrVerifier contracts.AddressVerifierInterface,
) (*BroadcastClients, error) {
config := configFetcher()
urlCount := len(config.URL)
Expand All @@ -48,7 +48,7 @@ func NewBroadcastClients(
txStreamer,
confirmedSequenceNumberListener,
fatalErrChan,
bpVerifier,
addrVerifier,
func(delta int32) { clients.adjustCount(delta) },
)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion contracts
Submodule contracts updated 0 files
14 changes: 7 additions & 7 deletions das/aggregator.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ type Aggregator struct {
maxAllowedServiceStoreFailures int
keysetHash [32]byte
keysetBytes []byte
bpVerifier *contracts.BatchPosterVerifier
addrVerifier *contracts.AddressVerifier
}

type ServiceDetails struct {
Expand Down Expand Up @@ -123,9 +123,9 @@ func NewAggregatorWithSeqInboxCaller(
return nil, err
}

var bpVerifier *contracts.BatchPosterVerifier
var addrVerifier *contracts.AddressVerifier
if seqInboxCaller != nil {
bpVerifier = contracts.NewBatchPosterVerifier(seqInboxCaller)
addrVerifier = contracts.NewAddressVerifier(seqInboxCaller)
}

return &Aggregator{
Expand All @@ -136,7 +136,7 @@ func NewAggregatorWithSeqInboxCaller(
maxAllowedServiceStoreFailures: config.RPCAggregator.AssumedHonest - 1,
keysetHash: keysetHash,
keysetBytes: keysetBytes,
bpVerifier: bpVerifier,
addrVerifier: addrVerifier,
}, nil
}

Expand Down Expand Up @@ -166,16 +166,16 @@ type storeResponse struct {
// signature is not checked, which is useful for testing.
func (a *Aggregator) Store(ctx context.Context, message []byte, timeout uint64, sig []byte) (*arbstate.DataAvailabilityCertificate, error) {
log.Trace("das.Aggregator.Store", "message", pretty.FirstFewBytes(message), "timeout", time.Unix(int64(timeout), 0), "sig", pretty.FirstFewBytes(sig))
if a.bpVerifier != nil {
if a.addrVerifier != nil {
actualSigner, err := DasRecoverSigner(message, timeout, sig)
if err != nil {
return nil, err
}
isBatchPoster, err := a.bpVerifier.IsBatchPoster(ctx, actualSigner)
isBatchPosterOrSequencer, err := a.addrVerifier.IsBatchPosterOrSequencer(ctx, actualSigner)
if err != nil {
return nil, err
}
if !isBatchPoster {
if !isBatchPosterOrSequencer {
return nil, errors.New("store request not properly signed")
}
}
Expand Down
14 changes: 7 additions & 7 deletions das/sign_after_store_das_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ type SignAfterStoreDASWriter struct {
keysetHash [32]byte
keysetBytes []byte
storageService StorageService
bpVerifier *contracts.BatchPosterVerifier
addrVerifier *contracts.AddressVerifier

// Extra batch poster verifier, for local installations to have their
// own way of testing Stores.
Expand Down Expand Up @@ -136,9 +136,9 @@ func NewSignAfterStoreDASWriterWithSeqInboxCaller(
return nil, err
}

var bpVerifier *contracts.BatchPosterVerifier
var addrVerifier *contracts.AddressVerifier
if seqInboxCaller != nil {
bpVerifier = contracts.NewBatchPosterVerifier(seqInboxCaller)
addrVerifier = contracts.NewAddressVerifier(seqInboxCaller)
}

var extraBpVerifier func(message []byte, timeout uint64, sig []byte) bool
Expand Down Expand Up @@ -173,7 +173,7 @@ func NewSignAfterStoreDASWriterWithSeqInboxCaller(
keysetHash: ksHash,
keysetBytes: ksBuf.Bytes(),
storageService: storageService,
bpVerifier: bpVerifier,
addrVerifier: addrVerifier,
extraBpVerifier: extraBpVerifier,
}, nil
}
Expand All @@ -187,16 +187,16 @@ func (d *SignAfterStoreDASWriter) Store(
verified = d.extraBpVerifier(message, timeout, sig)
}

if !verified && d.bpVerifier != nil {
if !verified && d.addrVerifier != nil {
actualSigner, err := DasRecoverSigner(message, timeout, sig)
if err != nil {
return nil, err
}
isBatchPoster, err := d.bpVerifier.IsBatchPoster(ctx, actualSigner)
isBatchPosterOrSequencer, err := d.addrVerifier.IsBatchPosterOrSequencer(ctx, actualSigner)
if err != nil {
return nil, err
}
if !isBatchPoster {
if !isBatchPosterOrSequencer {
return nil, errors.New("store request not properly signed")
}
}
Expand Down
99 changes: 99 additions & 0 deletions util/contracts/address_verifier.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE

package contracts

import (
"context"
"sync"
"time"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/offchainlabs/nitro/solgen/go/bridgegen"
)

type AddressVerifier struct {
seqInboxCaller *bridgegen.SequencerInboxCaller
cache map[common.Address]bool
cacheExpiry time.Time
mutex sync.Mutex
}

// Note that we only cache positive instances, not negative ones. That's because we're willing to accept the
// consequences of a false positive (accepting a Store from a recently retired batch poster), but we don't want
// to accept the consequences of a false negative (rejecting a Store from a recently added batch poster).

var addressVerifierLifetime = time.Hour

func NewAddressVerifier(seqInboxCaller *bridgegen.SequencerInboxCaller) *AddressVerifier {
return &AddressVerifier{
seqInboxCaller: seqInboxCaller,
cache: make(map[common.Address]bool),
cacheExpiry: time.Now().Add(addressVerifierLifetime),
}
}

func (av *AddressVerifier) IsBatchPosterOrSequencer(ctx context.Context, addr common.Address) (bool, error) {
av.mutex.Lock()
if time.Now().After(av.cacheExpiry) {
if err := av.flushCache_locked(ctx); err != nil {
av.mutex.Unlock()
return false, err
}
}
if av.cache[addr] {
av.mutex.Unlock()
return true, nil
}
av.mutex.Unlock()

result, err := av.seqInboxCaller.IsBatchPoster(&bind.CallOpts{Context: ctx}, addr)
if err != nil {
return false, err
}
if !result {
var err error
result, err = av.seqInboxCaller.IsSequencer(&bind.CallOpts{Context: ctx}, addr)
if err != nil {
return false, err
}
}
if result {
av.mutex.Lock()
av.cache[addr] = true
av.mutex.Unlock()
return true, nil
}
return result, nil
}

func (av *AddressVerifier) FlushCache(ctx context.Context) error {
av.mutex.Lock()
defer av.mutex.Unlock()
return av.flushCache_locked(ctx)
}

func (av *AddressVerifier) flushCache_locked(ctx context.Context) error {
av.cache = make(map[common.Address]bool)
av.cacheExpiry = time.Now().Add(addressVerifierLifetime)
return nil
}

func NewMockAddressVerifier(validAddr common.Address) *MockAddressVerifier {
return &MockAddressVerifier{
validAddr: validAddr,
}
}

type MockAddressVerifier struct {
validAddr common.Address
}

func (bpv *MockAddressVerifier) IsBatchPosterOrSequencer(_ context.Context, addr common.Address) (bool, error) {
return addr == bpv.validAddr, nil
}

type AddressVerifierInterface interface {
IsBatchPosterOrSequencer(ctx context.Context, addr common.Address) (bool, error)
}
91 changes: 0 additions & 91 deletions util/contracts/batch_poster_verifier.go

This file was deleted.

2 changes: 1 addition & 1 deletion util/signature/sign_verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ var DefaultSignVerifyConfig = SignVerifyConfig{
Symmetric: TestSimpleHmacConfig,
}

func NewSignVerify(config *SignVerifyConfig, signerFunc DataSignerFunc, bpValidator contracts.BatchPosterVerifierInterface) (*SignVerify, error) {
func NewSignVerify(config *SignVerifyConfig, signerFunc DataSignerFunc, bpValidator contracts.AddressVerifierInterface) (*SignVerify, error) {
var fallback *SimpleHmac
if config.SymmetricFallback {
var err error
Expand Down
Loading

0 comments on commit eb54048

Please sign in to comment.