Compare commits

..

13 Commits

Author SHA1 Message Date
Mikelle
4462fd9c53 updated eth/README.md 2021-03-31 19:51:18 +03:00
Mikelle
49280afc1a fixed rollup_test.go 2021-03-30 21:11:50 +03:00
Mikelle
5d06bfc4e4 fixed synchronizer_test.go 2021-03-25 19:44:41 +03:00
Mikelle
bc9d7fdc90 updated RollupVariables init with empty buckets 2021-03-25 19:31:26 +03:00
Mikelle
dde99d6178 fixed TestNodeInfo test 2021-03-24 20:13:26 +03:00
Mikelle
2841b4e22c fixed struct in historydb_test.go 2021-03-24 19:20:10 +03:00
Mikelle
ad4e6e8dcb fixed pr remarks 2021-03-24 19:13:54 +03:00
Mikelle
aa1f0a2618 fixed rollup event parsing 2021-03-23 10:54:14 +03:00
Mikelle
0f4be6a946 updated rollup according new contract api 2021-03-19 16:02:26 +03:00
Mikelle
602e1e7634 Merge remote-tracking branch 'origin/feature/update-smart-contracts' into refactore/rollupUpdateBuckets
# Conflicts:
#	eth/contracts/hermez/Hermez.go
2021-03-19 14:44:16 +03:00
Oleksandr Brezhniev
6aac050858 Update smart contract ABIs 2021-03-19 13:37:15 +02:00
Mikelle
cd7cdef339 fixed blockstamp naming in BucketParamsAPI 2021-03-19 12:56:57 +03:00
Mikelle
379ca78b4e updated rollup buckets to the current state 2021-03-19 12:36:34 +03:00
43 changed files with 819 additions and 703 deletions

View File

@@ -5,7 +5,7 @@ import (
"strconv"
"testing"
"github.com/hermeznetwork/hermez-node/api/apitypes"
"github.com/hermeznetwork/hermez-node/apitypes"
"github.com/hermeznetwork/hermez-node/common"
"github.com/hermeznetwork/hermez-node/db/historydb"
"github.com/mitchellh/copystructure"

View File

@@ -7,7 +7,7 @@ import (
ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/gin-gonic/gin"
"github.com/hermeznetwork/hermez-node/api/apitypes"
"github.com/hermeznetwork/hermez-node/apitypes"
"github.com/hermeznetwork/hermez-node/common"
"github.com/iden3/go-iden3-crypto/babyjub"
)

View File

@@ -50,40 +50,38 @@ func NewAPI(
hermezAddress: consts.HermezAddress,
}
v1 := server.Group("/v1")
// Add coordinator endpoints
if coordinatorEndpoints {
// Account
v1.POST("/account-creation-authorization", a.postAccountCreationAuth)
v1.GET("/account-creation-authorization/:hezEthereumAddress", a.getAccountCreationAuth)
server.POST("/account-creation-authorization", a.postAccountCreationAuth)
server.GET("/account-creation-authorization/:hezEthereumAddress", a.getAccountCreationAuth)
// Transaction
v1.POST("/transactions-pool", a.postPoolTx)
v1.GET("/transactions-pool/:id", a.getPoolTx)
server.POST("/transactions-pool", a.postPoolTx)
server.GET("/transactions-pool/:id", a.getPoolTx)
}
// Add explorer endpoints
if explorerEndpoints {
// Account
v1.GET("/accounts", a.getAccounts)
v1.GET("/accounts/:accountIndex", a.getAccount)
v1.GET("/exits", a.getExits)
v1.GET("/exits/:batchNum/:accountIndex", a.getExit)
server.GET("/accounts", a.getAccounts)
server.GET("/accounts/:accountIndex", a.getAccount)
server.GET("/exits", a.getExits)
server.GET("/exits/:batchNum/:accountIndex", a.getExit)
// Transaction
v1.GET("/transactions-history", a.getHistoryTxs)
v1.GET("/transactions-history/:id", a.getHistoryTx)
server.GET("/transactions-history", a.getHistoryTxs)
server.GET("/transactions-history/:id", a.getHistoryTx)
// Status
v1.GET("/batches", a.getBatches)
v1.GET("/batches/:batchNum", a.getBatch)
v1.GET("/full-batches/:batchNum", a.getFullBatch)
v1.GET("/slots", a.getSlots)
v1.GET("/slots/:slotNum", a.getSlot)
v1.GET("/bids", a.getBids)
v1.GET("/state", a.getState)
v1.GET("/config", a.getConfig)
v1.GET("/tokens", a.getTokens)
v1.GET("/tokens/:id", a.getToken)
v1.GET("/coordinators", a.getCoordinators)
server.GET("/batches", a.getBatches)
server.GET("/batches/:batchNum", a.getBatch)
server.GET("/full-batches/:batchNum", a.getFullBatch)
server.GET("/slots", a.getSlots)
server.GET("/slots/:slotNum", a.getSlot)
server.GET("/bids", a.getBids)
server.GET("/state", a.getState)
server.GET("/config", a.getConfig)
server.GET("/tokens", a.getTokens)
server.GET("/tokens/:id", a.getToken)
server.GET("/coordinators", a.getCoordinators)
}
return a, nil

View File

@@ -19,12 +19,12 @@ import (
ethCommon "github.com/ethereum/go-ethereum/common"
swagger "github.com/getkin/kin-openapi/openapi3filter"
"github.com/gin-gonic/gin"
"github.com/hermeznetwork/hermez-node/api/stateapiupdater"
"github.com/hermeznetwork/hermez-node/common"
"github.com/hermeznetwork/hermez-node/db"
"github.com/hermeznetwork/hermez-node/db/historydb"
"github.com/hermeznetwork/hermez-node/db/l2db"
"github.com/hermeznetwork/hermez-node/log"
"github.com/hermeznetwork/hermez-node/stateapiupdater"
"github.com/hermeznetwork/hermez-node/test"
"github.com/hermeznetwork/hermez-node/test/til"
"github.com/hermeznetwork/hermez-node/test/txsets"
@@ -40,8 +40,8 @@ type Pendinger interface {
New() Pendinger
}
const apiPort = "4010"
const apiURL = "http://localhost:" + apiPort + "/v1/"
const apiAddr = ":4010"
const apiURL = "http://localhost" + apiAddr + "/"
var SetBlockchain = `
Type: Blockchain
@@ -209,7 +209,7 @@ func TestMain(m *testing.M) {
panic(err)
}
// L2DB
l2DB := l2db.NewL2DB(database, database, 10, 1000, 0.0, 1000.0, 24*time.Hour, apiConnCon)
l2DB := l2db.NewL2DB(database, database, 10, 1000, 0.0, 24*time.Hour, apiConnCon)
test.WipeDB(l2DB.DB()) // this will clean HistoryDB and L2DB
// Config (smart contract constants)
chainID := uint16(0)
@@ -240,7 +240,6 @@ func TestMain(m *testing.M) {
nodeConfig := &historydb.NodeConfig{
MaxPoolTxs: 10,
MinFeeUSD: 0,
MaxFeeUSD: 10000000000,
}
if err := hdb.SetNodeConfig(nodeConfig); err != nil {
panic(err)
@@ -258,7 +257,7 @@ func TestMain(m *testing.M) {
panic(err)
}
// Start server
listener, err := net.Listen("tcp", ":"+apiPort) //nolint:gosec
listener, err := net.Listen("tcp", apiAddr) //nolint:gosec
if err != nil {
panic(err)
}
@@ -500,12 +499,14 @@ func TestMain(m *testing.M) {
// Slot 7
nextForgers[6].Coordinator = nonBootForger
var buckets [common.RollupConstNumBuckets]common.BucketParams
buckets := make([]common.BucketParams, 5)
for i := range buckets {
buckets[i].CeilUSD = big.NewInt(int64(i) * 10)
buckets[i].Withdrawals = big.NewInt(int64(i) * 100)
buckets[i].BlockWithdrawalRate = big.NewInt(int64(i) * 1000)
buckets[i].MaxWithdrawals = big.NewInt(int64(i) * 10000)
buckets[i].BlockStamp = big.NewInt(int64(i) * 100)
buckets[i].Withdrawals = big.NewInt(int64(i) * 1000)
buckets[i].RateBlocks = big.NewInt(int64(i) * 10000)
buckets[i].RateWithdrawals = big.NewInt(int64(i) * 100000)
buckets[i].MaxWithdrawals = big.NewInt(int64(i) * 1000000)
}
// Generate SC vars and add them to HistoryDB (if needed)
@@ -616,13 +617,13 @@ func TestTimeout(t *testing.T) {
hdbTO := historydb.NewHistoryDB(databaseTO, databaseTO, apiConnConTO)
require.NoError(t, err)
// L2DB
l2DBTO := l2db.NewL2DB(databaseTO, databaseTO, 10, 1000, 1.0, 1000.0, 24*time.Hour, apiConnConTO)
l2DBTO := l2db.NewL2DB(databaseTO, databaseTO, 10, 1000, 1.0, 24*time.Hour, apiConnConTO)
// API
apiGinTO := gin.Default()
finishWait := make(chan interface{})
startWait := make(chan interface{})
apiGinTO.GET("/v1/wait", func(c *gin.Context) {
apiGinTO.GET("/wait", func(c *gin.Context) {
cancel, err := apiConnConTO.Acquire()
defer cancel()
require.NoError(t, err)
@@ -650,9 +651,9 @@ func TestTimeout(t *testing.T) {
require.NoError(t, err)
client := &http.Client{}
httpReq, err := http.NewRequest("GET", "http://localhost:4444/v1/tokens", nil)
httpReq, err := http.NewRequest("GET", "http://localhost:4444/tokens", nil)
require.NoError(t, err)
httpReqWait, err := http.NewRequest("GET", "http://localhost:4444/v1/wait", nil)
httpReqWait, err := http.NewRequest("GET", "http://localhost:4444/wait", nil)
require.NoError(t, err)
// Request that will get timed out
var wg sync.WaitGroup

View File

@@ -7,7 +7,7 @@ import (
"time"
ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/hermeznetwork/hermez-node/api/apitypes"
"github.com/hermeznetwork/hermez-node/apitypes"
"github.com/hermeznetwork/hermez-node/common"
"github.com/hermeznetwork/hermez-node/db/historydb"
"github.com/mitchellh/copystructure"

View File

@@ -41,7 +41,6 @@ func newRollupConstants(publicConstants common.RollupConstants) *rollupConstants
MaxL1UserTx: common.RollupConstMaxL1UserTx,
MaxL1Tx: common.RollupConstMaxL1Tx,
InputSHAConstantBytes: common.RollupConstInputSHAConstantBytes,
NumBuckets: common.RollupConstNumBuckets,
MaxWithdrawalDelay: common.RollupConstMaxWithdrawalDelay,
ExchangeMultiplier: common.RollupConstExchangeMultiplier,
}

View File

@@ -4,7 +4,7 @@ import (
"fmt"
"testing"
"github.com/hermeznetwork/hermez-node/api/apitypes"
"github.com/hermeznetwork/hermez-node/apitypes"
"github.com/hermeznetwork/hermez-node/common"
"github.com/hermeznetwork/hermez-node/db/historydb"
"github.com/mitchellh/copystructure"

View File

@@ -4,7 +4,7 @@ import (
"math/big"
"testing"
"github.com/hermeznetwork/hermez-node/api/apitypes"
"github.com/hermeznetwork/hermez-node/apitypes"
"github.com/hermeznetwork/hermez-node/common"
"github.com/hermeznetwork/hermez-node/db/historydb"
"github.com/stretchr/testify/assert"
@@ -43,7 +43,9 @@ func assertEqualRollupVariables(t *testing.T, rollupVariables common.RollupVaria
assert.Equal(t, rollupVariables.SafeMode, apiVariables.SafeMode)
if checkBuckets {
for i, bucket := range rollupVariables.Buckets {
assert.Equal(t, apitypes.NewBigIntStr(bucket.BlockWithdrawalRate), apiVariables.Buckets[i].BlockWithdrawalRate)
assert.Equal(t, apitypes.NewBigIntStr(bucket.BlockStamp), apiVariables.Buckets[i].BlockStamp)
assert.Equal(t, apitypes.NewBigIntStr(bucket.RateBlocks), apiVariables.Buckets[i].RateBlocks)
assert.Equal(t, apitypes.NewBigIntStr(bucket.RateWithdrawals), apiVariables.Buckets[i].RateWithdrawals)
assert.Equal(t, apitypes.NewBigIntStr(bucket.CeilUSD), apiVariables.Buckets[i].CeilUSD)
assert.Equal(t, apitypes.NewBigIntStr(bucket.MaxWithdrawals), apiVariables.Buckets[i].MaxWithdrawals)
assert.Equal(t, apitypes.NewBigIntStr(bucket.Withdrawals), apiVariables.Buckets[i].Withdrawals)
@@ -145,8 +147,8 @@ func TestUpdateMetrics(t *testing.T) {
assert.Greater(t, ni.StateAPI.Metrics.TransactionsPerBatch, float64(0))
assert.Greater(t, ni.StateAPI.Metrics.BatchFrequency, float64(0))
assert.Greater(t, ni.StateAPI.Metrics.TransactionsPerSecond, float64(0))
assert.Greater(t, ni.StateAPI.Metrics.TokenAccounts, int64(0))
assert.Greater(t, ni.StateAPI.Metrics.Wallets, int64(0))
assert.Greater(t, ni.StateAPI.Metrics.TotalAccounts, int64(0))
assert.Greater(t, ni.StateAPI.Metrics.TotalBJJs, int64(0))
assert.Greater(t, ni.StateAPI.Metrics.AvgTransactionFee, float64(0))
}
@@ -210,8 +212,8 @@ func TestGetState(t *testing.T) {
assert.Greater(t, status.Metrics.TransactionsPerBatch, float64(0))
assert.Greater(t, status.Metrics.BatchFrequency, float64(0))
assert.Greater(t, status.Metrics.TransactionsPerSecond, float64(0))
assert.Greater(t, status.Metrics.TokenAccounts, int64(0))
assert.Greater(t, status.Metrics.Wallets, int64(0))
assert.Greater(t, status.Metrics.TotalAccounts, int64(0))
assert.Greater(t, status.Metrics.TotalBJJs, int64(0))
assert.Greater(t, status.Metrics.AvgTransactionFee, float64(0))
// Recommended fee
// TODO: perform real asserts (not just greater than 0)

View File

@@ -59,10 +59,10 @@ externalDocs:
description: Find out more about Hermez network.
url: 'https://hermez.io'
servers:
- description: Testnet api, connected to Rinkeby deployment
url: https://api.testnet.hermez.io/v1
- description: Localhost usefull for testing/developing the api
url: http://localhost:4010/v1
- description: Hosted mock up
url: https://apimock.hermez.network
- description: Localhost mock Up
url: http://localhost:4010
tags:
- name: Coordinator
description: Endpoints used by the nodes running in coordinator mode. They are used to interact with the network.
@@ -2569,9 +2569,9 @@ components:
description: List of next coordinators to forge.
items:
$ref: '#/components/schemas/NextForger'
Node:
NodeConfig:
type: object
description: Configuration and metrics of the coordinator node. Note that this is specific for each coordinator.
description: Configuration of the coordinator node. Note that this is specific for each coordinator.
properties:
forgeDelay:
type: number
@@ -2581,14 +2581,9 @@ components:
forge at the maximum rate. Note that this is a configuration parameter of a node,
so each coordinator may have a different value.
example: 193.4
poolLoad:
type: number
description: Number of pending transactions in the pool
example: 23201
additionalProperties: false
required:
- forgeDelay
- poolLoad
State:
type: object
description: Gobal variables of the network
@@ -2605,8 +2600,8 @@ components:
$ref: '#/components/schemas/StateWithdrawDelayer'
recommendedFee:
$ref: '#/components/schemas/RecommendedFee'
node:
$ref: '#/components/schemas/Node'
nodeConfig:
$ref: '#/components/schemas/NodeConfig'
additionalProperties: false
required:
- network
@@ -2615,7 +2610,7 @@ components:
- auction
- withdrawalDelayer
- recommendedFee
- node
- nodeConfig
StateNetwork:
type: object
description: Gobal statistics of the network
@@ -2639,10 +2634,6 @@ components:
- example: 2334
nextForgers:
$ref: '#/components/schemas/NextForgers'
pendingL1Transactions:
type: number
description: Number of pending L1 transactions (added in the smart contract queue but not forged).
example: 22
additionalProperties: false
required:
- lastEthereumBlock
@@ -2738,16 +2729,24 @@ components:
properties:
ceilUSD:
type: string
description: Max USD value
description: Max USD value that bucket holds
example: "1000"
blockStamp:
type: string
description: Block number of the last bucket update
example: "1"
withdrawals:
type: string
description: Available withdrawals of the bucket
example: "4"
blockWithdrawalRate:
rateBlocks:
type: string
description: Every `blockWithdrawalRate` blocks add 1 withdrawal
example: "8"
description: rateBlocks every `rateBlocks` blocks add `rateWithdrawals` withdrawal
example: "2"
rateWithdrawals:
type: string
description: add `rateWithdrawals` every `rateBlocks`
example: "3"
maxWithdrawals:
type: string
description: Max withdrawals the bucket can hold
@@ -2755,8 +2754,10 @@ components:
additionalProperties: false
required:
- ceilUSD
- blockStamp
- withdrawals
- blockWithdrawalRate
- rateBlocks
- rateWithdrawals
- maxWithdrawals
additionalProperties: false
required:
@@ -2818,11 +2819,11 @@ components:
type: number
description: Average transactions per second in the last 24 hours.
example: 302.3
tokenAccounts:
totalAccounts:
type: integer
description: Number of created accounts.
example: 90473
wallets:
totalBJJs:
type: integer
description: Number of different registered BJJs.
example: 23067
@@ -2839,8 +2840,8 @@ components:
- transactionsPerBatch
- batchFrequency
- transactionsPerSecond
- tokenAccounts
- wallets
- totalAccounts
- totalBJJs
- avgTransactionFee
- estimatedTimeToForgeL1
PendingItems:

View File

@@ -8,7 +8,7 @@ import (
"testing"
"time"
"github.com/hermeznetwork/hermez-node/api/apitypes"
"github.com/hermeznetwork/hermez-node/apitypes"
"github.com/hermeznetwork/hermez-node/common"
"github.com/hermeznetwork/hermez-node/db/historydb"
"github.com/hermeznetwork/hermez-node/test"

View File

@@ -8,7 +8,7 @@ import (
ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/gin-gonic/gin"
"github.com/hermeznetwork/hermez-node/api/apitypes"
"github.com/hermeznetwork/hermez-node/apitypes"
"github.com/hermeznetwork/hermez-node/common"
"github.com/hermeznetwork/hermez-node/db/l2db"
"github.com/hermeznetwork/tracerr"

View File

@@ -99,7 +99,6 @@ BJJ = "0x1b176232f78ba0d388ecc5f4896eca2d3b3d4f272092469f559247297f5c0c13"
SafetyPeriod = 10
MaxTxs = 512
MinFeeUSD = 0.0
MaxFeeUSD = 50.0
TTL = "24h"
PurgeBatchDelay = 10
InvalidateBatchDelay = 20

View File

@@ -318,7 +318,6 @@ func cmdDiscard(c *cli.Context) error {
cfg.Coordinator.L2DB.SafetyPeriod,
cfg.Coordinator.L2DB.MaxTxs,
cfg.Coordinator.L2DB.MinFeeUSD,
cfg.Coordinator.L2DB.MaxFeeUSD,
cfg.Coordinator.L2DB.TTL.Duration,
nil,
)

View File

@@ -37,8 +37,6 @@ const (
// _L1_USER_TOTALBYTES bytes] l1TxsData + totalL2TxsDataLength + feeIdxCoordinatorLength +
// [2 bytes] chainID = 18542 bytes + totalL2TxsDataLength + feeIdxCoordinatorLength
RollupConstInputSHAConstantBytes = 18546
// RollupConstNumBuckets Number of buckets
RollupConstNumBuckets = 5
// RollupConstMaxWithdrawalDelay max withdrawal delay in seconds
RollupConstMaxWithdrawalDelay = 2 * 7 * 24 * 60 * 60
// RollupConstExchangeMultiplier exchange multiplier
@@ -133,8 +131,10 @@ func (c *RollupConstants) FindVerifierIdx(MaxTx, NLevels int64) (int, error) {
// Contract
type BucketParams struct {
CeilUSD *big.Int
BlockStamp *big.Int
Withdrawals *big.Int
BlockWithdrawalRate *big.Int
RateBlocks *big.Int
RateWithdrawals *big.Int
MaxWithdrawals *big.Int
}
@@ -162,7 +162,7 @@ type RollupVariables struct {
FeeAddToken *big.Int `meddler:"fee_add_token,bigint" validate:"required"`
ForgeL1L2BatchTimeout int64 `meddler:"forge_l1_timeout" validate:"required"`
WithdrawalDelay uint64 `meddler:"withdrawal_delay" validate:"required"`
Buckets [RollupConstNumBuckets]BucketParams `meddler:"buckets,json"`
Buckets []BucketParams `meddler:"buckets,json"`
SafeMode bool `meddler:"safe_mode"`
}

View File

@@ -144,10 +144,6 @@ type Coordinator struct {
// order to be accepted into the pool. Txs with lower than
// minimum fee will be rejected at the API level.
MinFeeUSD float64
// MaxFeeUSD is the maximum fee in USD that a tx must pay in
// order to be accepted into the pool. Txs with greater than
// maximum fee will be rejected at the API level.
MaxFeeUSD float64 `validate:"required"`
// TTL is the Time To Live for L2Txs in the pool. Once MaxTxs
// L2Txs is reached, L2Txs older than TTL will be deleted.
TTL Duration `validate:"required"`
@@ -380,10 +376,6 @@ type APIServer struct {
// order to be accepted into the pool. Txs with lower than
// minimum fee will be rejected at the API level.
MinFeeUSD float64
// MaxFeeUSD is the maximum fee in USD that a tx must pay in
// order to be accepted into the pool. Txs with greater than
// maximum fee will be rejected at the API level.
MaxFeeUSD float64 `validate:"required"`
} `validate:"required"`
}
Debug NodeDebug `validate:"required"`

View File

@@ -105,7 +105,7 @@ func newTestModules(t *testing.T) modules {
db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
require.NoError(t, err)
test.WipeDB(db)
l2DB := l2db.NewL2DB(db, db, 10, 100, 0.0, 1000.0, 24*time.Hour, nil)
l2DB := l2db.NewL2DB(db, db, 10, 100, 0.0, 24*time.Hour, nil)
historyDB := historydb.NewHistoryDB(db, db, nil)
txSelDBPath, err = ioutil.TempDir("", "tmpTxSelDB")

View File

@@ -21,7 +21,7 @@ func newL2DB(t *testing.T) *l2db.L2DB {
db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
require.NoError(t, err)
test.WipeDB(db)
return l2db.NewL2DB(db, db, 10, 100, 0.0, 1000.0, 24*time.Hour, nil)
return l2db.NewL2DB(db, db, 10, 100, 0.0, 24*time.Hour, nil)
}
func newStateDB(t *testing.T) *statedb.LocalStateDB {

View File

@@ -8,7 +8,7 @@ import (
"time"
ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/hermeznetwork/hermez-node/api/apitypes"
"github.com/hermeznetwork/hermez-node/apitypes"
"github.com/hermeznetwork/hermez-node/common"
"github.com/hermeznetwork/hermez-node/db"
"github.com/hermeznetwork/tracerr"
@@ -1083,8 +1083,12 @@ func (hdb *HistoryDB) GetNextForgersInternalAPI(auctionVars *common.AuctionVaria
}
// GetMetricsInternalAPI returns the MetricsAPI
func (hdb *HistoryDB) GetMetricsInternalAPI(lastBatchNum common.BatchNum) (metrics *MetricsAPI, poolLoad int64, err error) {
metrics = &MetricsAPI{}
func (hdb *HistoryDB) GetMetricsInternalAPI(lastBatchNum common.BatchNum) (*MetricsAPI, error) {
var metrics MetricsAPI
// Get the first and last batch of the last 24h and their timestamps
// if u.state.Network.LastBatch == nil {
// return &metrics, nil
// }
type period struct {
FromBatchNum common.BatchNum `meddler:"from_batch_num"`
FromTimestamp time.Time `meddler:"from_timestamp"`
@@ -1102,7 +1106,7 @@ func (hdb *HistoryDB) GetMetricsInternalAPI(lastBatchNum common.BatchNum) (metri
FROM batch INNER JOIN block ON batch.eth_block_num = block.eth_block_num
WHERE block.timestamp >= NOW() - INTERVAL '24 HOURS';`,
); err != nil {
return nil, 0, tracerr.Wrap(err)
return nil, tracerr.Wrap(err)
}
// Get the amount of txs of that period
row := hdb.dbRead.QueryRow(
@@ -1111,7 +1115,7 @@ func (hdb *HistoryDB) GetMetricsInternalAPI(lastBatchNum common.BatchNum) (metri
)
var nTxs int
if err := row.Scan(&nTxs); err != nil {
return nil, 0, tracerr.Wrap(err)
return nil, tracerr.Wrap(err)
}
// Set txs/s
seconds := p.ToTimestamp.Sub(p.FromTimestamp).Seconds()
@@ -1137,7 +1141,7 @@ func (hdb *HistoryDB) GetMetricsInternalAPI(lastBatchNum common.BatchNum) (metri
)
var totalFee float64
if err := row.Scan(&totalFee); err != nil {
return nil, 0, tracerr.Wrap(err)
return nil, tracerr.Wrap(err)
}
// Set batch frequency
metrics.BatchFrequency = seconds / float64(nBatches)
@@ -1148,7 +1152,7 @@ func (hdb *HistoryDB) GetMetricsInternalAPI(lastBatchNum common.BatchNum) (metri
)
var nL2Txs int
if err := row.Scan(&nL2Txs); err != nil {
return nil, 0, tracerr.Wrap(err)
return nil, tracerr.Wrap(err)
}
if nL2Txs > 0 {
metrics.AvgTransactionFee = totalFee / float64(nL2Txs)
@@ -1157,18 +1161,18 @@ func (hdb *HistoryDB) GetMetricsInternalAPI(lastBatchNum common.BatchNum) (metri
}
// Get and set amount of registered accounts
type registeredAccounts struct {
TokenAccounts int64 `meddler:"token_accounts"`
Wallets int64 `meddler:"wallets"`
TotalIdx int64 `meddler:"total_idx"`
TotalBJJ int64 `meddler:"total_bjj"`
}
ra := &registeredAccounts{}
if err := meddler.QueryRow(
hdb.dbRead, ra,
`SELECT COUNT(*) AS token_accounts, COUNT(DISTINCT(bjj)) AS wallets FROM account;`,
`SELECT COUNT(*) AS total_bjj, COUNT(DISTINCT(bjj)) AS total_idx FROM account;`,
); err != nil {
return nil, 0, tracerr.Wrap(err)
return nil, tracerr.Wrap(err)
}
metrics.TokenAccounts = ra.TokenAccounts
metrics.Wallets = ra.Wallets
metrics.TotalAccounts = ra.TotalIdx
metrics.TotalBJJs = ra.TotalBJJ
// Get and set estimated time to forge L1 tx
row = hdb.dbRead.QueryRow(
`SELECT COALESCE (AVG(EXTRACT(EPOCH FROM (forged.timestamp - added.timestamp))), 0) FROM tx
@@ -1180,18 +1184,10 @@ func (hdb *HistoryDB) GetMetricsInternalAPI(lastBatchNum common.BatchNum) (metri
)
var timeToForgeL1 float64
if err := row.Scan(&timeToForgeL1); err != nil {
return nil, 0, tracerr.Wrap(err)
return nil, tracerr.Wrap(err)
}
metrics.EstimatedTimeToForgeL1 = timeToForgeL1
// Get amount of txs in the pool
row = hdb.dbRead.QueryRow(
`SELECT COUNT(*) FROM tx_pool WHERE state = $1 AND NOT external_delete;`,
common.PoolL2TxStatePending,
)
if err := row.Scan(&poolLoad); err != nil {
return nil, 0, tracerr.Wrap(err)
}
return metrics, poolLoad, nil
return &metrics, nil
}
// GetStateAPI returns the StateAPI

View File

@@ -1181,7 +1181,7 @@ const (
)
// GetRecommendedFee returns the RecommendedFee information
func (hdb *HistoryDB) GetRecommendedFee(minFeeUSD, maxFeeUSD float64) (*common.RecommendedFee, error) {
func (hdb *HistoryDB) GetRecommendedFee(minFeeUSD float64) (*common.RecommendedFee, error) {
var recommendedFee common.RecommendedFee
// Get total txs and the batch of the first selected tx of the last hour
type totalTxsSinceBatchNum struct {
@@ -1217,11 +1217,11 @@ func (hdb *HistoryDB) GetRecommendedFee(minFeeUSD, maxFeeUSD float64) (*common.R
} else {
avgTransactionFee = 0
}
recommendedFee.ExistingAccount = math.Min(maxFeeUSD,
math.Max(avgTransactionFee, minFeeUSD))
recommendedFee.CreatesAccount = math.Min(maxFeeUSD,
math.Max(CreateAccountExtraFeePercentage*avgTransactionFee, minFeeUSD))
recommendedFee.CreatesAccountInternal = math.Min(maxFeeUSD,
math.Max(CreateAccountInternalExtraFeePercentage*avgTransactionFee, minFeeUSD))
recommendedFee.ExistingAccount =
math.Max(avgTransactionFee, minFeeUSD)
recommendedFee.CreatesAccount =
math.Max(CreateAccountExtraFeePercentage*avgTransactionFee, minFeeUSD)
recommendedFee.CreatesAccountInternal =
math.Max(CreateAccountInternalExtraFeePercentage*avgTransactionFee, minFeeUSD)
return &recommendedFee, nil
}

View File

@@ -11,7 +11,7 @@ import (
"time"
ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/hermeznetwork/hermez-node/api/apitypes"
"github.com/hermeznetwork/hermez-node/apitypes"
"github.com/hermeznetwork/hermez-node/common"
dbUtils "github.com/hermeznetwork/hermez-node/db"
"github.com/hermeznetwork/hermez-node/log"
@@ -738,7 +738,7 @@ func exampleInitSCVars() (*common.RollupVariables, *common.AuctionVariables, *co
big.NewInt(10),
12,
13,
[5]common.BucketParams{},
[]common.BucketParams{},
false,
}
//nolint:govet
@@ -1177,7 +1177,7 @@ func TestGetMetricsAPI(t *testing.T) {
assert.NoError(t, err)
}
res, _, err := historyDB.GetMetricsInternalAPI(common.BatchNum(numBatches))
res, err := historyDB.GetMetricsInternalAPI(common.BatchNum(numBatches))
assert.NoError(t, err)
assert.Equal(t, float64(numTx)/float64(numBatches), res.TransactionsPerBatch)
@@ -1186,8 +1186,8 @@ func TestGetMetricsAPI(t *testing.T) {
// There is a -2 as time for first and last batch is not taken into account
assert.InEpsilon(t, float64(frequency)*float64(numBatches-2)/float64(numBatches), res.BatchFrequency, 0.01)
assert.InEpsilon(t, float64(numTx)/float64(frequency*blockNum-frequency), res.TransactionsPerSecond, 0.01)
assert.Equal(t, int64(3), res.TokenAccounts)
assert.Equal(t, int64(3), res.Wallets)
assert.Equal(t, int64(3), res.TotalAccounts)
assert.Equal(t, int64(3), res.TotalBJJs)
// Til does not set fees
assert.Equal(t, float64(0), res.AvgTransactionFee)
}
@@ -1255,22 +1255,22 @@ func TestGetMetricsAPIMoreThan24Hours(t *testing.T) {
assert.NoError(t, err)
}
res, _, err := historyDBWithACC.GetMetricsInternalAPI(common.BatchNum(numBatches))
res, err := historyDBWithACC.GetMetricsInternalAPI(common.BatchNum(numBatches))
assert.NoError(t, err)
assert.InEpsilon(t, 1.0, res.TransactionsPerBatch, 0.1)
assert.InEpsilon(t, res.BatchFrequency, float64(blockTime/time.Second), 0.1)
assert.InEpsilon(t, 1.0/float64(blockTime/time.Second), res.TransactionsPerSecond, 0.1)
assert.Equal(t, int64(3), res.TokenAccounts)
assert.Equal(t, int64(3), res.Wallets)
assert.Equal(t, int64(3), res.TotalAccounts)
assert.Equal(t, int64(3), res.TotalBJJs)
// Til does not set fees
assert.Equal(t, float64(0), res.AvgTransactionFee)
}
func TestGetMetricsAPIEmpty(t *testing.T) {
test.WipeDB(historyDB.DB())
_, _, err := historyDBWithACC.GetMetricsInternalAPI(0)
_, err := historyDBWithACC.GetMetricsInternalAPI(0)
assert.NoError(t, err)
}
@@ -1485,7 +1485,7 @@ func TestNodeInfo(t *testing.T) {
addr := ethCommon.HexToAddress("0x1234")
hash := ethCommon.HexToHash("0x5678")
stateAPI := &StateAPI{
NodePublicInfo: NodePublicInfo{
NodePublicConfig: NodePublicConfig{
ForgeDelay: 3.1,
},
Network: NetworkAPI{
@@ -1544,7 +1544,7 @@ func TestNodeInfo(t *testing.T) {
},
Metrics: MetricsAPI{
TransactionsPerBatch: 1.1,
TokenAccounts: 42,
TotalAccounts: 42,
},
Rollup: *NewRollupVariablesAPI(clientSetup.RollupVariables),
Auction: *NewAuctionVariablesAPI(clientSetup.AuctionVariables),

View File

@@ -4,7 +4,7 @@ import (
"time"
ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/hermeznetwork/hermez-node/api/apitypes"
"github.com/hermeznetwork/hermez-node/apitypes"
"github.com/hermeznetwork/hermez-node/common"
"github.com/hermeznetwork/tracerr"
"github.com/russross/meddler"
@@ -32,20 +32,18 @@ type NetworkAPI struct {
LastBatch *BatchAPI `json:"lastBatch"`
CurrentSlot int64 `json:"currentSlot"`
NextForgers []NextForgerAPI `json:"nextForgers"`
PendingL1Txs int `json:"pendingL1Transactions"`
}
// NodePublicInfo is the configuration and metrics of the node that is exposed via API
type NodePublicInfo struct {
// NodePublicConfig is the configuration of the node that is exposed via API
type NodePublicConfig struct {
// ForgeDelay in seconds
ForgeDelay float64 `json:"forgeDelay"`
// PoolLoad amount of transactions in the pool
PoolLoad int64 `json:"poolLoad"`
}
// StateAPI is an object representing the node and network state exposed via the API
type StateAPI struct {
NodePublicInfo NodePublicInfo `json:"node"`
// NodePublicConfig is the configuration of the node that is exposed via API
NodePublicConfig NodePublicConfig `json:"nodeConfig"`
Network NetworkAPI `json:"network"`
Metrics MetricsAPI `json:"metrics"`
Rollup RollupVariablesAPI `json:"rollup"`
@@ -65,7 +63,6 @@ type Constants struct {
type NodeConfig struct {
MaxPoolTxs uint32
MinFeeUSD float64
MaxFeeUSD float64
ForgeDelay float64
}

View File

@@ -6,7 +6,7 @@ import (
"time"
ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/hermeznetwork/hermez-node/api/apitypes"
"github.com/hermeznetwork/hermez-node/apitypes"
"github.com/hermeznetwork/hermez-node/common"
"github.com/iden3/go-iden3-crypto/babyjub"
"github.com/iden3/go-merkletree"
@@ -314,8 +314,8 @@ type MetricsAPI struct {
TransactionsPerBatch float64 `json:"transactionsPerBatch"`
BatchFrequency float64 `json:"batchFrequency"`
TransactionsPerSecond float64 `json:"transactionsPerSecond"`
TokenAccounts int64 `json:"tokenAccounts"`
Wallets int64 `json:"wallets"`
TotalAccounts int64 `json:"totalAccounts" meddler:"total_accounts"`
TotalBJJs int64 `json:"totalBJJs" meddler:"total_bjjs"`
AvgTransactionFee float64 `json:"avgTransactionFee"`
EstimatedTimeToForgeL1 float64 `json:"estimatedTimeToForgeL1" meddler:"estimated_time_to_forge_l1"`
}
@@ -355,8 +355,10 @@ type BucketUpdateAPI struct {
// Contract
type BucketParamsAPI struct {
CeilUSD *apitypes.BigIntStr `json:"ceilUSD"`
BlockStamp *apitypes.BigIntStr `json:"blockStamp"`
Withdrawals *apitypes.BigIntStr `json:"withdrawals"`
BlockWithdrawalRate *apitypes.BigIntStr `json:"blockWithdrawalRate"`
RateBlocks *apitypes.BigIntStr `json:"rateBlocks"`
RateWithdrawals *apitypes.BigIntStr `json:"rateWithdrawals"`
MaxWithdrawals *apitypes.BigIntStr `json:"maxWithdrawals"`
}
@@ -366,25 +368,28 @@ type RollupVariablesAPI struct {
FeeAddToken *apitypes.BigIntStr `json:"feeAddToken" meddler:"fee_add_token" validate:"required"`
ForgeL1L2BatchTimeout int64 `json:"forgeL1L2BatchTimeout" meddler:"forge_l1_timeout" validate:"required"`
WithdrawalDelay uint64 `json:"withdrawalDelay" meddler:"withdrawal_delay" validate:"required"`
Buckets [common.RollupConstNumBuckets]BucketParamsAPI `json:"buckets" meddler:"buckets,json"`
Buckets []BucketParamsAPI `json:"buckets" meddler:"buckets,json"`
SafeMode bool `json:"safeMode" meddler:"safe_mode"`
}
// NewRollupVariablesAPI creates a RollupVariablesAPI from common.RollupVariables
func NewRollupVariablesAPI(rollupVariables *common.RollupVariables) *RollupVariablesAPI {
buckets := make([]BucketParamsAPI, len(rollupVariables.Buckets))
rollupVars := RollupVariablesAPI{
EthBlockNum: rollupVariables.EthBlockNum,
FeeAddToken: apitypes.NewBigIntStr(rollupVariables.FeeAddToken),
ForgeL1L2BatchTimeout: rollupVariables.ForgeL1L2BatchTimeout,
WithdrawalDelay: rollupVariables.WithdrawalDelay,
SafeMode: rollupVariables.SafeMode,
Buckets: buckets,
}
for i, bucket := range rollupVariables.Buckets {
rollupVars.Buckets[i] = BucketParamsAPI{
CeilUSD: apitypes.NewBigIntStr(bucket.CeilUSD),
BlockStamp: apitypes.NewBigIntStr(bucket.BlockStamp),
Withdrawals: apitypes.NewBigIntStr(bucket.Withdrawals),
BlockWithdrawalRate: apitypes.NewBigIntStr(bucket.BlockWithdrawalRate),
RateBlocks: apitypes.NewBigIntStr(bucket.RateBlocks),
RateWithdrawals: apitypes.NewBigIntStr(bucket.RateWithdrawals),
MaxWithdrawals: apitypes.NewBigIntStr(bucket.MaxWithdrawals),
}
}

View File

@@ -62,10 +62,6 @@ func (l2db *L2DB) AddTxAPI(tx *PoolL2TxWrite) error {
return tracerr.Wrap(fmt.Errorf("tx.feeUSD (%v) < minFeeUSD (%v)",
feeUSD, l2db.minFeeUSD))
}
if feeUSD > l2db.maxFeeUSD {
return tracerr.Wrap(fmt.Errorf("tx.feeUSD (%v) > maxFeeUSD (%v)",
feeUSD, l2db.maxFeeUSD))
}
// Prepare insert SQL query argument parameters
namesPart, err := meddler.Default.ColumnsQuoted(tx, false)

View File

@@ -27,7 +27,6 @@ type L2DB struct {
ttl time.Duration
maxTxs uint32 // limit of txs that are accepted in the pool
minFeeUSD float64
maxFeeUSD float64
apiConnCon *db.APIConnectionController
}
@@ -39,7 +38,6 @@ func NewL2DB(
safetyPeriod common.BatchNum,
maxTxs uint32,
minFeeUSD float64,
maxFeeUSD float64,
TTL time.Duration,
apiConnCon *db.APIConnectionController,
) *L2DB {
@@ -50,7 +48,6 @@ func NewL2DB(
ttl: TTL,
maxTxs: maxTxs,
minFeeUSD: minFeeUSD,
maxFeeUSD: maxFeeUSD,
apiConnCon: apiConnCon,
}
}

View File

@@ -37,9 +37,9 @@ func TestMain(m *testing.M) {
if err != nil {
panic(err)
}
l2DB = NewL2DB(db, db, 10, 1000, 0.0, 1000.0, 24*time.Hour, nil)
l2DB = NewL2DB(db, db, 10, 1000, 0.0, 24*time.Hour, nil)
apiConnCon := dbUtils.NewAPIConnectionController(1, time.Second)
l2DBWithACC = NewL2DB(db, db, 10, 1000, 0.0, 1000.0, 24*time.Hour, apiConnCon)
l2DBWithACC = NewL2DB(db, db, 10, 1000, 0.0, 24*time.Hour, apiConnCon)
test.WipeDB(l2DB.DB())
historyDB = historydb.NewHistoryDB(db, db, nil)
// Run tests

View File

@@ -6,7 +6,7 @@ import (
"time"
ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/hermeznetwork/hermez-node/api/apitypes"
"github.com/hermeznetwork/hermez-node/apitypes"
"github.com/hermeznetwork/hermez-node/common"
"github.com/iden3/go-iden3-crypto/babyjub"
)

View File

@@ -677,22 +677,12 @@ CREATE TABLE node_info (
);
INSERT INTO node_info(item_id) VALUES (1); -- Always have a single row that we will update
CREATE VIEW account_state AS SELECT DISTINCT idx,
first_value(nonce) OVER w AS nonce,
first_value(balance) OVER w AS balance,
first_value(eth_block_num) OVER w AS eth_block_num,
first_value(batch_num) OVER w AS batch_num
FROM account_update
window w AS (partition by idx ORDER BY item_id desc);
-- +migrate Down
-- triggers
DROP TRIGGER IF EXISTS trigger_token_usd_update ON token;
DROP TRIGGER IF EXISTS trigger_set_tx ON tx;
DROP TRIGGER IF EXISTS trigger_forge_l1_txs ON batch;
DROP TRIGGER IF EXISTS trigger_set_pool_tx ON tx_pool;
-- drop views IF EXISTS
DROP VIEW IF EXISTS account_state;
-- functions
DROP FUNCTION IF EXISTS hez_idx;
DROP FUNCTION IF EXISTS set_token_usd_update;

View File

@@ -8,7 +8,7 @@ The first step is to clone the github repository where the contracts are located
While the prepared deployment is not found to master, branch in repository must be changed:
`git checkout feature/newDeploymentScript-eth-edu` (tested with commit `e6c5b7db8da2de1b9cc55e281c8d1dfa524b06f0`)
`git checkout feature/newDeploymentScript-eth-mik` (tested with commit `0eccd237dda102a4ad788a6e11f98361d39d0d9c`)
Now, install the dependencies:

View File

@@ -309,9 +309,12 @@ func (_HermezAuctionProtocol *HermezAuctionProtocolCaller) Coordinators(opts *bi
Forger common.Address
CoordinatorURL string
})
if err != nil {
return *outstruct, err
}
outstruct.Forger = out[0].(common.Address)
outstruct.CoordinatorURL = out[1].(string)
outstruct.Forger = *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
outstruct.CoordinatorURL = *abi.ConvertType(out[1], new(string)).(*string)
return *outstruct, err
@@ -884,12 +887,15 @@ func (_HermezAuctionProtocol *HermezAuctionProtocolCaller) Slots(opts *bind.Call
BidAmount *big.Int
ClosedMinBid *big.Int
})
if err != nil {
return *outstruct, err
}
outstruct.Bidder = out[0].(common.Address)
outstruct.Fulfilled = out[1].(bool)
outstruct.ForgerCommitment = out[2].(bool)
outstruct.BidAmount = out[3].(*big.Int)
outstruct.ClosedMinBid = out[4].(*big.Int)
outstruct.Bidder = *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
outstruct.Fulfilled = *abi.ConvertType(out[1], new(bool)).(*bool)
outstruct.ForgerCommitment = *abi.ConvertType(out[2], new(bool)).(*bool)
outstruct.BidAmount = *abi.ConvertType(out[3], new(*big.Int)).(**big.Int)
outstruct.ClosedMinBid = *abi.ConvertType(out[4], new(*big.Int)).(**big.Int)
return *outstruct, err

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"math/big"
"strconv"
"strings"
"github.com/ethereum/go-ethereum"
@@ -61,21 +60,12 @@ type RollupEventInitialize struct {
// RollupVariables returns the RollupVariables from the initialize event
func (ei *RollupEventInitialize) RollupVariables() *common.RollupVariables {
var buckets [common.RollupConstNumBuckets]common.BucketParams
for i := range buckets {
buckets[i] = common.BucketParams{
CeilUSD: big.NewInt(0),
Withdrawals: big.NewInt(0),
BlockWithdrawalRate: big.NewInt(0),
MaxWithdrawals: big.NewInt(0),
}
}
return &common.RollupVariables{
EthBlockNum: 0,
FeeAddToken: ei.FeeAddToken,
ForgeL1L2BatchTimeout: int64(ei.ForgeL1L2BatchTimeout),
WithdrawalDelay: ei.WithdrawalDelay,
Buckets: buckets,
Buckets: []common.BucketParams{},
SafeMode: false,
}
}
@@ -147,19 +137,20 @@ type RollupEventUpdateWithdrawalDelay struct {
// RollupUpdateBucketsParameters are the bucket parameters used in an update
type RollupUpdateBucketsParameters struct {
CeilUSD *big.Int
BlockStamp *big.Int
Withdrawals *big.Int
BlockWithdrawalRate *big.Int
RateBlocks *big.Int
RateWithdrawals *big.Int
MaxWithdrawals *big.Int
}
type rollupEventUpdateBucketsParametersAux struct {
ArrayBuckets [common.RollupConstNumBuckets][4]*big.Int
ArrayBuckets []*big.Int
}
// RollupEventUpdateBucketsParameters is an event of the Rollup Smart Contract
type RollupEventUpdateBucketsParameters struct {
// ArrayBuckets [common.RollupConstNumBuckets][4]*big.Int
ArrayBuckets [common.RollupConstNumBuckets]RollupUpdateBucketsParameters
ArrayBuckets []RollupUpdateBucketsParameters
SafeMode bool
}
@@ -493,8 +484,8 @@ func (c *RollupClient) RollupL1UserTxERC20ETH(fromBJJ babyjub.PublicKeyComp, fro
auth.Value = depositAmount
}
var permit []byte
return c.hermez.AddL1Transaction(auth, babyPubKey, fromIdxBig, uint16(depositAmountF),
uint16(amountF), tokenID, toIdxBig, permit)
return c.hermez.AddL1Transaction(auth, babyPubKey, fromIdxBig, big.NewInt(int64(depositAmountF)),
big.NewInt(int64(amountF)), tokenID, toIdxBig, permit)
},
); err != nil {
return nil, tracerr.Wrap(fmt.Errorf("Failed add L1 Tx ERC20/ETH: %w", err))
@@ -542,7 +533,7 @@ func (c *RollupClient) RollupL1UserTxERC20Permit(fromBJJ babyjub.PublicKeyComp,
signature, _ := c.client.ks.SignHash(*c.client.account, digest)
permit := createPermit(owner, spender, amount, deadline, digest, signature)
return c.hermez.AddL1Transaction(auth, babyPubKey, fromIdxBig,
uint16(depositAmountF), uint16(amountF), tokenID, toIdxBig, permit)
big.NewInt(int64(depositAmountF)), big.NewInt(int64(amountF)), tokenID, toIdxBig, permit)
},
); err != nil {
return nil, tracerr.Wrap(fmt.Errorf("Failed add L1 Tx ERC20Permit: %w", err))
@@ -604,18 +595,20 @@ func (c *RollupClient) RollupUpdateFeeAddToken(newFeeAddToken *big.Int) (tx *typ
// RollupUpdateBucketsParameters is the interface to call the smart contract function
func (c *RollupClient) RollupUpdateBucketsParameters(
arrayBuckets [common.RollupConstNumBuckets]RollupUpdateBucketsParameters,
arrayBuckets []RollupUpdateBucketsParameters,
) (tx *types.Transaction, err error) {
params := [common.RollupConstNumBuckets][4]*big.Int{}
for i, bucket := range arrayBuckets {
params[i][0] = bucket.CeilUSD
params[i][1] = bucket.Withdrawals
params[i][2] = bucket.BlockWithdrawalRate
params[i][3] = bucket.MaxWithdrawals
}
if tx, err = c.client.CallAuth(
12500000, //nolint:gomnd
func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
params := make([]*big.Int, len(arrayBuckets))
for i, bucket := range arrayBuckets {
params[i], err = c.hermez.PackBucket(c.opts,
bucket.CeilUSD, bucket.BlockStamp, bucket.Withdrawals,
bucket.RateBlocks, bucket.RateWithdrawals, bucket.MaxWithdrawals)
if err != nil {
return nil, tracerr.Wrap(fmt.Errorf("failed to pack bucket: %w", err))
}
}
return c.hermez.UpdateBucketsParameters(auth, params)
},
); err != nil {
@@ -739,7 +732,7 @@ var (
logHermezUpdateWithdrawalDelay = crypto.Keccak256Hash([]byte(
"UpdateWithdrawalDelay(uint64)"))
logHermezUpdateBucketsParameters = crypto.Keccak256Hash([]byte(
"UpdateBucketsParameters(uint256[4][" + strconv.Itoa(common.RollupConstNumBuckets) + "])"))
"UpdateBucketsParameters(uint256[])"))
logHermezUpdateTokenExchange = crypto.Keccak256Hash([]byte(
"UpdateTokenExchange(address[],uint64[])"))
logHermezSafeMode = crypto.Keccak256Hash([]byte(
@@ -906,11 +899,18 @@ func (c *RollupClient) RollupEventsByBlock(blockNum int64,
if err != nil {
return nil, tracerr.Wrap(err)
}
bucketsParameters.ArrayBuckets = make([]RollupUpdateBucketsParameters, len(bucketsParametersAux.ArrayBuckets))
for i, bucket := range bucketsParametersAux.ArrayBuckets {
bucketsParameters.ArrayBuckets[i].CeilUSD = bucket[0]
bucketsParameters.ArrayBuckets[i].Withdrawals = bucket[1]
bucketsParameters.ArrayBuckets[i].BlockWithdrawalRate = bucket[2]
bucketsParameters.ArrayBuckets[i].MaxWithdrawals = bucket[3]
bucket, err := c.hermez.UnpackBucket(c.opts, bucket)
if err != nil {
return nil, tracerr.Wrap(err)
}
bucketsParameters.ArrayBuckets[i].CeilUSD = bucket.CeilUSD
bucketsParameters.ArrayBuckets[i].BlockStamp = bucket.BlockStamp
bucketsParameters.ArrayBuckets[i].Withdrawals = bucket.Withdrawals
bucketsParameters.ArrayBuckets[i].RateBlocks = bucket.RateBlocks
bucketsParameters.ArrayBuckets[i].RateWithdrawals = bucket.RateWithdrawals
bucketsParameters.ArrayBuckets[i].MaxWithdrawals = bucket.MaxWithdrawals
}
rollupEvents.UpdateBucketsParameters =
append(rollupEvents.UpdateBucketsParameters, bucketsParameters)
@@ -932,8 +932,10 @@ func (c *RollupClient) RollupEventsByBlock(blockNum int64,
}
for i := range bucketsParameters.ArrayBuckets {
bucketsParameters.ArrayBuckets[i].CeilUSD = big.NewInt(0)
bucketsParameters.ArrayBuckets[i].BlockStamp = big.NewInt(0)
bucketsParameters.ArrayBuckets[i].Withdrawals = big.NewInt(0)
bucketsParameters.ArrayBuckets[i].BlockWithdrawalRate = big.NewInt(0)
bucketsParameters.ArrayBuckets[i].RateBlocks = big.NewInt(0)
bucketsParameters.ArrayBuckets[i].RateWithdrawals = big.NewInt(0)
bucketsParameters.ArrayBuckets[i].MaxWithdrawals = big.NewInt(0)
}
rollupEvents.UpdateBucketsParameters = append(rollupEvents.UpdateBucketsParameters,

View File

@@ -234,12 +234,15 @@ func TestRollupUpdateFeeAddToken(t *testing.T) {
}
func TestRollupUpdateBucketsParameters(t *testing.T) {
var bucketsParameters [common.RollupConstNumBuckets]RollupUpdateBucketsParameters
bucketsParameters := make([]RollupUpdateBucketsParameters, 5)
ceilUSD, _ := new(big.Int).SetString("10000000", 10)
for i := range bucketsParameters {
bucketsParameters[i].CeilUSD = big.NewInt(int64((i + 1) * 100))
bucketsParameters[i].CeilUSD = big.NewInt(0).Mul(ceilUSD, big.NewInt(int64(i+1)))
bucketsParameters[i].BlockStamp = big.NewInt(int64(0))
bucketsParameters[i].Withdrawals = big.NewInt(int64(i + 1))
bucketsParameters[i].BlockWithdrawalRate = big.NewInt(int64(i+1) * 100)
bucketsParameters[i].MaxWithdrawals = big.NewInt(int64(100000000000))
bucketsParameters[i].RateBlocks = big.NewInt(int64(i+1) * 4)
bucketsParameters[i].RateWithdrawals = big.NewInt(int64(3))
bucketsParameters[i].MaxWithdrawals = big.NewInt(int64(1215752192))
}
_, err := rollupClient.RollupUpdateBucketsParameters(bucketsParameters)
require.NoError(t, err)
@@ -248,7 +251,14 @@ func TestRollupUpdateBucketsParameters(t *testing.T) {
blockStampBucket = currentBlockNum
rollupEvents, err := rollupClient.RollupEventsByBlock(currentBlockNum, nil)
require.NoError(t, err)
assert.Equal(t, bucketsParameters, rollupEvents.UpdateBucketsParameters[0].ArrayBuckets)
for i := range bucketsParameters {
assert.Equal(t, 0, bucketsParameters[i].CeilUSD.Cmp(rollupEvents.UpdateBucketsParameters[0].ArrayBuckets[i].CeilUSD))
assert.Equal(t, 0, bucketsParameters[i].BlockStamp.Cmp(rollupEvents.UpdateBucketsParameters[0].ArrayBuckets[i].BlockStamp))
assert.Equal(t, 0, bucketsParameters[i].Withdrawals.Cmp(rollupEvents.UpdateBucketsParameters[0].ArrayBuckets[i].Withdrawals))
assert.Equal(t, 0, bucketsParameters[i].RateBlocks.Cmp(rollupEvents.UpdateBucketsParameters[0].ArrayBuckets[i].RateBlocks))
assert.Equal(t, 0, bucketsParameters[i].RateWithdrawals.Cmp(rollupEvents.UpdateBucketsParameters[0].ArrayBuckets[i].RateWithdrawals))
assert.Equal(t, 0, bucketsParameters[i].MaxWithdrawals.Cmp(rollupEvents.UpdateBucketsParameters[0].ArrayBuckets[i].MaxWithdrawals))
}
}
func TestRollupUpdateWithdrawalDelay(t *testing.T) {
@@ -1016,9 +1026,9 @@ func TestRollupWithdrawMerkleProof(t *testing.T) {
// Bucket 1
// Bucket[0].withdrawals = 1, Bucket[1].withdrawals = 2, ...
// Bucket[1].withdrawals - 1 = 1
assert.Equal(t, 1, rollupEvents.UpdateBucketWithdraw[0].NumBucket)
assert.Equal(t, blockStampBucket, rollupEvents.UpdateBucketWithdraw[0].BlockStamp)
assert.Equal(t, big.NewInt(1), rollupEvents.UpdateBucketWithdraw[0].Withdrawals)
assert.Equal(t, 0, rollupEvents.UpdateBucketWithdraw[0].NumBucket)
assert.Equal(t, int64(442), rollupEvents.UpdateBucketWithdraw[0].BlockStamp)
assert.Equal(t, big.NewInt(15), rollupEvents.UpdateBucketWithdraw[0].Withdrawals)
}
func TestRollupSafeMode(t *testing.T) {

View File

@@ -15,7 +15,6 @@ import (
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/hermeznetwork/hermez-node/api"
"github.com/hermeznetwork/hermez-node/api/stateapiupdater"
"github.com/hermeznetwork/hermez-node/batchbuilder"
"github.com/hermeznetwork/hermez-node/common"
"github.com/hermeznetwork/hermez-node/config"
@@ -28,6 +27,7 @@ import (
"github.com/hermeznetwork/hermez-node/log"
"github.com/hermeznetwork/hermez-node/priceupdater"
"github.com/hermeznetwork/hermez-node/prover"
"github.com/hermeznetwork/hermez-node/stateapiupdater"
"github.com/hermeznetwork/hermez-node/synchronizer"
"github.com/hermeznetwork/hermez-node/test/debugapi"
"github.com/hermeznetwork/hermez-node/txprocessor"
@@ -230,7 +230,6 @@ func NewNode(mode Mode, cfg *config.Node) (*Node, error) {
cfg.Coordinator.L2DB.SafetyPeriod,
cfg.Coordinator.L2DB.MaxTxs,
cfg.Coordinator.L2DB.MinFeeUSD,
cfg.Coordinator.L2DB.MaxFeeUSD,
cfg.Coordinator.L2DB.TTL.Duration,
apiConnCon,
)
@@ -254,7 +253,6 @@ func NewNode(mode Mode, cfg *config.Node) (*Node, error) {
hdbNodeCfg := historydb.NodeConfig{
MaxPoolTxs: cfg.Coordinator.L2DB.MaxTxs,
MinFeeUSD: cfg.Coordinator.L2DB.MinFeeUSD,
MaxFeeUSD: cfg.Coordinator.L2DB.MaxFeeUSD,
ForgeDelay: cfg.Coordinator.ForgeDelay.Duration.Seconds(),
}
if err := historyDB.SetNodeConfig(&hdbNodeCfg); err != nil {
@@ -524,7 +522,6 @@ func NewAPIServer(mode Mode, cfg *config.APIServer) (*APIServer, error) {
0,
cfg.Coordinator.L2DB.MaxTxs,
cfg.Coordinator.L2DB.MinFeeUSD,
cfg.Coordinator.L2DB.MaxFeeUSD,
0,
apiConnCon,
)

View File

@@ -27,7 +27,7 @@ func NewUpdater(hdb *historydb.HistoryDB, config *historydb.NodeConfig, vars *co
config: *config,
consts: *consts,
state: historydb.StateAPI{
NodePublicInfo: historydb.NodePublicInfo{
NodePublicConfig: historydb.NodePublicConfig{
ForgeDelay: config.ForgeDelay,
},
},
@@ -65,7 +65,7 @@ func (u *Updater) SetSCVars(vars *common.SCVariablesPtr) {
// UpdateRecommendedFee update Status.RecommendedFee information
func (u *Updater) UpdateRecommendedFee() error {
recommendedFee, err := u.hdb.GetRecommendedFee(u.config.MinFeeUSD, u.config.MaxFeeUSD)
recommendedFee, err := u.hdb.GetRecommendedFee(u.config.MinFeeUSD)
if err != nil {
return tracerr.Wrap(err)
}
@@ -84,13 +84,12 @@ func (u *Updater) UpdateMetrics() error {
return nil
}
lastBatchNum := lastBatch.BatchNum
metrics, poolLoad, err := u.hdb.GetMetricsInternalAPI(lastBatchNum)
metrics, err := u.hdb.GetMetricsInternalAPI(lastBatchNum)
if err != nil {
return tracerr.Wrap(err)
}
u.rw.Lock()
u.state.Metrics = *metrics
u.state.NodePublicInfo.PoolLoad = poolLoad
u.rw.Unlock()
return nil
}
@@ -146,17 +145,11 @@ func (u *Updater) UpdateNetworkInfo(
}
}
}
// Update pending L1s
pendingL1s, err := u.hdb.GetUnforgedL1UserTxsCount()
if err != nil {
return tracerr.Wrap(err)
}
u.state.Network.LastSyncBlock = lastSyncBlock.Num
u.state.Network.LastEthBlock = lastEthBlock.Num
u.state.Network.LastBatch = lastBatch
u.state.Network.CurrentSlot = currentSlot
u.state.Network.NextForgers = nextForgers
u.state.Network.PendingL1Txs = pendingL1s
u.rw.Unlock()
return nil
}

View File

@@ -1126,8 +1126,10 @@ func (s *Synchronizer) rollupSync(ethBlock *common.Block) (*common.RollupData, e
for i, bucket := range evt.ArrayBuckets {
s.vars.Rollup.Buckets[i] = common.BucketParams{
CeilUSD: bucket.CeilUSD,
BlockStamp: bucket.BlockStamp,
Withdrawals: bucket.Withdrawals,
BlockWithdrawalRate: bucket.BlockWithdrawalRate,
RateBlocks: bucket.RateBlocks,
RateWithdrawals: bucket.RateWithdrawals,
MaxWithdrawals: bucket.MaxWithdrawals,
}
}

View File

@@ -323,7 +323,7 @@ func newTestModules(t *testing.T) (*statedb.StateDB, *historydb.HistoryDB, *l2db
test.WipeDB(historyDB.DB())
// Init L2 DB
l2DB := l2db.NewL2DB(db, db, 10, 100, 0.0, 1000.0, 24*time.Hour, nil)
l2DB := l2db.NewL2DB(db, db, 10, 100, 0.0, 24*time.Hour, nil)
return stateDB, historyDB, l2DB
}

View File

@@ -301,20 +301,11 @@ func NewClientSetupExample() *ClientSetup {
HermezAuctionContract: ethCommon.HexToAddress("0x8E442975805fb1908f43050c9C1A522cB0e28D7b"),
WithdrawDelayerContract: ethCommon.HexToAddress("0x5CB7979cBdbf65719BEE92e4D15b7b7Ed3D79114"),
}
var buckets [common.RollupConstNumBuckets]common.BucketParams
for i := range buckets {
buckets[i] = common.BucketParams{
CeilUSD: big.NewInt(0),
Withdrawals: big.NewInt(0),
BlockWithdrawalRate: big.NewInt(0),
MaxWithdrawals: big.NewInt(0),
}
}
rollupVariables := &common.RollupVariables{
FeeAddToken: big.NewInt(11),
ForgeL1L2BatchTimeout: 10,
WithdrawalDelay: 80,
Buckets: buckets,
Buckets: []common.BucketParams{},
}
auctionConstants := &common.AuctionConstants{
BlocksPerSlot: 40,

View File

@@ -77,7 +77,7 @@ func initTxSelector(t *testing.T, chainID uint16, hermezContractAddr ethCommon.A
pass := os.Getenv("POSTGRES_PASS")
db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
require.NoError(t, err)
l2DB := l2db.NewL2DB(db, db, 10, 100, 0.0, 1000.0, 24*time.Hour, nil)
l2DB := l2db.NewL2DB(db, db, 10, 100, 0.0, 24*time.Hour, nil)
dir, err := ioutil.TempDir("", "tmpSyncDB")
require.NoError(t, err)

View File

@@ -164,18 +164,10 @@ func (txsel *TxSelector) getL1L2TxSelection(selectionConfig txprocessor.Config,
// implementation that can be used ASAP.
// Steps of this method:
// - ProcessL1Txs (User txs)
// - getPendingTxs (forgable directly with current state & not forgable
// yet)
// - split between l2TxsForgable & l2TxsNonForgable, where:
// - l2TxsForgable are the txs that are directly forgable with the
// current state
// - l2TxsNonForgable are the txs that are not directly forgable
// with the current state, but that may be forgable once the
// l2TxsForgable ones are processed
// - for l2TxsForgable, and if needed, for l2TxsNonForgable:
// - sort by Fee & Nonce
// - loop over l2Txs (txsel.processL2Txs)
// - getPendingTxs
// - ProcessL1Txs
// - getProfitable (sort by fee & nonce)
// - loop over l2Txs
// - Fill tx.TokenID tx.Nonce
// - Check enough Balance on sender
// - Check Nonce
@@ -188,9 +180,14 @@ func (txsel *TxSelector) getL1L2TxSelection(selectionConfig txprocessor.Config,
// - Distribute AccumulatedFees to CoordIdxs
// - MakeCheckpoint
// get pending l2-tx from tx-pool
l2TxsRaw, err := txsel.l2db.GetPendingTxs()
if err != nil {
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
txselStateDB := txsel.localAccountsDB.StateDB
tp := txprocessor.NewTxProcessor(txselStateDB, selectionConfig)
tp.AccumulatedFees = make(map[common.Idx]*big.Int)
// Process L1UserTxs
for i := 0; i < len(l1UserTxs); i++ {
@@ -201,139 +198,21 @@ func (txsel *TxSelector) getL1L2TxSelection(selectionConfig txprocessor.Config,
}
}
l2TxsFromDB, err := txsel.l2db.GetPendingTxs()
if err != nil {
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
l2TxsForgable, l2TxsNonForgable := splitL2ForgableAndNonForgable(tp, l2TxsFromDB)
// in case that length of l2TxsForgable is 0, no need to continue, there
// is no L2Txs to forge at all
if len(l2TxsForgable) == 0 {
var discardedL2Txs []common.PoolL2Tx
for i := 0; i < len(l2TxsNonForgable); i++ {
l2TxsNonForgable[i].Info =
"Tx not selected due impossibility to be forged with the current state"
discardedL2Txs = append(discardedL2Txs, l2TxsNonForgable[i])
}
err = tp.StateDB().MakeCheckpoint()
if err != nil {
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
metricSelectedL1UserTxs.Set(float64(len(l1UserTxs)))
metricSelectedL1CoordinatorTxs.Set(0)
metricSelectedL2Txs.Set(0)
metricDiscardedL2Txs.Set(float64(len(discardedL2Txs)))
return nil, nil, l1UserTxs, nil, nil, discardedL2Txs, nil
}
var accAuths [][]byte
var l1CoordinatorTxs []common.L1Tx
var validTxs, discardedL2Txs []common.PoolL2Tx
l2TxsForgable = sortL2Txs(l2TxsForgable)
accAuths, l1CoordinatorTxs, validTxs, discardedL2Txs, err =
txsel.processL2Txs(tp, selectionConfig, len(l1UserTxs),
l2TxsForgable, validTxs, discardedL2Txs)
if err != nil {
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
// if there is space for more txs get also the NonForgable txs, that may
// be unblocked once the Forgable ones are processed
if len(validTxs) < int(selectionConfig.MaxTx)-(len(l1UserTxs)+len(l1CoordinatorTxs)) {
l2TxsNonForgable = sortL2Txs(l2TxsNonForgable)
var accAuths2 [][]byte
var l1CoordinatorTxs2 []common.L1Tx
accAuths2, l1CoordinatorTxs2, validTxs, discardedL2Txs, err =
txsel.processL2Txs(tp, selectionConfig,
len(l1UserTxs)+len(l1CoordinatorTxs), l2TxsNonForgable,
validTxs, discardedL2Txs)
if err != nil {
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
accAuths = append(accAuths, accAuths2...)
l1CoordinatorTxs = append(l1CoordinatorTxs, l1CoordinatorTxs2...)
} else {
// if there is no space for NonForgable txs, put them at the
// discardedL2Txs array
for i := 0; i < len(l2TxsNonForgable); i++ {
l2TxsNonForgable[i].Info =
"Tx not selected due not available slots for L2Txs"
discardedL2Txs = append(discardedL2Txs, l2TxsNonForgable[i])
}
}
// get CoordIdxsMap for the TokenIDs
coordIdxsMap := make(map[common.TokenID]common.Idx)
for i := 0; i < len(validTxs); i++ {
// get TokenID from tx.Sender
accSender, err := tp.StateDB().GetAccount(validTxs[i].FromIdx)
if err != nil {
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
tokenID := accSender.TokenID
coordIdx, err := txsel.getCoordIdx(tokenID)
if err != nil {
// if err is db.ErrNotFound, should not happen, as all
// the validTxs.TokenID should have a CoordinatorIdx
// created in the DB at this point
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
coordIdxsMap[tokenID] = coordIdx
}
var coordIdxs []common.Idx
for _, idx := range coordIdxsMap {
coordIdxs = append(coordIdxs, idx)
}
// sort CoordIdxs
sort.SliceStable(coordIdxs, func(i, j int) bool {
return coordIdxs[i] < coordIdxs[j]
})
// distribute the AccumulatedFees from the processed L2Txs into the
// Coordinator Idxs
for idx, accumulatedFee := range tp.AccumulatedFees {
cmp := accumulatedFee.Cmp(big.NewInt(0))
if cmp == 1 { // accumulatedFee>0
// send the fee to the Idx of the Coordinator for the TokenID
accCoord, err := txsel.localAccountsDB.GetAccount(idx)
if err != nil {
log.Errorw("Can not distribute accumulated fees to coordinator "+
"account: No coord Idx to receive fee", "idx", idx)
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
accCoord.Balance = new(big.Int).Add(accCoord.Balance, accumulatedFee)
_, err = txsel.localAccountsDB.UpdateAccount(idx, accCoord)
if err != nil {
log.Error(err)
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
}
}
err = tp.StateDB().MakeCheckpoint()
if err != nil {
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
metricSelectedL1UserTxs.Set(float64(len(l1UserTxs)))
metricSelectedL1CoordinatorTxs.Set(float64(len(l1CoordinatorTxs)))
metricSelectedL2Txs.Set(float64(len(validTxs)))
metricDiscardedL2Txs.Set(float64(len(discardedL2Txs)))
return coordIdxs, accAuths, l1UserTxs, l1CoordinatorTxs, validTxs, discardedL2Txs, nil
}
func (txsel *TxSelector) processL2Txs(tp *txprocessor.TxProcessor,
selectionConfig txprocessor.Config, nL1Txs int, l2Txs, validTxs, discardedL2Txs []common.PoolL2Tx) (
[][]byte, []common.L1Tx, []common.PoolL2Tx, []common.PoolL2Tx, error) {
var l1CoordinatorTxs []common.L1Tx
positionL1 := nL1Txs
positionL1 := len(l1UserTxs)
var accAuths [][]byte
// Sort l2TxsRaw (cropping at MaxTx at this point).
// discardedL2Txs contains an array of the L2Txs that have not been
// selected in this Batch.
l2Txs, discardedL2Txs := txsel.getL2Profitable(l2TxsRaw, selectionConfig.MaxTx-uint32(len(l1UserTxs)))
for i := range discardedL2Txs {
discardedL2Txs[i].Info =
"Tx not selected due to low absolute fee (does not fit inside the profitable set)"
}
var validTxs []common.PoolL2Tx
tp.AccumulatedFees = make(map[common.Idx]*big.Int)
// Iterate over l2Txs
// - check Nonces
// - check enough Balance for the Amount+Fee
@@ -342,22 +221,20 @@ func (txsel *TxSelector) processL2Txs(tp *txprocessor.TxProcessor,
// - put the valid txs into validTxs array
for i := 0; i < len(l2Txs); i++ {
// Check if there is space for more L2Txs in the selection
maxL2Txs := int(selectionConfig.MaxTx) - nL1Txs - len(l1CoordinatorTxs)
maxL2Txs := int(selectionConfig.MaxTx) -
len(l1UserTxs) - len(l1CoordinatorTxs)
if len(validTxs) >= maxL2Txs {
// no more available slots for L2Txs, so mark this tx
// but also the rest of remaining txs as discarded
for j := i; j < len(l2Txs); j++ {
l2Txs[j].Info =
// no more available slots for L2Txs
l2Txs[i].Info =
"Tx not selected due not available slots for L2Txs"
discardedL2Txs = append(discardedL2Txs, l2Txs[j])
}
break
discardedL2Txs = append(discardedL2Txs, l2Txs[i])
continue
}
// get Nonce & TokenID from the Account by l2Tx.FromIdx
accSender, err := tp.StateDB().GetAccount(l2Txs[i].FromIdx)
if err != nil {
return nil, nil, nil, nil, tracerr.Wrap(err)
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
l2Txs[i].TokenID = accSender.TokenID
@@ -395,13 +272,13 @@ func (txsel *TxSelector) processL2Txs(tp *txprocessor.TxProcessor,
txsel.coordAccountForTokenID(l1CoordinatorTxs,
accSender.TokenID, positionL1)
if err != nil {
return nil, nil, nil, nil, tracerr.Wrap(err)
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
if newL1CoordTx != nil {
// if there is no space for the L1CoordinatorTx as MaxL1Tx, or no space
// for L1CoordinatorTx + L2Tx as MaxTx, discard the L2Tx
if len(l1CoordinatorTxs) >= int(selectionConfig.MaxL1Tx)-nL1Txs ||
len(l1CoordinatorTxs)+1 >= int(selectionConfig.MaxTx)-nL1Txs {
if len(l1CoordinatorTxs) >= int(selectionConfig.MaxL1Tx)-len(l1UserTxs) ||
len(l1CoordinatorTxs)+1 >= int(selectionConfig.MaxTx)-len(l1UserTxs) {
// discard L2Tx, and update Info parameter of
// the tx, and add it to the discardedTxs array
l2Txs[i].Info = "Tx not selected because the L2Tx depends on a " +
@@ -417,7 +294,7 @@ func (txsel *TxSelector) processL2Txs(tp *txprocessor.TxProcessor,
// process the L1CoordTx
_, _, _, _, err := tp.ProcessL1Tx(nil, newL1CoordTx)
if err != nil {
return nil, nil, nil, nil, tracerr.Wrap(err)
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
}
@@ -432,7 +309,7 @@ func (txsel *TxSelector) processL2Txs(tp *txprocessor.TxProcessor,
if l2Txs[i].ToIdx == 0 { // ToEthAddr/ToBJJ case
validL2Tx, l1CoordinatorTx, accAuth, err :=
txsel.processTxToEthAddrBJJ(validTxs, selectionConfig,
nL1Txs, l1CoordinatorTxs, positionL1, l2Txs[i])
len(l1UserTxs), l1CoordinatorTxs, positionL1, l2Txs[i])
if err != nil {
log.Debugw("txsel.processTxToEthAddrBJJ", "err", err)
// Discard L2Tx, and update Info parameter of
@@ -444,8 +321,8 @@ func (txsel *TxSelector) processL2Txs(tp *txprocessor.TxProcessor,
}
// if there is no space for the L1CoordinatorTx as MaxL1Tx, or no space
// for L1CoordinatorTx + L2Tx as MaxTx, discard the L2Tx
if len(l1CoordinatorTxs) >= int(selectionConfig.MaxL1Tx)-nL1Txs ||
len(l1CoordinatorTxs)+1 >= int(selectionConfig.MaxTx)-nL1Txs {
if len(l1CoordinatorTxs) >= int(selectionConfig.MaxL1Tx)-len(l1UserTxs) ||
len(l1CoordinatorTxs)+1 >= int(selectionConfig.MaxTx)-len(l1UserTxs) {
// discard L2Tx, and update Info parameter of
// the tx, and add it to the discardedTxs array
l2Txs[i].Info = "Tx not selected because the L2Tx depends on a " +
@@ -474,7 +351,7 @@ func (txsel *TxSelector) processL2Txs(tp *txprocessor.TxProcessor,
// process the L1CoordTx
_, _, _, _, err := tp.ProcessL1Tx(nil, l1CoordinatorTx)
if err != nil {
return nil, nil, nil, nil, tracerr.Wrap(err)
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
}
if validL2Tx == nil {
@@ -536,7 +413,7 @@ func (txsel *TxSelector) processL2Txs(tp *txprocessor.TxProcessor,
// if err is db.ErrNotFound, should not happen, as all
// the validTxs.TokenID should have a CoordinatorIdx
// created in the DB at this point
return nil, nil, nil, nil,
return nil, nil, nil, nil, nil, nil,
tracerr.Wrap(fmt.Errorf("Could not get CoordIdx for TokenID=%d, "+
"due: %s", tokenID, err))
}
@@ -562,7 +439,68 @@ func (txsel *TxSelector) processL2Txs(tp *txprocessor.TxProcessor,
validTxs = append(validTxs, l2Txs[i])
} // after this loop, no checks to discard txs should be done
return accAuths, l1CoordinatorTxs, validTxs, discardedL2Txs, nil
// get CoordIdxsMap for the TokenIDs
coordIdxsMap := make(map[common.TokenID]common.Idx)
for i := 0; i < len(validTxs); i++ {
// get TokenID from tx.Sender
accSender, err := tp.StateDB().GetAccount(validTxs[i].FromIdx)
if err != nil {
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
tokenID := accSender.TokenID
coordIdx, err := txsel.getCoordIdx(tokenID)
if err != nil {
// if err is db.ErrNotFound, should not happen, as all
// the validTxs.TokenID should have a CoordinatorIdx
// created in the DB at this point
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
coordIdxsMap[tokenID] = coordIdx
}
var coordIdxs []common.Idx
for _, idx := range coordIdxsMap {
coordIdxs = append(coordIdxs, idx)
}
// sort CoordIdxs
sort.SliceStable(coordIdxs, func(i, j int) bool {
return coordIdxs[i] < coordIdxs[j]
})
// distribute the AccumulatedFees from the processed L2Txs into the
// Coordinator Idxs
for idx, accumulatedFee := range tp.AccumulatedFees {
cmp := accumulatedFee.Cmp(big.NewInt(0))
if cmp == 1 { // accumulatedFee>0
// send the fee to the Idx of the Coordinator for the TokenID
accCoord, err := txsel.localAccountsDB.GetAccount(idx)
if err != nil {
log.Errorw("Can not distribute accumulated fees to coordinator "+
"account: No coord Idx to receive fee", "idx", idx)
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
accCoord.Balance = new(big.Int).Add(accCoord.Balance, accumulatedFee)
_, err = txsel.localAccountsDB.UpdateAccount(idx, accCoord)
if err != nil {
log.Error(err)
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
}
}
err = tp.StateDB().MakeCheckpoint()
if err != nil {
return nil, nil, nil, nil, nil, nil, tracerr.Wrap(err)
}
metricSelectedL1CoordinatorTxs.Set(float64(len(l1CoordinatorTxs)))
metricSelectedL1UserTxs.Set(float64(len(l1UserTxs)))
metricSelectedL2Txs.Set(float64(len(validTxs)))
metricDiscardedL2Txs.Set(float64(len(discardedL2Txs)))
// return coordIdxs, accAuths, l1UserTxs, l1CoordinatorTxs, validTxs, discardedL2Txs, nil
return coordIdxs, accAuths, l1UserTxs, l1CoordinatorTxs, validTxs, discardedL2Txs, nil
}
// processTxsToEthAddrBJJ process the common.PoolL2Tx in the case where
@@ -698,14 +636,26 @@ func checkAlreadyPendingToCreate(l1CoordinatorTxs []common.L1Tx, tokenID common.
return false
}
// sortL2Txs sorts the PoolL2Txs by AbsoluteFee and then by Nonce
func sortL2Txs(l2Txs []common.PoolL2Tx) []common.PoolL2Tx {
// getL2Profitable returns the profitable selection of L2Txssorted by Nonce
func (txsel *TxSelector) getL2Profitable(l2Txs []common.PoolL2Tx, max uint32) ([]common.PoolL2Tx,
[]common.PoolL2Tx) {
// First sort by nonce so that txs from the same account are sorted so
// that they could be applied in succession.
sort.Slice(l2Txs, func(i, j int) bool {
return l2Txs[i].Nonce < l2Txs[j].Nonce
})
// Sort by absolute fee with SliceStable, so that txs with same
// AbsoluteFee are not rearranged and nonce order is kept in such case
sort.SliceStable(l2Txs, func(i, j int) bool {
return l2Txs[i].AbsoluteFee > l2Txs[j].AbsoluteFee
})
discardedL2Txs := []common.PoolL2Tx{}
if len(l2Txs) > int(max) {
discardedL2Txs = l2Txs[max:]
l2Txs = l2Txs[:max]
}
// sort l2Txs by Nonce. This can be done in many different ways, what
// is needed is to output the l2Txs where the Nonce of l2Txs for each
// Account is sorted, but the l2Txs can not be grouped by sender Account
@@ -715,29 +665,5 @@ func sortL2Txs(l2Txs []common.PoolL2Tx) []common.PoolL2Tx {
return l2Txs[i].Nonce < l2Txs[j].Nonce
})
return l2Txs
}
func splitL2ForgableAndNonForgable(tp *txprocessor.TxProcessor,
l2Txs []common.PoolL2Tx) ([]common.PoolL2Tx, []common.PoolL2Tx) {
var l2TxsForgable, l2TxsNonForgable []common.PoolL2Tx
for i := 0; i < len(l2Txs); i++ {
accSender, err := tp.StateDB().GetAccount(l2Txs[i].FromIdx)
if err != nil {
l2TxsNonForgable = append(l2TxsNonForgable, l2Txs[i])
continue
}
if l2Txs[i].Nonce != accSender.Nonce {
l2TxsNonForgable = append(l2TxsNonForgable, l2Txs[i])
continue
}
enoughBalance, _, _ := tp.CheckEnoughBalance(l2Txs[i])
if !enoughBalance {
l2TxsNonForgable = append(l2TxsNonForgable, l2Txs[i])
continue
}
l2TxsForgable = append(l2TxsForgable, l2Txs[i])
}
return l2TxsForgable, l2TxsNonForgable
return l2Txs, discardedL2Txs
}

View File

@@ -26,13 +26,11 @@ import (
)
func initTest(t *testing.T, chainID uint16, hermezContractAddr ethCommon.Address,
coordUser *til.User) (*TxSelector, *historydb.HistoryDB) {
coordUser *til.User) *TxSelector {
pass := os.Getenv("POSTGRES_PASS")
db, err := dbUtils.InitSQLDB(5432, "localhost", "hermez", pass, "hermez")
require.NoError(t, err)
l2DB := l2db.NewL2DB(db, db, 10, 100, 0.0, 1000.0, 24*time.Hour, nil)
historyDB := historydb.NewHistoryDB(db, db, nil)
l2DB := l2db.NewL2DB(db, db, 10, 100, 0.0, 24*time.Hour, nil)
dir, err := ioutil.TempDir("", "tmpdb")
require.NoError(t, err)
@@ -67,7 +65,7 @@ func initTest(t *testing.T, chainID uint16, hermezContractAddr ethCommon.Address
test.WipeDB(txsel.l2db.DB())
return txsel, historyDB
return txsel
}
func addAccCreationAuth(t *testing.T, tc *til.Context, txsel *TxSelector, chainID uint16,
@@ -159,7 +157,7 @@ func TestGetL2TxSelectionMinimumFlow0(t *testing.T) {
assert.NoError(t, err)
hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
txsel, _ := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
txsel := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
// restart nonces of TilContext, as will be set by generating directly
// the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
@@ -419,7 +417,7 @@ func TestPoolL2TxsWithoutEnoughBalance(t *testing.T) {
assert.NoError(t, err)
hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
txsel, _ := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
txsel := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
// restart nonces of TilContext, as will be set by generating directly
// the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
@@ -472,6 +470,11 @@ func TestPoolL2TxsWithoutEnoughBalance(t *testing.T) {
tc.RestartNonces()
// batch3
// NOTE: this batch will result with 1 L2Tx, as the PoolExit tx is not
// possible, as the PoolTransferToEthAddr is not processed yet when
// checking availability of PoolExit. This, in a near-future iteration
// of the TxSelector will return the 2 transactions as valid and
// selected, as the TxSelector will handle this kind of combinations.
batchPoolL2 = `
Type: PoolL2
PoolTransferToEthAddr(0) A-B: 50 (126)`
@@ -485,11 +488,11 @@ func TestPoolL2TxsWithoutEnoughBalance(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, 0, len(oL1UserTxs))
assert.Equal(t, 0, len(oL1CoordTxs))
assert.Equal(t, 2, len(oL2Txs))
assert.Equal(t, 1, len(discardedL2Txs))
assert.Equal(t, 1, len(oL2Txs)) // see 'NOTE' at the beginning of 'batch3' of this test
assert.Equal(t, 2, len(discardedL2Txs))
assert.Equal(t, expectedTxID2, oL2Txs[0].TxID.String())
assert.Equal(t, expectedTxID1, oL2Txs[1].TxID.String())
assert.Equal(t, expectedTxID0, discardedL2Txs[0].TxID.String())
assert.Equal(t, expectedTxID1, discardedL2Txs[1].TxID.String())
assert.Equal(t, common.TxTypeTransferToEthAddr, oL2Txs[0].Type)
err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
txsel.localAccountsDB.CurrentBatch())
@@ -504,8 +507,12 @@ func TestPoolL2TxsWithoutEnoughBalance(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, 0, len(oL1UserTxs))
assert.Equal(t, 0, len(oL1CoordTxs))
assert.Equal(t, 0, len(oL2Txs))
assert.Equal(t, 1, len(oL2Txs))
assert.Equal(t, 1, len(discardedL2Txs))
// the Exit that was not accepted at the batch2
assert.Equal(t, expectedTxID1, oL2Txs[0].TxID.String())
assert.Equal(t, expectedTxID0, discardedL2Txs[0].TxID.String())
assert.Equal(t, common.TxTypeExit, oL2Txs[0].Type)
err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
txsel.localAccountsDB.CurrentBatch())
require.NoError(t, err)
@@ -532,7 +539,7 @@ func TestTransferToBjj(t *testing.T) {
assert.NoError(t, err)
hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
txsel, _ := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
txsel := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
// restart nonces of TilContext, as will be set by generating directly
// the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
@@ -663,7 +670,7 @@ func TestTransferManyFromSameAccount(t *testing.T) {
assert.NoError(t, err)
hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
txsel, _ := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
txsel := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
// restart nonces of TilContext, as will be set by generating directly
// the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
@@ -745,7 +752,7 @@ func TestPoolL2TxInvalidNonces(t *testing.T) {
assert.NoError(t, err)
hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
txsel, _ := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
txsel := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
// restart nonces of TilContext, as will be set by generating directly
// the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
@@ -858,7 +865,7 @@ func TestProcessL2Selection(t *testing.T) {
assert.NoError(t, err)
hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
txsel, _ := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
txsel := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
// restart nonces of TilContext, as will be set by generating directly
// the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
@@ -914,127 +921,3 @@ func TestProcessL2Selection(t *testing.T) {
txsel.localAccountsDB.CurrentBatch())
require.NoError(t, err)
}
func TestValidTxsWithLowFeeAndInvalidTxsWithHighFee(t *testing.T) {
// This test recreates the case where there are
set := `
Type: Blockchain
CreateAccountDeposit(0) Coord: 0
CreateAccountDeposit(0) A: 100
CreateAccountDeposit(0) B: 0
> batchL1 // Batch1: freeze L1User{3}
> batchL1 // Batch2: forge L1User{3}
> block
`
chainID := uint16(0)
tc := til.NewContext(chainID, common.RollupConstMaxL1UserTx)
tilCfgExtra := til.ConfigExtra{
BootCoordAddr: ethCommon.HexToAddress("0xE39fEc6224708f0772D2A74fd3f9055A90E0A9f2"),
CoordUser: "Coord",
}
blocks, err := tc.GenerateBlocks(set)
require.NoError(t, err)
err = tc.FillBlocksExtra(blocks, &tilCfgExtra)
require.NoError(t, err)
err = tc.FillBlocksForgedL1UserTxs(blocks)
require.NoError(t, err)
hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
txsel, historyDB := initTest(t, chainID, hermezContractAddr, tc.Users["Coord"])
// Insert blocks into DB
for i := range blocks {
err = historyDB.AddBlockSCData(&blocks[i])
assert.NoError(t, err)
}
err = historyDB.UpdateTokenValue(common.EmptyAddr, 1000)
require.NoError(t, err)
// restart nonces of TilContext, as will be set by generating directly
// the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
tc.RestartNonces()
tpc := txprocessor.Config{
NLevels: 16,
MaxFeeTx: 5,
MaxTx: 5,
MaxL1Tx: 3,
ChainID: chainID,
}
// batch1 to freeze L1UserTxs
l1UserTxs := []common.L1Tx{}
_, _, _, _, _, _, err = txsel.GetL1L2TxSelection(tpc, l1UserTxs)
require.NoError(t, err)
// batch 2 to crate the accounts (from L1UserTxs)
l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[1].Batch.ForgeL1TxsNum])
// select L1 & L2 txs
_, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err :=
txsel.GetL1L2TxSelection(tpc, l1UserTxs)
require.NoError(t, err)
require.Equal(t, 3, len(oL1UserTxs))
require.Equal(t, 0, len(oL1CoordTxs))
require.Equal(t, 0, len(oL2Txs))
require.Equal(t, 0, len(discardedL2Txs))
require.Equal(t, 0, len(accAuths))
err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
txsel.localAccountsDB.CurrentBatch())
require.NoError(t, err)
// batch 3. The A-B txs have lower fee, but are the only ones possible
// with the current Accounts Balances, as the B-A tx of amount 40 will
// not be included as will be processed first when there is not enough
// balance at B (processed first as the TxSelector sorts by Fee and then
// by Nonce).
batchPoolL2 := `
Type: PoolL2
PoolTransfer(0) B-A: 40 (130) // B-A txs are only possible once A-B txs are processed
PoolTransfer(0) B-A: 1 (126)
PoolTransfer(0) B-A: 1 (126)
PoolTransfer(0) B-A: 1 (126)
PoolTransfer(0) B-A: 1 (126)
PoolTransfer(0) B-A: 1 (126)
PoolTransfer(0) B-A: 1 (126)
PoolTransfer(0) B-A: 1 (126)
PoolTransfer(0) A-B: 20 (20)
PoolTransfer(0) A-B: 25 (150)
PoolTransfer(0) A-B: 20 (20)
`
poolL2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
require.NoError(t, err)
require.Equal(t, 11, len(poolL2Txs))
// add the PoolL2Txs to the l2DB
addL2Txs(t, txsel, poolL2Txs)
l1UserTxs = []common.L1Tx{}
_, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err =
txsel.GetL1L2TxSelection(tpc, l1UserTxs)
require.NoError(t, err)
require.Equal(t, 0, len(oL1UserTxs))
require.Equal(t, 0, len(oL1CoordTxs))
require.Equal(t, 3, len(oL2Txs)) // the 3 txs A-B
require.Equal(t, 8, len(discardedL2Txs)) // the 8 txs B-A
require.Equal(t, 0, len(accAuths))
err = txsel.l2db.StartForging(common.TxIDsFromPoolL2Txs(oL2Txs),
txsel.localAccountsDB.CurrentBatch())
require.NoError(t, err)
// batch 4. In this Batch, account B has enough balance to send the txs
_, accAuths, oL1UserTxs, oL1CoordTxs, oL2Txs, discardedL2Txs, err =
txsel.GetL1L2TxSelection(tpc, l1UserTxs)
require.NoError(t, err)
require.Equal(t, 0, len(oL1UserTxs))
require.Equal(t, 0, len(oL1CoordTxs))
require.Equal(t, 5, len(oL2Txs))
require.Equal(t, 3, len(discardedL2Txs))
require.Equal(t, 0, len(accAuths))
}