-
Notifications
You must be signed in to change notification settings - Fork 121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/beethoven #44
Changes from 2 commits
3bebb97
e774772
60e5635
7cc5d3b
9d1a90c
0abeeff
e2ef6a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,17 @@ | ||
# CONTAINER FOR BUILDING BINARY | ||
FROM golang:1.21 AS build | ||
|
||
# TODO: REMOVE SSH BEFORE MERGING, ONCE BEETHOVEN IS PUBLIC | ||
|
||
# SSH KEY | ||
ARG SSH_PRIVATE_KEY | ||
RUN mkdir /root/.ssh/ | ||
RUN echo "${SSH_PRIVATE_KEY}" > /root/.ssh/id_rsa | ||
RUN chmod 700 /root/.ssh/id_rsa | ||
RUN echo "Host github.com\n\tStrictHostKeyChecking no\n" >> /root/.ssh/config | ||
RUN git config --global --add url."[email protected]:".insteadOf "https://github.com/" | ||
ENV GOPRIVATE=github.com/0xPolygon/beethoven | ||
|
||
# INSTALL DEPENDENCIES | ||
RUN go install github.com/gobuffalo/packr/v2/[email protected] | ||
COPY go.mod go.sum /src/ | ||
|
@@ -11,6 +22,9 @@ COPY . /src | |
RUN cd /src/db && packr2 | ||
RUN cd /src && make build | ||
|
||
# REMOVE SSH PRIVATE KEY | ||
RUN rm /root/.ssh/id_rsa | ||
|
||
# CONTAINER FOR RUNNING BINARY | ||
FROM alpine:3.18.0 | ||
COPY --from=build /src/dist/zkevm-node /app/zkevm-node | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
|
||
import ( | ||
"context" | ||
"crypto/ecdsa" | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
|
@@ -13,6 +14,9 @@ | |
"time" | ||
"unicode" | ||
|
||
"github.com/0xPolygon/beethoven/client" | ||
beethovenTypes "github.com/0xPolygon/beethoven/rpc/types" | ||
Check failure on line 18 in aggregator/aggregator.go GitHub Actions / json-schema (1.21.x, amd64)
|
||
"github.com/0xPolygon/beethoven/tx" | ||
Check failure on line 19 in aggregator/aggregator.go GitHub Actions / json-schema (1.21.x, amd64)
|
||
"github.com/0xPolygonHermez/zkevm-node/aggregator/metrics" | ||
"github.com/0xPolygonHermez/zkevm-node/aggregator/prover" | ||
"github.com/0xPolygonHermez/zkevm-node/config/types" | ||
|
@@ -22,6 +26,7 @@ | |
"github.com/0xPolygonHermez/zkevm-node/log" | ||
"github.com/0xPolygonHermez/zkevm-node/state" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/crypto" | ||
"github.com/jackc/pgx/v4" | ||
"google.golang.org/grpc" | ||
grpchealth "google.golang.org/grpc/health/grpc_health_v1" | ||
|
@@ -64,6 +69,9 @@ | |
srv *grpc.Server | ||
ctx context.Context | ||
exit context.CancelFunc | ||
|
||
sequencerPrivateKey *ecdsa.PrivateKey | ||
BeethovenClient client.ClientInterface | ||
} | ||
|
||
// New creates a new aggregator. | ||
|
@@ -72,6 +80,8 @@ | |
stateInterface stateInterface, | ||
ethTxManager ethTxManager, | ||
etherman etherman, | ||
beethovenClient client.ClientInterface, | ||
sequencerPrivateKey *ecdsa.PrivateKey, | ||
) (Aggregator, error) { | ||
var profitabilityChecker aggregatorTxProfitabilityChecker | ||
switch cfg.TxProfitabilityCheckerType { | ||
|
@@ -81,6 +91,23 @@ | |
profitabilityChecker = NewTxProfitabilityCheckerAcceptAll(stateInterface, cfg.IntervalAfterWhichBatchConsolidateAnyway.Duration) | ||
} | ||
|
||
if cfg.SettlementBackend == Beethoven { | ||
if sequencerPrivateKey == nil { | ||
return Aggregator{}, fmt.Errorf("the private key of the sequencer needs to be provided") | ||
} | ||
sequencerAddr, err := etherman.GetSequencerAddr() | ||
if err != nil { | ||
return Aggregator{}, err | ||
} | ||
actualAddr := crypto.PubkeyToAddress(sequencerPrivateKey.PublicKey) | ||
if sequencerAddr != actualAddr { | ||
return Aggregator{}, fmt.Errorf( | ||
"the private key of the sequencer needs to be provided. Provided private key is for addr %s but sequencer addr is %s", | ||
actualAddr.Hex(), sequencerAddr.Hex(), | ||
) | ||
} | ||
} | ||
|
||
a := Aggregator{ | ||
cfg: cfg, | ||
|
||
|
@@ -92,7 +119,9 @@ | |
TimeSendFinalProofMutex: &sync.RWMutex{}, | ||
TimeCleanupLockedProofs: cfg.CleanupLockedProofsInterval, | ||
|
||
finalProof: make(chan finalProofMsg), | ||
finalProof: make(chan finalProofMsg), | ||
BeethovenClient: beethovenClient, | ||
sequencerPrivateKey: sequencerPrivateKey, | ||
} | ||
|
||
return a, nil | ||
|
@@ -266,27 +295,22 @@ | |
|
||
log.Infof("Final proof inputs: NewLocalExitRoot [%#x], NewStateRoot [%#x]", inputs.NewLocalExitRoot, inputs.NewStateRoot) | ||
|
||
// add batch verification to be monitored | ||
sender := common.HexToAddress(a.cfg.SenderAddress) | ||
to, data, err := a.Ethman.BuildTrustedVerifyBatchesTxData(proof.BatchNumber-1, proof.BatchNumberFinal, &inputs) | ||
if err != nil { | ||
log.Errorf("Error estimating batch verification to add to eth tx manager: %v", err) | ||
a.handleFailureToAddVerifyBatchToBeMonitored(ctx, proof) | ||
continue | ||
} | ||
monitoredTxID := buildMonitoredTxID(proof.BatchNumber, proof.BatchNumberFinal) | ||
err = a.EthTxManager.Add(ctx, ethTxManagerOwner, monitoredTxID, sender, to, nil, data, a.cfg.GasOffset, nil) | ||
if err != nil { | ||
mTxLogger := ethtxmanager.CreateLogger(ethTxManagerOwner, monitoredTxID, sender, to) | ||
mTxLogger.Errorf("Error to add batch verification tx to eth tx manager: %v", err) | ||
a.handleFailureToAddVerifyBatchToBeMonitored(ctx, proof) | ||
continue | ||
} | ||
log.Infof("Final proof inputs: NewLocalExitRoot [%#x], NewStateRoot [%#x]", inputs.NewLocalExitRoot, inputs.NewStateRoot) | ||
|
||
// process monitored batch verifications before starting a next cycle | ||
a.EthTxManager.ProcessPendingMonitoredTxs(ctx, ethTxManagerOwner, func(result ethtxmanager.MonitoredTxResult, dbTx pgx.Tx) { | ||
a.handleMonitoredTxResult(result) | ||
}, nil) | ||
switch a.cfg.SettlementBackend { | ||
case L1: | ||
if success := a.settleProofToL1(ctx, proof, inputs); !success { | ||
continue | ||
} | ||
case Beethoven: | ||
if success := a.settleProofToBeethoven(ctx, proof, inputs); !success { | ||
continue | ||
} | ||
default: | ||
if success := a.settleProofToL1(ctx, proof, inputs); !success { | ||
continue | ||
} | ||
} | ||
|
||
a.resetVerifyProofTime() | ||
a.endProofVerification() | ||
|
@@ -1094,3 +1118,78 @@ | |
runes[0] = unicode.ToUpper(runes[0]) | ||
return string(runes) | ||
} | ||
|
||
func (a *Aggregator) settleProofToL1(ctx context.Context, proof *state.Proof, inputs ethmanTypes.FinalProofInputs) (success bool) { | ||
// add batch verification to be monitored | ||
sender := common.HexToAddress(a.cfg.SenderAddress) | ||
to, data, err := a.Ethman.BuildTrustedVerifyBatchesTxData(proof.BatchNumber-1, proof.BatchNumberFinal, &inputs) | ||
if err != nil { | ||
log.Errorf("Error estimating batch verification to add to eth tx manager: %v", err) | ||
a.handleFailureToAddVerifyBatchToBeMonitored(ctx, proof) | ||
return false | ||
} | ||
monitoredTxID := buildMonitoredTxID(proof.BatchNumber, proof.BatchNumberFinal) | ||
err = a.EthTxManager.Add(ctx, ethTxManagerOwner, monitoredTxID, sender, to, nil, data, a.cfg.GasOffset, nil) | ||
if err != nil { | ||
log := log.WithFields("tx", monitoredTxID) | ||
log.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, ethTxManagerOwner, func(result ethtxmanager.MonitoredTxResult, dbTx pgx.Tx) { | ||
a.handleMonitoredTxResult(result) | ||
}, nil) | ||
return true | ||
} | ||
|
||
func (a *Aggregator) settleProofToBeethoven(ctx context.Context, proof *state.Proof, inputs ethmanTypes.FinalProofInputs) (success bool) { | ||
l1Contract := a.Ethman.GetL1ContractAddress() | ||
proofStrNo0x := strings.TrimPrefix(inputs.FinalProof.Proof, "0x") | ||
proofBytes := common.Hex2Bytes(proofStrNo0x) | ||
tx := tx.Tx{ | ||
L1Contract: l1Contract, | ||
LastVerifiedBatch: beethovenTypes.ArgUint64(proof.BatchNumber - 1), | ||
NewVerifiedBatch: beethovenTypes.ArgUint64(proof.BatchNumberFinal), | ||
ZKP: tx.ZKP{ | ||
NewStateRoot: common.BytesToHash(inputs.NewStateRoot), | ||
NewLocalExitRoot: common.BytesToHash(inputs.NewLocalExitRoot), | ||
Proof: beethovenTypes.ArgBytes(proofBytes), | ||
}, | ||
} | ||
signedTx, err := tx.Sign(a.sequencerPrivateKey) | ||
if err != nil { | ||
log.Errorf("failed to sign tx: %v", err) | ||
a.handleFailureToSendToBeethoven(ctx, proof) | ||
return false | ||
} | ||
log.Debug("final proof signedTx: ", signedTx.Tx.ZKP.Proof.Hex()) | ||
txHash, err := a.BeethovenClient.SendTx(*signedTx) | ||
if err != nil { | ||
log.Errorf("failed to send tx to the interop: %v", err) | ||
a.handleFailureToSendToBeethoven(ctx, proof) | ||
return false | ||
} | ||
log.Infof("tx %s sent to beethoven, waiting to be mined", txHash.Hex()) | ||
log.Debugf("Timeout set to %f seconds", a.cfg.BeethovenTxTimeout.Duration.Seconds()) | ||
waitCtx, cancelFunc := context.WithDeadline(ctx, time.Now().Add(a.cfg.BeethovenTxTimeout.Duration)) | ||
defer cancelFunc() | ||
if err := a.BeethovenClient.WaitTxToBeMined(txHash, waitCtx); err != nil { | ||
log.Errorf("interop didn't mine the tx: %v", err) | ||
a.handleFailureToSendToBeethoven(ctx, proof) | ||
return false | ||
} | ||
// TODO: wait for synchronizer to catch up | ||
return true | ||
} | ||
|
||
func (a *Aggregator) handleFailureToSendToBeethoven(ctx context.Context, proof *state.Proof) { | ||
log := log.WithFields("proofId", proof.ProofID, "batches", fmt.Sprintf("%d-%d", proof.BatchNumber, proof.BatchNumberFinal)) | ||
proof.GeneratingSince = nil | ||
err := a.State.UpdateGeneratedProof(ctx, proof, nil) | ||
if err != nil { | ||
log.Errorf("Failed updating proof state (false): %v", err) | ||
} | ||
a.endProofVerification() | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -28,6 +28,13 @@ func (t *TokenAmountWithDecimals) UnmarshalText(data []byte) error { | |||||
return nil | ||||||
} | ||||||
|
||||||
type SettlementBackend string | ||||||
|
||||||
const ( | ||||||
Beethoven SettlementBackend = "beethoven" | ||||||
L1 SettlementBackend = "l1" | ||||||
) | ||||||
|
||||||
// Config represents the configuration of the aggregator | ||||||
type Config struct { | ||||||
// Host for the grpc server | ||||||
|
@@ -85,4 +92,16 @@ type Config struct { | |||||
// gas offset: 100 | ||||||
// final gas: 1100 | ||||||
GasOffset uint64 `mapstructure:"GasOffset"` | ||||||
|
||||||
// SettlementBackend indicates where ZKPs are settled. It can be "l1" or "beethoven" | ||||||
SettlementBackend SettlementBackend `mapstructure:"SettlementBackend"` | ||||||
|
||||||
// BeethovenTxTimeout is the interval time to wait for a tx to be mined from the beethoven | ||||||
BeethovenTxTimeout types.Duration `mapstructure:"BeethovenTxTimeout"` | ||||||
|
||||||
// BeethovenURL url of the beethoven service | ||||||
BeethovenURL string `mapstructure:"BeethovenURL"` | ||||||
|
||||||
// PrivateKey of the sequencer, used to authorize txs sent to the beethoven | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Linter prefers
Suggested change
|
||||||
SequencerPrivateKey types.KeystoreFileConfig `mapstructure:"SequencerPrivateKey"` | ||||||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is another option to do it via git token
Dockerfile:
scripts/git-configure.sh
.gittoken (ignorred)
Also just FYI