mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 03:16:45 +01:00
Merge pull request #199 from hermeznetwork/feature/tkcio-tokenregister
Add transakcio Token Register instructions parser
This commit is contained in:
@@ -366,10 +366,7 @@ func (s *StateDB) processL2Tx(exitTree *merkletree.MerkleTree, tx *common.PoolL2
|
||||
return nil, nil, false, err
|
||||
}
|
||||
tx.Nonce = acc.Nonce
|
||||
// TokenID is also not set in the L2Txs from the blockchain
|
||||
// that the Synchronizer works with, but does not need to be
|
||||
// defined because is not used later for the L2Txs processing
|
||||
// (Transfer & Exit)
|
||||
tx.TokenID = acc.TokenID
|
||||
}
|
||||
|
||||
switch tx.Type {
|
||||
|
||||
@@ -22,7 +22,8 @@ func TestProcessTxsSynchronizer(t *testing.T) {
|
||||
|
||||
// generate test transactions from test.SetTest0 code
|
||||
tc := transakcio.NewTestContext()
|
||||
blocks := tc.GenerateBlocks(transakcio.SetBlockchain0)
|
||||
blocks, err := tc.GenerateBlocks(transakcio.SetBlockchain0)
|
||||
require.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 29, len(blocks[0].Batches[0].L1UserTxs))
|
||||
assert.Equal(t, 0, len(blocks[0].Batches[0].L1CoordinatorTxs))
|
||||
|
||||
@@ -5,11 +5,11 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"github.com/hermeznetwork/hermez-node/common"
|
||||
"github.com/hermeznetwork/hermez-node/log"
|
||||
)
|
||||
|
||||
var eof = rune(0)
|
||||
@@ -29,11 +29,16 @@ var setTypePoolL2 = setType("PoolL2")
|
||||
|
||||
// typeNewBatch is used for testing purposes only, and represents the
|
||||
// common.TxType of a new batch
|
||||
var typeNewBatch common.TxType = "TxTypeNewBatch"
|
||||
var typeNewBatch common.TxType = "InstrTypeNewBatch"
|
||||
|
||||
// typeNewBlock is used for testing purposes only, and represents the
|
||||
// common.TxType of a new ethereum block
|
||||
var typeNewBlock common.TxType = "TxTypeNewBlock"
|
||||
var typeNewBlock common.TxType = "InstrTypeNewBlock"
|
||||
|
||||
// typeRegisterToken is used for testing purposes only, and represents the
|
||||
// common.TxType of a new Token regsitration
|
||||
// It has 'nolint:gosec' as the string 'Token' triggers gosec as a potential leaked Token (which is not the case)
|
||||
var typeRegisterToken common.TxType = "InstrTypeRegisterToken" //nolint:gosec
|
||||
|
||||
var txTypeCreateAccountDepositCoordinator common.TxType = "TypeCreateAccountDepositCoordinator"
|
||||
|
||||
@@ -63,7 +68,6 @@ type parsedSet struct {
|
||||
// type string
|
||||
instructions []instruction
|
||||
accounts []string
|
||||
tokenIDs []common.TokenID
|
||||
}
|
||||
|
||||
func (i instruction) String() string {
|
||||
@@ -294,7 +298,28 @@ func (p *parser) parseLine(setType setType) (*instruction, error) {
|
||||
} else {
|
||||
return c, fmt.Errorf("Invalid set type: '%s'. Valid set types: 'Blockchain', 'PoolL2'", lit)
|
||||
}
|
||||
} else if lit == "RegisterToken" {
|
||||
if err := p.expectChar(c, "("); err != nil {
|
||||
return c, err
|
||||
}
|
||||
_, lit = p.scanIgnoreWhitespace()
|
||||
c.literal += lit
|
||||
tidI, err := strconv.Atoi(lit)
|
||||
if err != nil {
|
||||
line, _ := p.s.r.ReadString('\n')
|
||||
c.literal += line
|
||||
return c, err
|
||||
}
|
||||
c.tokenID = common.TokenID(tidI)
|
||||
if err := p.expectChar(c, ")"); err != nil {
|
||||
return c, err
|
||||
}
|
||||
c.typ = typeRegisterToken
|
||||
line, _ := p.s.r.ReadString('\n')
|
||||
c.literal += line
|
||||
return c, newEventLine
|
||||
}
|
||||
|
||||
if setType == "" {
|
||||
return c, fmt.Errorf("Set type not defined")
|
||||
}
|
||||
@@ -458,10 +483,9 @@ func idxTokenIDToString(idx string, tid common.TokenID) string {
|
||||
|
||||
// parse parses through reader
|
||||
func (p *parser) parse() (*parsedSet, error) {
|
||||
instructions := &parsedSet{}
|
||||
ps := &parsedSet{}
|
||||
i := 0
|
||||
accounts := make(map[string]bool)
|
||||
tokenids := make(map[common.TokenID]bool)
|
||||
var setTypeOfSet setType
|
||||
for {
|
||||
instruction, err := p.parseLine(setTypeOfSet)
|
||||
@@ -469,6 +493,9 @@ func (p *parser) parse() (*parsedSet, error) {
|
||||
break
|
||||
}
|
||||
if err == setTypeLine {
|
||||
if setTypeOfSet != "" {
|
||||
return ps, fmt.Errorf("Instruction of 'Type: %s' when there is already a previous instruction 'Type: %s' defined", instruction.typ, setTypeOfSet)
|
||||
}
|
||||
if instruction.typ == "PoolL2" {
|
||||
setTypeOfSet = setTypePoolL2
|
||||
} else if instruction.typ == "Blockchain" {
|
||||
@@ -484,30 +511,29 @@ func (p *parser) parse() (*parsedSet, error) {
|
||||
continue
|
||||
}
|
||||
if err == newEventLine {
|
||||
if instruction.typ == typeRegisterToken && instruction.tokenID == common.TokenID(0) {
|
||||
return ps, fmt.Errorf("RegisterToken can not register TokenID 0")
|
||||
}
|
||||
i++
|
||||
instructions.instructions = append(instructions.instructions, *instruction)
|
||||
ps.instructions = append(ps.instructions, *instruction)
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return instructions, fmt.Errorf("error parsing line %d: %s, err: %s", i, instruction.literal, err.Error())
|
||||
return ps, fmt.Errorf("error parsing line %d: %s, err: %s", i, instruction.literal, err.Error())
|
||||
}
|
||||
if setTypeOfSet == "" {
|
||||
return instructions, fmt.Errorf("Set type not defined")
|
||||
return ps, fmt.Errorf("Set type not defined")
|
||||
}
|
||||
instructions.instructions = append(instructions.instructions, *instruction)
|
||||
ps.instructions = append(ps.instructions, *instruction)
|
||||
accounts[instruction.from] = true
|
||||
if instruction.typ == common.TxTypeTransfer { // type: Transfer
|
||||
accounts[instruction.to] = true
|
||||
}
|
||||
tokenids[instruction.tokenID] = true
|
||||
i++
|
||||
}
|
||||
for a := range accounts {
|
||||
instructions.accounts = append(instructions.accounts, a)
|
||||
ps.accounts = append(ps.accounts, a)
|
||||
}
|
||||
sort.Strings(instructions.accounts)
|
||||
for tid := range tokenids {
|
||||
instructions.tokenIDs = append(instructions.tokenIDs, tid)
|
||||
}
|
||||
return instructions, nil
|
||||
sort.Strings(ps.accounts)
|
||||
return ps, nil
|
||||
}
|
||||
|
||||
@@ -14,6 +14,11 @@ var debug = false
|
||||
func TestParseBlockchainTxs(t *testing.T) {
|
||||
s := `
|
||||
Type: Blockchain
|
||||
|
||||
// token registrations
|
||||
RegisterToken(1)
|
||||
RegisterToken(2)
|
||||
|
||||
// deposits
|
||||
Deposit(1) A: 10
|
||||
Deposit(2) A: 20
|
||||
@@ -29,6 +34,7 @@ func TestParseBlockchainTxs(t *testing.T) {
|
||||
|
||||
// set new batch
|
||||
> batch
|
||||
RegisterToken(3)
|
||||
|
||||
DepositTransfer(1) A-B: 15, 10 (1)
|
||||
Transfer(1) C-A : 3 (1)
|
||||
@@ -53,9 +59,8 @@ func TestParseBlockchainTxs(t *testing.T) {
|
||||
parser := newParser(strings.NewReader(s))
|
||||
instructions, err := parser.parse()
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 22, len(instructions.instructions))
|
||||
assert.Equal(t, 25, len(instructions.instructions))
|
||||
assert.Equal(t, 7, len(instructions.accounts))
|
||||
assert.Equal(t, 3, len(instructions.tokenIDs))
|
||||
|
||||
if debug {
|
||||
fmt.Println(instructions)
|
||||
@@ -64,15 +69,15 @@ func TestParseBlockchainTxs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
assert.Equal(t, txTypeCreateAccountDepositCoordinator, instructions.instructions[5].typ)
|
||||
assert.Equal(t, typeNewBatch, instructions.instructions[9].typ)
|
||||
assert.Equal(t, "Deposit(1)User0:20", instructions.instructions[13].raw())
|
||||
assert.Equal(t, "Type: DepositTransfer, From: A, To: B, LoadAmount: 15, Amount: 10, Fee: 1, TokenID: 1\n", instructions.instructions[10].String())
|
||||
assert.Equal(t, "Type: Transfer, From: User1, To: User0, Amount: 15, Fee: 1, TokenID: 3\n", instructions.instructions[16].String())
|
||||
assert.Equal(t, "Transfer(2)A-B:15(1)", instructions.instructions[12].raw())
|
||||
assert.Equal(t, "Type: Transfer, From: A, To: B, Amount: 15, Fee: 1, TokenID: 2\n", instructions.instructions[12].String())
|
||||
assert.Equal(t, "Exit(1)A:5", instructions.instructions[21].raw())
|
||||
assert.Equal(t, "Type: Exit, From: A, Amount: 5, TokenID: 1\n", instructions.instructions[21].String())
|
||||
assert.Equal(t, txTypeCreateAccountDepositCoordinator, instructions.instructions[7].typ)
|
||||
assert.Equal(t, typeNewBatch, instructions.instructions[11].typ)
|
||||
assert.Equal(t, "Deposit(1)User0:20", instructions.instructions[16].raw())
|
||||
assert.Equal(t, "Type: DepositTransfer, From: A, To: B, LoadAmount: 15, Amount: 10, Fee: 1, TokenID: 1\n", instructions.instructions[13].String())
|
||||
assert.Equal(t, "Type: Transfer, From: User1, To: User0, Amount: 15, Fee: 1, TokenID: 3\n", instructions.instructions[19].String())
|
||||
assert.Equal(t, "Transfer(2)A-B:15(1)", instructions.instructions[15].raw())
|
||||
assert.Equal(t, "Type: Transfer, From: A, To: B, Amount: 15, Fee: 1, TokenID: 2\n", instructions.instructions[15].String())
|
||||
assert.Equal(t, "Exit(1)A:5", instructions.instructions[24].raw())
|
||||
assert.Equal(t, "Type: Exit, From: A, Amount: 5, TokenID: 1\n", instructions.instructions[24].String())
|
||||
}
|
||||
|
||||
func TestParsePoolTxs(t *testing.T) {
|
||||
@@ -90,7 +95,6 @@ func TestParsePoolTxs(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 5, len(instructions.instructions))
|
||||
assert.Equal(t, 4, len(instructions.accounts))
|
||||
assert.Equal(t, 2, len(instructions.tokenIDs))
|
||||
|
||||
if debug {
|
||||
fmt.Println(instructions)
|
||||
@@ -117,11 +121,12 @@ func TestParseErrors(t *testing.T) {
|
||||
|
||||
s = `
|
||||
Type: Blockchain
|
||||
RegisterToken(1)
|
||||
Deposit(1) A: 10 20
|
||||
`
|
||||
parser = newParser(strings.NewReader(s))
|
||||
_, err = parser.parse()
|
||||
assert.Equal(t, "error parsing line 2: 20, err: Unexpected Blockchain tx type: 20", err.Error())
|
||||
assert.Equal(t, "error parsing line 3: 20, err: Unexpected Blockchain tx type: 20", err.Error())
|
||||
|
||||
s = `
|
||||
Type: Blockchain
|
||||
@@ -141,6 +146,7 @@ func TestParseErrors(t *testing.T) {
|
||||
|
||||
s = `
|
||||
Type: Blockchain
|
||||
RegisterToken(1)
|
||||
Transfer(1) A-B: 10 (255)
|
||||
`
|
||||
parser = newParser(strings.NewReader(s))
|
||||
@@ -193,4 +199,17 @@ func TestParseErrors(t *testing.T) {
|
||||
parser = newParser(strings.NewReader(s))
|
||||
_, err = parser.parse()
|
||||
assert.Equal(t, "error parsing line 0: Type:, err: Invalid set type: 'PoolL1'. Valid set types: 'Blockchain', 'PoolL2'", err.Error())
|
||||
s = `Type: PoolL2
|
||||
Type: Blockchain`
|
||||
parser = newParser(strings.NewReader(s))
|
||||
_, err = parser.parse()
|
||||
assert.Equal(t, "Instruction of 'Type: Blockchain' when there is already a previous instruction 'Type: PoolL2' defined", err.Error())
|
||||
|
||||
s = `Type: Blockchain
|
||||
RegisterToken(1)
|
||||
RegisterToken(0)
|
||||
`
|
||||
parser = newParser(strings.NewReader(s))
|
||||
_, err = parser.parse()
|
||||
assert.Equal(t, "RegisterToken can not register TokenID 0", err.Error())
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ package transakcio
|
||||
var SetBlockchain0 = `
|
||||
// Set containing Blockchain transactions
|
||||
Type: Blockchain
|
||||
RegisterToken(1)
|
||||
RegisterToken(2)
|
||||
RegisterToken(3)
|
||||
|
||||
// deposits TokenID: 1
|
||||
CreateAccountDeposit(1) A: 50
|
||||
|
||||
@@ -16,6 +16,8 @@ func TestCompileSets(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
|
||||
tc := NewTestContext()
|
||||
_ = tc.GenerateBlocks(SetBlockchain0)
|
||||
_ = tc.GenerateBlocks(SetPool0)
|
||||
_, err = tc.GenerateBlocks(SetBlockchain0)
|
||||
assert.Nil(t, err)
|
||||
_, err = tc.GenerateBlocks(SetPool0)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package transakcio
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -10,7 +11,6 @@ import (
|
||||
ethCommon "github.com/ethereum/go-ethereum/common"
|
||||
ethCrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/hermeznetwork/hermez-node/common"
|
||||
"github.com/hermeznetwork/hermez-node/log"
|
||||
"github.com/iden3/go-iden3-crypto/babyjub"
|
||||
)
|
||||
|
||||
@@ -19,7 +19,7 @@ type TestContext struct {
|
||||
Instructions []instruction
|
||||
accountsNames []string
|
||||
Users map[string]*User
|
||||
TokenIDs []common.TokenID
|
||||
lastRegisteredTokenID common.TokenID
|
||||
l1CreatedAccounts map[string]*Account
|
||||
}
|
||||
|
||||
@@ -67,16 +67,15 @@ type BatchData struct {
|
||||
|
||||
// GenerateBlocks returns an array of BlockData for a given set. It uses the
|
||||
// accounts (keys & nonces) of the TestContext.
|
||||
func (tc *TestContext) GenerateBlocks(set string) []BlockData {
|
||||
func (tc *TestContext) GenerateBlocks(set string) ([]BlockData, error) {
|
||||
parser := newParser(strings.NewReader(set))
|
||||
parsedSet, err := parser.parse()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tc.Instructions = parsedSet.instructions
|
||||
tc.accountsNames = parsedSet.accounts
|
||||
tc.TokenIDs = parsedSet.tokenIDs
|
||||
|
||||
tc.generateKeys(tc.accountsNames)
|
||||
|
||||
@@ -88,6 +87,9 @@ func (tc *TestContext) GenerateBlocks(set string) []BlockData {
|
||||
for _, inst := range parsedSet.instructions {
|
||||
switch inst.typ {
|
||||
case common.TxTypeCreateAccountDeposit, common.TxTypeCreateAccountDepositTransfer, txTypeCreateAccountDepositCoordinator:
|
||||
if err := tc.checkIfTokenIsRegistered(inst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tx := common.L1Tx{
|
||||
// TxID
|
||||
FromEthAddr: tc.Users[inst.from].Addr,
|
||||
@@ -115,8 +117,11 @@ func (tc *TestContext) GenerateBlocks(set string) []BlockData {
|
||||
currBatch.L1UserTxs = append(currBatch.L1UserTxs, tx)
|
||||
}
|
||||
case common.TxTypeDeposit, common.TxTypeDepositTransfer:
|
||||
if err := tc.checkIfTokenIsRegistered(inst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tc.Users[inst.from].Accounts[inst.tokenID] == nil {
|
||||
log.Fatalf("Deposit at User %s for TokenID %d while account not created yet", inst.from, inst.tokenID)
|
||||
return nil, fmt.Errorf("Deposit at User %s for TokenID %d while account not created yet", inst.from, inst.tokenID)
|
||||
}
|
||||
tx := common.L1Tx{
|
||||
// TxID
|
||||
@@ -150,12 +155,15 @@ func (tc *TestContext) GenerateBlocks(set string) []BlockData {
|
||||
}
|
||||
currBatch.L1UserTxs = append(currBatch.L1UserTxs, tx)
|
||||
case common.TxTypeTransfer:
|
||||
if err := tc.checkIfTokenIsRegistered(inst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tc.Users[inst.from].Accounts[inst.tokenID] == nil {
|
||||
log.Fatalf("Transfer from User %s for TokenID %d while account not created yet", inst.from, inst.tokenID)
|
||||
return nil, fmt.Errorf("Transfer from User %s for TokenID %d while account not created yet", inst.from, inst.tokenID)
|
||||
}
|
||||
// if account of receiver does not exist, create a new CoordinatorL1Tx creating the account
|
||||
if _, ok := tc.l1CreatedAccounts[idxTokenIDToString(inst.to, inst.tokenID)]; !ok {
|
||||
log.Fatalf("Can not create Transfer for a non existing account. Batch %d, Instruction: %s", currBatchNum, inst)
|
||||
return nil, fmt.Errorf("Can not create Transfer for a non existing account. Batch %d, Instruction: %s", currBatchNum, inst)
|
||||
}
|
||||
tc.Users[inst.from].Accounts[inst.tokenID].Nonce++
|
||||
tx := common.L2Tx{
|
||||
@@ -168,13 +176,16 @@ func (tc *TestContext) GenerateBlocks(set string) []BlockData {
|
||||
}
|
||||
nTx, err := common.NewPoolL2Tx(tx.PoolL2Tx())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
tx = nTx.L2Tx()
|
||||
tx.BatchNum = common.BatchNum(currBatchNum) // when converted to PoolL2Tx BatchNum parameter is lost
|
||||
|
||||
currBatch.L2Txs = append(currBatch.L2Txs, tx)
|
||||
case common.TxTypeExit:
|
||||
if err := tc.checkIfTokenIsRegistered(inst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tc.Users[inst.from].Accounts[inst.tokenID].Nonce++
|
||||
tx := common.L2Tx{
|
||||
FromIdx: tc.Users[inst.from].Accounts[inst.tokenID].Idx,
|
||||
@@ -185,11 +196,14 @@ func (tc *TestContext) GenerateBlocks(set string) []BlockData {
|
||||
}
|
||||
nTx, err := common.NewPoolL2Tx(tx.PoolL2Tx())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
tx = nTx.L2Tx()
|
||||
currBatch.L2Txs = append(currBatch.L2Txs, tx)
|
||||
case common.TxTypeForceExit:
|
||||
if err := tc.checkIfTokenIsRegistered(inst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tx := common.L1Tx{
|
||||
FromIdx: tc.Users[inst.from].Accounts[inst.tokenID].Idx,
|
||||
ToIdx: common.Idx(1), // as is an Exit
|
||||
@@ -208,28 +222,43 @@ func (tc *TestContext) GenerateBlocks(set string) []BlockData {
|
||||
currBatch = BatchData{}
|
||||
blocks = append(blocks, currBlock)
|
||||
currBlock = BlockData{}
|
||||
case typeRegisterToken:
|
||||
newToken := common.Token{
|
||||
TokenID: inst.tokenID,
|
||||
EthBlockNum: int64(len(blocks)),
|
||||
}
|
||||
if inst.tokenID != tc.lastRegisteredTokenID+1 {
|
||||
return nil, fmt.Errorf("RegisterToken TokenID should be sequential, expected TokenID: %d, defined TokenID: %d", tc.lastRegisteredTokenID+1, inst.tokenID)
|
||||
}
|
||||
tc.lastRegisteredTokenID++
|
||||
currBlock.RegisteredTokens = append(currBlock.RegisteredTokens, newToken)
|
||||
default:
|
||||
log.Fatalf("Unexpected type: %s", inst.typ)
|
||||
return nil, fmt.Errorf("Unexpected type: %s", inst.typ)
|
||||
}
|
||||
}
|
||||
currBlock.Batches = append(currBlock.Batches, currBatch)
|
||||
blocks = append(blocks, currBlock)
|
||||
|
||||
return blocks
|
||||
return blocks, nil
|
||||
}
|
||||
func (tc *TestContext) checkIfTokenIsRegistered(inst instruction) error {
|
||||
if inst.tokenID > tc.lastRegisteredTokenID {
|
||||
return fmt.Errorf("Can not process %s: TokenID %d not registered, last registered TokenID: %d", inst.typ, inst.tokenID, tc.lastRegisteredTokenID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GeneratePoolL2Txs returns an array of common.PoolL2Tx from a given set. It
|
||||
// uses the accounts (keys & nonces) of the TestContext.
|
||||
func (tc *TestContext) GeneratePoolL2Txs(set string) []common.PoolL2Tx {
|
||||
func (tc *TestContext) GeneratePoolL2Txs(set string) ([]common.PoolL2Tx, error) {
|
||||
parser := newParser(strings.NewReader(set))
|
||||
parsedSet, err := parser.parse()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tc.Instructions = parsedSet.instructions
|
||||
tc.accountsNames = parsedSet.accounts
|
||||
tc.TokenIDs = parsedSet.tokenIDs
|
||||
|
||||
tc.generateKeys(tc.accountsNames)
|
||||
|
||||
@@ -238,10 +267,10 @@ func (tc *TestContext) GeneratePoolL2Txs(set string) []common.PoolL2Tx {
|
||||
switch inst.typ {
|
||||
case common.TxTypeTransfer:
|
||||
if tc.Users[inst.from].Accounts[inst.tokenID] == nil {
|
||||
log.Fatalf("Transfer from User %s for TokenID %d while account not created yet", inst.from, inst.tokenID)
|
||||
return nil, fmt.Errorf("Transfer from User %s for TokenID %d while account not created yet", inst.from, inst.tokenID)
|
||||
}
|
||||
if tc.Users[inst.to].Accounts[inst.tokenID] == nil {
|
||||
log.Fatalf("Transfer to User %s for TokenID %d while account not created yet", inst.to, inst.tokenID)
|
||||
return nil, fmt.Errorf("Transfer to User %s for TokenID %d while account not created yet", inst.to, inst.tokenID)
|
||||
}
|
||||
tc.Users[inst.from].Accounts[inst.tokenID].Nonce++
|
||||
// if account of receiver does not exist, don't use
|
||||
@@ -263,13 +292,13 @@ func (tc *TestContext) GeneratePoolL2Txs(set string) []common.PoolL2Tx {
|
||||
}
|
||||
nTx, err := common.NewPoolL2Tx(&tx)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
tx = *nTx
|
||||
// perform signature and set it to tx.Signature
|
||||
toSign, err := tx.HashToSign()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
sig := tc.Users[inst.to].BJJ.SignPoseidon(toSign)
|
||||
tx.Signature = sig
|
||||
@@ -287,11 +316,11 @@ func (tc *TestContext) GeneratePoolL2Txs(set string) []common.PoolL2Tx {
|
||||
}
|
||||
txs = append(txs, tx)
|
||||
default:
|
||||
log.Fatalf("instruction type unrecognized: %s", inst.typ)
|
||||
return nil, fmt.Errorf("instruction type unrecognized: %s", inst.typ)
|
||||
}
|
||||
}
|
||||
|
||||
return txs
|
||||
return txs, nil
|
||||
}
|
||||
|
||||
// generateKeys generates BabyJubJub & Address keys for the given list of
|
||||
|
||||
@@ -6,11 +6,15 @@ import (
|
||||
|
||||
"github.com/hermeznetwork/hermez-node/common"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGenerateBlocks(t *testing.T) {
|
||||
set := `
|
||||
Type: Blockchain
|
||||
RegisterToken(1)
|
||||
RegisterToken(2)
|
||||
RegisterToken(3)
|
||||
|
||||
CreateAccountDeposit(1) A: 10
|
||||
CreateAccountDeposit(2) A: 20
|
||||
@@ -51,7 +55,8 @@ func TestGenerateBlocks(t *testing.T) {
|
||||
Exit(1) A: 5
|
||||
`
|
||||
tc := NewTestContext()
|
||||
blocks := tc.GenerateBlocks(set)
|
||||
blocks, err := tc.GenerateBlocks(set)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 2, len(blocks))
|
||||
assert.Equal(t, 3, len(blocks[0].Batches))
|
||||
assert.Equal(t, 1, len(blocks[1].Batches))
|
||||
@@ -136,6 +141,9 @@ func (tc *TestContext) checkL2TxParams(t *testing.T, tx common.L2Tx, typ common.
|
||||
func TestGeneratePoolL2Txs(t *testing.T) {
|
||||
set := `
|
||||
Type: Blockchain
|
||||
RegisterToken(1)
|
||||
RegisterToken(2)
|
||||
RegisterToken(3)
|
||||
|
||||
CreateAccountDeposit(1) A: 10
|
||||
CreateAccountDeposit(2) A: 20
|
||||
@@ -149,7 +157,8 @@ func TestGeneratePoolL2Txs(t *testing.T) {
|
||||
CreateAccountDeposit(2) D: 0
|
||||
`
|
||||
tc := NewTestContext()
|
||||
_ = tc.GenerateBlocks(set)
|
||||
_, err := tc.GenerateBlocks(set)
|
||||
require.Nil(t, err)
|
||||
set = `
|
||||
Type: PoolL2
|
||||
PoolTransfer(1) A-B: 6 (1)
|
||||
@@ -162,7 +171,8 @@ func TestGeneratePoolL2Txs(t *testing.T) {
|
||||
PoolTransfer(2) B-D: 3 (1)
|
||||
PoolExit(1) A: 3
|
||||
`
|
||||
poolL2Txs := tc.GeneratePoolL2Txs(set)
|
||||
poolL2Txs, err := tc.GeneratePoolL2Txs(set)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 9, len(poolL2Txs))
|
||||
assert.Equal(t, common.TxTypeTransfer, poolL2Txs[0].Type)
|
||||
assert.Equal(t, common.TxTypeExit, poolL2Txs[8].Type)
|
||||
@@ -182,8 +192,47 @@ func TestGeneratePoolL2Txs(t *testing.T) {
|
||||
PoolTransfer(1) B-C: 3 (1)
|
||||
PoolTransfer(1) A-C: 3 (1)
|
||||
`
|
||||
poolL2Txs = tc.GeneratePoolL2Txs(set)
|
||||
poolL2Txs, err = tc.GeneratePoolL2Txs(set)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, common.Nonce(4), poolL2Txs[0].Nonce)
|
||||
assert.Equal(t, common.Nonce(2), poolL2Txs[1].Nonce)
|
||||
assert.Equal(t, common.Nonce(5), poolL2Txs[2].Nonce)
|
||||
}
|
||||
|
||||
func TestGenerateErrors(t *testing.T) {
|
||||
// unregistered token
|
||||
set := `Type: Blockchain
|
||||
CreateAccountDeposit(1) A: 5
|
||||
`
|
||||
tc := NewTestContext()
|
||||
_, err := tc.GenerateBlocks(set)
|
||||
assert.Equal(t, "Can not process CreateAccountDeposit: TokenID 1 not registered, last registered TokenID: 0", err.Error())
|
||||
|
||||
// ensure RegisterToken sequentiality and not using 0
|
||||
set = `
|
||||
Type: Blockchain
|
||||
RegisterToken(0)
|
||||
`
|
||||
tc = NewTestContext()
|
||||
_, err = tc.GenerateBlocks(set)
|
||||
require.Equal(t, "RegisterToken can not register TokenID 0", err.Error())
|
||||
|
||||
set = `
|
||||
Type: Blockchain
|
||||
RegisterToken(2)
|
||||
`
|
||||
tc = NewTestContext()
|
||||
_, err = tc.GenerateBlocks(set)
|
||||
require.Equal(t, "RegisterToken TokenID should be sequential, expected TokenID: 1, defined TokenID: 2", err.Error())
|
||||
|
||||
set = `
|
||||
Type: Blockchain
|
||||
RegisterToken(1)
|
||||
RegisterToken(2)
|
||||
RegisterToken(3)
|
||||
RegisterToken(5)
|
||||
`
|
||||
tc = NewTestContext()
|
||||
_, err = tc.GenerateBlocks(set)
|
||||
require.Equal(t, "RegisterToken TokenID should be sequential, expected TokenID: 4, defined TokenID: 5", err.Error())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user