diff --git a/aggregator/agglayer_client.go b/aggregator/agglayer_client.go new file mode 100644 index 0000000..4726ccc --- /dev/null +++ b/aggregator/agglayer_client.go @@ -0,0 +1,81 @@ +package aggregator + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + "github.com/0xPolygon/cdk-rpc/rpc" + "github.com/0xPolygon/cdk-rpc/types" + "github.com/ethereum/go-ethereum/common" +) + +// AgglayerClientInterface is the interface that defines the methods that the AggLayerClient will implement +type AgglayerClientInterface interface { + SendTx(signedTx SignedTx) (common.Hash, error) + WaitTxToBeMined(hash common.Hash, ctx context.Context) error +} + +// AggLayerClient is the client that will be used to interact with the AggLayer +type AggLayerClient struct { + url string +} + +// NewAggLayerClient returns a client ready to be used +func NewAggLayerClient(url string) *AggLayerClient { + return &AggLayerClient{ + url: url, + } +} + +// SendTx sends a signed transaction to the AggLayer +func (c *AggLayerClient) SendTx(signedTx SignedTx) (common.Hash, error) { + response, err := rpc.JSONRPCCall(c.url, "interop_sendTx", signedTx) + if err != nil { + return common.Hash{}, err + } + + if response.Error != nil { + return common.Hash{}, fmt.Errorf("%v %v", response.Error.Code, response.Error.Message) + } + + var result types.ArgHash + err = json.Unmarshal(response.Result, &result) + if err != nil { + return common.Hash{}, err + } + + return result.Hash(), nil +} + +// WaitTxToBeMined waits for a transaction to be mined +func (c *AggLayerClient) WaitTxToBeMined(hash common.Hash, ctx context.Context) error { + ticker := time.NewTicker(time.Second) + for { + select { + case <-ctx.Done(): + return errors.New("context finished before tx was mined") + case <-ticker.C: + response, err := rpc.JSONRPCCall(c.url, "interop_getTxStatus", hash) + if err != nil { + return err + } + + if response.Error != nil { + return fmt.Errorf("%v %v", response.Error.Code, response.Error.Message) + } + + var result string + err = json.Unmarshal(response.Result, &result) + if err != nil { + return err + } + if strings.ToLower(result) == "done" { + return nil + } + } + } +} diff --git a/aggregator/agglayer_tx.go b/aggregator/agglayer_tx.go new file mode 100644 index 0000000..b0cd09c --- /dev/null +++ b/aggregator/agglayer_tx.go @@ -0,0 +1,63 @@ +package aggregator + +import ( + "crypto/ecdsa" + + "github.com/0xPolygon/cdk-rpc/types" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +) + +// ZKP is the struct that contains the zero-knowledge proof +type ZKP struct { + NewStateRoot common.Hash `json:"newStateRoot"` + NewLocalExitRoot common.Hash `json:"newLocalExitRoot"` + Proof types.ArgBytes `json:"proof"` +} + +// Tx is the struct that contains the verified batch transaction +type Tx struct { + RollupID uint32 + LastVerifiedBatch types.ArgUint64 `json:"lastVerifiedBatch"` + NewVerifiedBatch types.ArgUint64 `json:"newVerifiedBatch"` + ZKP ZKP `json:"ZKP"` +} + +// Hash returns a hash that uniquely identifies the tx +func (t *Tx) Hash() common.Hash { + return common.BytesToHash(crypto.Keccak256( + []byte(t.LastVerifiedBatch.Hex()), + []byte(t.NewVerifiedBatch.Hex()), + t.ZKP.NewStateRoot[:], + t.ZKP.NewLocalExitRoot[:], + []byte(t.ZKP.Proof.Hex()), + )) +} + +// Sign returns a signed batch by the private key +func (t *Tx) Sign(privateKey *ecdsa.PrivateKey) (*SignedTx, error) { + hashToSign := t.Hash() + sig, err := crypto.Sign(hashToSign.Bytes(), privateKey) + if err != nil { + return nil, err + } + return &SignedTx{ + Tx: *t, + Signature: sig, + }, nil +} + +// SignedTx is the struct that contains the signed batch transaction +type SignedTx struct { + Tx Tx `json:"tx"` + Signature types.ArgBytes `json:"signature"` +} + +// Signer returns the address of the signer +func (s *SignedTx) Signer() (common.Address, error) { + pubKey, err := crypto.SigToPub(s.Tx.Hash().Bytes(), s.Signature) + if err != nil { + return common.Address{}, err + } + return crypto.PubkeyToAddress(*pubKey), nil +} diff --git a/aggregator/aggregator.go b/aggregator/aggregator.go index 0f6fa42..efb03d5 100644 --- a/aggregator/aggregator.go +++ b/aggregator/aggregator.go @@ -2,6 +2,7 @@ package aggregator import ( "context" + "crypto/ecdsa" "encoding/json" "errors" "fmt" @@ -13,13 +14,14 @@ import ( "time" "unicode" + "github.com/0xPolygon/cdk-rpc/rpc" + cdkTypes "github.com/0xPolygon/cdk-rpc/types" "github.com/0xPolygonHermez/zkevm-aggregator/aggregator/metrics" "github.com/0xPolygonHermez/zkevm-aggregator/aggregator/prover" "github.com/0xPolygonHermez/zkevm-aggregator/config/types" ethmanTypes "github.com/0xPolygonHermez/zkevm-aggregator/etherman/types" "github.com/0xPolygonHermez/zkevm-aggregator/l1infotree" "github.com/0xPolygonHermez/zkevm-aggregator/log" - "github.com/0xPolygonHermez/zkevm-aggregator/rpclient" "github.com/0xPolygonHermez/zkevm-aggregator/state" "github.com/0xPolygonHermez/zkevm-aggregator/state/datastream" "github.com/0xPolygonHermez/zkevm-data-streamer/datastreamer" @@ -81,10 +83,17 @@ type Aggregator struct { srv *grpc.Server ctx context.Context exit context.CancelFunc + + sequencerPrivateKey *ecdsa.PrivateKey + aggLayerClient AgglayerClientInterface } // New creates a new aggregator. -func New(ctx context.Context, cfg Config, stateInterface stateInterface, etherman etherman) (*Aggregator, error) { +func New( + ctx context.Context, + cfg Config, + stateInterface stateInterface, + etherman etherman) (*Aggregator, error) { var profitabilityChecker aggregatorTxProfitabilityChecker switch cfg.TxProfitabilityCheckerType { @@ -138,6 +147,20 @@ func New(ctx context.Context, cfg Config, stateInterface stateInterface, etherma log.Fatalf("failed to create synchronizer client, error: %v", err) } + var ( + aggLayerClient AgglayerClientInterface + sequencerPrivateKey *ecdsa.PrivateKey + ) + + if cfg.SettlementBackend == AggLayer { + aggLayerClient = NewAggLayerClient(cfg.AggLayerURL) + + sequencerPrivateKey, err = newKeyFromKeystore(cfg.SequencerPrivateKey) + if err != nil { + return nil, err + } + } + a := &Aggregator{ cfg: cfg, state: stateInterface, @@ -151,6 +174,8 @@ func New(ctx context.Context, cfg Config, stateInterface stateInterface, etherma timeCleanupLockedProofs: cfg.CleanupLockedProofsInterval, finalProof: make(chan finalProofMsg), currentBatchStreamData: []byte{}, + aggLayerClient: aggLayerClient, + sequencerPrivateKey: sequencerPrivateKey, } // Set function to handle the batches from the data stream @@ -599,35 +624,101 @@ func (a *Aggregator) sendFinalProof() { NewStateRoot: finalBatch.StateRoot.Bytes(), } - // add batch verification to be monitored - sender := common.HexToAddress(a.cfg.SenderAddress) - to, data, err := a.etherman.BuildTrustedVerifyBatchesTxData(proof.BatchNumber-1, proof.BatchNumberFinal, &inputs, sender) - if err != nil { - log.Errorf("Error estimating batch verification to add to eth tx manager: %v", err) - a.handleFailureToAddVerifyBatchToBeMonitored(ctx, proof) - continue - } - - monitoredTxID, err := a.ethTxManager.Add(ctx, to, nil, big.NewInt(0), data, a.cfg.GasOffset, nil) - if err != nil { - log.Errorf("Error Adding TX to ethTxManager: %v", err) - mTxLogger := ethtxmanager.CreateLogger(monitoredTxID, sender, to) - mTxLogger.Errorf("Error to add batch verification tx to eth tx manager: %v", err) - a.handleFailureToAddVerifyBatchToBeMonitored(ctx, proof) - continue + switch a.cfg.SettlementBackend { + case AggLayer: + if success := a.settleWithAggLayer(ctx, proof, inputs); !success { + continue + } + default: + if success := a.settleDirect(ctx, proof, inputs); !success { + continue + } } - // process monitored batch verifications before starting a next cycle - a.ethTxManager.ProcessPendingMonitoredTxs(ctx, func(result ethtxmanager.MonitoredTxResult) { - a.handleMonitoredTxResult(result) - }) - a.resetVerifyProofTime() a.endProofVerification() } } } +func (a *Aggregator) settleWithAggLayer( + ctx context.Context, + proof *state.Proof, + inputs ethmanTypes.FinalProofInputs) bool { + proofStrNo0x := strings.TrimPrefix(inputs.FinalProof.Proof, "0x") + proofBytes := common.Hex2Bytes(proofStrNo0x) + tx := Tx{ + LastVerifiedBatch: cdkTypes.ArgUint64(proof.BatchNumber - 1), + NewVerifiedBatch: cdkTypes.ArgUint64(proof.BatchNumberFinal), + ZKP: ZKP{ + NewStateRoot: common.BytesToHash(inputs.NewStateRoot), + NewLocalExitRoot: common.BytesToHash(inputs.NewLocalExitRoot), + Proof: cdkTypes.ArgBytes(proofBytes), + }, + RollupID: a.etherman.GetRollupId(), + } + signedTx, err := tx.Sign(a.sequencerPrivateKey) + if err != nil { + log.Errorf("failed to sign tx: %v", err) + a.handleFailureToAddVerifyBatchToBeMonitored(ctx, proof) + + return false + } + + log.Debug("final proof signedTx: ", signedTx.Tx.ZKP.Proof.Hex()) + txHash, err := a.aggLayerClient.SendTx(*signedTx) + if err != nil { + log.Errorf("failed to send tx to the agglayer: %v", err) + a.handleFailureToAddVerifyBatchToBeMonitored(ctx, proof) + + return false + } + + log.Infof("tx %s sent to agglayer, waiting to be mined", txHash.Hex()) + log.Debugf("Timeout set to %f seconds", a.cfg.AggLayerTxTimeout.Duration.Seconds()) + waitCtx, cancelFunc := context.WithDeadline(ctx, time.Now().Add(a.cfg.AggLayerTxTimeout.Duration)) + defer cancelFunc() + if err := a.aggLayerClient.WaitTxToBeMined(txHash, waitCtx); err != nil { + log.Errorf("agglayer didn't mine the tx: %v", err) + a.handleFailureToAddVerifyBatchToBeMonitored(ctx, proof) + + return false + } + + return true +} + +// settleDirect sends the final proof to the L1 smart contract directly. +func (a *Aggregator) settleDirect( + ctx context.Context, + proof *state.Proof, + inputs ethmanTypes.FinalProofInputs) bool { + // add batch verification to be monitored + sender := common.HexToAddress(a.cfg.SenderAddress) + to, data, err := a.etherman.BuildTrustedVerifyBatchesTxData(proof.BatchNumber-1, proof.BatchNumberFinal, &inputs, sender) + if err != nil { + log.Errorf("Error estimating batch verification to add to eth tx manager: %v", err) + a.handleFailureToAddVerifyBatchToBeMonitored(ctx, proof) + return false + } + + monitoredTxID, err := a.ethTxManager.Add(ctx, to, nil, big.NewInt(0), data, a.cfg.GasOffset, nil) + if err != nil { + log.Errorf("Error Adding TX to ethTxManager: %v", err) + mTxLogger := ethtxmanager.CreateLogger(monitoredTxID, sender, to) + mTxLogger.Errorf("Error to add batch verification tx to eth tx manager: %v", err) + a.handleFailureToAddVerifyBatchToBeMonitored(ctx, proof) + return false + } + + // process monitored batch verifications before starting a next cycle + a.ethTxManager.ProcessPendingMonitoredTxs(ctx, func(result ethtxmanager.MonitoredTxResult) { + a.handleMonitoredTxResult(result) + }) + + return true +} + func (a *Aggregator) handleFailureToAddVerifyBatchToBeMonitored(ctx context.Context, proof *state.Proof) { log := log.WithFields("proofId", proof.ProofID, "batches", fmt.Sprintf("%d-%d", proof.BatchNumber, proof.BatchNumberFinal)) proof.GeneratingSince = nil @@ -1461,16 +1552,16 @@ func calculateAccInputHash(oldAccInputHash common.Hash, batchData []byte, l1Info func getWitness(batchNumber uint64, URL string, fullWitness bool) ([]byte, error) { var witness string - var response rpclient.Response + var response rpc.Response var err error if fullWitness { - response, err = rpclient.JSONRPCCall(URL, "zkevm_getBatchWitness", nil, "1", batchNumber, "full") + response, err = rpc.JSONRPCCall(URL, "zkevm_getBatchWitness", "1", batchNumber, "full") if err != nil { return nil, err } } else { - response, err = rpclient.JSONRPCCall(URL, "zkevm_getBatchWitness", nil, "batch-1", batchNumber) + response, err = rpc.JSONRPCCall(URL, "zkevm_getBatchWitness", "batch-1", batchNumber) if err != nil { return nil, err } diff --git a/aggregator/config.go b/aggregator/config.go index 63341ea..b9e329c 100644 --- a/aggregator/config.go +++ b/aggregator/config.go @@ -1,8 +1,11 @@ package aggregator import ( + "crypto/ecdsa" "fmt" "math/big" + "os" + "path/filepath" "github.com/0xPolygonHermez/zkevm-aggregator/config/types" "github.com/0xPolygonHermez/zkevm-aggregator/db" @@ -10,6 +13,18 @@ import ( "github.com/0xPolygonHermez/zkevm-aggregator/log" "github.com/0xPolygonHermez/zkevm-ethtx-manager/ethtxmanager" syncronizerConfig "github.com/0xPolygonHermez/zkevm-synchronizer-l1/config" + "github.com/ethereum/go-ethereum/accounts/keystore" +) + +// SettlementBackend is the type of the settlement backend +type SettlementBackend string + +const ( + // AggLayer settlement backend + AggLayer SettlementBackend = "agglayer" + + // L1 settlement backend + L1 SettlementBackend = "l1" ) // TokenAmountWithDecimals is a wrapper type that parses token amount with decimals to big int @@ -113,6 +128,18 @@ type Config struct { // Synchornizer config Synchronizer syncronizerConfig.Config `mapstructure:"Synchronizer"` + + // SettlementBackend configuration defines how a final ZKP should be settled. Directly to L1 or over the Beethoven service. + SettlementBackend SettlementBackend `mapstructure:"SettlementBackend" jsonschema:"enum=agglayer,enum=l1"` + + // SequencerPrivateKey Private key of the trusted sequencer + SequencerPrivateKey types.KeystoreFileConfig `mapstructure:"SequencerPrivateKey"` + + // AggLayerTxTimeout is the interval time to wait for a tx to be mined from the agglayer + AggLayerTxTimeout types.Duration `mapstructure:"AggLayerTxTimeout"` + + // AggLayerURL url of the agglayer service + AggLayerURL string `mapstructure:"AggLayerURL"` } // StreamClientCfg contains the data streamer's configuration properties @@ -122,3 +149,19 @@ type StreamClientCfg struct { // Log is the log configuration Log log.Config `mapstructure:"Log"` } + +// newKeyFromKeystore creates a private key from a keystore file +func newKeyFromKeystore(cfg types.KeystoreFileConfig) (*ecdsa.PrivateKey, error) { + if cfg.Path == "" && cfg.Password == "" { + return nil, nil + } + keystoreEncrypted, err := os.ReadFile(filepath.Clean(cfg.Path)) + if err != nil { + return nil, err + } + key, err := keystore.DecryptKey(keystoreEncrypted, cfg.Password) + if err != nil { + return nil, err + } + return key.PrivateKey, nil +} diff --git a/aggregator/interfaces.go b/aggregator/interfaces.go index 0c2a1e4..a7988fe 100644 --- a/aggregator/interfaces.go +++ b/aggregator/interfaces.go @@ -28,6 +28,7 @@ type proverInterface interface { // etherman contains the methods required to interact with ethereum type etherman interface { + GetRollupId() uint32 GetLatestVerifiedBatchNum() (uint64, error) BuildTrustedVerifyBatchesTxData(lastVerifiedBatch, newVerifiedBatch uint64, inputs *ethmanTypes.FinalProofInputs, beneficiary common.Address) (to *common.Address, data []byte, err error) GetLatestBlockHeader(ctx context.Context) (*types.Header, error) diff --git a/config/default.go b/config/default.go index acf7f57..0cdd582 100644 --- a/config/default.go +++ b/config/default.go @@ -18,6 +18,10 @@ GasOffset = 0 WitnessURL = "localhost:8123" UseL1BatchData = false UseFullWitness = false +SettlementBackend = "l1" +AggLayerTxTimeout = "5m" +AggLayerURL = "" +SequencerPrivateKey = {} [Aggregator.DB] Name = "aggregator_db" User = "aggregator_user" diff --git a/etherman/aggregator.go b/etherman/aggregator.go index c482264..c231dc1 100644 --- a/etherman/aggregator.go +++ b/etherman/aggregator.go @@ -98,6 +98,11 @@ func (etherman *Client) GetBatchAccInputHash(ctx context.Context, batchNumber ui return rollupData.AccInputHash, nil } +// GetRollupId returns the rollup id +func (etherMan *Client) GetRollupId() uint32 { + return etherMan.RollupID +} + // generateRandomAuth generates an authorization instance from a // randomly generated private key to be used to estimate gas for PoE // operations NOT restricted to the Trusted Sequencer diff --git a/go.mod b/go.mod index c92868c..157dffa 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/0xPolygonHermez/zkevm-aggregator go 1.21.3 require ( + github.com/0xPolygon/cdk-rpc v0.0.0-20240419104226-c0a62ba0f49d github.com/0xPolygonHermez/zkevm-data-streamer v0.2.2 github.com/0xPolygonHermez/zkevm-ethtx-manager v0.1.9 github.com/0xPolygonHermez/zkevm-synchronizer-l1 v0.5.4 @@ -50,12 +51,14 @@ require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect + github.com/didip/tollbooth/v6 v6.1.2 // indirect github.com/ethereum/c-kzg-4844 v1.0.0 // indirect github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-pkgz/expirable-cache v0.0.3 // indirect github.com/gobuffalo/logger v1.0.6 // indirect github.com/gobuffalo/packd v1.0.1 // indirect github.com/gofrs/flock v0.8.1 // indirect @@ -73,6 +76,7 @@ require ( github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgtype v1.14.0 // indirect github.com/jackc/puddle v1.3.0 // indirect + github.com/jmoiron/sqlx v1.2.0 // indirect github.com/karrick/godirwalk v1.16.1 // indirect github.com/klauspost/compress v1.17.2 // indirect github.com/kr/pretty v0.3.1 // indirect @@ -116,6 +120,7 @@ require ( golang.org/x/sys v0.21.0 // indirect golang.org/x/term v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect + golang.org/x/time v0.5.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index a6c99f0..beab95b 100644 --- a/go.sum +++ b/go.sum @@ -37,6 +37,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/0xPolygon/cdk-rpc v0.0.0-20240419104226-c0a62ba0f49d h1:sxh6hZ2jF/sxxj2jd5o1vuNNCZjYmn4aRG9SRlVaEFs= +github.com/0xPolygon/cdk-rpc v0.0.0-20240419104226-c0a62ba0f49d/go.mod h1:2scWqMMufrQXu7TikDgQ3BsyaKoX8qP26D6E262vSOg= github.com/0xPolygonHermez/zkevm-data-streamer v0.2.2 h1:XRMTk+W6vtJVGVjuEznfWyNt7HkRkkuSmlN5Y6p60Sc= github.com/0xPolygonHermez/zkevm-data-streamer v0.2.2/go.mod h1:0QkAXcFa92mFJrCbN3UPUJGJYes851yEgYHLONnaosE= github.com/0xPolygonHermez/zkevm-ethtx-manager v0.1.9 h1:vrAezzwTNke6NroDAltGh1k2AJ6ibmZPBsG0bCltbRc= @@ -131,6 +133,8 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= +github.com/didip/tollbooth/v6 v6.1.2 h1:Kdqxmqw9YTv0uKajBUiWQg+GURL/k4vy9gmLCL01PjQ= +github.com/didip/tollbooth/v6 v6.1.2/go.mod h1:xjcse6CTHCLuOkzsWrEgdy9WPJFv+p/x6v+MyfP+O9s= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -171,6 +175,9 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-pkgz/expirable-cache v0.0.3 h1:rTh6qNPp78z0bQE6HDhXBHUwqnV9i09Vm6dksJLXQDc= +github.com/go-pkgz/expirable-cache v0.0.3/go.mod h1:+IauqN00R2FqNRLCLA+X5YljQJrwB179PfiAoMPlTlQ= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -359,6 +366,8 @@ github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0= github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= +github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -419,6 +428,7 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI= github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -820,6 +830,7 @@ golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/rpclient/rpcclient.go b/rpclient/rpcclient.go deleted file mode 100644 index da1375b..0000000 --- a/rpclient/rpcclient.go +++ /dev/null @@ -1,102 +0,0 @@ -package rpclient - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "net/http" -) - -const jsonRPCVersion = "2.0" - -// Request is a jsonrpc request -type Request struct { - JSONRPC string `json:"jsonrpc"` - ID interface{} `json:"id"` - Method string `json:"method"` - Params json.RawMessage `json:"params,omitempty"` -} - -// Response is a jsonrpc success response -type Response struct { - JSONRPC string - ID interface{} - Result json.RawMessage -} - -// RPCClient is a client for the JSON RPC -type RPCClient struct { - url string -} - -// NewRPCClient creates an instance of client -func NewRPCClient(url string) *RPCClient { - return &RPCClient{ - url: url, - } -} - -// JSONRPCCall executes a 2.0 JSON RPC HTTP Post Request to the provided URL with -// the provided method and parameters, which is compatible with the Ethereum -// JSON RPC Server. -func JSONRPCCall(url, method string, httpHeaders map[string]string, id interface{}, parameters ...interface{}) (Response, error) { - params, err := json.Marshal(parameters) - if err != nil { - return Response{}, err - } - - request := Request{ - JSONRPC: jsonRPCVersion, - ID: id, - Method: method, - Params: params, - } - - httpRes, err := sendJSONRPC_HTTPRequest(url, request, httpHeaders) - if err != nil { - return Response{}, err - } - - resBody, err := io.ReadAll(httpRes.Body) - if err != nil { - return Response{}, err - } - defer httpRes.Body.Close() - - if httpRes.StatusCode != http.StatusOK { - return Response{}, fmt.Errorf("%v - %v", httpRes.StatusCode, string(resBody)) - } - - var res Response - err = json.Unmarshal(resBody, &res) - if err != nil { - return Response{}, err - } - return res, nil -} - -func sendJSONRPC_HTTPRequest(url string, payload interface{}, httpHeaders map[string]string) (*http.Response, error) { - reqBody, err := json.Marshal(payload) - if err != nil { - return nil, err - } - - reqBodyReader := bytes.NewReader(reqBody) - httpReq, err := http.NewRequest(http.MethodPost, url, reqBodyReader) - if err != nil { - return nil, err - } - - httpReq.Header.Add("Content-type", "application/json") - for key, value := range httpHeaders { - httpReq.Header.Add(key, value) - } - - httpRes, err := http.DefaultClient.Do(httpReq) - if err != nil { - return nil, err - } - - return httpRes, nil -} diff --git a/test/config/test.aggregator.config.toml b/test/config/test.aggregator.config.toml index 5948fbc..6848919 100644 --- a/test/config/test.aggregator.config.toml +++ b/test/config/test.aggregator.config.toml @@ -14,6 +14,10 @@ ForkId = 9 GasOffset = 0 WitnessURL = "http://zkevm-erigon-seq:8123" UseL1BatchData = true +SettlementBackend = "l1" +AggLayerTxTimeout = "5m" +AggLayerURL = "" +SequencerPrivateKey = {} UseFullWitness = false [Aggregator.DB] Name = "aggregator_db"