From 9f1919f1be7009fde799f77d2f213b1770819e6e Mon Sep 17 00:00:00 2001 From: joanestebanr <129153821+joanestebanr@users.noreply.github.com> Date: Mon, 1 Jul 2024 22:05:38 +0200 Subject: [PATCH] wip --- cmd/run.go | 54 +++++++++++-------- etherman2/builder_contracts.go | 52 ++++++++++++++++++ etherman2/{builder.go => builder_eth2.go} | 8 +-- etherman2/interface.go | 6 +-- etherman2/interface_contracts.go | 24 +++++++++ etherman2/internal/contracts/base.go | 33 ++++++++++++ etherman2/internal/contracts/elderberry.go | 26 +++++++++ .../etherman2seqsender/eth2elderberry.go | 21 +++----- sequencesender/sequencesender.go | 20 +++---- 9 files changed, 184 insertions(+), 60 deletions(-) create mode 100644 etherman2/builder_contracts.go rename etherman2/{builder.go => builder_eth2.go} (94%) create mode 100644 etherman2/interface_contracts.go create mode 100644 etherman2/internal/contracts/base.go create mode 100644 etherman2/internal/contracts/elderberry.go diff --git a/cmd/run.go b/cmd/run.go index fa7f2939..6c1b8ffb 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -25,6 +25,7 @@ import ( "github.com/0xPolygon/cdk/state/pgstatestorage" ethtxman "github.com/0xPolygonHermez/zkevm-ethtx-manager/etherman" "github.com/0xPolygonHermez/zkevm-ethtx-manager/etherman/etherscan" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/jackc/pgx/v4/pgxpool" "github.com/urfave/cli/v2" ) @@ -113,6 +114,18 @@ func createAggregator(ctx context.Context, c config.Config, runMigrations bool) return aggregator } +func registerValidium(selector *txbuilder.TxBuilderRouter, cfg config.Config, + ethman *etherman.Client, contracts *etherman2.Contracts, + sender *bind.TransactOpts) { + da, err := newDataAvailability(cfg, ethman) + if err != nil { + log.Fatal(err) + } + eth2elderberry := etherman2seqsender.NewEth2Elderberry(contracts.RollupElderberry) + txbuilder := txbuilder.NewBuildSequenceBatchesTxValidium(da, eth2elderberry, cfg.SequenceSender.L2Coinbase, sender) + selector.Register("elderberry", txbuilder) +} + func createSequenceSender(cfg config.Config) *sequencesender.SequenceSender { ethman, err := etherman.NewClient(etherman.Config{ EthermanConfig: ethtxman.Config{ @@ -135,35 +148,30 @@ func createSequenceSender(cfg config.Config) *sequencesender.SequenceSender { if err != nil { log.Fatal(err) } - - eth2, err := etherman2.NewEtherman2Builder(). - ChainReader(cfg.Etherman.URL). - AuthStore(nil). - Build(context.Background()) - if err != nil { - log.Fatal(err) - } - err = eth2.AddOrReplaceAuth(*auth) - if err != nil { - log.Fatal(err) - } cfg.SequenceSender.SenderAddress = auth.From - - da, err := newDataAvailability(cfg, ethman) + /* + This code is just an example, but not needed + eth2, err := etherman2.NewEtherman2Builder(). + ChainReader(cfg.Etherman.URL). + AuthStore(nil). + Build(context.Background()) + if err != nil { + log.Fatal(err) + } + */ + contracts, err := etherman2.NewEtherman2ContractBuilder(cfg.Etherman.URL). + AddRollupElderberry(cfg.NetworkConfig.L1Config.ZkEVMAddr). + Build() if err != nil { log.Fatal(err) } - txBuilder := txbuilder.NewTxBuilderSelector(txbuilder.NewSelectorPerForkID()) + + txBuilderSelector := txbuilder.NewTxBuilderSelector(txbuilder.NewSelectorPerForkID()) if cfg.SequenceSender.IsValidiumMode { - eth2c := etherman2seqsender.NewEth2Elderberry(nil) - err := eth2c.LoadContract(cfg.NetworkConfig.L1Config.ZkEVMAddr, ethman.EthClient) - if err != nil { - log.Fatal(err) - } - txBV := txbuilder.NewBuildSequenceBatchesTxValidium(da, eth2c, cfg.SequenceSender.L2Coinbase, auth) - txBuilder.Register("elderberry", txBV) + registerValidium(txBuilderSelector, cfg, ethman, contracts, auth) } - seqSender, err := sequencesender.New(cfg.SequenceSender, ethman, da) + + seqSender, err := sequencesender.New(cfg.SequenceSender, ethman, txBuilderSelector) if err != nil { log.Fatal(err) } diff --git a/etherman2/builder_contracts.go b/etherman2/builder_contracts.go new file mode 100644 index 00000000..2edf6c16 --- /dev/null +++ b/etherman2/builder_contracts.go @@ -0,0 +1,52 @@ +package etherman2 + +import ( + "log" + + internal_contracts "github.com/0xPolygon/cdk/etherman2/internal/contracts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" +) + +type Etherman2ContractBuilder struct { + build struct { + result *Contracts + } + params struct { + rpcURL string + RollupElderberry *common.Address + } +} + +func NewEtherman2ContractBuilder(rpcURL string) *Etherman2ContractBuilder { + res := &Etherman2ContractBuilder{} + res.params.rpcURL = rpcURL + return res +} + +func (e *Etherman2ContractBuilder) AddRollupElderberry(address common.Address) *Etherman2ContractBuilder { + if e.build.result != nil { + log.Fatal("Cannot add contracts after build") + } + e.params.RollupElderberry = &address + return e +} + +func (e *Etherman2ContractBuilder) Build() (*Contracts, error) { + if e.build.result != nil { + return e.build.result, nil + } + l1Client, err := ethclient.Dial(e.params.rpcURL) + if err != nil { + return nil, err + } + e.build.result = &Contracts{} + if e.params.RollupElderberry != nil { + rollupElderberry, err := internal_contracts.NewContractRollupElderberry(*e.params.RollupElderberry, l1Client) + if err != nil { + return nil, err + } + e.build.result.RollupElderberry = rollupElderberry + } + return e.build.result, nil +} diff --git a/etherman2/builder.go b/etherman2/builder_eth2.go similarity index 94% rename from etherman2/builder.go rename to etherman2/builder_eth2.go index 0ad77527..0125dfd9 100644 --- a/etherman2/builder.go +++ b/etherman2/builder_eth2.go @@ -9,8 +9,8 @@ import ( ) type etherman2Impl struct { - *internal.Etherman2AuthStore - *internal.Etherman2ChainReader + Etherman2ChainReader + Etherman2AuthStorerRW } /* @@ -31,6 +31,7 @@ type Etherman2Builder struct { enabled bool forcedChainID *uint64 } + result etherman2Impl } @@ -63,6 +64,7 @@ func (e *Etherman2Builder) Build(ctx context.Context) (*etherman2Impl, error) { return nil, err } } + return &e.result, nil } @@ -89,7 +91,7 @@ func (e *Etherman2Builder) newChainReader() error { func (e *Etherman2Builder) newAuthStore(ctx context.Context) error { if e.authStore.enabled { chainID, err := e.getChainID(ctx) - e.result.Etherman2AuthStore, err = internal.NewEtherman2L1Auth(chainID) + e.result.Etherman2AuthStorerRW, err = internal.NewEtherman2L1Auth(chainID) if err != nil { return err } diff --git a/etherman2/interface.go b/etherman2/interface.go index f385f9b7..5f082ad1 100644 --- a/etherman2/interface.go +++ b/etherman2/interface.go @@ -24,11 +24,7 @@ type Etherman2AuthStorerRW interface { AddOrReplaceAuth(auth bind.TransactOpts) error } -type Etherman2ContractLoader[T any] interface { - LoadContract(address common.Address, backend bind.ContractBackend, funcConstructor func(common.Address, bind.ContractBackend) (T, error)) (T, error) -} - -type Etherman2 interface { +type Etherman2Composite interface { Etherman2ChainReader Etherman2AuthStorerRW } diff --git a/etherman2/interface_contracts.go b/etherman2/interface_contracts.go new file mode 100644 index 00000000..a2e56a07 --- /dev/null +++ b/etherman2/interface_contracts.go @@ -0,0 +1,24 @@ +package etherman2 + +import ( + "github.com/0xPolygon/cdk-contracts-tooling/contracts/elderberry/polygonvalidiumetrog" + "github.com/ethereum/go-ethereum/common" +) + +type Etherman2Contract[T any] interface { + GetContract() *T + GetAddress() common.Address +} + +type Etherman2ContractRollupCommon interface { + TrustedSequencer() (common.Address, error) +} + +type Etherman2ContractRollupElderberry interface { + Etherman2Contract[polygonvalidiumetrog.Polygonvalidiumetrog] + Etherman2ContractRollupCommon +} + +type Contracts struct { + RollupElderberry Etherman2ContractRollupElderberry +} diff --git a/etherman2/internal/contracts/base.go b/etherman2/internal/contracts/base.go new file mode 100644 index 00000000..41e98a8e --- /dev/null +++ b/etherman2/internal/contracts/base.go @@ -0,0 +1,33 @@ +package internal_contracts + +import ( + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" +) + +type ContractBase[T any] struct { + contractBind *T + address common.Address +} + +type contractConstructorFunc[T any] func(address common.Address, backend bind.ContractBackend) (*T, error) + +func NewContractBase[T any](constructor contractConstructorFunc[T], address common.Address, backend bind.ContractBackend) (*ContractBase[T], error) { + contractBind, err := constructor(address, backend) + if err != nil { + return nil, err + } + + return &ContractBase[T]{ + contractBind: contractBind, + address: address, + }, nil +} + +func (e *ContractBase[T]) GetContract() *T { + return e.contractBind +} + +func (e *ContractBase[T]) GetAddress() common.Address { + return e.address +} diff --git a/etherman2/internal/contracts/elderberry.go b/etherman2/internal/contracts/elderberry.go new file mode 100644 index 00000000..9ce1cc15 --- /dev/null +++ b/etherman2/internal/contracts/elderberry.go @@ -0,0 +1,26 @@ +package internal_contracts + +import ( + "github.com/0xPolygon/cdk-contracts-tooling/contracts/elderberry/polygonvalidiumetrog" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" +) + +type ContractRollupElderberry struct { + *ContractBase[polygonvalidiumetrog.Polygonvalidiumetrog] +} + +func NewContractRollupElderberry(address common.Address, backend bind.ContractBackend) (*ContractRollupElderberry, error) { + //ZkEVM, err := polygonvalidiumetrog.NewPolygonvalidiumetrog(address, backend) + base, err := NewContractBase(polygonvalidiumetrog.NewPolygonvalidiumetrog, address, backend) + if err != nil { + return nil, err + } + return &ContractRollupElderberry{ + ContractBase: base, + }, nil +} + +func (e *ContractRollupElderberry) TrustedSequencer() (common.Address, error) { + return e.GetContract().TrustedSequencer(&bind.CallOpts{Pending: false}) +} diff --git a/sequencesender/etherman2seqsender/eth2elderberry.go b/sequencesender/etherman2seqsender/eth2elderberry.go index 2781738e..be10235c 100644 --- a/sequencesender/etherman2seqsender/eth2elderberry.go +++ b/sequencesender/etherman2seqsender/eth2elderberry.go @@ -11,24 +11,15 @@ import ( ) type Eth2Elderberry struct { - ZkEVM *polygonvalidiumetrog.Polygonvalidiumetrog + ZkEVM etherman2.Etherman2ContractRollupElderberry } -func NewEth2Elderberry(zkEVM *polygonvalidiumetrog.Polygonvalidiumetrog) *Eth2Elderberry { +func NewEth2Elderberry(zkEVM etherman2.Etherman2ContractRollupElderberry) *Eth2Elderberry { return &Eth2Elderberry{ ZkEVM: zkEVM, } } -func (etherMan *Eth2Elderberry) LoadContract(address common.Address, backend bind.ContractBackend) error { - var err error - etherMan.ZkEVM, err = polygonvalidiumetrog.NewPolygonvalidiumetrog(address, backend) - if err != nil { - return err - } - return nil -} - // func (etherMan *Eth2Elderberry) BuildSequenceBatchesTxZKEVM(opts bind.TransactOpts, sequences []ethmanTypes.Sequence, maxSequenceTimestamp uint64, lastSequencedBatchNumber uint64, l2Coinbase common.Address) (*types.Transaction, error) { func (etherMan *Eth2Elderberry) BuildSequenceBatchesTxZKEVM(opts *bind.TransactOpts, params BuildSequenceBatchesParams) (*types.Transaction, error) { batches := make([]polygonvalidiumetrog.PolygonRollupBaseEtrogBatchData, len(params.Sequences)) @@ -45,8 +36,8 @@ func (etherMan *Eth2Elderberry) BuildSequenceBatchesTxZKEVM(opts *bind.TransactO ForcedBlockHashL1: seq.PrevBlockHash, } } - - tx, err := etherMan.ZkEVM.SequenceBatches(opts, batches, params.MaxSequenceTimestamp, params.LastSequencedBatchNumber, params.L2Coinbase) + ZkEVM := etherMan.ZkEVM.GetContract() + tx, err := ZkEVM.SequenceBatches(opts, batches, params.MaxSequenceTimestamp, params.LastSequencedBatchNumber, params.L2Coinbase) if err != nil { etherMan.warningMessage(batches, params.L2Coinbase, opts) if parsedErr, ok := etherman2.TryParseError(err); ok { @@ -72,8 +63,8 @@ func (etherMan *Eth2Elderberry) BuildSequenceBatchesTxValidium(opts *bind.Transa ForcedBlockHashL1: seq.PrevBlockHash, } } - - tx, err := etherMan.ZkEVM.SequenceBatchesValidium(opts, batches, params.MaxSequenceTimestamp, + ZkEVM := etherMan.ZkEVM.GetContract() + tx, err := ZkEVM.SequenceBatchesValidium(opts, batches, params.MaxSequenceTimestamp, params.LastSequencedBatchNumber, params.L2Coinbase, dataAvailabilityMessage) if err != nil { if parsedErr, ok := etherman2.TryParseError(err); ok { diff --git a/sequencesender/sequencesender.go b/sequencesender/sequencesender.go index 0f073978..0b6e15a8 100644 --- a/sequencesender/sequencesender.go +++ b/sequencesender/sequencesender.go @@ -12,7 +12,6 @@ import ( "sync" "time" - "github.com/0xPolygon/cdk/dataavailability" "github.com/0xPolygon/cdk/etherman" "github.com/0xPolygon/cdk/etherman/types" "github.com/0xPolygon/cdk/log" @@ -54,7 +53,6 @@ type SequenceSender struct { latestStreamBatch uint64 // Latest batch received by the streaming seqSendingStopped bool // If there is a critical error streamClient *datastreamer.StreamClient - da *dataavailability.DataAvailability txBuilder txbuilder.TxBuilder } @@ -84,12 +82,7 @@ type ethTxAdditionalData struct { } // New inits sequence sender -func New(cfg Config, etherman *etherman.Client, da *dataavailability.DataAvailability) (*SequenceSender, error) { - txBuilder := txbuilder.NewTxBuilderSelector(txbuilder.NewSelectorPerForkID()) - if cfg.IsValidiumMode{ - txBuilder.Register("elderberry", txbuilder.NewBuildSequenceBatchesTxValidium(da, - ) - } +func New(cfg Config, etherman *etherman.Client, txBuilder txbuilder.TxBuilder) (*SequenceSender, error) { // Create sequencesender s := SequenceSender{ @@ -101,8 +94,8 @@ func New(cfg Config, etherman *etherman.Client, da *dataavailability.DataAvailab validStream: false, latestStreamBatch: 0, seqSendingStopped: false, - da: da, - txBuilder: txBuilder, + + txBuilder: txBuilder, } // Restore pending sent sequences @@ -554,8 +547,6 @@ func (s *SequenceSender) buildSendTx(ctx context.Context, sequences []types.Sequ return s.txBuilder.BuildSequenceBatchesTx(ctx, sequences, lastSequence, firstSequence) } - - // sendTx adds transaction to the ethTxManager to send it to L1 func (s *SequenceSender) sendTx(ctx context.Context, resend bool, txOldHash *common.Hash, to *common.Address, fromBatch uint64, toBatch uint64, data []byte) error { // Params if new tx to send or resend a previous tx @@ -631,6 +622,7 @@ func (s *SequenceSender) sendTx(ctx context.Context, resend bool, txOldHash *com // getSequencesToSend generates sequences to be sent to L1. Empty array means there are no sequences to send or it's not worth sending func (s *SequenceSender) getSequencesToSend() ([]types.Sequence, error) { + ctx := context.Background() // Add sequences until too big for a single L1 tx or last batch is reached s.mutexSequence.Lock() defer s.mutexSequence.Unlock() @@ -681,7 +673,7 @@ func (s *SequenceSender) getSequencesToSend() ([]types.Sequence, error) { // Check if can be sent //tx, err := s.etherman.BuildSequenceBatchesTx(s.cfg.SenderAddress, sequences, lastSequence.LastL2BLockTimestamp, firstSequence.BatchNumber-1, s.cfg.L2Coinbase, nil) - tx, err := s.buildSendTx(s.ctx, s.cfg.SenderAddress, sequences, lastSequence.LastL2BLockTimestamp, firstSequence.BatchNumber-1, s.cfg.L2Coinbase, nil) + tx, err := s.buildSendTx(ctx, sequences, lastSequence, firstSequence) if err == nil && tx.Size() > s.cfg.MaxTxSizeForL1 { log.Infof("[SeqSender] oversized Data on TX oldHash %s (txSize %d > %d)", tx.Hash(), tx.Size(), s.cfg.MaxTxSizeForL1) err = ErrOversizedData @@ -694,7 +686,7 @@ func (s *SequenceSender) getSequencesToSend() ([]types.Sequence, error) { // Handling the error gracefully, re-processing the sequence as a sanity check lastSequence = sequences[len(sequences)-1] //_, err = s.etherman.BuildSequenceBatchesTx(s.cfg.SenderAddress, sequences, lastSequence.LastL2BLockTimestamp, firstSequence.BatchNumber-1, s.cfg.L2Coinbase, nil) - _, err= s.buildSendTx(s.ctx, s.cfg.SenderAddress, sequences, lastSequence.LastL2BLockTimestamp, firstSequence.BatchNumber-1, s.cfg.L2Coinbase, nil) + _, err = s.buildSendTx(ctx, sequences, lastSequence, firstSequence) return sequences, err } return sequences, err