mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 03:16:45 +01:00
Feature/null refactor (#173)
* WIP: rebase * Make nullable fields use pointers
This commit is contained in:
@@ -223,7 +223,7 @@ func TestMain(m *testing.M) {
|
||||
panic("Token not found")
|
||||
}
|
||||
} else {
|
||||
token = test.GetToken(genericTx.FromIdx, accs, tokens)
|
||||
token = test.GetToken(*genericTx.FromIdx, accs, tokens)
|
||||
}
|
||||
var usd, loadUSD, feeUSD *float64
|
||||
if token.USD != nil {
|
||||
@@ -244,7 +244,7 @@ func TestMain(m *testing.M) {
|
||||
Type: genericTx.Type,
|
||||
Position: genericTx.Position,
|
||||
FromIdx: genericTx.FromIdx,
|
||||
ToIdx: genericTx.ToIdx,
|
||||
ToIdx: *genericTx.ToIdx,
|
||||
Amount: genericTx.Amount,
|
||||
AmountFloat: genericTx.AmountFloat,
|
||||
HistoricUSD: usd,
|
||||
@@ -361,7 +361,7 @@ func TestGetHistoryTxs(t *testing.T) {
|
||||
// idx
|
||||
fetchedTxs = historyTxAPIs{}
|
||||
limit = 4
|
||||
idx := tc.allTxs[0].FromIdx
|
||||
idx := tc.allTxs[0].ToIdx
|
||||
path = fmt.Sprintf(
|
||||
"%s?accountIndex=%s&limit=%d&offset=",
|
||||
endpoint, idx, limit,
|
||||
@@ -370,7 +370,8 @@ func TestGetHistoryTxs(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
idxTxs := historyTxAPIs{}
|
||||
for i := 0; i < len(tc.allTxs); i++ {
|
||||
if tc.allTxs[i].FromIdx[6:] == idx[6:] {
|
||||
if (tc.allTxs[i].FromIdx != nil && (*tc.allTxs[i].FromIdx)[6:] == idx[6:]) ||
|
||||
tc.allTxs[i].ToIdx[6:] == idx[6:] {
|
||||
idxTxs = append(idxTxs, tc.allTxs[i])
|
||||
}
|
||||
}
|
||||
@@ -396,7 +397,6 @@ func TestGetHistoryTxs(t *testing.T) {
|
||||
// type
|
||||
txTypes := []common.TxType{
|
||||
common.TxTypeExit,
|
||||
common.TxTypeWithdrawn,
|
||||
common.TxTypeTransfer,
|
||||
common.TxTypeDeposit,
|
||||
common.TxTypeCreateAccountDeposit,
|
||||
|
||||
@@ -38,7 +38,7 @@ func (htx *historyTxsAPI) GetPagination() pagination { return htx.Pagination }
|
||||
func (htx *historyTxsAPI) Len() int { return len(htx.Txs) }
|
||||
|
||||
type l1Info struct {
|
||||
ToForgeL1TxsNum int64 `json:"toForgeL1TransactionsNum"`
|
||||
ToForgeL1TxsNum *int64 `json:"toForgeL1TransactionsNum"`
|
||||
UserOrigin bool `json:"userOrigin"`
|
||||
FromEthAddr string `json:"fromHezEthereumAddress"`
|
||||
FromBJJ string `json:"fromBJJ"`
|
||||
@@ -58,7 +58,7 @@ type historyTxAPI struct {
|
||||
TxID string `json:"id"`
|
||||
Type common.TxType `json:"type"`
|
||||
Position int `json:"position"`
|
||||
FromIdx string `json:"fromAccountIndex"`
|
||||
FromIdx *string `json:"fromAccountIndex"`
|
||||
ToIdx string `json:"toAccountIndex"`
|
||||
Amount string `json:"amount"`
|
||||
BatchNum *common.BatchNum `json:"batchNum"`
|
||||
@@ -76,7 +76,6 @@ func historyTxsToAPI(dbTxs []*historydb.HistoryTx) []historyTxAPI {
|
||||
TxID: dbTxs[i].TxID.String(),
|
||||
Type: dbTxs[i].Type,
|
||||
Position: dbTxs[i].Position,
|
||||
FromIdx: idxToHez(dbTxs[i].FromIdx, dbTxs[i].TokenSymbol),
|
||||
ToIdx: idxToHez(dbTxs[i].ToIdx, dbTxs[i].TokenSymbol),
|
||||
Amount: dbTxs[i].Amount.String(),
|
||||
HistoricUSD: dbTxs[i].HistoricUSD,
|
||||
@@ -95,12 +94,17 @@ func historyTxsToAPI(dbTxs []*historydb.HistoryTx) []historyTxAPI {
|
||||
L1Info: nil,
|
||||
L2Info: nil,
|
||||
}
|
||||
if dbTxs[i].FromIdx != nil {
|
||||
fromIdx := new(string)
|
||||
*fromIdx = idxToHez(*dbTxs[i].FromIdx, dbTxs[i].TokenSymbol)
|
||||
apiTx.FromIdx = fromIdx
|
||||
}
|
||||
if dbTxs[i].IsL1 {
|
||||
apiTx.IsL1 = "L1"
|
||||
apiTx.L1Info = &l1Info{
|
||||
ToForgeL1TxsNum: dbTxs[i].ToForgeL1TxsNum,
|
||||
UserOrigin: dbTxs[i].UserOrigin,
|
||||
FromEthAddr: ethAddrToHez(dbTxs[i].FromEthAddr),
|
||||
UserOrigin: *dbTxs[i].UserOrigin,
|
||||
FromEthAddr: ethAddrToHez(*dbTxs[i].FromEthAddr),
|
||||
FromBJJ: bjjToString(dbTxs[i].FromBJJ),
|
||||
LoadAmount: dbTxs[i].LoadAmount.String(),
|
||||
HistoricLoadAmountUSD: dbTxs[i].HistoricLoadAmountUSD,
|
||||
|
||||
@@ -149,9 +149,6 @@ func parseQueryTxType(c querier) (*common.TxType, error) {
|
||||
case common.TxTypeExit:
|
||||
ret := common.TxTypeExit
|
||||
return &ret, nil
|
||||
case common.TxTypeWithdrawn:
|
||||
ret := common.TxTypeWithdrawn
|
||||
return &ret, nil
|
||||
case common.TxTypeTransfer:
|
||||
ret := common.TxTypeTransfer
|
||||
return &ret, nil
|
||||
|
||||
@@ -239,10 +239,6 @@ func TestParseQueryTxType(t *testing.T) {
|
||||
res, err = parseQueryTxType(c)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, common.TxTypeExit, *res)
|
||||
c.m[name] = string(common.TxTypeWithdrawn)
|
||||
res, err = parseQueryTxType(c)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, common.TxTypeWithdrawn, *res)
|
||||
c.m[name] = string(common.TxTypeTransfer)
|
||||
res, err = parseQueryTxType(c)
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -1240,13 +1240,24 @@ components:
|
||||
fromAccountIndex:
|
||||
$ref: '#/components/schemas/AccountIndex'
|
||||
toAccountIndex:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/AccountIndex'
|
||||
- example: "hez:DAI:672"
|
||||
type: string
|
||||
description: >-
|
||||
Identifier of the destination account. It references the position where the account is inside the state Merkle tree.
|
||||
The identifier is built using: `hez:` + `token symbol:` + `index`
|
||||
example: null
|
||||
nullable: true
|
||||
toHezEthereumAddress:
|
||||
$ref: '#/components/schemas/HezEthereumAddress'
|
||||
type: string
|
||||
description: "Address of an Etherum account linked to the Hermez network."
|
||||
pattern: "^hez:0x[a-fA-F0-9]{40}$"
|
||||
example: "hez:0xaa942cfcd25ad4d90a62358b0dd84f33b398262a"
|
||||
nullable: true
|
||||
toBjj:
|
||||
$ref: '#/components/schemas/BJJ'
|
||||
type: string
|
||||
description: "BabyJubJub public key, encoded as base64 URL (RFC 4648), which result in 33 bytes. The padding byte is replaced by a sum of the encoded bytes."
|
||||
pattern: "^hez:[A-Za-z0-9_-]{44}$"
|
||||
example: null
|
||||
nullable: true
|
||||
amount:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BigInt'
|
||||
@@ -1308,6 +1319,7 @@ components:
|
||||
- type
|
||||
- tokenId
|
||||
- fromAccountIndex
|
||||
- toAccountIndex
|
||||
- toHezAccountIndex
|
||||
- toHezEthereumAddress
|
||||
- toBjj
|
||||
@@ -1333,13 +1345,24 @@ components:
|
||||
fromAccountIndex:
|
||||
$ref: '#/components/schemas/AccountIndex'
|
||||
toAccountIndex:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/AccountIndex'
|
||||
- example: "hez:DAI:672"
|
||||
type: string
|
||||
description: >-
|
||||
Identifier of the destination account. It references the position where the account is inside the state Merkle tree.
|
||||
The identifier is built using: `hez:` + `token symbol:` + `index`
|
||||
example: "hez:DAI:309"
|
||||
nullable: true
|
||||
toHezEthereumAddress:
|
||||
$ref: '#/components/schemas/HezEthereumAddress'
|
||||
type: string
|
||||
description: "Address of an Etherum account linked to the Hermez network."
|
||||
pattern: "^hez:0x[a-fA-F0-9]{40}$"
|
||||
example: null
|
||||
nullable: true
|
||||
toBjj:
|
||||
$ref: '#/components/schemas/BJJ'
|
||||
type: string
|
||||
description: "BabyJubJub public key, encoded as base64 URL (RFC 4648), which result in 33 bytes. The padding byte is replaced by a sum of the encoded bytes."
|
||||
pattern: "^hez:[A-Za-z0-9_-]{44}$"
|
||||
example: null
|
||||
nullable: true
|
||||
amount:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BigInt'
|
||||
@@ -1448,7 +1471,6 @@ components:
|
||||
description: Type of transaction.
|
||||
enum:
|
||||
- Exit
|
||||
- Withdrawn
|
||||
- Transfer
|
||||
- Deposit
|
||||
- CreateAccountDeposit
|
||||
@@ -1539,7 +1561,12 @@ components:
|
||||
position:
|
||||
$ref: '#/components/schemas/TransactionPosition'
|
||||
fromAccountIndex:
|
||||
$ref: '#/components/schemas/AccountIndex'
|
||||
type: string
|
||||
description: >-
|
||||
Identifier of an account. It references the position where the account is inside the state Merkle tree.
|
||||
The identifier is built using: `hez:` + `token symbol:` + `index`
|
||||
example: "hez:DAI:4444"
|
||||
nullable: true
|
||||
toAccountIndex:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/AccountIndex'
|
||||
@@ -1666,6 +1693,7 @@ components:
|
||||
minimum: 0
|
||||
maximum: 4294967295
|
||||
example: 784
|
||||
nullable: true
|
||||
TransactionPosition:
|
||||
type: integer
|
||||
description: Position that a transaction occupies in a batch.
|
||||
@@ -1689,8 +1717,8 @@ components:
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
token:
|
||||
$ref: '#/components/schemas/Token'
|
||||
tokenId:
|
||||
$ref: '#/components/schemas/TokenId'
|
||||
amount:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/BigInt'
|
||||
@@ -1716,6 +1744,9 @@ components:
|
||||
$ref: '#/components/schemas/EthereumAddress'
|
||||
collectedFees:
|
||||
$ref: '#/components/schemas/CollectedFees'
|
||||
totalCollectedFeesUSD:
|
||||
type: number
|
||||
description: Value in USD of the collected tokens by the forger in concept of fees. This is calculated at the moment the batch is forged, with the conversion rates at that time.
|
||||
historicTotalCollectedFeesUSD:
|
||||
type: number
|
||||
description: Sum of the all the fees collected, in USD, at the moment the batch was forged.
|
||||
@@ -1737,7 +1768,6 @@ components:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/ToForgeL1TransactionsNum'
|
||||
- description: Identifier that corresponds to the group of L1 transactions forged in the current batch.
|
||||
- nullable: true
|
||||
- example: 5
|
||||
slotNum:
|
||||
$ref: '#/components/schemas/SlotNum'
|
||||
|
||||
@@ -19,8 +19,9 @@ type Batch struct {
|
||||
StateRoot Hash `meddler:"state_root"`
|
||||
NumAccounts int `meddler:"num_accounts"`
|
||||
ExitRoot Hash `meddler:"exit_root"`
|
||||
ForgeL1TxsNum int64 `meddler:"forge_l1_txs_num"` // optional, Only when the batch forges L1 txs. Identifier that corresponds to the group of L1 txs forged in the current batch.
|
||||
ForgeL1TxsNum *int64 `meddler:"forge_l1_txs_num"` // optional, Only when the batch forges L1 txs. Identifier that corresponds to the group of L1 txs forged in the current batch.
|
||||
SlotNum SlotNum `meddler:"slot_num"` // Slot in which the batch is forged
|
||||
TotalFeesUSD *float64 `meddler:"total_fees_usd"`
|
||||
}
|
||||
|
||||
// BatchNum identifies a batch
|
||||
|
||||
@@ -25,10 +25,10 @@ type L1Tx struct {
|
||||
// - L1UserTx: 0
|
||||
// - L1CoordinatorTx: 1
|
||||
TxID TxID
|
||||
ToForgeL1TxsNum int64 // toForgeL1TxsNum in which the tx was forged / will be forged
|
||||
ToForgeL1TxsNum *int64 // toForgeL1TxsNum in which the tx was forged / will be forged
|
||||
Position int
|
||||
UserOrigin bool // true if the tx was originated by a user, false if it was aoriginated by a coordinator. Note that this differ from the spec for implementation simplification purpposes
|
||||
FromIdx Idx // FromIdx is used by L1Tx/Deposit to indicate the Idx receiver of the L1Tx.LoadAmount (deposit)
|
||||
FromIdx *Idx // FromIdx is used by L1Tx/Deposit to indicate the Idx receiver of the L1Tx.LoadAmount (deposit)
|
||||
FromEthAddr ethCommon.Address
|
||||
FromBJJ *babyjub.PublicKey
|
||||
ToIdx Idx // ToIdx is ignored in L1Tx/Deposit, but used in the L1Tx/DepositAndTransfer
|
||||
@@ -47,7 +47,7 @@ type L1Tx struct {
|
||||
func NewL1Tx(l1Tx *L1Tx) (*L1Tx, error) {
|
||||
// calculate TxType
|
||||
var txType TxType
|
||||
if l1Tx.FromIdx == Idx(0) {
|
||||
if l1Tx.FromIdx == nil {
|
||||
if l1Tx.ToIdx == Idx(0) {
|
||||
txType = TxTypeCreateAccountDeposit
|
||||
} else if l1Tx.ToIdx >= IdxUserThreshold {
|
||||
@@ -55,7 +55,7 @@ func NewL1Tx(l1Tx *L1Tx) (*L1Tx, error) {
|
||||
} else {
|
||||
return l1Tx, fmt.Errorf("Can not determine type of L1Tx, invalid ToIdx value: %d", l1Tx.ToIdx)
|
||||
}
|
||||
} else if l1Tx.FromIdx >= IdxUserThreshold {
|
||||
} else if *l1Tx.FromIdx >= IdxUserThreshold {
|
||||
if l1Tx.ToIdx == Idx(0) {
|
||||
txType = TxTypeDeposit
|
||||
} else if l1Tx.ToIdx == Idx(1) {
|
||||
@@ -83,7 +83,11 @@ func NewL1Tx(l1Tx *L1Tx) (*L1Tx, error) {
|
||||
txid[0] = TxIDPrefixL1CoordTx
|
||||
}
|
||||
var toForgeL1TxsNumBytes [8]byte
|
||||
binary.BigEndian.PutUint64(toForgeL1TxsNumBytes[:], uint64(l1Tx.ToForgeL1TxsNum))
|
||||
var toForge uint64 = 0
|
||||
if l1Tx.ToForgeL1TxsNum != nil {
|
||||
toForge = uint64(*l1Tx.ToForgeL1TxsNum)
|
||||
}
|
||||
binary.BigEndian.PutUint64(toForgeL1TxsNumBytes[:], toForge)
|
||||
copy(txid[1:9], toForgeL1TxsNumBytes[:])
|
||||
|
||||
var positionBytes [2]byte
|
||||
@@ -98,19 +102,25 @@ func NewL1Tx(l1Tx *L1Tx) (*L1Tx, error) {
|
||||
func (tx *L1Tx) Tx() *Tx {
|
||||
f := new(big.Float).SetInt(tx.Amount)
|
||||
amountFloat, _ := f.Float64()
|
||||
userOrigin := new(bool)
|
||||
*userOrigin = tx.UserOrigin
|
||||
fromEthAddr := new(ethCommon.Address)
|
||||
*fromEthAddr = tx.FromEthAddr
|
||||
toIdx := new(Idx)
|
||||
*toIdx = tx.ToIdx
|
||||
genericTx := &Tx{
|
||||
IsL1: true,
|
||||
TxID: tx.TxID,
|
||||
Type: tx.Type,
|
||||
Position: tx.Position,
|
||||
FromIdx: tx.FromIdx,
|
||||
ToIdx: tx.ToIdx,
|
||||
ToIdx: toIdx,
|
||||
Amount: tx.Amount,
|
||||
AmountFloat: amountFloat,
|
||||
TokenID: tx.TokenID,
|
||||
ToForgeL1TxsNum: tx.ToForgeL1TxsNum,
|
||||
UserOrigin: tx.UserOrigin,
|
||||
FromEthAddr: tx.FromEthAddr,
|
||||
UserOrigin: userOrigin,
|
||||
FromEthAddr: fromEthAddr,
|
||||
FromBJJ: tx.FromBJJ,
|
||||
LoadAmount: tx.LoadAmount,
|
||||
EthBlockNum: tx.EthBlockNum,
|
||||
@@ -171,10 +181,14 @@ func L1TxFromBytes(b []byte) (*L1Tx, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tx.FromIdx, err = IdxFromBytes(b[52:58])
|
||||
fromIdx, err := IdxFromBytes(b[52:58])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if fromIdx != 0 {
|
||||
tx.FromIdx = new(Idx)
|
||||
*tx.FromIdx = fromIdx
|
||||
}
|
||||
tx.LoadAmount = Float16FromBytes(b[58:60]).BigInt()
|
||||
tx.Amount = Float16FromBytes(b[60:62]).BigInt()
|
||||
tx.TokenID, err = TokenIDFromBytes(b[62:66])
|
||||
|
||||
@@ -12,14 +12,18 @@ import (
|
||||
)
|
||||
|
||||
func TestNewL1Tx(t *testing.T) {
|
||||
toForge := new(int64)
|
||||
*toForge = 123456
|
||||
fromIdx := new(Idx)
|
||||
*fromIdx = 300
|
||||
l1Tx := &L1Tx{
|
||||
ToForgeL1TxsNum: int64(123456),
|
||||
ToForgeL1TxsNum: toForge,
|
||||
Position: 71,
|
||||
ToIdx: 301,
|
||||
TokenID: 5,
|
||||
Amount: big.NewInt(1),
|
||||
LoadAmount: big.NewInt(2),
|
||||
FromIdx: 300,
|
||||
FromIdx: fromIdx,
|
||||
}
|
||||
l1Tx, err := NewL1Tx(l1Tx)
|
||||
assert.Nil(t, err)
|
||||
@@ -34,12 +38,14 @@ func TestL1TxByteParsers(t *testing.T) {
|
||||
pk, err := pkComp.Decompress()
|
||||
require.Nil(t, err)
|
||||
|
||||
fromIdx := new(Idx)
|
||||
*fromIdx = 2
|
||||
l1Tx := &L1Tx{
|
||||
ToIdx: 3,
|
||||
TokenID: 5,
|
||||
Amount: big.NewInt(1),
|
||||
LoadAmount: big.NewInt(2),
|
||||
FromIdx: 2,
|
||||
FromIdx: fromIdx,
|
||||
FromBJJ: pk,
|
||||
FromEthAddr: ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),
|
||||
}
|
||||
|
||||
@@ -68,13 +68,17 @@ func (tx *L2Tx) Tx() *Tx {
|
||||
*fee = tx.Fee
|
||||
nonce := new(Nonce)
|
||||
*nonce = tx.Nonce
|
||||
fromIdx := new(Idx)
|
||||
*fromIdx = tx.FromIdx
|
||||
toIdx := new(Idx)
|
||||
*toIdx = tx.ToIdx
|
||||
return &Tx{
|
||||
IsL1: false,
|
||||
TxID: tx.TxID,
|
||||
Type: tx.Type,
|
||||
Position: tx.Position,
|
||||
FromIdx: tx.FromIdx,
|
||||
ToIdx: tx.ToIdx,
|
||||
FromIdx: fromIdx,
|
||||
ToIdx: toIdx,
|
||||
Amount: tx.Amount,
|
||||
USD: tx.USD,
|
||||
AmountFloat: amountFloat,
|
||||
@@ -89,11 +93,15 @@ func (tx *L2Tx) Tx() *Tx {
|
||||
// PoolL2Tx returns the data structure of PoolL2Tx with the parameters of a
|
||||
// L2Tx filled
|
||||
func (tx *L2Tx) PoolL2Tx() *PoolL2Tx {
|
||||
batchNum := new(BatchNum)
|
||||
*batchNum = tx.BatchNum
|
||||
toIdx := new(Idx)
|
||||
*toIdx = tx.ToIdx
|
||||
return &PoolL2Tx{
|
||||
TxID: tx.TxID,
|
||||
BatchNum: tx.BatchNum,
|
||||
BatchNum: batchNum,
|
||||
FromIdx: tx.FromIdx,
|
||||
ToIdx: tx.ToIdx,
|
||||
ToIdx: toIdx,
|
||||
Amount: tx.Amount,
|
||||
Fee: tx.Fee,
|
||||
Nonce: tx.Nonce,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
@@ -19,8 +20,8 @@ type PoolL2Tx struct {
|
||||
// values: | type | FromIdx | Nonce |
|
||||
TxID TxID `meddler:"tx_id"`
|
||||
FromIdx Idx `meddler:"from_idx"` // FromIdx is used by L1Tx/Deposit to indicate the Idx receiver of the L1Tx.LoadAmount (deposit)
|
||||
ToIdx Idx `meddler:"to_idx"` // ToIdx is ignored in L1Tx/Deposit, but used in the L1Tx/DepositAndTransfer
|
||||
ToEthAddr ethCommon.Address `meddler:"to_eth_addr"`
|
||||
ToIdx *Idx `meddler:"to_idx"` // ToIdx is ignored in L1Tx/Deposit, but used in the L1Tx/DepositAndTransfer
|
||||
ToEthAddr *ethCommon.Address `meddler:"to_eth_addr"`
|
||||
ToBJJ *babyjub.PublicKey `meddler:"to_bjj"` // TODO: stop using json, use scanner/valuer
|
||||
TokenID TokenID `meddler:"token_id"`
|
||||
Amount *big.Int `meddler:"amount,bigint"` // TODO: change to float16
|
||||
@@ -32,21 +33,20 @@ type PoolL2Tx struct {
|
||||
Signature *babyjub.Signature `meddler:"signature"` // tx signature
|
||||
Timestamp time.Time `meddler:"timestamp,utctime"` // time when added to the tx pool
|
||||
// Stored in DB: optional fileds, may be uninitialized
|
||||
BatchNum BatchNum `meddler:"batch_num,zeroisnull"` // batchNum in which this tx was forged. Presence indicates "forged" state.
|
||||
RqFromIdx Idx `meddler:"rq_from_idx,zeroisnull"` // FromIdx is used by L1Tx/Deposit to indicate the Idx receiver of the L1Tx.LoadAmount (deposit)
|
||||
RqToIdx Idx `meddler:"rq_to_idx,zeroisnull"` // FromIdx is used by L1Tx/Deposit to indicate the Idx receiver of the L1Tx.LoadAmount (deposit)
|
||||
RqToEthAddr ethCommon.Address `meddler:"rq_to_eth_addr"`
|
||||
BatchNum *BatchNum `meddler:"batch_num"` // batchNum in which this tx was forged. Presence indicates "forged" state.
|
||||
RqFromIdx *Idx `meddler:"rq_from_idx"` // FromIdx is used by L1Tx/Deposit to indicate the Idx receiver of the L1Tx.LoadAmount (deposit)
|
||||
RqToIdx *Idx `meddler:"rq_to_idx"` // FromIdx is used by L1Tx/Deposit to indicate the Idx receiver of the L1Tx.LoadAmount (deposit)
|
||||
RqToEthAddr *ethCommon.Address `meddler:"rq_to_eth_addr"`
|
||||
RqToBJJ *babyjub.PublicKey `meddler:"rq_to_bjj"` // TODO: stop using json, use scanner/valuer
|
||||
RqTokenID TokenID `meddler:"rq_token_id,zeroisnull"`
|
||||
RqTokenID *TokenID `meddler:"rq_token_id"`
|
||||
RqAmount *big.Int `meddler:"rq_amount,bigintnull"` // TODO: change to float16
|
||||
RqFee FeeSelector `meddler:"rq_fee,zeroisnull"`
|
||||
RqNonce uint64 `meddler:"rq_nonce,zeroisnull"` // effective 48 bits used
|
||||
RqFee *FeeSelector `meddler:"rq_fee"`
|
||||
RqNonce *uint64 `meddler:"rq_nonce"` // effective 48 bits used
|
||||
AbsoluteFee *float64 `meddler:"fee_usd"`
|
||||
AbsoluteFeeUpdate *time.Time `meddler:"usd_update,utctime"`
|
||||
Type TxType `meddler:"tx_type"`
|
||||
// Extra metadata, may be uninitialized
|
||||
RqTxCompressedData []byte `meddler:"-"` // 253 bits, optional for atomic txs
|
||||
TokenSymbol string `meddler:"token_symbol"`
|
||||
}
|
||||
|
||||
// NewPoolL2Tx returns the given L2Tx with the TxId & Type parameters calculated
|
||||
@@ -54,11 +54,11 @@ type PoolL2Tx struct {
|
||||
func NewPoolL2Tx(poolL2Tx *PoolL2Tx) (*PoolL2Tx, error) {
|
||||
// calculate TxType
|
||||
var txType TxType
|
||||
if poolL2Tx.ToIdx == Idx(0) {
|
||||
if poolL2Tx.ToIdx == nil || *poolL2Tx.ToIdx == Idx(0) {
|
||||
txType = TxTypeTransfer
|
||||
} else if poolL2Tx.ToIdx == Idx(1) {
|
||||
} else if *poolL2Tx.ToIdx == Idx(1) {
|
||||
txType = TxTypeExit
|
||||
} else if poolL2Tx.ToIdx >= IdxUserThreshold {
|
||||
} else if *poolL2Tx.ToIdx >= IdxUserThreshold {
|
||||
txType = TxTypeTransfer
|
||||
} else {
|
||||
return poolL2Tx, fmt.Errorf("Can not determine type of PoolL2Tx, invalid ToIdx value: %d", poolL2Tx.ToIdx)
|
||||
@@ -189,14 +189,21 @@ func (tx *PoolL2Tx) HashToSign() (*big.Int, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
toEthAddr := EthAddrToBigInt(tx.ToEthAddr)
|
||||
toEthAddr := big.NewInt(0)
|
||||
if tx.ToEthAddr != nil {
|
||||
toEthAddr = EthAddrToBigInt(*tx.ToEthAddr)
|
||||
}
|
||||
rqToEthAddr := big.NewInt(0)
|
||||
if tx.RqToEthAddr != nil {
|
||||
rqToEthAddr = EthAddrToBigInt(*tx.RqToEthAddr)
|
||||
}
|
||||
toBJJAy := tx.ToBJJ.Y
|
||||
rqTxCompressedDataV2, err := tx.TxCompressedDataV2()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return poseidon.Hash([]*big.Int{toCompressedData, toEthAddr, toBJJAy, rqTxCompressedDataV2, EthAddrToBigInt(tx.RqToEthAddr), tx.RqToBJJ.Y})
|
||||
return poseidon.Hash([]*big.Int{toCompressedData, toEthAddr, toBJJAy, rqTxCompressedDataV2, rqToEthAddr, tx.RqToBJJ.Y})
|
||||
}
|
||||
|
||||
// VerifySignature returns true if the signature verification is correct for the given PublicKey
|
||||
@@ -209,39 +216,51 @@ func (tx *PoolL2Tx) VerifySignature(pk *babyjub.PublicKey) bool {
|
||||
}
|
||||
|
||||
// L2Tx returns a *L2Tx from the PoolL2Tx
|
||||
func (tx *PoolL2Tx) L2Tx() *L2Tx {
|
||||
func (tx *PoolL2Tx) L2Tx() (*L2Tx, error) {
|
||||
if tx.ToIdx == nil || tx.BatchNum == nil {
|
||||
return nil, errors.New("PoolL2Tx must have ToIdx != nil and BatchNum != nil in order to be able to transform to Tx")
|
||||
}
|
||||
return &L2Tx{
|
||||
TxID: tx.TxID,
|
||||
BatchNum: tx.BatchNum,
|
||||
BatchNum: *tx.BatchNum,
|
||||
FromIdx: tx.FromIdx,
|
||||
ToIdx: tx.ToIdx,
|
||||
ToIdx: *tx.ToIdx,
|
||||
Amount: tx.Amount,
|
||||
Fee: tx.Fee,
|
||||
Nonce: tx.Nonce,
|
||||
Type: tx.Type,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Tx returns a *Tx from the PoolL2Tx
|
||||
func (tx *PoolL2Tx) Tx() *Tx {
|
||||
func (tx *PoolL2Tx) Tx() (*Tx, error) {
|
||||
if tx.ToIdx == nil {
|
||||
return nil, errors.New("PoolL2Tx must have ToIdx != nil in order to be able to transform to Tx")
|
||||
}
|
||||
fromIdx := new(Idx)
|
||||
*fromIdx = tx.FromIdx
|
||||
return &Tx{
|
||||
TxID: tx.TxID,
|
||||
FromIdx: tx.FromIdx,
|
||||
FromIdx: fromIdx,
|
||||
ToIdx: tx.ToIdx,
|
||||
Amount: tx.Amount,
|
||||
Nonce: &tx.Nonce,
|
||||
Fee: &tx.Fee,
|
||||
Type: tx.Type,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// PoolL2TxsToL2Txs returns an array of []*L2Tx from an array of []*PoolL2Tx
|
||||
func PoolL2TxsToL2Txs(txs []*PoolL2Tx) []*L2Tx {
|
||||
func PoolL2TxsToL2Txs(txs []*PoolL2Tx) ([]*L2Tx, error) {
|
||||
var r []*L2Tx
|
||||
for _, tx := range txs {
|
||||
r = append(r, tx.L2Tx())
|
||||
for _, poolTx := range txs {
|
||||
tx, err := poolTx.L2Tx()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r
|
||||
r = append(r, tx)
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// PoolL2TxState is a struct that represents the status of a L2 transaction
|
||||
|
||||
@@ -11,9 +11,11 @@ import (
|
||||
)
|
||||
|
||||
func TestNewPoolL2Tx(t *testing.T) {
|
||||
toIdx := new(Idx)
|
||||
*toIdx = 300
|
||||
poolL2Tx := &PoolL2Tx{
|
||||
FromIdx: 87654,
|
||||
ToIdx: 300,
|
||||
ToIdx: toIdx,
|
||||
Amount: big.NewInt(4),
|
||||
TokenID: 5,
|
||||
Nonce: 144,
|
||||
@@ -27,10 +29,11 @@ func TestTxCompressedData(t *testing.T) {
|
||||
var sk babyjub.PrivateKey
|
||||
_, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
|
||||
assert.Nil(t, err)
|
||||
|
||||
toIdx := new(Idx)
|
||||
*toIdx = 3
|
||||
tx := PoolL2Tx{
|
||||
FromIdx: 2,
|
||||
ToIdx: 3,
|
||||
ToIdx: toIdx,
|
||||
Amount: big.NewInt(4),
|
||||
TokenID: 5,
|
||||
Nonce: 6,
|
||||
@@ -45,10 +48,10 @@ func TestTxCompressedData(t *testing.T) {
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, expected.Bytes(), txCompressedData.Bytes())
|
||||
assert.Equal(t, "10000000000060000000500040000000000030000000000020001c60be60f", hex.EncodeToString(txCompressedData.Bytes())[1:])
|
||||
|
||||
*toIdx = 8
|
||||
tx = PoolL2Tx{
|
||||
FromIdx: 7,
|
||||
ToIdx: 8,
|
||||
ToIdx: toIdx,
|
||||
Amount: big.NewInt(9),
|
||||
TokenID: 10,
|
||||
Nonce: 11,
|
||||
@@ -71,15 +74,16 @@ func TestHashToSign(t *testing.T) {
|
||||
_, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
|
||||
assert.Nil(t, err)
|
||||
ethAddr := ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370")
|
||||
|
||||
toIdx := new(Idx)
|
||||
*toIdx = 3
|
||||
tx := PoolL2Tx{
|
||||
FromIdx: 2,
|
||||
ToIdx: 3,
|
||||
ToIdx: toIdx,
|
||||
Amount: big.NewInt(4),
|
||||
TokenID: 5,
|
||||
Nonce: 6,
|
||||
ToBJJ: sk.Public(),
|
||||
RqToEthAddr: ethAddr,
|
||||
RqToEthAddr: ðAddr,
|
||||
RqToBJJ: sk.Public(),
|
||||
}
|
||||
toSign, err := tx.HashToSign()
|
||||
@@ -92,15 +96,16 @@ func TestVerifyTxSignature(t *testing.T) {
|
||||
_, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
|
||||
assert.Nil(t, err)
|
||||
ethAddr := ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370")
|
||||
|
||||
toIdx := new(Idx)
|
||||
*toIdx = 3
|
||||
tx := PoolL2Tx{
|
||||
FromIdx: 2,
|
||||
ToIdx: 3,
|
||||
ToIdx: toIdx,
|
||||
Amount: big.NewInt(4),
|
||||
TokenID: 5,
|
||||
Nonce: 6,
|
||||
ToBJJ: sk.Public(),
|
||||
RqToEthAddr: ethAddr,
|
||||
RqToEthAddr: ðAddr,
|
||||
RqToBJJ: sk.Public(),
|
||||
}
|
||||
toSign, err := tx.HashToSign()
|
||||
|
||||
29
common/tx.go
29
common/tx.go
@@ -3,6 +3,7 @@ package common
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
@@ -57,8 +58,6 @@ type TxType string
|
||||
const (
|
||||
// TxTypeExit represents L2->L1 token transfer. A leaf for this account appears in the exit tree of the block
|
||||
TxTypeExit TxType = "Exit"
|
||||
// TxTypeWithdrawn represents the balance that was moved from L2->L1 has been widthrawn from the smart contract
|
||||
TxTypeWithdrawn TxType = "Withdrawn"
|
||||
// TxTypeTransfer represents L2->L2 token transfer
|
||||
TxTypeTransfer TxType = "Transfer"
|
||||
// TxTypeDeposit represents L1->L2 transfer
|
||||
@@ -86,8 +85,8 @@ type Tx struct {
|
||||
TxID TxID `meddler:"id"`
|
||||
Type TxType `meddler:"type"`
|
||||
Position int `meddler:"position"`
|
||||
FromIdx Idx `meddler:"from_idx"`
|
||||
ToIdx Idx `meddler:"to_idx"`
|
||||
FromIdx *Idx `meddler:"from_idx"`
|
||||
ToIdx *Idx `meddler:"to_idx"`
|
||||
Amount *big.Int `meddler:"amount,bigint"`
|
||||
AmountFloat float64 `meddler:"amount_f"`
|
||||
TokenID TokenID `meddler:"token_id"`
|
||||
@@ -95,9 +94,9 @@ type Tx struct {
|
||||
BatchNum *BatchNum `meddler:"batch_num"` // batchNum in which this tx was forged. If the tx is L2, this must be != 0
|
||||
EthBlockNum int64 `meddler:"eth_block_num"` // Ethereum Block Number in which this L1Tx was added to the queue
|
||||
// L1
|
||||
ToForgeL1TxsNum int64 `meddler:"to_forge_l1_txs_num"` // toForgeL1TxsNum in which the tx was forged / will be forged
|
||||
UserOrigin bool `meddler:"user_origin"` // true if the tx was originated by a user, false if it was aoriginated by a coordinator. Note that this differ from the spec for implementation simplification purpposes
|
||||
FromEthAddr ethCommon.Address `meddler:"from_eth_addr"`
|
||||
ToForgeL1TxsNum *int64 `meddler:"to_forge_l1_txs_num"` // toForgeL1TxsNum in which the tx was forged / will be forged
|
||||
UserOrigin *bool `meddler:"user_origin"` // true if the tx was originated by a user, false if it was aoriginated by a coordinator. Note that this differ from the spec for implementation simplification purpposes
|
||||
FromEthAddr *ethCommon.Address `meddler:"from_eth_addr"`
|
||||
FromBJJ *babyjub.PublicKey `meddler:"from_bjj"`
|
||||
LoadAmount *big.Int `meddler:"load_amount,bigintnull"`
|
||||
LoadAmountFloat *float64 `meddler:"load_amount_f"`
|
||||
@@ -109,22 +108,24 @@ type Tx struct {
|
||||
}
|
||||
|
||||
// L1Tx returns a *L1Tx from the Tx
|
||||
func (tx *Tx) L1Tx() *L1Tx {
|
||||
l1Tx := &L1Tx{
|
||||
func (tx *Tx) L1Tx() (*L1Tx, error) {
|
||||
if tx.UserOrigin == nil || tx.FromEthAddr == nil {
|
||||
return nil, errors.New("Tx must have UserOrigin != nil and FromEthAddr != nil in order to be able to transform to L1Tx")
|
||||
}
|
||||
return &L1Tx{
|
||||
TxID: tx.TxID,
|
||||
ToForgeL1TxsNum: tx.ToForgeL1TxsNum,
|
||||
Position: tx.Position,
|
||||
UserOrigin: tx.UserOrigin,
|
||||
UserOrigin: *tx.UserOrigin,
|
||||
FromIdx: tx.FromIdx,
|
||||
FromEthAddr: tx.FromEthAddr,
|
||||
FromEthAddr: *tx.FromEthAddr,
|
||||
FromBJJ: tx.FromBJJ,
|
||||
ToIdx: tx.ToIdx,
|
||||
ToIdx: *tx.ToIdx,
|
||||
TokenID: tx.TokenID,
|
||||
Amount: tx.Amount,
|
||||
LoadAmount: tx.LoadAmount,
|
||||
EthBlockNum: tx.EthBlockNum,
|
||||
Type: tx.Type,
|
||||
BatchNum: tx.BatchNum,
|
||||
}
|
||||
return l1Tx
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -133,7 +133,8 @@ func (hdb *HistoryDB) addBatches(d meddler.DB, batches []common.Batch) error {
|
||||
num_accounts,
|
||||
exit_root,
|
||||
forge_l1_txs_num,
|
||||
slot_num
|
||||
slot_num,
|
||||
total_fees_usd
|
||||
) VALUES %s;`,
|
||||
batches[:],
|
||||
)
|
||||
|
||||
@@ -109,7 +109,7 @@ func TestBatches(t *testing.T) {
|
||||
// Test GetLastL1TxsNum
|
||||
fetchedLastL1TxsNum, err = historyDB.GetLastL1TxsNum()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, batches[nBatches-1].ForgeL1TxsNum, *fetchedLastL1TxsNum)
|
||||
assert.Equal(t, *batches[nBatches-1].ForgeL1TxsNum, *fetchedLastL1TxsNum)
|
||||
}
|
||||
|
||||
func TestBids(t *testing.T) {
|
||||
|
||||
@@ -17,7 +17,7 @@ type HistoryTx struct {
|
||||
TxID common.TxID `meddler:"id"`
|
||||
Type common.TxType `meddler:"type"`
|
||||
Position int `meddler:"position"`
|
||||
FromIdx common.Idx `meddler:"from_idx"`
|
||||
FromIdx *common.Idx `meddler:"from_idx"`
|
||||
ToIdx common.Idx `meddler:"to_idx"`
|
||||
Amount *big.Int `meddler:"amount,bigint"`
|
||||
AmountFloat float64 `meddler:"amount_f"`
|
||||
@@ -25,9 +25,9 @@ type HistoryTx struct {
|
||||
BatchNum *common.BatchNum `meddler:"batch_num"` // batchNum in which this tx was forged. If the tx is L2, this must be != 0
|
||||
EthBlockNum int64 `meddler:"eth_block_num"` // Ethereum Block Number in which this L1Tx was added to the queue
|
||||
// L1
|
||||
ToForgeL1TxsNum int64 `meddler:"to_forge_l1_txs_num"` // toForgeL1TxsNum in which the tx was forged / will be forged
|
||||
UserOrigin bool `meddler:"user_origin"` // true if the tx was originated by a user, false if it was aoriginated by a coordinator. Note that this differ from the spec for implementation simplification purpposes
|
||||
FromEthAddr ethCommon.Address `meddler:"from_eth_addr"`
|
||||
ToForgeL1TxsNum *int64 `meddler:"to_forge_l1_txs_num"` // toForgeL1TxsNum in which the tx was forged / will be forged
|
||||
UserOrigin *bool `meddler:"user_origin"` // true if the tx was originated by a user, false if it was aoriginated by a coordinator. Note that this differ from the spec for implementation simplification purpposes
|
||||
FromEthAddr *ethCommon.Address `meddler:"from_eth_addr"`
|
||||
FromBJJ *babyjub.PublicKey `meddler:"from_bjj"`
|
||||
LoadAmount *big.Int `meddler:"load_amount,bigintnull"`
|
||||
LoadAmountFloat *float64 `meddler:"load_amount_f"`
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package l2db
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
@@ -49,7 +50,10 @@ func (l2db *L2DB) AddAccountCreationAuth(auth *common.AccountCreationAuth) error
|
||||
}
|
||||
|
||||
// GetAccountCreationAuth returns an account creation authorization into the DB
|
||||
func (l2db *L2DB) GetAccountCreationAuth(addr ethCommon.Address) (*common.AccountCreationAuth, error) {
|
||||
func (l2db *L2DB) GetAccountCreationAuth(addr *ethCommon.Address) (*common.AccountCreationAuth, error) {
|
||||
if addr == nil {
|
||||
return nil, errors.New("addr cannot be nil")
|
||||
}
|
||||
auth := new(common.AccountCreationAuth)
|
||||
return auth, meddler.QueryRow(
|
||||
l2db.db, auth,
|
||||
@@ -64,8 +68,8 @@ func (l2db *L2DB) AddTxTest(tx *common.PoolL2Tx) error {
|
||||
type withouUSD struct {
|
||||
TxID common.TxID `meddler:"tx_id"`
|
||||
FromIdx common.Idx `meddler:"from_idx"`
|
||||
ToIdx common.Idx `meddler:"to_idx"`
|
||||
ToEthAddr ethCommon.Address `meddler:"to_eth_addr"`
|
||||
ToIdx *common.Idx `meddler:"to_idx"`
|
||||
ToEthAddr *ethCommon.Address `meddler:"to_eth_addr"`
|
||||
ToBJJ *babyjub.PublicKey `meddler:"to_bjj"`
|
||||
TokenID common.TokenID `meddler:"token_id"`
|
||||
Amount *big.Int `meddler:"amount,bigint"`
|
||||
@@ -75,15 +79,15 @@ func (l2db *L2DB) AddTxTest(tx *common.PoolL2Tx) error {
|
||||
State common.PoolL2TxState `meddler:"state"`
|
||||
Signature *babyjub.Signature `meddler:"signature"`
|
||||
Timestamp time.Time `meddler:"timestamp,utctime"`
|
||||
BatchNum common.BatchNum `meddler:"batch_num,zeroisnull"`
|
||||
RqFromIdx common.Idx `meddler:"rq_from_idx,zeroisnull"`
|
||||
RqToIdx common.Idx `meddler:"rq_to_idx,zeroisnull"`
|
||||
RqToEthAddr ethCommon.Address `meddler:"rq_to_eth_addr"`
|
||||
BatchNum *common.BatchNum `meddler:"batch_num"`
|
||||
RqFromIdx *common.Idx `meddler:"rq_from_idx"`
|
||||
RqToIdx *common.Idx `meddler:"rq_to_idx"`
|
||||
RqToEthAddr *ethCommon.Address `meddler:"rq_to_eth_addr"`
|
||||
RqToBJJ *babyjub.PublicKey `meddler:"rq_to_bjj"`
|
||||
RqTokenID common.TokenID `meddler:"rq_token_id,zeroisnull"`
|
||||
RqTokenID *common.TokenID `meddler:"rq_token_id"`
|
||||
RqAmount *big.Int `meddler:"rq_amount,bigintnull"`
|
||||
RqFee common.FeeSelector `meddler:"rq_fee,zeroisnull"`
|
||||
RqNonce uint64 `meddler:"rq_nonce,zeroisnull"`
|
||||
RqFee *common.FeeSelector `meddler:"rq_fee"`
|
||||
RqNonce *uint64 `meddler:"rq_nonce"`
|
||||
Type common.TxType `meddler:"tx_type"`
|
||||
}
|
||||
return meddler.Insert(l2db.db, "tx_pool", &withouUSD{
|
||||
@@ -115,8 +119,8 @@ func (l2db *L2DB) AddTxTest(tx *common.PoolL2Tx) error {
|
||||
|
||||
// selectPoolTx select part of queries to get common.PoolL2Tx
|
||||
const selectPoolTx = `SELECT tx_pool.*, token.usd * tx_pool.amount_f AS value_usd,
|
||||
fee_percentage(tx_pool.fee::NUMERIC) * token.usd * tx_pool.amount_f AS fee_usd, token.usd_update,
|
||||
token.symbol AS token_symbol FROM tx_pool INNER JOIN token ON tx_pool.token_id = token.token_id `
|
||||
fee_percentage(tx_pool.fee::NUMERIC) * token.usd * tx_pool.amount_f AS fee_usd, token.usd_update
|
||||
FROM tx_pool INNER JOIN token ON tx_pool.token_id = token.token_id `
|
||||
|
||||
// GetTx return the specified Tx
|
||||
func (l2db *L2DB) GetTx(txID common.TxID) (*common.PoolL2Tx, error) {
|
||||
|
||||
@@ -141,7 +141,7 @@ func TestStartForging(t *testing.T) {
|
||||
fetchedTx, err := l2DB.GetTx(id)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, common.PoolL2TxStateForging, fetchedTx.State)
|
||||
assert.Equal(t, fakeBatchNum, fetchedTx.BatchNum)
|
||||
assert.Equal(t, fakeBatchNum, *fetchedTx.BatchNum)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ func TestDoneForging(t *testing.T) {
|
||||
fetchedTx, err := l2DB.GetTx(id)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, common.PoolL2TxStateForged, fetchedTx.State)
|
||||
assert.Equal(t, fakeBatchNum, fetchedTx.BatchNum)
|
||||
assert.Equal(t, fakeBatchNum, *fetchedTx.BatchNum)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ func TestInvalidate(t *testing.T) {
|
||||
fetchedTx, err := l2DB.GetTx(id)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, common.PoolL2TxStateInvalid, fetchedTx.State)
|
||||
assert.Equal(t, fakeBatchNum, fetchedTx.BatchNum)
|
||||
assert.Equal(t, fakeBatchNum, *fetchedTx.BatchNum)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ func TestCheckNonces(t *testing.T) {
|
||||
fetchedTx, err := l2DB.GetTx(id)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, common.PoolL2TxStateInvalid, fetchedTx.State)
|
||||
assert.Equal(t, fakeBatchNum, fetchedTx.BatchNum)
|
||||
assert.Equal(t, fakeBatchNum, *fetchedTx.BatchNum)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,11 +257,12 @@ func TestReorg(t *testing.T) {
|
||||
reorgedTxIDs := []common.TxID{}
|
||||
nonReorgedTxIDs := []common.TxID{}
|
||||
for i := 0; i < len(txs); i++ {
|
||||
txs[i].BatchNum = new(common.BatchNum)
|
||||
if txs[i].State == common.PoolL2TxStateForged || txs[i].State == common.PoolL2TxStateInvalid {
|
||||
txs[i].BatchNum = reorgBatch
|
||||
*txs[i].BatchNum = reorgBatch
|
||||
reorgedTxIDs = append(reorgedTxIDs, txs[i].TxID)
|
||||
} else {
|
||||
txs[i].BatchNum = lastValidBatch
|
||||
*txs[i].BatchNum = lastValidBatch
|
||||
nonReorgedTxIDs = append(nonReorgedTxIDs, txs[i].TxID)
|
||||
}
|
||||
err := l2DB.AddTxTest(txs[i])
|
||||
@@ -269,17 +270,16 @@ func TestReorg(t *testing.T) {
|
||||
}
|
||||
err := l2DB.Reorg(lastValidBatch)
|
||||
assert.NoError(t, err)
|
||||
var nullBatchNum common.BatchNum
|
||||
for _, id := range reorgedTxIDs {
|
||||
tx, err := l2DB.GetTx(id)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, nullBatchNum, tx.BatchNum)
|
||||
assert.Nil(t, tx.BatchNum)
|
||||
assert.Equal(t, common.PoolL2TxStatePending, tx.State)
|
||||
}
|
||||
for _, id := range nonReorgedTxIDs {
|
||||
tx, err := l2DB.GetTx(id)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, lastValidBatch, tx.BatchNum)
|
||||
assert.Equal(t, lastValidBatch, *tx.BatchNum)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,11 +294,12 @@ func TestPurge(t *testing.T) {
|
||||
safeBatchNum := toDeleteBatchNum + l2DB.safetyPeriod + 1
|
||||
// Add txs to the DB
|
||||
for i := 0; i < int(l2DB.maxTxs); i++ {
|
||||
txs[i].BatchNum = new(common.BatchNum)
|
||||
if i%1 == 0 { // keep tx
|
||||
txs[i].BatchNum = safeBatchNum
|
||||
*txs[i].BatchNum = safeBatchNum
|
||||
keepedIDs = append(keepedIDs, txs[i].TxID)
|
||||
} else if i%2 == 0 { // delete after safety period
|
||||
txs[i].BatchNum = toDeleteBatchNum
|
||||
*txs[i].BatchNum = toDeleteBatchNum
|
||||
if i%3 == 0 {
|
||||
txs[i].State = common.PoolL2TxStateForged
|
||||
} else {
|
||||
@@ -343,7 +344,7 @@ func TestAuth(t *testing.T) {
|
||||
err := l2DB.AddAccountCreationAuth(auths[i])
|
||||
assert.NoError(t, err)
|
||||
// Fetch from DB
|
||||
auth, err := l2DB.GetAccountCreationAuth(auths[i].EthAddr)
|
||||
auth, err := l2DB.GetAccountCreationAuth(&auths[i].EthAddr)
|
||||
assert.NoError(t, err)
|
||||
// Check fetched vs generated
|
||||
assert.Equal(t, auths[i].EthAddr, auth.EthAddr)
|
||||
|
||||
@@ -17,14 +17,15 @@ CREATE TABLE coordinator (
|
||||
|
||||
CREATE TABLE batch (
|
||||
batch_num BIGINT PRIMARY KEY,
|
||||
eth_block_num BIGINT REFERENCES block (eth_block_num) ON DELETE CASCADE,
|
||||
eth_block_num BIGINT NOT NULL REFERENCES block (eth_block_num) ON DELETE CASCADE,
|
||||
forger_addr BYTEA NOT NULL, -- fake foreign key for coordinator
|
||||
fees_collected BYTEA NOT NULL,
|
||||
state_root BYTEA NOT NULL,
|
||||
num_accounts BIGINT NOT NULL,
|
||||
exit_root BYTEA NOT NULL,
|
||||
forge_l1_txs_num BIGINT,
|
||||
slot_num BIGINT NOT NULL
|
||||
slot_num BIGINT NOT NULL,
|
||||
total_fees_usd NUMERIC
|
||||
);
|
||||
|
||||
CREATE TABLE exit_tree (
|
||||
@@ -80,7 +81,7 @@ CREATE TABLE tx (
|
||||
id BYTEA PRIMARY KEY,
|
||||
type VARCHAR(40) NOT NULL,
|
||||
position INT NOT NULL,
|
||||
from_idx BIGINT NOT NULL,
|
||||
from_idx BIGINT,
|
||||
to_idx BIGINT NOT NULL,
|
||||
amount BYTEA NOT NULL,
|
||||
amount_f NUMERIC NOT NULL,
|
||||
@@ -470,9 +471,9 @@ CREATE TABLE consensus_vars (
|
||||
CREATE TABLE tx_pool (
|
||||
tx_id BYTEA PRIMARY KEY,
|
||||
from_idx BIGINT NOT NULL,
|
||||
to_idx BIGINT NOT NULL,
|
||||
to_eth_addr BYTEA NOT NULL,
|
||||
to_bjj BYTEA NOT NULL,
|
||||
to_idx BIGINT,
|
||||
to_eth_addr BYTEA,
|
||||
to_bjj BYTEA,
|
||||
token_id INT NOT NULL REFERENCES token (token_id) ON DELETE CASCADE,
|
||||
amount BYTEA NOT NULL,
|
||||
amount_f NUMERIC NOT NULL,
|
||||
|
||||
@@ -247,13 +247,19 @@ func (s *StateDB) Reset(batchNum common.BatchNum) error {
|
||||
}
|
||||
|
||||
// GetAccount returns the account for the given Idx
|
||||
func (s *StateDB) GetAccount(idx common.Idx) (*common.Account, error) {
|
||||
func (s *StateDB) GetAccount(idx *common.Idx) (*common.Account, error) {
|
||||
if idx == nil {
|
||||
return nil, errors.New("idx cannot be nil")
|
||||
}
|
||||
return getAccountInTreeDB(s.db, idx)
|
||||
}
|
||||
|
||||
// getAccountInTreeDB is abstracted from StateDB to be used from StateDB and
|
||||
// from ExitTree. GetAccount returns the account for the given Idx
|
||||
func getAccountInTreeDB(sto db.Storage, idx common.Idx) (*common.Account, error) {
|
||||
func getAccountInTreeDB(sto db.Storage, idx *common.Idx) (*common.Account, error) {
|
||||
if idx == nil {
|
||||
return nil, errors.New("idx cannot be nil")
|
||||
}
|
||||
idxBytes, err := idx.Bytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -275,12 +281,12 @@ func getAccountInTreeDB(sto db.Storage, idx common.Idx) (*common.Account, error)
|
||||
// StateDB.mt==nil, MerkleTree is not affected, otherwise updates the
|
||||
// MerkleTree, returning a CircomProcessorProof.
|
||||
func (s *StateDB) CreateAccount(idx common.Idx, account *common.Account) (*merkletree.CircomProcessorProof, error) {
|
||||
cpp, err := createAccountInTreeDB(s.db, s.mt, idx, account)
|
||||
cpp, err := createAccountInTreeDB(s.db, s.mt, &idx, account)
|
||||
if err != nil {
|
||||
return cpp, err
|
||||
}
|
||||
// store idx by EthAddr & BJJ
|
||||
err = s.setIdxByEthAddrBJJ(idx, account.EthAddr, account.PublicKey)
|
||||
err = s.setIdxByEthAddrBJJ(idx, &account.EthAddr, account.PublicKey)
|
||||
return cpp, err
|
||||
}
|
||||
|
||||
@@ -288,7 +294,10 @@ func (s *StateDB) CreateAccount(idx common.Idx, account *common.Account) (*merkl
|
||||
// from ExitTree. Creates a new Account in the StateDB for the given Idx. If
|
||||
// StateDB.mt==nil, MerkleTree is not affected, otherwise updates the
|
||||
// MerkleTree, returning a CircomProcessorProof.
|
||||
func createAccountInTreeDB(sto db.Storage, mt *merkletree.MerkleTree, idx common.Idx, account *common.Account) (*merkletree.CircomProcessorProof, error) {
|
||||
func createAccountInTreeDB(sto db.Storage, mt *merkletree.MerkleTree, idx *common.Idx, account *common.Account) (*merkletree.CircomProcessorProof, error) {
|
||||
if idx == nil {
|
||||
return nil, errors.New("idx cannot be nil")
|
||||
}
|
||||
// store at the DB the key: v, and value: leaf.Bytes()
|
||||
v, err := account.HashValue()
|
||||
if err != nil {
|
||||
@@ -337,7 +346,10 @@ func createAccountInTreeDB(sto db.Storage, mt *merkletree.MerkleTree, idx common
|
||||
// UpdateAccount updates the Account in the StateDB for the given Idx. If
|
||||
// StateDB.mt==nil, MerkleTree is not affected, otherwise updates the
|
||||
// MerkleTree, returning a CircomProcessorProof.
|
||||
func (s *StateDB) UpdateAccount(idx common.Idx, account *common.Account) (*merkletree.CircomProcessorProof, error) {
|
||||
func (s *StateDB) UpdateAccount(idx *common.Idx, account *common.Account) (*merkletree.CircomProcessorProof, error) {
|
||||
if idx == nil {
|
||||
return nil, errors.New("idx cannot be nil")
|
||||
}
|
||||
return updateAccountInTreeDB(s.db, s.mt, idx, account)
|
||||
}
|
||||
|
||||
@@ -345,7 +357,10 @@ func (s *StateDB) UpdateAccount(idx common.Idx, account *common.Account) (*merkl
|
||||
// from ExitTree. Updates the Account in the StateDB for the given Idx. If
|
||||
// StateDB.mt==nil, MerkleTree is not affected, otherwise updates the
|
||||
// MerkleTree, returning a CircomProcessorProof.
|
||||
func updateAccountInTreeDB(sto db.Storage, mt *merkletree.MerkleTree, idx common.Idx, account *common.Account) (*merkletree.CircomProcessorProof, error) {
|
||||
func updateAccountInTreeDB(sto db.Storage, mt *merkletree.MerkleTree, idx *common.Idx, account *common.Account) (*merkletree.CircomProcessorProof, error) {
|
||||
if idx == nil {
|
||||
return nil, errors.New("idx cannot be nil")
|
||||
}
|
||||
// store at the DB the key: v, and value: account.Bytes()
|
||||
v, err := account.HashValue()
|
||||
if err != nil {
|
||||
|
||||
@@ -129,7 +129,8 @@ func TestStateDBWithoutMT(t *testing.T) {
|
||||
}
|
||||
|
||||
// get non-existing account, expecting an error
|
||||
_, err = sdb.GetAccount(common.Idx(1))
|
||||
unexistingAccount := common.Idx(1)
|
||||
_, err = sdb.GetAccount(&unexistingAccount)
|
||||
assert.NotNil(t, err)
|
||||
assert.Equal(t, db.ErrNotFound, err)
|
||||
|
||||
@@ -140,13 +141,15 @@ func TestStateDBWithoutMT(t *testing.T) {
|
||||
}
|
||||
|
||||
for i := 0; i < len(accounts); i++ {
|
||||
accGetted, err := sdb.GetAccount(common.Idx(i))
|
||||
existingAccount := common.Idx(i)
|
||||
accGetted, err := sdb.GetAccount(&existingAccount)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, accounts[i], accGetted)
|
||||
}
|
||||
|
||||
// try already existing idx and get error
|
||||
_, err = sdb.GetAccount(common.Idx(1)) // check that exist
|
||||
existingAccount := common.Idx(1)
|
||||
_, err = sdb.GetAccount(&existingAccount) // check that exist
|
||||
assert.Nil(t, err)
|
||||
_, err = sdb.CreateAccount(common.Idx(1), accounts[1]) // check that can not be created twice
|
||||
assert.NotNil(t, err)
|
||||
@@ -155,7 +158,8 @@ func TestStateDBWithoutMT(t *testing.T) {
|
||||
// update accounts
|
||||
for i := 0; i < len(accounts); i++ {
|
||||
accounts[i].Nonce = accounts[i].Nonce + 1
|
||||
_, err = sdb.UpdateAccount(common.Idx(i), accounts[i])
|
||||
existingAccount = common.Idx(i)
|
||||
_, err = sdb.UpdateAccount(&existingAccount, accounts[i])
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
@@ -178,7 +182,8 @@ func TestStateDBWithMT(t *testing.T) {
|
||||
}
|
||||
|
||||
// get non-existing account, expecting an error
|
||||
_, err = sdb.GetAccount(common.Idx(1))
|
||||
accountIdx := common.Idx(1)
|
||||
_, err = sdb.GetAccount(&accountIdx)
|
||||
assert.NotNil(t, err)
|
||||
assert.Equal(t, db.ErrNotFound, err)
|
||||
|
||||
@@ -189,13 +194,15 @@ func TestStateDBWithMT(t *testing.T) {
|
||||
}
|
||||
|
||||
for i := 0; i < len(accounts); i++ {
|
||||
accGetted, err := sdb.GetAccount(common.Idx(i))
|
||||
accountIdx = common.Idx(i)
|
||||
accGetted, err := sdb.GetAccount(&accountIdx)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, accounts[i], accGetted)
|
||||
}
|
||||
|
||||
// try already existing idx and get error
|
||||
_, err = sdb.GetAccount(common.Idx(1)) // check that exist
|
||||
accountIdx = 1
|
||||
_, err = sdb.GetAccount(&accountIdx) // check that exist
|
||||
assert.Nil(t, err)
|
||||
_, err = sdb.CreateAccount(common.Idx(1), accounts[1]) // check that can not be created twice
|
||||
assert.NotNil(t, err)
|
||||
@@ -207,10 +214,12 @@ func TestStateDBWithMT(t *testing.T) {
|
||||
// update accounts
|
||||
for i := 0; i < len(accounts); i++ {
|
||||
accounts[i].Nonce = accounts[i].Nonce + 1
|
||||
_, err = sdb.UpdateAccount(common.Idx(i), accounts[i])
|
||||
accountIdx = common.Idx(i)
|
||||
_, err = sdb.UpdateAccount(&accountIdx, accounts[i])
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
a, err := sdb.GetAccount(common.Idx(1)) // check that account value has been updated
|
||||
accountIdx = 1
|
||||
a, err := sdb.GetAccount(&accountIdx) // check that account value has been updated
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, accounts[1].Nonce, a.Nonce)
|
||||
}
|
||||
|
||||
@@ -227,7 +227,11 @@ func (s *StateDB) processL1Tx(exitTree *merkletree.MerkleTree, tx *common.L1Tx)
|
||||
if s.zki != nil {
|
||||
// Txs
|
||||
// s.zki.TxCompressedData[s.i] = tx.TxCompressedData() // uncomment once L1Tx.TxCompressedData is ready
|
||||
if tx.FromIdx != nil {
|
||||
s.zki.FromIdx[s.i] = tx.FromIdx.BigInt()
|
||||
} else {
|
||||
s.zki.FromIdx[s.i] = big.NewInt(0)
|
||||
}
|
||||
s.zki.ToIdx[s.i] = tx.ToIdx.BigInt()
|
||||
s.zki.OnChain[s.i] = big.NewInt(1)
|
||||
|
||||
@@ -292,7 +296,7 @@ func (s *StateDB) processL1Tx(exitTree *merkletree.MerkleTree, tx *common.L1Tx)
|
||||
if err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
return &tx.FromIdx, exitAccount, newExit, nil
|
||||
return tx.FromIdx, exitAccount, newExit, nil
|
||||
default:
|
||||
}
|
||||
|
||||
@@ -307,7 +311,7 @@ func (s *StateDB) processL2Tx(exitTree *merkletree.MerkleTree, tx *common.PoolL2
|
||||
var err error
|
||||
var auxToIdx common.Idx
|
||||
// if tx.ToIdx==0, get toIdx by ToEthAddr or ToBJJ
|
||||
if tx.ToIdx == common.Idx(0) {
|
||||
if tx.ToIdx == nil || *tx.ToIdx == common.Idx(0) {
|
||||
auxToIdx, err = s.GetIdxByEthAddrBJJ(tx.ToEthAddr, tx.ToBJJ)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
@@ -324,7 +328,7 @@ func (s *StateDB) processL2Tx(exitTree *merkletree.MerkleTree, tx *common.PoolL2
|
||||
s.zki.ToIdx[s.i] = tx.ToIdx.BigInt()
|
||||
|
||||
// fill AuxToIdx if needed
|
||||
if tx.ToIdx == common.Idx(0) {
|
||||
if tx.ToIdx == nil {
|
||||
// use toIdx that can have been filled by tx.ToIdx or
|
||||
// if tx.Idx==0 (this case), toIdx is filled by the Idx
|
||||
// from db by ToEthAddr&ToBJJ
|
||||
@@ -332,7 +336,12 @@ func (s *StateDB) processL2Tx(exitTree *merkletree.MerkleTree, tx *common.PoolL2
|
||||
}
|
||||
|
||||
s.zki.ToBJJAy[s.i] = tx.ToBJJ.Y
|
||||
s.zki.ToEthAddr[s.i] = common.EthAddrToBigInt(tx.ToEthAddr)
|
||||
if tx.ToEthAddr != nil {
|
||||
s.zki.ToEthAddr[s.i] = common.EthAddrToBigInt(*tx.ToEthAddr)
|
||||
} else {
|
||||
// Not sure if this should throw an error
|
||||
s.zki.ToEthAddr[s.i] = big.NewInt(0)
|
||||
}
|
||||
|
||||
s.zki.OnChain[s.i] = big.NewInt(0)
|
||||
s.zki.NewAccount[s.i] = big.NewInt(0)
|
||||
@@ -362,13 +371,21 @@ func (s *StateDB) processL2Tx(exitTree *merkletree.MerkleTree, tx *common.PoolL2
|
||||
case common.TxTypeTransfer:
|
||||
// go to the MT account of sender and receiver, and update
|
||||
// balance & nonce
|
||||
err = s.applyTransfer(tx.Tx(), auxToIdx)
|
||||
tmpTx, err := tx.Tx()
|
||||
if err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
err = s.applyTransfer(tmpTx, auxToIdx)
|
||||
if err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
case common.TxTypeExit:
|
||||
// execute exit flow
|
||||
exitAccount, newExit, err := s.applyExit(exitTree, tx.Tx())
|
||||
tmpTx, err := tx.Tx()
|
||||
if err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
exitAccount, newExit, err := s.applyExit(exitTree, tmpTx)
|
||||
if err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
@@ -428,7 +445,7 @@ func (s *StateDB) applyDeposit(tx *common.L1Tx, transfer bool) error {
|
||||
// in case that the tx is a L1Tx>DepositTransfer
|
||||
var accReceiver *common.Account
|
||||
if transfer {
|
||||
accReceiver, err = s.GetAccount(tx.ToIdx)
|
||||
accReceiver, err = s.GetAccount(&tx.ToIdx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -458,7 +475,7 @@ func (s *StateDB) applyDeposit(tx *common.L1Tx, transfer bool) error {
|
||||
// this is done after updating Sender Account (depositer)
|
||||
if transfer {
|
||||
// update receiver account in localStateDB
|
||||
p, err := s.UpdateAccount(tx.ToIdx, accReceiver)
|
||||
p, err := s.UpdateAccount(&tx.ToIdx, accReceiver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -487,14 +504,17 @@ func (s *StateDB) applyDeposit(tx *common.L1Tx, transfer bool) error {
|
||||
// the real ToIdx is found trhrough the ToEthAddr or ToBJJ.
|
||||
func (s *StateDB) applyTransfer(tx *common.Tx, auxToIdx common.Idx) error {
|
||||
if auxToIdx == 0 {
|
||||
auxToIdx = tx.ToIdx
|
||||
if tx.ToIdx == nil {
|
||||
return errors.New("tx.ToIdx cannot be nil if auxToIdx is 0")
|
||||
}
|
||||
auxToIdx = *tx.ToIdx
|
||||
}
|
||||
// get sender and receiver accounts from localStateDB
|
||||
accSender, err := s.GetAccount(tx.FromIdx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
accReceiver, err := s.GetAccount(auxToIdx)
|
||||
accReceiver, err := s.GetAccount(&auxToIdx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -525,7 +545,7 @@ func (s *StateDB) applyTransfer(tx *common.Tx, auxToIdx common.Idx) error {
|
||||
}
|
||||
|
||||
// update receiver account in localStateDB
|
||||
pReceiver, err := s.UpdateAccount(auxToIdx, accReceiver)
|
||||
pReceiver, err := s.UpdateAccount(&auxToIdx, accReceiver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -555,7 +575,7 @@ func (s *StateDB) applyCreateAccountDepositTransfer(tx *common.L1Tx) error {
|
||||
EthAddr: tx.FromEthAddr,
|
||||
}
|
||||
accSender.Balance = new(big.Int).Add(accSender.Balance, tx.LoadAmount)
|
||||
accReceiver, err := s.GetAccount(tx.ToIdx)
|
||||
accReceiver, err := s.GetAccount(&tx.ToIdx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -587,7 +607,7 @@ func (s *StateDB) applyCreateAccountDepositTransfer(tx *common.L1Tx) error {
|
||||
}
|
||||
|
||||
// update receiver account in localStateDB
|
||||
p, err = s.UpdateAccount(tx.ToIdx, accReceiver)
|
||||
p, err = s.UpdateAccount(&tx.ToIdx, accReceiver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -40,7 +40,8 @@ func TestProcessTxs(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
acc, err := sdb.GetAccount(common.Idx(256))
|
||||
accountIdx := common.Idx(256)
|
||||
acc, err := sdb.GetAccount(&accountIdx)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "23", acc.Balance.String())
|
||||
}
|
||||
@@ -79,7 +80,8 @@ func TestProcessTxsSynchronizer(t *testing.T) {
|
||||
// Nonce & TokenID =0, after ProcessTxs call has the expected value
|
||||
|
||||
assert.Equal(t, 0, len(exitInfos))
|
||||
acc, err := sdb.GetAccount(common.Idx(256))
|
||||
accountIdx := common.Idx(256)
|
||||
acc, err := sdb.GetAccount(&accountIdx)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "28", acc.Balance.String())
|
||||
|
||||
@@ -88,7 +90,7 @@ func TestProcessTxsSynchronizer(t *testing.T) {
|
||||
_, exitInfos, err = sdb.ProcessTxs(l1Txs[1], coordinatorL1Txs[1], poolL2Txs[1])
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 5, len(exitInfos))
|
||||
acc, err = sdb.GetAccount(common.Idx(256))
|
||||
acc, err = sdb.GetAccount(&accountIdx)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "48", acc.Balance.String())
|
||||
|
||||
@@ -97,7 +99,7 @@ func TestProcessTxsSynchronizer(t *testing.T) {
|
||||
_, exitInfos, err = sdb.ProcessTxs(l1Txs[2], coordinatorL1Txs[2], poolL2Txs[2])
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 1, len(exitInfos))
|
||||
acc, err = sdb.GetAccount(common.Idx(256))
|
||||
acc, err = sdb.GetAccount(&accountIdx)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "23", acc.Balance.String())
|
||||
}
|
||||
@@ -130,7 +132,8 @@ func TestProcessTxsBatchBuilder(t *testing.T) {
|
||||
_, exitInfos, err := sdb.ProcessTxs(l1Txs[0], coordinatorL1Txs[0], poolL2Txs[0])
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 0, len(exitInfos))
|
||||
acc, err := sdb.GetAccount(common.Idx(256))
|
||||
accountIdx := common.Idx(256)
|
||||
acc, err := sdb.GetAccount(&accountIdx)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "28", acc.Balance.String())
|
||||
|
||||
@@ -139,7 +142,7 @@ func TestProcessTxsBatchBuilder(t *testing.T) {
|
||||
_, exitInfos, err = sdb.ProcessTxs(l1Txs[1], coordinatorL1Txs[1], poolL2Txs[1])
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 5, len(exitInfos))
|
||||
acc, err = sdb.GetAccount(common.Idx(256))
|
||||
acc, err = sdb.GetAccount(&accountIdx)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "48", acc.Balance.String())
|
||||
|
||||
@@ -148,7 +151,7 @@ func TestProcessTxsBatchBuilder(t *testing.T) {
|
||||
_, exitInfos, err = sdb.ProcessTxs(l1Txs[2], coordinatorL1Txs[2], poolL2Txs[2])
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 1, len(exitInfos))
|
||||
acc, err = sdb.GetAccount(common.Idx(256))
|
||||
acc, err = sdb.GetAccount(&accountIdx)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "23", acc.Balance.String())
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package statedb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
ethCommon "github.com/ethereum/go-ethereum/common"
|
||||
@@ -11,7 +12,7 @@ import (
|
||||
"github.com/iden3/go-merkletree"
|
||||
)
|
||||
|
||||
func concatEthAddrBJJ(addr ethCommon.Address, pk *babyjub.PublicKey) []byte {
|
||||
func concatEthAddrBJJ(addr *ethCommon.Address, pk *babyjub.PublicKey) []byte {
|
||||
pkComp := pk.Compress()
|
||||
var b []byte
|
||||
b = append(b, addr.Bytes()...)
|
||||
@@ -24,7 +25,7 @@ func concatEthAddrBJJ(addr ethCommon.Address, pk *babyjub.PublicKey) []byte {
|
||||
// - key: EthAddr & BabyJubJub PublicKey Compressed, value: idx
|
||||
// If Idx already exist for the given EthAddr & BJJ, the remaining Idx will be
|
||||
// always the smallest one.
|
||||
func (s *StateDB) setIdxByEthAddrBJJ(idx common.Idx, addr ethCommon.Address, pk *babyjub.PublicKey) error {
|
||||
func (s *StateDB) setIdxByEthAddrBJJ(idx common.Idx, addr *ethCommon.Address, pk *babyjub.PublicKey) error {
|
||||
oldIdx, err := s.GetIdxByEthAddrBJJ(addr, pk)
|
||||
if err == nil {
|
||||
// EthAddr & BJJ already have an Idx
|
||||
@@ -70,7 +71,10 @@ func (s *StateDB) setIdxByEthAddrBJJ(idx common.Idx, addr ethCommon.Address, pk
|
||||
// GetIdxByEthAddr returns the smallest Idx in the StateDB for the given
|
||||
// Ethereum Address. Will return common.Idx(0) and error in case that Idx is
|
||||
// not found in the StateDB.
|
||||
func (s *StateDB) GetIdxByEthAddr(addr ethCommon.Address) (common.Idx, error) {
|
||||
func (s *StateDB) GetIdxByEthAddr(addr *ethCommon.Address) (common.Idx, error) {
|
||||
if addr == nil {
|
||||
return 0, errors.New("addr cannot be nil")
|
||||
}
|
||||
b, err := s.db.Get(addr.Bytes())
|
||||
if err != nil {
|
||||
return common.Idx(0), ErrToIdxNotFound
|
||||
@@ -87,7 +91,10 @@ func (s *StateDB) GetIdxByEthAddr(addr ethCommon.Address) (common.Idx, error) {
|
||||
// address, it's ignored in the query. If `pk` is nil, it's ignored in the
|
||||
// query. Will return common.Idx(0) and error in case that Idx is not found in
|
||||
// the StateDB.
|
||||
func (s *StateDB) GetIdxByEthAddrBJJ(addr ethCommon.Address, pk *babyjub.PublicKey) (common.Idx, error) {
|
||||
func (s *StateDB) GetIdxByEthAddrBJJ(addr *ethCommon.Address, pk *babyjub.PublicKey) (common.Idx, error) {
|
||||
if addr == nil {
|
||||
return 0, errors.New("addr cannot be nil")
|
||||
}
|
||||
if !bytes.Equal(addr.Bytes(), common.EmptyAddr.Bytes()) && pk == nil {
|
||||
// case ToEthAddr!=0 && ToBJJ=0
|
||||
return s.GetIdxByEthAddr(addr)
|
||||
|
||||
@@ -32,47 +32,47 @@ func TestGetIdx(t *testing.T) {
|
||||
idx3 := common.Idx(1233)
|
||||
|
||||
// store the keys for idx by Addr & BJJ
|
||||
err = sdb.setIdxByEthAddrBJJ(idx, addr, pk)
|
||||
err = sdb.setIdxByEthAddrBJJ(idx, &addr, pk)
|
||||
require.Nil(t, err)
|
||||
|
||||
idxR, err := sdb.GetIdxByEthAddrBJJ(addr, pk)
|
||||
idxR, err := sdb.GetIdxByEthAddrBJJ(&addr, pk)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, idx, idxR)
|
||||
|
||||
// expect error when getting only by EthAddr, as value does not exist
|
||||
// in the db for only EthAddr
|
||||
_, err = sdb.GetIdxByEthAddr(addr)
|
||||
_, err = sdb.GetIdxByEthAddr(&addr)
|
||||
assert.Nil(t, err)
|
||||
_, err = sdb.GetIdxByEthAddr(addr2)
|
||||
_, err = sdb.GetIdxByEthAddr(&addr2)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
// expect to fail
|
||||
idxR, err = sdb.GetIdxByEthAddrBJJ(addr2, pk)
|
||||
idxR, err = sdb.GetIdxByEthAddrBJJ(&addr2, pk)
|
||||
assert.NotNil(t, err)
|
||||
assert.Equal(t, common.Idx(0), idxR)
|
||||
idxR, err = sdb.GetIdxByEthAddrBJJ(addr, pk2)
|
||||
idxR, err = sdb.GetIdxByEthAddrBJJ(&addr, pk2)
|
||||
assert.NotNil(t, err)
|
||||
assert.Equal(t, common.Idx(0), idxR)
|
||||
|
||||
// try to store bigger idx, will not affect as already exist a smaller
|
||||
// Idx for that Addr & BJJ
|
||||
err = sdb.setIdxByEthAddrBJJ(idx2, addr, pk)
|
||||
err = sdb.setIdxByEthAddrBJJ(idx2, &addr, pk)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// store smaller idx
|
||||
err = sdb.setIdxByEthAddrBJJ(idx3, addr, pk)
|
||||
err = sdb.setIdxByEthAddrBJJ(idx3, &addr, pk)
|
||||
assert.Nil(t, err)
|
||||
|
||||
idxR, err = sdb.GetIdxByEthAddrBJJ(addr, pk)
|
||||
idxR, err = sdb.GetIdxByEthAddrBJJ(&addr, pk)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, idx3, idxR)
|
||||
|
||||
// by EthAddr should work
|
||||
idxR, err = sdb.GetIdxByEthAddr(addr)
|
||||
idxR, err = sdb.GetIdxByEthAddr(&addr)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, idx3, idxR)
|
||||
// expect error when trying to get Idx by addr2 & pk2
|
||||
idxR, err = sdb.GetIdxByEthAddrBJJ(addr2, pk2)
|
||||
idxR, err = sdb.GetIdxByEthAddrBJJ(&addr2, pk2)
|
||||
assert.NotNil(t, err)
|
||||
assert.Equal(t, ErrToIdxNotFound, err)
|
||||
assert.Equal(t, common.Idx(0), idxR)
|
||||
|
||||
@@ -340,13 +340,15 @@ func (s *Synchronizer) rollupSync(blockNum int64) (*rollupData, error) {
|
||||
}
|
||||
|
||||
// TODO: Replace GetLastL1TxsNum by GetNextL1TxsNum
|
||||
nextForgeL1TxsNum := int64(0)
|
||||
var nextForgeL1TxsNum int64
|
||||
nextForgeL1TxsNumPtr, err := s.historyDB.GetLastL1TxsNum()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if nextForgeL1TxsNumPtr != nil {
|
||||
nextForgeL1TxsNum = *nextForgeL1TxsNumPtr + 1
|
||||
} else {
|
||||
nextForgeL1TxsNum = 0
|
||||
}
|
||||
|
||||
// Get newLastIdx that will be used to complete the accounts
|
||||
@@ -371,11 +373,9 @@ func (s *Synchronizer) rollupSync(blockNum int64) (*rollupData, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
forgeL1TxsNum := int64(0)
|
||||
forgeL1TxsNum := nextForgeL1TxsNum
|
||||
// Check if this is a L1Batch to get L1 Tx from it
|
||||
if forgeBatchArgs.L1Batch {
|
||||
forgeL1TxsNum = nextForgeL1TxsNum
|
||||
|
||||
// Get L1 User Txs from History DB
|
||||
// TODO: Get L1TX from HistoryDB filtered by toforgeL1txNum & fromidx = 0 and
|
||||
// update batch number and add accounts to createdAccounts updating idx
|
||||
@@ -395,7 +395,7 @@ func (s *Synchronizer) rollupSync(blockNum int64) (*rollupData, error) {
|
||||
// Get L1 Coordinator Txs
|
||||
for _, l1CoordinatorTx := range forgeBatchArgs.L1CoordinatorTxs {
|
||||
l1CoordinatorTx.Position = position
|
||||
l1CoordinatorTx.ToForgeL1TxsNum = nextForgeL1TxsNum
|
||||
l1CoordinatorTx.ToForgeL1TxsNum = &forgeL1TxsNum
|
||||
l1CoordinatorTx.UserOrigin = false
|
||||
l1CoordinatorTx.EthBlockNum = blockNum
|
||||
bn := new(common.BatchNum)
|
||||
@@ -440,7 +440,10 @@ func (s *Synchronizer) rollupSync(blockNum int64) (*rollupData, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l2Txs := common.PoolL2TxsToL2Txs(poolL2Txs) // TODO: This is a big uggly, find a better way
|
||||
l2Txs, err := common.PoolL2TxsToL2Txs(poolL2Txs) // TODO: This is a big uggly, find a better way
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
batchData.l2Txs = append(batchData.l2Txs, l2Txs...)
|
||||
|
||||
batchData.exitTree = exitInfo
|
||||
@@ -454,7 +457,7 @@ func (s *Synchronizer) rollupSync(blockNum int64) (*rollupData, error) {
|
||||
StateRoot: common.Hash(forgeBatchArgs.NewStRoot.Bytes()),
|
||||
NumAccounts: numAccounts,
|
||||
ExitRoot: common.Hash(forgeBatchArgs.NewExitRoot.Bytes()),
|
||||
ForgeL1TxsNum: forgeL1TxsNum,
|
||||
ForgeL1TxsNum: &forgeL1TxsNum,
|
||||
// SlotNum: TODO: Calculate once ethClient provides the info // calculate from blockNum + ethClient Constants
|
||||
}
|
||||
batchData.batch = batch
|
||||
@@ -573,7 +576,9 @@ func getL1UserTx(l1UserTxEvents []eth.RollupEventL1UserTx, blockNum int64) ([]*c
|
||||
|
||||
for _, eL1UserTx := range l1UserTxEvents {
|
||||
// Fill aditional Tx fields
|
||||
eL1UserTx.L1Tx.ToForgeL1TxsNum = eL1UserTx.ToForgeL1TxsNum
|
||||
toForge := new(int64)
|
||||
*toForge = eL1UserTx.ToForgeL1TxsNum
|
||||
eL1UserTx.L1Tx.ToForgeL1TxsNum = toForge
|
||||
eL1UserTx.L1Tx.Position = eL1UserTx.Position
|
||||
eL1UserTx.L1Tx.UserOrigin = true
|
||||
eL1UserTx.L1Tx.EthBlockNum = blockNum
|
||||
|
||||
@@ -566,7 +566,7 @@ func (c *Client) CtlAddL1TxUser(l1Tx *common.L1Tx) {
|
||||
r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
|
||||
queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
|
||||
}
|
||||
if int64(l1Tx.FromIdx) > r.State.CurrentIdx {
|
||||
if l1Tx.FromIdx != nil && int64(*l1Tx.FromIdx) > r.State.CurrentIdx {
|
||||
panic("l1Tx.FromIdx > r.State.CurrentIdx")
|
||||
}
|
||||
if int(l1Tx.TokenID)+1 > len(r.State.TokenList) {
|
||||
|
||||
@@ -140,7 +140,7 @@ func TestClientRollup(t *testing.T) {
|
||||
for i := 0; i < N; i++ {
|
||||
keys[i] = genKeys(int64(i))
|
||||
l1UserTx := common.L1Tx{
|
||||
FromIdx: common.Idx(0),
|
||||
FromIdx: nil,
|
||||
FromEthAddr: keys[i].Addr,
|
||||
FromBJJ: keys[i].BJJPublicKey,
|
||||
TokenID: common.TokenID(0),
|
||||
|
||||
@@ -74,7 +74,9 @@ func GenBatches(nBatches int, blocks []common.Block) []common.Batch {
|
||||
SlotNum: common.SlotNum(i),
|
||||
}
|
||||
if i%2 == 0 {
|
||||
batch.ForgeL1TxsNum = int64(i)
|
||||
toForge := new(int64)
|
||||
*toForge = int64(i)
|
||||
batch.ForgeL1TxsNum = toForge
|
||||
}
|
||||
batches = append(batches, batch)
|
||||
}
|
||||
@@ -155,7 +157,7 @@ func GenL1Txs(
|
||||
panic(err)
|
||||
}
|
||||
tx = *nTx
|
||||
if batches[i%len(batches)].ForgeL1TxsNum != 0 {
|
||||
if batches[i%len(batches)].ForgeL1TxsNum != nil {
|
||||
// Add already forged txs
|
||||
tx.BatchNum = &batches[i%len(batches)].BatchNum
|
||||
setFromToAndAppend(fromIdx, tx, i, nUserTxs, userAddr, accounts, &userTxs, &othersTxs)
|
||||
@@ -170,13 +172,13 @@ func GenL1Txs(
|
||||
}
|
||||
|
||||
// GetNextToForgeNumAndBatch returns the next BatchNum and ForgeL1TxsNum to be added
|
||||
func GetNextToForgeNumAndBatch(batches []common.Batch) (common.BatchNum, int64) {
|
||||
func GetNextToForgeNumAndBatch(batches []common.Batch) (common.BatchNum, *int64) {
|
||||
batchNum := batches[len(batches)-1].BatchNum + 1
|
||||
var toForgeL1TxsNum int64
|
||||
toForgeL1TxsNum := new(int64)
|
||||
found := false
|
||||
for i := len(batches) - 1; i >= 0; i-- {
|
||||
if batches[i].ForgeL1TxsNum != 0 {
|
||||
toForgeL1TxsNum = batches[i].ForgeL1TxsNum + 1
|
||||
if batches[i].ForgeL1TxsNum != nil {
|
||||
*toForgeL1TxsNum = *batches[i].ForgeL1TxsNum + 1
|
||||
found = true
|
||||
break
|
||||
}
|
||||
@@ -218,7 +220,9 @@ func setFromToAndAppend(
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
tx.FromIdx = from.Idx
|
||||
fromIdx := new(common.Idx)
|
||||
*fromIdx = from.Idx
|
||||
tx.FromIdx = fromIdx
|
||||
tx.FromEthAddr = from.EthAddr
|
||||
tx.FromBJJ = from.PublicKey
|
||||
tx.ToIdx = to.Idx
|
||||
@@ -232,7 +236,9 @@ func setFromToAndAppend(
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tx.FromIdx = from.Idx
|
||||
fromIdx := new(common.Idx)
|
||||
*fromIdx = from.Idx
|
||||
tx.FromIdx = fromIdx
|
||||
tx.FromEthAddr = from.EthAddr
|
||||
tx.FromBJJ = from.PublicKey
|
||||
tx.ToIdx = to.Idx
|
||||
@@ -435,9 +441,6 @@ func randomTxType(seed int) common.TxType {
|
||||
case 0:
|
||||
return common.TxTypeExit
|
||||
//nolint:gomnd
|
||||
case 1:
|
||||
return common.TxTypeWithdrawn
|
||||
//nolint:gomnd
|
||||
case 2:
|
||||
return common.TxTypeTransfer
|
||||
//nolint:gomnd
|
||||
|
||||
37
test/l2db.go
37
test/l2db.go
@@ -53,10 +53,14 @@ func GenPoolTxs(n int, tokens []common.Token) []*common.PoolL2Tx {
|
||||
*usd = *token.USD * amountF
|
||||
*absFee = fee.Percentage() * *usd
|
||||
}
|
||||
toIdx := new(common.Idx)
|
||||
*toIdx = common.Idx(i + 1)
|
||||
toEthAddr := new(ethCommon.Address)
|
||||
*toEthAddr = ethCommon.BigToAddress(big.NewInt(int64(i)))
|
||||
tx := &common.PoolL2Tx{
|
||||
FromIdx: common.Idx(i),
|
||||
ToIdx: common.Idx(i + 1),
|
||||
ToEthAddr: ethCommon.BigToAddress(big.NewInt(int64(i))),
|
||||
ToIdx: toIdx,
|
||||
ToEthAddr: toEthAddr,
|
||||
ToBJJ: privK.Public(),
|
||||
TokenID: token.TokenID,
|
||||
Amount: big.NewInt(int64(i)),
|
||||
@@ -67,7 +71,6 @@ func GenPoolTxs(n int, tokens []common.Token) []*common.PoolL2Tx {
|
||||
State: state,
|
||||
Signature: privK.SignPoseidon(big.NewInt(int64(i))),
|
||||
Timestamp: time.Now().UTC(),
|
||||
TokenSymbol: token.Symbol,
|
||||
AbsoluteFee: absFee,
|
||||
AbsoluteFeeUpdate: token.USDUpdate,
|
||||
}
|
||||
@@ -77,17 +80,31 @@ func GenPoolTxs(n int, tokens []common.Token) []*common.PoolL2Tx {
|
||||
panic(err)
|
||||
}
|
||||
if i%2 == 0 { // Optional parameters: rq
|
||||
tx.RqFromIdx = common.Idx(i)
|
||||
tx.RqToIdx = common.Idx(i + 1)
|
||||
tx.RqToEthAddr = ethCommon.BigToAddress(big.NewInt(int64(i)))
|
||||
rqFromIdx := new(common.Idx)
|
||||
*rqFromIdx = common.Idx(i)
|
||||
tx.RqFromIdx = rqFromIdx
|
||||
rqToIdx := new(common.Idx)
|
||||
*rqToIdx = common.Idx(i + 1)
|
||||
tx.RqToIdx = rqToIdx
|
||||
rqToEthAddr := new(ethCommon.Address)
|
||||
*rqToEthAddr = ethCommon.BigToAddress(big.NewInt(int64(i)))
|
||||
tx.RqToEthAddr = rqToEthAddr
|
||||
tx.RqToBJJ = privK.Public()
|
||||
tx.RqTokenID = common.TokenID(i)
|
||||
rqTokenID := new(common.TokenID)
|
||||
*rqTokenID = common.TokenID(i)
|
||||
tx.RqTokenID = rqTokenID
|
||||
tx.RqAmount = big.NewInt(int64(i))
|
||||
tx.RqFee = common.FeeSelector(i)
|
||||
tx.RqNonce = uint64(i)
|
||||
rqFee := new(common.FeeSelector)
|
||||
*rqFee = common.FeeSelector(i)
|
||||
tx.RqFee = rqFee
|
||||
rqNonce := new(uint64)
|
||||
*rqNonce = uint64(i)
|
||||
tx.RqNonce = rqNonce
|
||||
}
|
||||
if i%3 == 0 { // Optional parameters: things that get updated "a posteriori"
|
||||
tx.BatchNum = 489
|
||||
batchNum := new(common.BatchNum)
|
||||
*batchNum = 489
|
||||
tx.BatchNum = batchNum
|
||||
}
|
||||
txs = append(txs, tx)
|
||||
}
|
||||
|
||||
19
test/txs.go
19
test/txs.go
@@ -96,11 +96,16 @@ func GenerateTestTxs(t *testing.T, instructions Instructions) ([][]*common.L1Tx,
|
||||
batchCoordinatorL1Txs = append(batchCoordinatorL1Txs, &tx)
|
||||
idx++
|
||||
}
|
||||
|
||||
toIdx := new(common.Idx)
|
||||
*toIdx = accounts[idxTokenIDToString(inst.To, inst.TokenID)].Idx
|
||||
toEthAddr := new(ethCommon.Address)
|
||||
*toEthAddr = accounts[idxTokenIDToString(inst.To, inst.TokenID)].Addr
|
||||
rqToEthAddr := new(ethCommon.Address)
|
||||
*rqToEthAddr = accounts[idxTokenIDToString(inst.To, inst.TokenID)].Addr
|
||||
tx := common.PoolL2Tx{
|
||||
FromIdx: accounts[idxTokenIDToString(inst.From, inst.TokenID)].Idx,
|
||||
ToIdx: accounts[idxTokenIDToString(inst.To, inst.TokenID)].Idx,
|
||||
ToEthAddr: accounts[idxTokenIDToString(inst.To, inst.TokenID)].Addr,
|
||||
ToIdx: toIdx,
|
||||
ToEthAddr: toEthAddr,
|
||||
ToBJJ: accounts[idxTokenIDToString(inst.To, inst.TokenID)].BJJ.Public(),
|
||||
TokenID: inst.TokenID,
|
||||
Amount: big.NewInt(int64(inst.Amount)),
|
||||
@@ -108,8 +113,8 @@ func GenerateTestTxs(t *testing.T, instructions Instructions) ([][]*common.L1Tx,
|
||||
Nonce: accounts[idxTokenIDToString(inst.From, inst.TokenID)].Nonce,
|
||||
State: common.PoolL2TxStatePending,
|
||||
Timestamp: time.Now(),
|
||||
BatchNum: common.BatchNum(0),
|
||||
RqToEthAddr: accounts[idxTokenIDToString(inst.To, inst.TokenID)].Addr,
|
||||
BatchNum: nil,
|
||||
RqToEthAddr: rqToEthAddr,
|
||||
RqToBJJ: accounts[idxTokenIDToString(inst.To, inst.TokenID)].BJJ.Public(),
|
||||
Type: common.TxTypeTransfer,
|
||||
}
|
||||
@@ -130,8 +135,10 @@ func GenerateTestTxs(t *testing.T, instructions Instructions) ([][]*common.L1Tx,
|
||||
batchPoolL2Txs = append(batchPoolL2Txs, &tx)
|
||||
|
||||
case common.TxTypeExit, common.TxTypeForceExit:
|
||||
fromIdx := new(common.Idx)
|
||||
*fromIdx = accounts[idxTokenIDToString(inst.From, inst.TokenID)].Idx
|
||||
tx := common.L1Tx{
|
||||
FromIdx: accounts[idxTokenIDToString(inst.From, inst.TokenID)].Idx,
|
||||
FromIdx: fromIdx,
|
||||
ToIdx: common.Idx(1), // as is an Exit
|
||||
TokenID: inst.TokenID,
|
||||
Amount: big.NewInt(int64(inst.Amount)),
|
||||
|
||||
@@ -50,7 +50,7 @@ func TestGenerateTestL2Txs(t *testing.T) {
|
||||
// l2txs
|
||||
assert.Equal(t, common.TxTypeTransfer, l2txs[0][0].Type)
|
||||
assert.Equal(t, common.Idx(256), l2txs[0][0].FromIdx)
|
||||
assert.Equal(t, common.Idx(258), l2txs[0][0].ToIdx)
|
||||
assert.Equal(t, common.Idx(258), *l2txs[0][0].ToIdx)
|
||||
assert.Equal(t, accounts["B1"].BJJ.Public().String(), l2txs[0][0].ToBJJ.String())
|
||||
assert.Equal(t, accounts["B1"].Addr.Hex(), l2txs[0][0].ToEthAddr.Hex())
|
||||
assert.Equal(t, common.Nonce(0), l2txs[0][0].Nonce)
|
||||
|
||||
@@ -78,7 +78,7 @@ func (txsel *TxSelector) GetL2TxSelection(batchNum common.BatchNum) ([]*common.P
|
||||
// discard the txs that don't have an Account in the AccountDB
|
||||
var validTxs txs
|
||||
for _, tx := range l2TxsRaw {
|
||||
_, err = txsel.localAccountsDB.GetAccount(tx.FromIdx)
|
||||
_, err = txsel.localAccountsDB.GetAccount(&tx.FromIdx)
|
||||
if err == nil {
|
||||
// if FromIdx has an account into the AccountsDB
|
||||
validTxs = append(validTxs, tx)
|
||||
@@ -120,16 +120,7 @@ func (txsel *TxSelector) GetL1L2TxSelection(batchNum common.BatchNum, l1Txs []*c
|
||||
// in AccountCreationAuthDB, if so, tx is used and L1CoordinatorTx of
|
||||
// CreateAccountAndDeposit is created.
|
||||
for i := 0; i < len(l2TxsRaw); i++ {
|
||||
if l2TxsRaw[i].ToIdx >= common.IdxUserThreshold {
|
||||
_, err = txsel.localAccountsDB.GetAccount(l2TxsRaw[i].ToIdx)
|
||||
if err != nil {
|
||||
// tx not valid
|
||||
log.Debugw("invalid L2Tx: ToIdx not found in StateDB", "ToIdx", l2TxsRaw[i].ToIdx)
|
||||
continue
|
||||
}
|
||||
// Account found in the DB, include the l2Tx in the selection
|
||||
validTxs = append(validTxs, l2TxsRaw[i])
|
||||
} else if l2TxsRaw[i].ToIdx == common.Idx(0) {
|
||||
if l2TxsRaw[i].ToIdx == nil {
|
||||
if checkAlreadyPendingToCreate(l1CoordinatorTxs, l2TxsRaw[i].ToEthAddr, l2TxsRaw[i].ToBJJ) {
|
||||
// if L2Tx needs a new L1CoordinatorTx of CreateAccount type,
|
||||
// and a previous L2Tx in the current process already created
|
||||
@@ -215,10 +206,14 @@ func (txsel *TxSelector) GetL1L2TxSelection(batchNum common.BatchNum, l1Txs []*c
|
||||
// coordinator can create a new account without
|
||||
// L1Authorization, as ToEthAddr==0xff
|
||||
// create L1CoordinatorTx for the accountCreation
|
||||
if l2TxsRaw[i].ToEthAddr == nil {
|
||||
log.Warn("l2TxsRaw[i].ToEthAddr should not be nil")
|
||||
continue
|
||||
}
|
||||
l1CoordinatorTx := &common.L1Tx{
|
||||
Position: positionL1,
|
||||
UserOrigin: false,
|
||||
FromEthAddr: l2TxsRaw[i].ToEthAddr,
|
||||
FromEthAddr: *l2TxsRaw[i].ToEthAddr,
|
||||
FromBJJ: l2TxsRaw[i].ToBJJ,
|
||||
TokenID: l2TxsRaw[i].TokenID,
|
||||
LoadAmount: big.NewInt(0),
|
||||
@@ -227,7 +222,16 @@ func (txsel *TxSelector) GetL1L2TxSelection(batchNum common.BatchNum, l1Txs []*c
|
||||
positionL1++
|
||||
l1CoordinatorTxs = append(l1CoordinatorTxs, l1CoordinatorTx)
|
||||
}
|
||||
} else if l2TxsRaw[i].ToIdx == common.Idx(1) {
|
||||
} else if *l2TxsRaw[i].ToIdx >= common.IdxUserThreshold {
|
||||
_, err = txsel.localAccountsDB.GetAccount(l2TxsRaw[i].ToIdx)
|
||||
if err != nil {
|
||||
// tx not valid
|
||||
log.Debugw("invalid L2Tx: ToIdx not found in StateDB", "ToIdx", l2TxsRaw[i].ToIdx)
|
||||
continue
|
||||
}
|
||||
// Account found in the DB, include the l2Tx in the selection
|
||||
validTxs = append(validTxs, l2TxsRaw[i])
|
||||
} else if *l2TxsRaw[i].ToIdx == common.Idx(1) { // nil already checked before
|
||||
// valid txs (of Exit type)
|
||||
validTxs = append(validTxs, l2TxsRaw[i])
|
||||
}
|
||||
@@ -250,7 +254,11 @@ func (txsel *TxSelector) GetL1L2TxSelection(batchNum common.BatchNum, l1Txs []*c
|
||||
return l1Txs, l1CoordinatorTxs, l2Txs, nil
|
||||
}
|
||||
|
||||
func checkAlreadyPendingToCreate(l1CoordinatorTxs []*common.L1Tx, addr ethCommon.Address, bjj *babyjub.PublicKey) bool {
|
||||
func checkAlreadyPendingToCreate(l1CoordinatorTxs []*common.L1Tx, addr *ethCommon.Address, bjj *babyjub.PublicKey) bool {
|
||||
if addr == nil {
|
||||
log.Warn("The provided addr is nil")
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(l1CoordinatorTxs); i++ {
|
||||
if bytes.Equal(l1CoordinatorTxs[i].FromEthAddr.Bytes(), addr.Bytes()) {
|
||||
if bjj == nil {
|
||||
|
||||
Reference in New Issue
Block a user