Browse Source

Add transakcio Token Register instructions parser

feature/sql-semaphore1
arnaucube 4 years ago
parent
commit
a6006ebde7
8 changed files with 192 additions and 66 deletions
  1. +1
    -4
      db/statedb/txprocessors.go
  2. +2
    -1
      db/statedb/txprocessors_test.go
  3. +43
    -17
      test/transakcio/lang.go
  4. +32
    -13
      test/transakcio/lang_test.go
  5. +3
    -0
      test/transakcio/sets.go
  6. +4
    -2
      test/transakcio/sets_test.go
  7. +54
    -25
      test/transakcio/txs.go
  8. +53
    -4
      test/transakcio/txs_test.go

+ 1
- 4
db/statedb/txprocessors.go

@ -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 {

+ 2
- 1
db/statedb/txprocessors_test.go

@ -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))

+ 43
- 17
test/transakcio/lang.go

@ -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)
}
sort.Strings(instructions.accounts)
for tid := range tokenids {
instructions.tokenIDs = append(instructions.tokenIDs, tid)
ps.accounts = append(ps.accounts, a)
}
return instructions, nil
sort.Strings(ps.accounts)
return ps, nil
}

+ 32
- 13
test/transakcio/lang_test.go

@ -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())
}

+ 3
- 0
test/transakcio/sets.go

@ -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

+ 4
- 2
test/transakcio/sets_test.go

@ -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)
}

+ 54
- 25
test/transakcio/txs.go

@ -2,6 +2,7 @@ package transakcio
import (
"crypto/ecdsa"
"fmt"
"math/big"
"strconv"
"strings"
@ -10,17 +11,16 @@ 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"
)
// TestContext contains the data of the test
type TestContext struct {
Instructions []instruction
accountsNames []string
Users map[string]*User
TokenIDs []common.TokenID
l1CreatedAccounts map[string]*Account
Instructions []instruction
accountsNames []string
Users map[string]*User
lastRegisteredTokenID common.TokenID
l1CreatedAccounts map[string]*Account
}
// NewTestContext returns a new TestContext
@ -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

+ 53
- 4
test/transakcio/txs_test.go

@ -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())
}

Loading…
Cancel
Save