mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 11:26:44 +01:00
Merge pull request #222 from hermeznetwork/feature/txtransfertoethaddrbjj
Add TxTypeTransferToEthAddr&ToBJJ to StateDB & Til
This commit is contained in:
@@ -331,6 +331,7 @@ func (s *StateDB) processL2Tx(exitTree *merkletree.MerkleTree, tx *common.PoolL2
|
|||||||
var err error
|
var err error
|
||||||
// if tx.ToIdx==0, get toIdx by ToEthAddr or ToBJJ
|
// if tx.ToIdx==0, get toIdx by ToEthAddr or ToBJJ
|
||||||
if tx.ToIdx == common.Idx(0) && tx.AuxToIdx == common.Idx(0) {
|
if tx.ToIdx == common.Idx(0) && tx.AuxToIdx == common.Idx(0) {
|
||||||
|
// case when tx.Type== common.TxTypeTransferToEthAddr or common.TxTypeTransferToBJJ
|
||||||
tx.AuxToIdx, err = s.GetIdxByEthAddrBJJ(tx.ToEthAddr, tx.ToBJJ)
|
tx.AuxToIdx, err = s.GetIdxByEthAddrBJJ(tx.ToEthAddr, tx.ToBJJ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
@@ -390,7 +391,7 @@ func (s *StateDB) processL2Tx(exitTree *merkletree.MerkleTree, tx *common.PoolL2
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch tx.Type {
|
switch tx.Type {
|
||||||
case common.TxTypeTransfer:
|
case common.TxTypeTransfer, common.TxTypeTransferToEthAddr, common.TxTypeTransferToBJJ:
|
||||||
// go to the MT account of sender and receiver, and update
|
// go to the MT account of sender and receiver, and update
|
||||||
// balance & nonce
|
// balance & nonce
|
||||||
err = s.applyTransfer(tx.Tx(), tx.AuxToIdx)
|
err = s.applyTransfer(tx.Tx(), tx.AuxToIdx)
|
||||||
|
|||||||
@@ -70,9 +70,9 @@ type instruction struct {
|
|||||||
|
|
||||||
// parsedSet contains the full Set of Instructions representing a full code
|
// parsedSet contains the full Set of Instructions representing a full code
|
||||||
type parsedSet struct {
|
type parsedSet struct {
|
||||||
// type string
|
typ setType
|
||||||
instructions []instruction
|
instructions []instruction
|
||||||
accounts []string
|
users []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i instruction) String() string {
|
func (i instruction) String() string {
|
||||||
@@ -365,6 +365,12 @@ func (p *parser) parseLine(setType setType) (*instruction, error) {
|
|||||||
case "PoolTransfer":
|
case "PoolTransfer":
|
||||||
c.typ = common.TxTypeTransfer
|
c.typ = common.TxTypeTransfer
|
||||||
transferring = true
|
transferring = true
|
||||||
|
case "PoolTransferToEthAddr":
|
||||||
|
c.typ = common.TxTypeTransferToEthAddr
|
||||||
|
transferring = true
|
||||||
|
case "PoolTransferToBJJ":
|
||||||
|
c.typ = common.TxTypeTransferToBJJ
|
||||||
|
transferring = true
|
||||||
case "PoolExit":
|
case "PoolExit":
|
||||||
c.typ = common.TxTypeExit
|
c.typ = common.TxTypeExit
|
||||||
default:
|
default:
|
||||||
@@ -493,22 +499,21 @@ func idxTokenIDToString(idx string, tid common.TokenID) string {
|
|||||||
func (p *parser) parse() (*parsedSet, error) {
|
func (p *parser) parse() (*parsedSet, error) {
|
||||||
ps := &parsedSet{}
|
ps := &parsedSet{}
|
||||||
i := 0 // lines will start counting at line 1
|
i := 0 // lines will start counting at line 1
|
||||||
accounts := make(map[string]bool)
|
users := make(map[string]bool)
|
||||||
var setTypeOfSet setType
|
|
||||||
for {
|
for {
|
||||||
i++
|
i++
|
||||||
instruction, err := p.parseLine(setTypeOfSet)
|
instruction, err := p.parseLine(ps.typ)
|
||||||
if err == errof {
|
if err == errof {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err == setTypeLine {
|
if err == setTypeLine {
|
||||||
if setTypeOfSet != "" {
|
if ps.typ != "" {
|
||||||
return ps, fmt.Errorf("Line %d: Instruction of 'Type: %s' when there is already a previous instruction 'Type: %s' defined", i, instruction.typ, setTypeOfSet)
|
return ps, fmt.Errorf("Line %d: Instruction of 'Type: %s' when there is already a previous instruction 'Type: %s' defined", i, instruction.typ, ps.typ)
|
||||||
}
|
}
|
||||||
if instruction.typ == "PoolL2" {
|
if instruction.typ == "PoolL2" {
|
||||||
setTypeOfSet = setTypePoolL2
|
ps.typ = setTypePoolL2
|
||||||
} else if instruction.typ == "Blockchain" {
|
} else if instruction.typ == "Blockchain" {
|
||||||
setTypeOfSet = setTypeBlockchain
|
ps.typ = setTypeBlockchain
|
||||||
} else {
|
} else {
|
||||||
log.Fatalf("Line %d: Invalid set type: '%s'. Valid set types: 'Blockchain', 'PoolL2'", i, instruction.typ)
|
log.Fatalf("Line %d: Invalid set type: '%s'. Valid set types: 'Blockchain', 'PoolL2'", i, instruction.typ)
|
||||||
}
|
}
|
||||||
@@ -528,18 +533,18 @@ func (p *parser) parse() (*parsedSet, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return ps, fmt.Errorf("Line %d: %s, err: %s", i, instruction.literal, err.Error())
|
return ps, fmt.Errorf("Line %d: %s, err: %s", i, instruction.literal, err.Error())
|
||||||
}
|
}
|
||||||
if setTypeOfSet == "" {
|
if ps.typ == "" {
|
||||||
return ps, fmt.Errorf("Line %d: Set type not defined", i)
|
return ps, fmt.Errorf("Line %d: Set type not defined", i)
|
||||||
}
|
}
|
||||||
ps.instructions = append(ps.instructions, *instruction)
|
ps.instructions = append(ps.instructions, *instruction)
|
||||||
accounts[instruction.from] = true
|
users[instruction.from] = true
|
||||||
if instruction.typ == common.TxTypeTransfer { // type: Transfer
|
if instruction.typ == common.TxTypeTransfer || instruction.typ == common.TxTypeTransferToEthAddr || instruction.typ == common.TxTypeTransferToBJJ { // type: Transfer
|
||||||
accounts[instruction.to] = true
|
users[instruction.to] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for a := range accounts {
|
for u := range users {
|
||||||
ps.accounts = append(ps.accounts, a)
|
ps.users = append(ps.users, u)
|
||||||
}
|
}
|
||||||
sort.Strings(ps.accounts)
|
sort.Strings(ps.users)
|
||||||
return ps, nil
|
return ps, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ func TestParseBlockchainTxs(t *testing.T) {
|
|||||||
instructions, err := parser.parse()
|
instructions, err := parser.parse()
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, 25, len(instructions.instructions))
|
assert.Equal(t, 25, len(instructions.instructions))
|
||||||
assert.Equal(t, 7, len(instructions.accounts))
|
assert.Equal(t, 7, len(instructions.users))
|
||||||
|
|
||||||
if debug {
|
if debug {
|
||||||
fmt.Println(instructions)
|
fmt.Println(instructions)
|
||||||
@@ -94,7 +94,7 @@ func TestParsePoolTxs(t *testing.T) {
|
|||||||
instructions, err := parser.parse()
|
instructions, err := parser.parse()
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, 5, len(instructions.instructions))
|
assert.Equal(t, 5, len(instructions.instructions))
|
||||||
assert.Equal(t, 4, len(instructions.accounts))
|
assert.Equal(t, 4, len(instructions.users))
|
||||||
|
|
||||||
if debug {
|
if debug {
|
||||||
fmt.Println(instructions)
|
fmt.Println(instructions)
|
||||||
|
|||||||
@@ -176,4 +176,6 @@ PoolExit(1) A: 3
|
|||||||
PoolTransfer(1) A-B: 6 (1)
|
PoolTransfer(1) A-B: 6 (1)
|
||||||
PoolTransfer(1) B-C: 3 (1)
|
PoolTransfer(1) B-C: 3 (1)
|
||||||
PoolTransfer(1) A-C: 3 (1)
|
PoolTransfer(1) A-C: 3 (1)
|
||||||
|
PoolTransferToEthAddr(1) A-C: 3 (1)
|
||||||
|
PoolTransferToBJJ(1) A-C: 3 (1)
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -19,6 +19,6 @@ func TestCompileSets(t *testing.T) {
|
|||||||
tc := NewContext(eth.RollupConstMaxL1UserTx)
|
tc := NewContext(eth.RollupConstMaxL1UserTx)
|
||||||
_, err = tc.GenerateBlocks(SetBlockchain0)
|
_, err = tc.GenerateBlocks(SetBlockchain0)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
_, err = tc.GenerateBlocks(SetPool0)
|
_, err = tc.GeneratePoolL2Txs(SetPool0)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import (
|
|||||||
// Context contains the data of the test
|
// Context contains the data of the test
|
||||||
type Context struct {
|
type Context struct {
|
||||||
Instructions []instruction
|
Instructions []instruction
|
||||||
accountsNames []string
|
userNames []string
|
||||||
Users map[string]*User
|
Users map[string]*User
|
||||||
lastRegisteredTokenID common.TokenID
|
lastRegisteredTokenID common.TokenID
|
||||||
l1CreatedAccounts map[string]*Account
|
l1CreatedAccounts map[string]*Account
|
||||||
@@ -98,18 +98,21 @@ type L2Tx struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GenerateBlocks returns an array of BlockData for a given set. It uses the
|
// GenerateBlocks returns an array of BlockData for a given set. It uses the
|
||||||
// accounts (keys & nonces) of the Context.
|
// users (keys & nonces) of the Context.
|
||||||
func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) {
|
func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) {
|
||||||
parser := newParser(strings.NewReader(set))
|
parser := newParser(strings.NewReader(set))
|
||||||
parsedSet, err := parser.parse()
|
parsedSet, err := parser.parse()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if parsedSet.typ != setTypeBlockchain {
|
||||||
|
return nil, fmt.Errorf("Expected set type: %s, found: %s", setTypeBlockchain, parsedSet.typ)
|
||||||
|
}
|
||||||
|
|
||||||
tc.Instructions = parsedSet.instructions
|
tc.Instructions = parsedSet.instructions
|
||||||
tc.accountsNames = parsedSet.accounts
|
tc.userNames = parsedSet.users
|
||||||
|
|
||||||
tc.generateKeys(tc.accountsNames)
|
tc.generateKeys(tc.userNames)
|
||||||
|
|
||||||
var blocks []common.BlockData
|
var blocks []common.BlockData
|
||||||
for _, inst := range parsedSet.instructions {
|
for _, inst := range parsedSet.instructions {
|
||||||
@@ -418,39 +421,42 @@ func (tc *Context) checkIfTokenIsRegistered(inst instruction) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GeneratePoolL2Txs returns an array of common.PoolL2Tx from a given set. It
|
// GeneratePoolL2Txs returns an array of common.PoolL2Tx from a given set. It
|
||||||
// uses the accounts (keys & nonces) of the Context.
|
// uses the users (keys) of the Context.
|
||||||
func (tc *Context) GeneratePoolL2Txs(set string) ([]common.PoolL2Tx, error) {
|
func (tc *Context) GeneratePoolL2Txs(set string) ([]common.PoolL2Tx, error) {
|
||||||
parser := newParser(strings.NewReader(set))
|
parser := newParser(strings.NewReader(set))
|
||||||
parsedSet, err := parser.parse()
|
parsedSet, err := parser.parse()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if parsedSet.typ != setTypePoolL2 {
|
||||||
|
return nil, fmt.Errorf("Expected set type: %s, found: %s", setTypePoolL2, parsedSet.typ)
|
||||||
|
}
|
||||||
|
|
||||||
tc.Instructions = parsedSet.instructions
|
tc.Instructions = parsedSet.instructions
|
||||||
tc.accountsNames = parsedSet.accounts
|
tc.userNames = parsedSet.users
|
||||||
|
|
||||||
tc.generateKeys(tc.accountsNames)
|
tc.generateKeys(tc.userNames)
|
||||||
|
|
||||||
txs := []common.PoolL2Tx{}
|
txs := []common.PoolL2Tx{}
|
||||||
for _, inst := range tc.Instructions {
|
for _, inst := range tc.Instructions {
|
||||||
switch inst.typ {
|
switch inst.typ {
|
||||||
case common.TxTypeTransfer:
|
case common.TxTypeTransfer, common.TxTypeTransferToEthAddr, common.TxTypeTransferToBJJ:
|
||||||
if err := tc.checkIfAccountExists(inst.from, inst); err != nil {
|
if err := tc.checkIfAccountExists(inst.from, inst); err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
return nil, fmt.Errorf("Line %d: %s", inst.lineNum, err.Error())
|
return nil, fmt.Errorf("Line %d: %s", inst.lineNum, err.Error())
|
||||||
}
|
}
|
||||||
|
if inst.typ == common.TxTypeTransfer {
|
||||||
|
// if TxTypeTransfer, need to exist the ToIdx account
|
||||||
if err := tc.checkIfAccountExists(inst.to, inst); err != nil {
|
if err := tc.checkIfAccountExists(inst.to, inst); err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
return nil, fmt.Errorf("Line %d: %s", inst.lineNum, err.Error())
|
return nil, fmt.Errorf("Line %d: %s", inst.lineNum, err.Error())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
tc.Users[inst.from].Accounts[inst.tokenID].Nonce++
|
tc.Users[inst.from].Accounts[inst.tokenID].Nonce++
|
||||||
// if account of receiver does not exist, don't use
|
// if account of receiver does not exist, don't use
|
||||||
// ToIdx, and use only ToEthAddr & ToBJJ
|
// ToIdx, and use only ToEthAddr & ToBJJ
|
||||||
tx := common.PoolL2Tx{
|
tx := common.PoolL2Tx{
|
||||||
FromIdx: tc.Users[inst.from].Accounts[inst.tokenID].Idx,
|
FromIdx: tc.Users[inst.from].Accounts[inst.tokenID].Idx,
|
||||||
ToIdx: tc.Users[inst.to].Accounts[inst.tokenID].Idx,
|
|
||||||
ToEthAddr: tc.Users[inst.to].Addr,
|
|
||||||
ToBJJ: tc.Users[inst.to].BJJ.Public(),
|
|
||||||
TokenID: inst.tokenID,
|
TokenID: inst.tokenID,
|
||||||
Amount: big.NewInt(int64(inst.amount)),
|
Amount: big.NewInt(int64(inst.amount)),
|
||||||
Fee: common.FeeSelector(inst.fee),
|
Fee: common.FeeSelector(inst.fee),
|
||||||
@@ -459,7 +465,19 @@ func (tc *Context) GeneratePoolL2Txs(set string) ([]common.PoolL2Tx, error) {
|
|||||||
Timestamp: time.Now(),
|
Timestamp: time.Now(),
|
||||||
RqToEthAddr: common.EmptyAddr,
|
RqToEthAddr: common.EmptyAddr,
|
||||||
RqToBJJ: nil,
|
RqToBJJ: nil,
|
||||||
Type: common.TxTypeTransfer,
|
Type: inst.typ,
|
||||||
|
}
|
||||||
|
if tx.Type == common.TxTypeTransfer {
|
||||||
|
tx.ToIdx = tc.Users[inst.to].Accounts[inst.tokenID].Idx
|
||||||
|
tx.ToEthAddr = tc.Users[inst.to].Addr
|
||||||
|
tx.ToBJJ = tc.Users[inst.to].BJJ.Public()
|
||||||
|
} else if tx.Type == common.TxTypeTransferToEthAddr {
|
||||||
|
tx.ToIdx = common.Idx(0)
|
||||||
|
tx.ToEthAddr = tc.Users[inst.to].Addr
|
||||||
|
} else if tx.Type == common.TxTypeTransferToBJJ {
|
||||||
|
tx.ToIdx = common.Idx(0)
|
||||||
|
tx.ToEthAddr = common.FFAddr
|
||||||
|
tx.ToBJJ = tc.Users[inst.to].BJJ.Public()
|
||||||
}
|
}
|
||||||
nTx, err := common.NewPoolL2Tx(&tx)
|
nTx, err := common.NewPoolL2Tx(&tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -506,12 +524,12 @@ func (tc *Context) GeneratePoolL2Txs(set string) ([]common.PoolL2Tx, error) {
|
|||||||
return txs, nil
|
return txs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateKeys generates BabyJubJub & Address keys for the given list of
|
// generateKeys generates BabyJubJub & Address keys for the given list of user
|
||||||
// account names in a deterministic way. This means, that for the same given
|
// names in a deterministic way. This means, that for the same given
|
||||||
// 'accNames' in a certain order, the keys will be always the same.
|
// 'userNames' in a certain order, the keys will be always the same.
|
||||||
func (tc *Context) generateKeys(accNames []string) {
|
func (tc *Context) generateKeys(userNames []string) {
|
||||||
for i := 1; i < len(accNames)+1; i++ {
|
for i := 1; i < len(userNames)+1; i++ {
|
||||||
if _, ok := tc.Users[accNames[i-1]]; ok {
|
if _, ok := tc.Users[userNames[i-1]]; ok {
|
||||||
// account already created
|
// account already created
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -531,6 +549,6 @@ func (tc *Context) generateKeys(accNames []string) {
|
|||||||
Addr: addr,
|
Addr: addr,
|
||||||
Accounts: make(map[common.TokenID]*Account),
|
Accounts: make(map[common.TokenID]*Account),
|
||||||
}
|
}
|
||||||
tc.Users[accNames[i-1]] = &u
|
tc.Users[userNames[i-1]] = &u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,10 +207,12 @@ func TestGeneratePoolL2Txs(t *testing.T) {
|
|||||||
PoolTransfer(3) User1-User0: 15 (1)
|
PoolTransfer(3) User1-User0: 15 (1)
|
||||||
PoolTransfer(2) B-D: 3 (1)
|
PoolTransfer(2) B-D: 3 (1)
|
||||||
PoolExit(1) A: 3
|
PoolExit(1) A: 3
|
||||||
|
PoolTransferToEthAddr(1) A-B: 1 (1)
|
||||||
|
PoolTransferToBJJ(1) A-B: 1 (1)
|
||||||
`
|
`
|
||||||
poolL2Txs, err := tc.GeneratePoolL2Txs(set)
|
poolL2Txs, err := tc.GeneratePoolL2Txs(set)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, 9, len(poolL2Txs))
|
assert.Equal(t, 11, len(poolL2Txs))
|
||||||
assert.Equal(t, common.TxTypeTransfer, poolL2Txs[0].Type)
|
assert.Equal(t, common.TxTypeTransfer, poolL2Txs[0].Type)
|
||||||
assert.Equal(t, common.TxTypeExit, poolL2Txs[8].Type)
|
assert.Equal(t, common.TxTypeExit, poolL2Txs[8].Type)
|
||||||
assert.Equal(t, tc.Users["B"].Addr.Hex(), poolL2Txs[0].ToEthAddr.Hex())
|
assert.Equal(t, tc.Users["B"].Addr.Hex(), poolL2Txs[0].ToEthAddr.Hex())
|
||||||
@@ -222,6 +224,13 @@ func TestGeneratePoolL2Txs(t *testing.T) {
|
|||||||
assert.Equal(t, common.Nonce(2), poolL2Txs[3].Nonce)
|
assert.Equal(t, common.Nonce(2), poolL2Txs[3].Nonce)
|
||||||
assert.Equal(t, common.Nonce(3), poolL2Txs[8].Nonce)
|
assert.Equal(t, common.Nonce(3), poolL2Txs[8].Nonce)
|
||||||
|
|
||||||
|
assert.Equal(t, tc.Users["B"].Addr.Hex(), poolL2Txs[9].ToEthAddr.Hex())
|
||||||
|
assert.Nil(t, poolL2Txs[9].ToBJJ)
|
||||||
|
assert.Equal(t, common.TxTypeTransferToEthAddr, poolL2Txs[9].Type)
|
||||||
|
assert.Equal(t, common.FFAddr, poolL2Txs[10].ToEthAddr)
|
||||||
|
assert.Equal(t, tc.Users["B"].BJJ.Public().String(), poolL2Txs[10].ToBJJ.String())
|
||||||
|
assert.Equal(t, common.TxTypeTransferToBJJ, poolL2Txs[10].Type)
|
||||||
|
|
||||||
// load another set in the same Context
|
// load another set in the same Context
|
||||||
set = `
|
set = `
|
||||||
Type: PoolL2
|
Type: PoolL2
|
||||||
@@ -231,9 +240,37 @@ func TestGeneratePoolL2Txs(t *testing.T) {
|
|||||||
`
|
`
|
||||||
poolL2Txs, err = tc.GeneratePoolL2Txs(set)
|
poolL2Txs, err = tc.GeneratePoolL2Txs(set)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, common.Nonce(4), poolL2Txs[0].Nonce)
|
assert.Equal(t, common.Nonce(6), poolL2Txs[0].Nonce)
|
||||||
assert.Equal(t, common.Nonce(2), poolL2Txs[1].Nonce)
|
assert.Equal(t, common.Nonce(2), poolL2Txs[1].Nonce)
|
||||||
assert.Equal(t, common.Nonce(5), poolL2Txs[2].Nonce)
|
assert.Equal(t, common.Nonce(7), poolL2Txs[2].Nonce)
|
||||||
|
|
||||||
|
// check that a PoolL2Tx can be done to a non existing ToIdx
|
||||||
|
set = `
|
||||||
|
Type: Blockchain
|
||||||
|
AddToken(1)
|
||||||
|
CreateAccountDeposit(1) A: 10
|
||||||
|
> batchL1
|
||||||
|
> batchL1
|
||||||
|
> block
|
||||||
|
`
|
||||||
|
tc = NewContext(eth.RollupConstMaxL1UserTx)
|
||||||
|
_, err = tc.GenerateBlocks(set)
|
||||||
|
require.Nil(t, err)
|
||||||
|
set = `
|
||||||
|
Type: PoolL2
|
||||||
|
PoolTransferToEthAddr(1) A-B: 3 (1)
|
||||||
|
PoolTransferToBJJ(1) A-C: 3 (1)
|
||||||
|
`
|
||||||
|
_, err = tc.GeneratePoolL2Txs(set)
|
||||||
|
require.Nil(t, err)
|
||||||
|
// expect error, as FromIdx=B is still not created for TokenID=1
|
||||||
|
set = `
|
||||||
|
Type: PoolL2
|
||||||
|
PoolTransferToEthAddr(1) B-A: 3 (1)
|
||||||
|
PoolTransferToBJJ(1) B-A: 3 (1)
|
||||||
|
`
|
||||||
|
_, err = tc.GeneratePoolL2Txs(set)
|
||||||
|
require.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerateErrors(t *testing.T) {
|
func TestGenerateErrors(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user