From 18c854fbaa948162fd18ead95dde8e8ecf55d659 Mon Sep 17 00:00:00 2001 From: Eduard S Date: Wed, 30 Dec 2020 13:32:19 +0100 Subject: [PATCH] Add circuit configuration to node config - Remove MaxL1CoordTxs parameter from the TxSelector because this parameter doesn't exist - Use ChainID in l1tx byte encoding - Pass txprocessor configuration to batch builder via an existing parameter --- batchbuilder/batchbuilder.go | 17 ++++------ cli/node/cfg.buidler.toml | 4 +++ common/ethrollup.go | 58 ++++++++------------------------- common/l1tx.go | 4 +-- common/l1tx_test.go | 3 +- config/config.go | 7 +++- coordinator/batch.go | 1 + coordinator/coordinator.go | 48 ++++++++++++--------------- coordinator/coordinator_test.go | 27 +++++++-------- node/node.go | 23 +++++++++++-- prover/prover.go | 1 - txprocessor/txprocessor.go | 2 +- 12 files changed, 88 insertions(+), 107 deletions(-) diff --git a/batchbuilder/batchbuilder.go b/batchbuilder/batchbuilder.go index 40730d9..545ef7f 100644 --- a/batchbuilder/batchbuilder.go +++ b/batchbuilder/batchbuilder.go @@ -24,7 +24,8 @@ type BatchBuilder struct { // ConfigBatch contains the batch configuration type ConfigBatch struct { - ForgerAddress ethCommon.Address + ForgerAddress ethCommon.Address + TxProcessorConfig txprocessor.Config } // NewBatchBuilder constructs a new BatchBuilder, and executes the bb.Reset @@ -54,17 +55,11 @@ func (bb *BatchBuilder) Reset(batchNum common.BatchNum, fromSynchronizer bool) e } // BuildBatch takes the transactions and returns the common.ZKInputs of the next batch -func (bb *BatchBuilder) BuildBatch(coordIdxs []common.Idx, configBatch *ConfigBatch, l1usertxs, l1coordinatortxs []common.L1Tx, pooll2txs []common.PoolL2Tx, tokenIDs []common.TokenID) (*common.ZKInputs, error) { - //nolint:gomnd - tpc := txprocessor.Config{ // TODO TMP - NLevels: 32, - MaxFeeTx: 64, - MaxTx: 512, - MaxL1Tx: 64, - ChainID: uint16(0), - } +func (bb *BatchBuilder) BuildBatch(coordIdxs []common.Idx, configBatch *ConfigBatch, l1usertxs, + l1coordinatortxs []common.L1Tx, pooll2txs []common.PoolL2Tx, + tokenIDs []common.TokenID) (*common.ZKInputs, error) { bbStateDB := bb.localStateDB.StateDB - tp := txprocessor.NewTxProcessor(bbStateDB, tpc) + tp := txprocessor.NewTxProcessor(bbStateDB, configBatch.TxProcessorConfig) ptOut, err := tp.ProcessTxs(coordIdxs, l1usertxs, l1coordinatortxs, pooll2txs) return ptOut.ZKInputs, tracerr.Wrap(err) diff --git a/cli/node/cfg.buidler.toml b/cli/node/cfg.buidler.toml index b7cb0c0..b5791ab 100644 --- a/cli/node/cfg.buidler.toml +++ b/cli/node/cfg.buidler.toml @@ -63,6 +63,10 @@ Path = "/tmp/iden3-test/hermez/batchbuilder" [[Coordinator.ServerProofs]] URL = "http://localhost:3000/api" +[Coordinator.Circuit] +MaxTx = 512 +NLevels = 32 + [Coordinator.EthClient] CallGasLimit = 300000 DeployGasLimit = 1000000 diff --git a/common/ethrollup.go b/common/ethrollup.go index cd7ed86..8f2db0b 100644 --- a/common/ethrollup.go +++ b/common/ethrollup.go @@ -1,56 +1,14 @@ package common import ( + "fmt" "math/big" ethCommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/hermeznetwork/tracerr" ) -// RollupVars contain the Rollup smart contract variables -// type RollupVars struct { -// EthBlockNum uint64 -// ForgeL1Timeout *big.Int -// FeeL1UserTx *big.Int -// FeeAddToken *big.Int -// TokensHEZ eth.Address -// Governance eth.Address -// } - -// AuctionVars contain the Auction smart contract variables -// type AuctionVars struct { -// EthBlockNum uint64 -// SlotDeadline uint -// CloseAuctionSlots uint -// OpenAuctionSlots uint -// Governance eth.Address -// MinBidSlots MinBidSlots -// Outbidding int -// DonationAddress eth.Address -// GovernanceAddress eth.Address -// AllocationRatio AllocationRatio -// } - -// WithdrawDelayerVars contains the Withdrawal Delayer smart contract variables -// type WithdrawDelayerVars struct { -// HermezRollupAddress eth.Address -// HermezGovernanceAddress eth.Address -// EmergencyCouncilAddress eth.Address -// WithdrawalDelay uint -// EmergencyModeStartingTime time.Time -// EmergencyModeEnabled bool -// } - -// MinBidSlots TODO -// type MinBidSlots [6]uint -// -// // AllocationRatio TODO -// type AllocationRatio struct { -// Donation uint -// Burn uint -// Forger uint -// } - const ( // RollupConstMaxFeeIdxCoordinator is the maximum number of tokens the // coordinator can use to collect fees (determines the number of tokens @@ -146,6 +104,18 @@ type RollupConstants struct { WithdrawDelayerContract ethCommon.Address `json:"withdrawDelayerContract"` } +// FindVerifierIdx tries to find a matching verifier in the RollupConstants and +// returns its index +func (c *RollupConstants) FindVerifierIdx(MaxTx, NLevels int64) (int, error) { + for i, verifier := range c.Verifiers { + if verifier.MaxTx == MaxTx && verifier.NLevels == NLevels { + return i, nil + } + } + return 0, tracerr.Wrap(fmt.Errorf("verifier not found for MaxTx: %v, NLevels: %v", + MaxTx, NLevels)) +} + // BucketParams are the parameter variables of each Bucket of Rollup Smart // Contract type BucketParams struct { diff --git a/common/l1tx.go b/common/l1tx.go index 2bd4244..9c86fb3 100644 --- a/common/l1tx.go +++ b/common/l1tx.go @@ -176,7 +176,7 @@ func (tx L1Tx) Tx() Tx { // [ 16 bits ] chainId // 2 bytes // [ 32 bits ] empty (signatureConstant) // 4 bytes // Total bits compressed data: 241 bits // 31 bytes in *big.Int representation -func (tx L1Tx) TxCompressedData() (*big.Int, error) { +func (tx L1Tx) TxCompressedData(chainID uint16) (*big.Int, error) { amountFloat16, err := NewFloat16(tx.Amount) if err != nil { return nil, tracerr.Wrap(err) @@ -196,7 +196,7 @@ func (tx L1Tx) TxCompressedData() (*big.Int, error) { return nil, tracerr.Wrap(err) } copy(b[19:25], fromIdxBytes[:]) - copy(b[25:27], []byte{0, 0}) // TODO this will be generated by the ChainID config parameter + binary.BigEndian.PutUint16(b[25:27], chainID) copy(b[27:31], SignatureConstantBytes[:]) bi := new(big.Int).SetBytes(b[:]) diff --git a/common/l1tx_test.go b/common/l1tx_test.go index 38b8b65..1f56d28 100644 --- a/common/l1tx_test.go +++ b/common/l1tx_test.go @@ -56,7 +56,8 @@ func TestL1TxCompressedData(t *testing.T) { Amount: big.NewInt(4), TokenID: 5, } - txCompressedData, err := tx.TxCompressedData() + chainID := uint16(0) + txCompressedData, err := tx.TxCompressedData(chainID) assert.NoError(t, err) // test vector value generated from javascript implementation diff --git a/config/config.go b/config/config.go index 0c63a0e..236f4a3 100644 --- a/config/config.go +++ b/config/config.go @@ -68,7 +68,12 @@ type Coordinator struct { Path string `validate:"required"` } `validate:"required"` ServerProofs []ServerProof `validate:"required"` - EthClient struct { + Circuit struct { + // VerifierIdx uint8 `validate:"required"` + MaxTx int64 `validate:"required"` + NLevels int64 `validate:"required"` + } `validate:"required"` + EthClient struct { CallGasLimit uint64 `validate:"required"` DeployGasLimit uint64 `validate:"required"` GasPriceDiv uint64 `validate:"required"` diff --git a/coordinator/batch.go b/coordinator/batch.go index a611e16..195f8de 100644 --- a/coordinator/batch.go +++ b/coordinator/batch.go @@ -32,6 +32,7 @@ type BatchInfo struct { Proof *prover.Proof PublicInputs []*big.Int L1Batch bool + VerifierIdx uint8 L1UserTxsExtra []common.L1Tx L1CoordTxs []common.L1Tx L1CoordinatorTxsAuths [][]byte diff --git a/coordinator/coordinator.go b/coordinator/coordinator.go index b10e229..cbbbd6c 100644 --- a/coordinator/coordinator.go +++ b/coordinator/coordinator.go @@ -50,8 +50,10 @@ type Config struct { TxManagerCheckInterval time.Duration // DebugBatchPath if set, specifies the path where batchInfo is stored // in JSON in every step/update of the pipeline - DebugBatchPath string - Purger PurgerCfg + DebugBatchPath string + Purger PurgerCfg + VerifierIdx uint8 + TxProcessorConfig txprocessor.Config } func (c *Config) debugBatchStore(batchInfo *BatchInfo) { @@ -213,20 +215,6 @@ func (c *Coordinator) canForge(stats *synchronizer.Stats) bool { func (c *Coordinator) syncStats(ctx context.Context, stats *synchronizer.Stats) error { c.txManager.SetLastBlock(stats.Eth.LastBlock.Num) - // TMP - //nolint:gomnd - selectionConfig := &txselector.SelectionConfig{ - MaxL1UserTxs: 32, - MaxL1CoordinatorTxs: 32, - TxProcessorConfig: txprocessor.Config{ - NLevels: 32, - MaxFeeTx: 64, - MaxTx: 512, - MaxL1Tx: 64, - ChainID: uint16(0), - }, - } - canForge := c.canForge(stats) if c.pipeline == nil { if canForge { @@ -238,7 +226,7 @@ func (c *Coordinator) syncStats(ctx context.Context, stats *synchronizer.Stats) return tracerr.Wrap(err) } if err := c.pipeline.Start(batchNum, stats.Sync.LastForgeL1TxsNum, - stats, &c.vars, selectionConfig); err != nil { + stats, &c.vars); err != nil { c.pipeline = nil return tracerr.Wrap(err) } @@ -689,8 +677,7 @@ func (p *Pipeline) reset(batchNum common.BatchNum, lastForgeL1TxsNum int64, // Start the forging pipeline func (p *Pipeline) Start(batchNum common.BatchNum, lastForgeL1TxsNum int64, - syncStats *synchronizer.Stats, initSCVars *synchronizer.SCVariables, - selectionConfig *txselector.SelectionConfig) error { + syncStats *synchronizer.Stats, initSCVars *synchronizer.SCVariables) error { if p.started { log.Fatal("Pipeline already started") } @@ -716,7 +703,7 @@ func (p *Pipeline) Start(batchNum common.BatchNum, lastForgeL1TxsNum int64, p.stats = syncStats default: batchNum = p.batchNum + 1 - batchInfo, err := p.forgeBatch(p.ctx, batchNum, selectionConfig) + batchInfo, err := p.forgeBatch(batchNum) if p.ctx.Err() != nil { continue } else if err != nil { @@ -818,7 +805,7 @@ func (p *Pipeline) sendServerProof(ctx context.Context, batchInfo *BatchInfo) er } // forgeBatch the next batch. -func (p *Pipeline) forgeBatch(ctx context.Context, batchNum common.BatchNum, selectionConfig *txselector.SelectionConfig) (*BatchInfo, error) { +func (p *Pipeline) forgeBatch(batchNum common.BatchNum) (*BatchInfo, error) { // remove transactions from the pool that have been there for too long _, err := p.purger.InvalidateMaybe(p.l2DB, p.txSelector.LocalAccountsDB(), p.stats.Sync.LastBlock.Num, int64(batchNum)) @@ -832,6 +819,11 @@ func (p *Pipeline) forgeBatch(ctx context.Context, batchNum common.BatchNum, sel batchInfo := BatchInfo{BatchNum: batchNum} // to accumulate metadata of the batch + selectionCfg := &txselector.SelectionConfig{ + MaxL1UserTxs: common.RollupConstMaxL1UserTx, + TxProcessorConfig: p.cfg.TxProcessorConfig, + } + var poolL2Txs []common.PoolL2Tx // var feesInfo var l1UserTxsExtra, l1CoordTxs []common.L1Tx @@ -847,16 +839,15 @@ func (p *Pipeline) forgeBatch(ctx context.Context, batchNum common.BatchNum, sel if err != nil { return nil, tracerr.Wrap(err) } - // TODO once feesInfo is added to method return, add the var coordIdxs, auths, l1UserTxsExtra, l1CoordTxs, poolL2Txs, err = - p.txSelector.GetL1L2TxSelection(selectionConfig, batchNum, l1UserTxs) + p.txSelector.GetL1L2TxSelection(selectionCfg, batchNum, l1UserTxs) if err != nil { return nil, tracerr.Wrap(err) } } else { // 2b: only L2 txs coordIdxs, auths, l1CoordTxs, poolL2Txs, err = - p.txSelector.GetL2TxSelection(selectionConfig, batchNum) + p.txSelector.GetL2TxSelection(selectionCfg, batchNum) if err != nil { return nil, tracerr.Wrap(err) } @@ -864,11 +855,11 @@ func (p *Pipeline) forgeBatch(ctx context.Context, batchNum common.BatchNum, sel } // 3. Save metadata from TxSelector output for BatchNum - // TODO feesInfo batchInfo.L1UserTxsExtra = l1UserTxsExtra batchInfo.L1CoordTxs = l1CoordTxs batchInfo.L1CoordinatorTxsAuths = auths batchInfo.CoordIdxs = coordIdxs + batchInfo.VerifierIdx = p.cfg.VerifierIdx if err := p.l2DB.StartForging(poolL2TxsIDs(poolL2Txs), batchInfo.BatchNum); err != nil { return nil, tracerr.Wrap(err) @@ -885,10 +876,11 @@ func (p *Pipeline) forgeBatch(ctx context.Context, batchNum common.BatchNum, sel // 4. Call BatchBuilder with TxSelector output configBatch := &batchbuilder.ConfigBatch{ - ForgerAddress: p.cfg.ForgerAddress, + ForgerAddress: p.cfg.ForgerAddress, + TxProcessorConfig: p.cfg.TxProcessorConfig, } zkInputs, err := p.batchBuilder.BuildBatch(coordIdxs, configBatch, l1UserTxsExtra, - l1CoordTxs, poolL2Txs, nil) // TODO []common.TokenID --> feesInfo + l1CoordTxs, poolL2Txs, nil) if err != nil { return nil, tracerr.Wrap(err) } @@ -948,7 +940,7 @@ func prepareForgeBatchArgs(batchInfo *BatchInfo) *eth.RollupForgeBatchArgs { L2TxsData: batchInfo.L2Txs, FeeIdxCoordinator: batchInfo.CoordIdxs, // Circuit selector - VerifierIdx: 0, // TODO + VerifierIdx: batchInfo.VerifierIdx, L1Batch: batchInfo.L1Batch, ProofA: [2]*big.Int{proof.PiA[0], proof.PiA[1]}, ProofB: [2][2]*big.Int{ diff --git a/coordinator/coordinator_test.go b/coordinator/coordinator_test.go index 21fa24a..af7d448 100644 --- a/coordinator/coordinator_test.go +++ b/coordinator/coordinator_test.go @@ -90,9 +90,7 @@ type modules struct { stateDB *statedb.StateDB } -var maxL1UserTxs uint64 = 128 var maxL1Txs uint64 = 256 -var maxL1CoordinatorTxs uint64 = maxL1Txs - maxL1UserTxs var maxTxs uint64 = 376 var nLevels uint32 = 32 //nolint:deadcode,unused var maxFeeTxs uint32 = 64 //nolint:deadcode,varcheck @@ -174,7 +172,16 @@ func newTestCoordinator(t *testing.T, forgerAddr ethCommon.Address, ethClient *t InvalidateBatchDelay: 4, InvalidateBlockDelay: 4, }, + TxProcessorConfig: txprocessor.Config{ + NLevels: nLevels, + MaxFeeTx: maxFeeTxs, + MaxTx: uint32(maxTxs), + MaxL1Tx: uint32(maxL1Txs), + ChainID: chainID, + }, + VerifierIdx: 0, } + serverProofs := []prover.Client{ &prover.MockClient{Delay: 300 * time.Millisecond}, &prover.MockClient{Delay: 400 * time.Millisecond}, @@ -627,24 +634,12 @@ PoolTransfer(0) User2-User3: 300 (126) batchNum++ - selectionConfig := &txselector.SelectionConfig{ - MaxL1UserTxs: maxL1UserTxs, - MaxL1CoordinatorTxs: maxL1CoordinatorTxs, - TxProcessorConfig: txprocessor.Config{ - NLevels: nLevels, - MaxFeeTx: maxFeeTxs, - MaxTx: uint32(maxTxs), - MaxL1Tx: uint32(maxL1Txs), - ChainID: chainID, - }, - } - - batchInfo, err := pipeline.forgeBatch(ctx, batchNum, selectionConfig) + batchInfo, err := pipeline.forgeBatch(batchNum) require.NoError(t, err) assert.Equal(t, 3, len(batchInfo.L2Txs)) batchNum++ - batchInfo, err = pipeline.forgeBatch(ctx, batchNum, selectionConfig) + batchInfo, err = pipeline.forgeBatch(batchNum) require.NoError(t, err) assert.Equal(t, 0, len(batchInfo.L2Txs)) } diff --git a/node/node.go b/node/node.go index 1d21c7b..cda0997 100644 --- a/node/node.go +++ b/node/node.go @@ -28,6 +28,7 @@ import ( "github.com/hermeznetwork/hermez-node/prover" "github.com/hermeznetwork/hermez-node/synchronizer" "github.com/hermeznetwork/hermez-node/test/debugapi" + "github.com/hermeznetwork/hermez-node/txprocessor" "github.com/hermeznetwork/hermez-node/txselector" "github.com/hermeznetwork/tracerr" "github.com/jmoiron/sqlx" @@ -202,8 +203,8 @@ func NewNode(mode Mode, cfg *config.Node) (*Node, error) { return nil, tracerr.Wrap(err) } // TODO: Get (configCircuits []ConfigCircuit, batchNum common.BatchNum, nLevels uint64) from smart contract - nLevels := uint64(32) //nolint:gomnd - batchBuilder, err := batchbuilder.NewBatchBuilder(cfg.Coordinator.BatchBuilder.Path, stateDB, nil, 0, nLevels) + batchBuilder, err := batchbuilder.NewBatchBuilder(cfg.Coordinator.BatchBuilder.Path, + stateDB, nil, 0, uint64(cfg.Coordinator.Circuit.NLevels)) if err != nil { return nil, tracerr.Wrap(err) } @@ -216,6 +217,22 @@ func NewNode(mode Mode, cfg *config.Node) (*Node, error) { cfg.Coordinator.ProofServerPollInterval.Duration) } + txProcessorCfg := txprocessor.Config{ + NLevels: uint32(cfg.Coordinator.Circuit.NLevels), + MaxTx: uint32(cfg.Coordinator.Circuit.MaxTx), + ChainID: chainIDU16, + MaxFeeTx: common.RollupConstMaxFeeIdxCoordinator, + MaxL1Tx: common.RollupConstMaxL1Tx, + } + verifierIdx, err := scConsts.Rollup.FindVerifierIdx( + cfg.Coordinator.Circuit.MaxTx, + cfg.Coordinator.Circuit.NLevels, + ) + if err != nil { + return nil, tracerr.Wrap(err) + } + log.Infow("Found verifier that matches circuit config", "verifierIdx", verifierIdx) + coord, err = coordinator.NewCoordinator( coordinator.Config{ ForgerAddress: cfg.Coordinator.ForgerAddress, @@ -232,6 +249,8 @@ func NewNode(mode Mode, cfg *config.Node) (*Node, error) { PurgeBlockDelay: cfg.Coordinator.L2DB.PurgeBlockDelay, InvalidateBlockDelay: cfg.Coordinator.L2DB.InvalidateBlockDelay, }, + VerifierIdx: uint8(verifierIdx), + TxProcessorConfig: txProcessorCfg, }, historyDB, l2DB, diff --git a/prover/prover.go b/prover/prover.go index 53ddca4..51e75bb 100644 --- a/prover/prover.go +++ b/prover/prover.go @@ -65,7 +65,6 @@ func (p *Proof) UnmarshalJSON(data []byte) error { if p.PiC[2].Int64() != 1 { return tracerr.Wrap(fmt.Errorf("Expected PiC[2] == 1, but got %v", p.PiC[2])) } - // TODO: Assert ones and zeroes p.Protocol = proof.Protocol return nil } diff --git a/txprocessor/txprocessor.go b/txprocessor/txprocessor.go index 825f1fd..ba8e922 100644 --- a/txprocessor/txprocessor.go +++ b/txprocessor/txprocessor.go @@ -441,7 +441,7 @@ func (tp *TxProcessor) ProcessL1Tx(exitTree *merkletree.MerkleTree, tx *common.L if tp.zki != nil { // Txs var err error - tp.zki.TxCompressedData[tp.i], err = tx.TxCompressedData() + tp.zki.TxCompressedData[tp.i], err = tx.TxCompressedData(tp.config.ChainID) if err != nil { log.Error(err) return nil, nil, false, nil, tracerr.Wrap(err)