Skip to content

Commit 6fbef6a

Browse files
committed
AggLayer integration
This PR adds config options and logic to send proofs to AggLayer
1 parent a5b8cd5 commit 6fbef6a

14 files changed

+391
-45
lines changed

aggregator/aggregator.go

+137-20
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package aggregator
22

33
import (
44
"context"
5+
"crypto/ecdsa"
56
"encoding/json"
67
"errors"
78
"fmt"
@@ -13,6 +14,9 @@ import (
1314
"time"
1415
"unicode"
1516

17+
"github.com/0xPolygon/agglayer/client"
18+
agglayerTypes "github.com/0xPolygon/agglayer/rpc/types"
19+
"github.com/0xPolygon/agglayer/tx"
1620
"github.com/0xPolygonHermez/zkevm-node/aggregator/metrics"
1721
"github.com/0xPolygonHermez/zkevm-node/aggregator/prover"
1822
"github.com/0xPolygonHermez/zkevm-node/config/types"
@@ -65,6 +69,9 @@ type Aggregator struct {
6569
srv *grpc.Server
6670
ctx context.Context
6771
exit context.CancelFunc
72+
73+
AggLayerClient client.ClientInterface
74+
sequencerPrivateKey *ecdsa.PrivateKey
6875
}
6976

7077
// New creates a new aggregator.
@@ -73,6 +80,8 @@ func New(
7380
stateInterface stateInterface,
7481
ethTxManager ethTxManager,
7582
etherman etherman,
83+
agglayerClient client.ClientInterface,
84+
sequencerPrivateKey *ecdsa.PrivateKey,
7685
) (Aggregator, error) {
7786
var profitabilityChecker aggregatorTxProfitabilityChecker
7887
switch cfg.TxProfitabilityCheckerType {
@@ -94,6 +103,9 @@ func New(
94103
TimeCleanupLockedProofs: cfg.CleanupLockedProofsInterval,
95104

96105
finalProof: make(chan finalProofMsg),
106+
107+
AggLayerClient: agglayerClient,
108+
sequencerPrivateKey: sequencerPrivateKey,
97109
}
98110

99111
return a, nil
@@ -267,34 +279,139 @@ func (a *Aggregator) sendFinalProof() {
267279

268280
log.Infof("Final proof inputs: NewLocalExitRoot [%#x], NewStateRoot [%#x]", inputs.NewLocalExitRoot, inputs.NewStateRoot)
269281

270-
// add batch verification to be monitored
271-
sender := common.HexToAddress(a.cfg.SenderAddress)
272-
to, data, err := a.Ethman.BuildTrustedVerifyBatchesTxData(proof.BatchNumber-1, proof.BatchNumberFinal, &inputs, sender)
273-
if err != nil {
274-
log.Errorf("Error estimating batch verification to add to eth tx manager: %v", err)
275-
a.handleFailureToAddVerifyBatchToBeMonitored(ctx, proof)
276-
continue
277-
}
278-
monitoredTxID := buildMonitoredTxID(proof.BatchNumber, proof.BatchNumberFinal)
279-
err = a.EthTxManager.Add(ctx, ethTxManagerOwner, monitoredTxID, sender, to, nil, data, a.cfg.GasOffset, nil)
280-
if err != nil {
281-
mTxLogger := ethtxmanager.CreateLogger(ethTxManagerOwner, monitoredTxID, sender, to)
282-
mTxLogger.Errorf("Error to add batch verification tx to eth tx manager: %v", err)
283-
a.handleFailureToAddVerifyBatchToBeMonitored(ctx, proof)
284-
continue
282+
switch a.cfg.SettlementBackend {
283+
case AggLayer:
284+
if success := a.settleWithAggLayer(ctx, proof, inputs); !success {
285+
continue
286+
}
287+
default:
288+
if success := a.settleDirect(ctx, proof, inputs); !success {
289+
continue
290+
}
285291
}
286292

287-
// process monitored batch verifications before starting a next cycle
288-
a.EthTxManager.ProcessPendingMonitoredTxs(ctx, ethTxManagerOwner, func(result ethtxmanager.MonitoredTxResult, dbTx pgx.Tx) {
289-
a.handleMonitoredTxResult(result)
290-
}, nil)
291-
292293
a.resetVerifyProofTime()
293294
a.endProofVerification()
294295
}
295296
}
296297
}
297298

299+
func (a *Aggregator) settleDirect(
300+
ctx context.Context,
301+
proof *state.Proof,
302+
inputs ethmanTypes.FinalProofInputs,
303+
) (success bool) {
304+
// add batch verification to be monitored
305+
sender := common.HexToAddress(a.cfg.SenderAddress)
306+
307+
to, data, err := a.Ethman.BuildTrustedVerifyBatchesTxData(
308+
proof.BatchNumber-1,
309+
proof.BatchNumberFinal,
310+
&inputs,
311+
sender,
312+
)
313+
if err != nil {
314+
log.Errorf("Error estimating batch verification to add to eth tx manager: %v", err)
315+
a.handleFailureToAddVerifyBatchToBeMonitored(ctx, proof)
316+
317+
return false
318+
}
319+
320+
monitoredTxID := buildMonitoredTxID(proof.BatchNumber, proof.BatchNumberFinal)
321+
err = a.EthTxManager.Add(
322+
ctx,
323+
ethTxManagerOwner,
324+
monitoredTxID,
325+
sender,
326+
to,
327+
nil,
328+
data,
329+
a.cfg.GasOffset,
330+
nil,
331+
)
332+
if err != nil {
333+
mTxLogger := ethtxmanager.CreateLogger(ethTxManagerOwner, monitoredTxID, sender, to)
334+
mTxLogger.Errorf("Error to add batch verification tx to eth tx manager: %v", err)
335+
a.handleFailureToAddVerifyBatchToBeMonitored(ctx, proof)
336+
337+
return false
338+
}
339+
340+
// process monitored batch verifications before starting a next cycle
341+
a.EthTxManager.ProcessPendingMonitoredTxs(
342+
ctx,
343+
ethTxManagerOwner,
344+
func(result ethtxmanager.MonitoredTxResult, dbTx pgx.Tx) {
345+
a.handleMonitoredTxResult(result)
346+
},
347+
nil,
348+
)
349+
350+
return true
351+
}
352+
353+
func (a *Aggregator) settleWithAggLayer(
354+
ctx context.Context,
355+
proof *state.Proof,
356+
inputs ethmanTypes.FinalProofInputs,
357+
) (success bool) {
358+
proofStrNo0x := strings.TrimPrefix(inputs.FinalProof.Proof, "0x")
359+
proofBytes := common.Hex2Bytes(proofStrNo0x)
360+
tx := tx.Tx{
361+
LastVerifiedBatch: agglayerTypes.ArgUint64(proof.BatchNumber - 1),
362+
NewVerifiedBatch: agglayerTypes.ArgUint64(proof.BatchNumberFinal),
363+
ZKP: tx.ZKP{
364+
NewStateRoot: common.BytesToHash(inputs.NewStateRoot),
365+
NewLocalExitRoot: common.BytesToHash(inputs.NewLocalExitRoot),
366+
Proof: agglayerTypes.ArgBytes(proofBytes),
367+
},
368+
RollupID: a.Ethman.GetRollupId(),
369+
}
370+
signedTx, err := tx.Sign(a.sequencerPrivateKey)
371+
372+
if err != nil {
373+
log.Errorf("failed to sign tx: %v", err)
374+
a.handleFailureToSendToAggLayer(ctx, proof)
375+
376+
return false
377+
}
378+
379+
log.Debug("final proof signedTx: ", signedTx.Tx.ZKP.Proof.Hex())
380+
txHash, err := a.AggLayerClient.SendTx(*signedTx)
381+
if err != nil {
382+
log.Errorf("failed to send tx to the interop: %v", err)
383+
a.handleFailureToSendToAggLayer(ctx, proof)
384+
385+
return false
386+
}
387+
388+
log.Infof("tx %s sent to agglayer, waiting to be mined", txHash.Hex())
389+
log.Debugf("Timeout set to %f seconds", a.cfg.AggLayerTxTimeout.Duration.Seconds())
390+
waitCtx, cancelFunc := context.WithDeadline(ctx, time.Now().Add(a.cfg.AggLayerTxTimeout.Duration))
391+
defer cancelFunc()
392+
if err := a.AggLayerClient.WaitTxToBeMined(txHash, waitCtx); err != nil {
393+
log.Errorf("interop didn't mine the tx: %v", err)
394+
a.handleFailureToSendToAggLayer(ctx, proof)
395+
396+
return false
397+
}
398+
399+
// TODO: wait for synchronizer to catch up
400+
return true
401+
}
402+
403+
func (a *Aggregator) handleFailureToSendToAggLayer(ctx context.Context, proof *state.Proof) {
404+
log := log.WithFields("proofId", proof.ProofID, "batches", fmt.Sprintf("%d-%d", proof.BatchNumber, proof.BatchNumberFinal))
405+
proof.GeneratingSince = nil
406+
407+
err := a.State.UpdateGeneratedProof(ctx, proof, nil)
408+
if err != nil {
409+
log.Errorf("Failed updating proof state (false): %v", err)
410+
}
411+
412+
a.endProofVerification()
413+
}
414+
298415
func (a *Aggregator) handleFailureToAddVerifyBatchToBeMonitored(ctx context.Context, proof *state.Proof) {
299416
log := log.WithFields("proofId", proof.ProofID, "batches", fmt.Sprintf("%d-%d", proof.BatchNumber, proof.BatchNumberFinal))
300417
proof.GeneratingSince = nil

aggregator/aggregator_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ func TestSendFinalProof(t *testing.T) {
190190
stateMock := mocks.NewStateMock(t)
191191
ethTxManager := mocks.NewEthTxManager(t)
192192
etherman := mocks.NewEtherman(t)
193-
a, err := New(cfg, stateMock, ethTxManager, etherman)
193+
a, err := New(cfg, stateMock, ethTxManager, etherman, nil, nil)
194194
require.NoError(err)
195195
a.ctx, a.exit = context.WithCancel(context.Background())
196196
m := mox{
@@ -685,7 +685,7 @@ func TestTryAggregateProofs(t *testing.T) {
685685
ethTxManager := mocks.NewEthTxManager(t)
686686
etherman := mocks.NewEtherman(t)
687687
proverMock := mocks.NewProverMock(t)
688-
a, err := New(cfg, stateMock, ethTxManager, etherman)
688+
a, err := New(cfg, stateMock, ethTxManager, etherman, nil, nil)
689689
require.NoError(err)
690690
aggregatorCtx := context.WithValue(context.Background(), "owner", "aggregator") //nolint:staticcheck
691691
a.ctx, a.exit = context.WithCancel(aggregatorCtx)
@@ -1023,7 +1023,7 @@ func TestTryGenerateBatchProof(t *testing.T) {
10231023
ethTxManager := mocks.NewEthTxManager(t)
10241024
etherman := mocks.NewEtherman(t)
10251025
proverMock := mocks.NewProverMock(t)
1026-
a, err := New(cfg, stateMock, ethTxManager, etherman)
1026+
a, err := New(cfg, stateMock, ethTxManager, etherman, nil, nil)
10271027
require.NoError(err)
10281028
aggregatorCtx := context.WithValue(context.Background(), "owner", "aggregator") //nolint:staticcheck
10291029
a.ctx, a.exit = context.WithCancel(aggregatorCtx)
@@ -1300,7 +1300,7 @@ func TestTryBuildFinalProof(t *testing.T) {
13001300
ethTxManager := mocks.NewEthTxManager(t)
13011301
etherman := mocks.NewEtherman(t)
13021302
proverMock := mocks.NewProverMock(t)
1303-
a, err := New(cfg, stateMock, ethTxManager, etherman)
1303+
a, err := New(cfg, stateMock, ethTxManager, etherman, nil, nil)
13041304
require.NoError(err)
13051305
aggregatorCtx := context.WithValue(context.Background(), "owner", "aggregator") //nolint:staticcheck
13061306
a.ctx, a.exit = context.WithCancel(aggregatorCtx)
@@ -1430,7 +1430,7 @@ func TestIsSynced(t *testing.T) {
14301430
ethTxManager := mocks.NewEthTxManager(t)
14311431
etherman := mocks.NewEtherman(t)
14321432
proverMock := mocks.NewProverMock(t)
1433-
a, err := New(cfg, stateMock, ethTxManager, etherman)
1433+
a, err := New(cfg, stateMock, ethTxManager, etherman, nil, nil)
14341434
require.NoError(err)
14351435
aggregatorCtx := context.WithValue(context.Background(), "owner", "aggregator") //nolint:staticcheck
14361436
a.ctx, a.exit = context.WithCancel(aggregatorCtx)

aggregator/config.go

+23
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@ import (
88
"github.com/0xPolygonHermez/zkevm-node/encoding"
99
)
1010

11+
// SettlementBackend is the type of the settlement backend
12+
type SettlementBackend string
13+
14+
const (
15+
// AggLayer settlement backend
16+
AggLayer SettlementBackend = "agglayer"
17+
18+
// L1 settlement backend
19+
L1 SettlementBackend = "l1"
20+
)
21+
1122
// TokenAmountWithDecimals is a wrapper type that parses token amount with decimals to big int
1223
type TokenAmountWithDecimals struct {
1324
*big.Int `validate:"required"`
@@ -88,4 +99,16 @@ type Config struct {
8899

89100
// UpgradeEtrogBatchNumber is the number of the first batch after upgrading to etrog
90101
UpgradeEtrogBatchNumber uint64 `mapstructure:"UpgradeEtrogBatchNumber"`
102+
103+
// SettlementBackend configuration defines how a final ZKP should be settled. Directly to L1 or over the Beethoven service.
104+
SettlementBackend SettlementBackend `mapstructure:"SettlementBackend"`
105+
106+
// AggLayerTxTimeout is the interval time to wait for a tx to be mined from the agglayer
107+
AggLayerTxTimeout types.Duration `mapstructure:"AggLayerTxTimeout"`
108+
109+
// AggLayerURL url of the agglayer service
110+
AggLayerURL string `mapstructure:"AggLayerURL"`
111+
112+
// SequencerPrivateKey Private key of the trusted sequencer
113+
SequencerPrivateKey types.KeystoreFileConfig `mapstructure:"SequencerPrivateKey"`
91114
}

aggregator/interfaces.go

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ type ethTxManager interface {
3737

3838
// etherman contains the methods required to interact with ethereum
3939
type etherman interface {
40+
GetRollupId() uint32
4041
GetLatestVerifiedBatchNum() (uint64, error)
4142
BuildTrustedVerifyBatchesTxData(lastVerifiedBatch, newVerifiedBatch uint64, inputs *ethmanTypes.FinalProofInputs, beneficiary common.Address) (to *common.Address, data []byte, err error)
4243
}

aggregator/mocks/mock_etherman.go

+19-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/run.go

+18-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"runtime"
1414
"time"
1515

16+
agglayerClient "github.com/0xPolygon/agglayer/client"
1617
dataCommitteeClient "github.com/0xPolygon/cdk-data-availability/client"
1718
datastreamerlog "github.com/0xPolygonHermez/zkevm-data-streamer/log"
1819
"github.com/0xPolygonHermez/zkevm-node"
@@ -497,7 +498,23 @@ func createSequenceSender(cfg config.Config, pool *pool.Pool, etmStorage *ethtxm
497498
}
498499

499500
func runAggregator(ctx context.Context, c aggregator.Config, etherman *etherman.Client, ethTxManager *ethtxmanager.Client, st *state.State) {
500-
agg, err := aggregator.New(c, st, ethTxManager, etherman)
501+
var (
502+
aggCli *agglayerClient.Client
503+
pk *ecdsa.PrivateKey
504+
err error
505+
)
506+
507+
if c.SettlementBackend == aggregator.AggLayer {
508+
aggCli = agglayerClient.New(c.AggLayerURL)
509+
510+
// Load private key
511+
pk, err = config.NewKeyFromKeystore(c.SequencerPrivateKey)
512+
if err != nil {
513+
log.Fatal(err)
514+
}
515+
}
516+
517+
agg, err := aggregator.New(c, st, ethTxManager, etherman, aggCli, pk)
501518
if err != nil {
502519
log.Fatal(err)
503520
}

0 commit comments

Comments
 (0)