Skip to content
This repository was archived by the owner on Sep 23, 2024. It is now read-only.

Modularize Beethoven logic #29

Merged
merged 31 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/0xPolygon/beethoven/config"
"github.com/0xPolygon/beethoven/db"
"github.com/0xPolygon/beethoven/etherman"
"github.com/0xPolygon/beethoven/interop"
"github.com/0xPolygon/beethoven/network"
"github.com/0xPolygon/beethoven/rpc"
)
Expand Down Expand Up @@ -124,6 +125,18 @@ func start(cliCtx *cli.Context) error {
log.Fatal(err)
}

ctx, cancel := context.WithTimeout(context.Background(), c.RPC.ReadTimeout.Duration)
defer cancel()

executor := interop.New(
log.WithFields("module", "executor"),
c,
addr,
storage,
&ethMan,
etm,
)

// Register services
server := jsonrpc.NewServer(
c.RPC,
Expand All @@ -133,9 +146,8 @@ func start(cliCtx *cli.Context) error {
&dummyinterfaces.DummyStorage{},
[]jsonrpc.Service{
{
Name: rpc.INTEROP,
Service: rpc.NewInteropEndpoints(addr, storage, &ethMan,
c.FullNodeRPCs, c.RPC.ReadTimeout.Duration, etm),
Name: rpc.INTEROP,
Service: rpc.NewInteropEndpoints(ctx, executor, storage),
},
},
)
Expand Down
7 changes: 4 additions & 3 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,22 @@ import (
"github.com/0xPolygon/cdk-validium-node/jsonrpc"
"github.com/0xPolygon/cdk-validium-node/log"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/mitchellh/mapstructure"
"github.com/spf13/viper"
"github.com/urfave/cli/v2"

"github.com/0xPolygon/beethoven/rpc"
)

const (
// FlagCfg flag used for config aka cfg
FlagCfg = "cfg"
)

type FullNodeRPCs map[common.Address]string

// Config represents the full configuration of the data node
type Config struct {
FullNodeRPCs rpc.FullNodeRPCs `mapstructure:"FullNodeRPCs"`
FullNodeRPCs FullNodeRPCs `mapstructure:"FullNodeRPCs"`
RPC jsonrpc.Config `mapstructure:"RPC"`
Log log.Config `mapstructure:"Log"`
DB db.Config `mapstructure:"DB"`
Expand Down
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ require (
github.com/0xPolygon/cdk-validium-node v0.0.2-0.20230922123231-07ce723e6268
github.com/ethereum/go-ethereum v1.13.5
github.com/gobuffalo/packr/v2 v2.8.3
github.com/jackc/pgx/v4 v4.18.1
github.com/jackc/pgconn v1.14.1
github.com/jackc/pgx/v4 v4.18.1
github.com/mitchellh/mapstructure v1.5.0
github.com/prometheus/client_golang v1.17.0
github.com/rubenv/sql-migrate v1.5.2
Expand Down Expand Up @@ -44,6 +44,7 @@ require (
github.com/dlclark/regexp2 v1.7.0 // indirect
github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 // indirect
github.com/ethereum/c-kzg-4844 v0.4.0 // indirect
github.com/fatih/color v1.14.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
github.com/getsentry/sentry-go v0.18.0 // indirect
Expand All @@ -64,6 +65,7 @@ require (
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/go-hclog v1.6.2 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hermeznetwork/tracerr v0.3.2 // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
Expand All @@ -89,6 +91,8 @@ require (
github.com/markbates/errx v1.1.0 // indirect
github.com/markbates/oncer v1.0.0 // indirect
github.com/markbates/safe v1.0.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ github.com/ethereum/go-ethereum v1.13.5 h1:U6TCRciCqZRe4FPXmy1sMGxTfuk8P7u2UoinF
github.com/ethereum/go-ethereum v1.13.5/go.mod h1:yMTu38GSuyxaYzQMViqNmQ1s3cE84abZexQmTgenWk0=
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
Expand Down Expand Up @@ -351,6 +354,8 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv
github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE=
github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-hclog v1.6.2 h1:NOtoftovWkDheyUM/8JW3QMiXyxJK3uHRK7wV04nD2I=
github.com/hashicorp/go-hclog v1.6.2/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
Expand Down Expand Up @@ -513,7 +518,9 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
Expand All @@ -523,6 +530,7 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
Expand Down Expand Up @@ -1002,9 +1010,11 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
20 changes: 20 additions & 0 deletions interop/check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package interop

import (
"context"
"fmt"

"github.com/0xPolygon/beethoven/tx"
)

func (e *Executor) CheckTx(ctx context.Context, tx tx.SignedTx) error {
e.logger.Debug("check tx")

// Check if the RPC is actually registered, if not it won't be possible to assert soundness (in the future once we are stateless won't be needed)
// TODO: The JSON parsing of the contract is incorrect
if _, ok := e.config.FullNodeRPCs[tx.Tx.L1Contract]; !ok {
return fmt.Errorf("there is no RPC registered for %s", tx.Tx.L1Contract)
}

return nil
}
71 changes: 71 additions & 0 deletions interop/execute.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package interop

import (
"context"
"fmt"
"math/big"

"github.com/0xPolygon/beethoven/tx"
"github.com/jackc/pgx/v4"

"github.com/0xPolygon/cdk-validium-node/jsonrpc/client"
"github.com/0xPolygon/cdk-validium-node/log"
"github.com/ethereum/go-ethereum/common"
)

const ethTxManOwner = "interop"

func (e *Executor) Execute(signedTx tx.SignedTx) error {
ctx := context.TODO()

// Check expected root vs root from the managed full node
// TODO: go stateless, depends on https://github.com/0xPolygonHermez/zkevm-prover/issues/581
// when this happens we should go async from here, since processing all the batches could take a lot of time
zkEVMClient := client.NewClient(e.config.FullNodeRPCs[signedTx.Tx.L1Contract])
batch, err := zkEVMClient.BatchByNumber(
ctx,
big.NewInt(int64(signedTx.Tx.NewVerifiedBatch)),
)
if err != nil {
return fmt.Errorf("failed to get batch from our node, error: %s", err)
}
if batch.StateRoot != signedTx.Tx.ZKP.NewStateRoot || batch.LocalExitRoot != signedTx.Tx.ZKP.NewLocalExitRoot {
return fmt.Errorf(
"Missmatch detected, expected local exit root: %s actual: %s. expected state root: %s actual: %s",
signedTx.Tx.ZKP.NewLocalExitRoot.Hex(),
batch.LocalExitRoot.Hex(),
signedTx.Tx.ZKP.NewStateRoot.Hex(),
batch.StateRoot.Hex(),
)
}

return nil
}

func (e *Executor) Settle(signedTx tx.SignedTx, dbTx pgx.Tx) (common.Hash, error) {
// // Send L1 tx
// Verify ZKP using eth_call
l1TxData, err := e.etherman.BuildTrustedVerifyBatchesTxData(
uint64(signedTx.Tx.LastVerifiedBatch),
uint64(signedTx.Tx.NewVerifiedBatch),
signedTx.Tx.ZKP,
)
if err != nil {
return common.Hash{}, fmt.Errorf("failed to build verify ZKP tx: %s", err)
}

if err := e.ethTxMan.Add(
context.Background(),
ethTxManOwner,
signedTx.Tx.Hash().Hex(),
e.interopAdminAddr,
&signedTx.Tx.L1Contract,
nil,
l1TxData,
dbTx,
); err != nil {
return common.Hash{}, fmt.Errorf("failed to add tx to ethTxMan, error: %s", err)
}
log.Debugf("successfuly added tx %s to ethTxMan", signedTx.Tx.Hash().Hex())
return signedTx.Tx.Hash(), nil
}
31 changes: 31 additions & 0 deletions interop/executor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package interop

import (
"github.com/0xPolygon/beethoven/config"

"github.com/0xPolygon/cdk-validium-node/log"
"github.com/ethereum/go-ethereum/common"
)

type Executor struct {
logger *log.Logger
interopAdminAddr common.Address
config *config.Config
ethTxMan EthTxManager
etherman EthermanInterface
}

func New(logger *log.Logger, cfg *config.Config,
interopAdminAddr common.Address,
db DBInterface,
etherman EthermanInterface,
ethTxManager EthTxManager,
) *Executor {
return &Executor{
logger: logger,
interopAdminAddr: interopAdminAddr,
config: cfg,
ethTxMan: ethTxManager,
etherman: etherman,
}
}
2 changes: 1 addition & 1 deletion rpc/interfaces.go → interop/interfaces.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package rpc
package interop

import (
"context"
Expand Down
24 changes: 24 additions & 0 deletions interop/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package interop

import (
"context"
"fmt"

"github.com/0xPolygon/cdk-validium-node/jsonrpc/types"
"github.com/ethereum/go-ethereum/common"
"github.com/jackc/pgx/v4"
)

func (e *Executor) GetTxStatus(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (result string, err types.Error) {
res, innerErr := e.ethTxMan.Result(ctx, ethTxManOwner, hash.Hex(), dbTx)
if innerErr != nil {
result = "0x0"
err = types.NewRPCError(types.DefaultErrorCode, fmt.Sprintf("failed to get tx, error: %s", innerErr))

return
}

result = res.Status.String()

return
}
61 changes: 61 additions & 0 deletions interop/verify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package interop

import (
"context"
"errors"
"fmt"

"github.com/0xPolygon/beethoven/tx"

"github.com/ethereum/go-ethereum"
)

func (e *Executor) Verify(tx tx.SignedTx) error {
err := e.VerifyZKP(tx)
if err != nil {
return fmt.Errorf("failed to verify ZKP: %s", err)
}

return e.VerifySignature(tx)
}

func (e *Executor) VerifyZKP(stx tx.SignedTx) error {
// Verify ZKP using eth_call
l1TxData, err := e.etherman.BuildTrustedVerifyBatchesTxData(
uint64(stx.Tx.LastVerifiedBatch),
uint64(stx.Tx.NewVerifiedBatch),
stx.Tx.ZKP,
)
if err != nil {
return fmt.Errorf("failed to build verify ZKP tx: %s", err)
}
msg := ethereum.CallMsg{
From: e.interopAdminAddr,
To: &stx.Tx.L1Contract,
Data: l1TxData,
}
res, err := e.etherman.CallContract(context.Background(), msg, nil)
if err != nil {
return fmt.Errorf("failed to call verify ZKP response: %s, error: %s", res, err)
}

return nil
}

func (i *Executor) VerifySignature(stx tx.SignedTx) error {
// Auth: check signature vs admin
signer, err := stx.Signer()
if err != nil {
return errors.New("failed to get signer")
}

sequencer, err := i.etherman.GetSequencerAddr(stx.Tx.L1Contract)
if err != nil {
return errors.New("failed to get admin from L1")
}
if sequencer != signer {
return errors.New("unexpected signer")
}

return nil
}
Loading