mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 11:26:44 +01:00
Add GeneratePoolL2Txs for a parsed set
This commit is contained in:
14
test/lang.go
14
test/lang.go
@@ -45,9 +45,9 @@ type Instruction struct {
|
|||||||
Type common.TxType // D: Deposit, T: Transfer, E: ForceExit
|
Type common.TxType // D: Deposit, T: Transfer, E: ForceExit
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instructions contains the full Set of Instructions representing a full code
|
// ParsedSet contains the full Set of Instructions representing a full code
|
||||||
type Instructions struct {
|
type ParsedSet struct {
|
||||||
Instructions []*Instruction
|
Instructions []Instruction
|
||||||
Accounts []string
|
Accounts []string
|
||||||
TokenIDs []common.TokenID
|
TokenIDs []common.TokenID
|
||||||
}
|
}
|
||||||
@@ -389,8 +389,8 @@ func idxTokenIDToString(idx string, tid common.TokenID) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse parses through reader
|
// Parse parses through reader
|
||||||
func (p *Parser) Parse() (Instructions, error) {
|
func (p *Parser) Parse() (*ParsedSet, error) {
|
||||||
var instructions Instructions
|
instructions := &ParsedSet{}
|
||||||
i := 0
|
i := 0
|
||||||
accounts := make(map[string]bool)
|
accounts := make(map[string]bool)
|
||||||
tokenids := make(map[common.TokenID]bool)
|
tokenids := make(map[common.TokenID]bool)
|
||||||
@@ -405,13 +405,13 @@ func (p *Parser) Parse() (Instructions, error) {
|
|||||||
}
|
}
|
||||||
if err == newEvent {
|
if err == newEvent {
|
||||||
i++
|
i++
|
||||||
instructions.Instructions = append(instructions.Instructions, instruction)
|
instructions.Instructions = append(instructions.Instructions, *instruction)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return instructions, fmt.Errorf("error parsing line %d: %s, err: %s", i, instruction.Literal, err.Error())
|
return instructions, fmt.Errorf("error parsing line %d: %s, err: %s", i, instruction.Literal, err.Error())
|
||||||
}
|
}
|
||||||
instructions.Instructions = append(instructions.Instructions, instruction)
|
instructions.Instructions = append(instructions.Instructions, *instruction)
|
||||||
accounts[idxTokenIDToString(instruction.From, instruction.TokenID)] = true
|
accounts[idxTokenIDToString(instruction.From, instruction.TokenID)] = true
|
||||||
if instruction.Type == common.TxTypeTransfer { // type: Transfer
|
if instruction.Type == common.TxTypeTransfer { // type: Transfer
|
||||||
accounts[idxTokenIDToString(instruction.To, instruction.TokenID)] = true
|
accounts[idxTokenIDToString(instruction.To, instruction.TokenID)] = true
|
||||||
|
|||||||
134
test/txs.go
134
test/txs.go
@@ -6,14 +6,33 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
ethCommon "github.com/ethereum/go-ethereum/common"
|
ethCommon "github.com/ethereum/go-ethereum/common"
|
||||||
ethCrypto "github.com/ethereum/go-ethereum/crypto"
|
ethCrypto "github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/hermeznetwork/hermez-node/common"
|
"github.com/hermeznetwork/hermez-node/common"
|
||||||
|
"github.com/hermeznetwork/hermez-node/log"
|
||||||
"github.com/iden3/go-iden3-crypto/babyjub"
|
"github.com/iden3/go-iden3-crypto/babyjub"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type TestContext struct {
|
||||||
|
t *testing.T
|
||||||
|
Instructions []Instruction
|
||||||
|
accountsNames []string
|
||||||
|
accounts map[string]*Account
|
||||||
|
TokenIDs []common.TokenID
|
||||||
|
l1CreatedAccounts map[string]*Account
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTestContext(t *testing.T) *TestContext {
|
||||||
|
return &TestContext{
|
||||||
|
t: t,
|
||||||
|
accounts: make(map[string]*Account),
|
||||||
|
l1CreatedAccounts: make(map[string]*Account),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Account contains the data related to a testing account
|
// Account contains the data related to a testing account
|
||||||
type Account struct {
|
type Account struct {
|
||||||
BJJ *babyjub.PrivateKey
|
BJJ *babyjub.PrivateKey
|
||||||
@@ -22,12 +41,105 @@ type Account struct {
|
|||||||
Nonce common.Nonce
|
Nonce common.Nonce
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateKeys generates BabyJubJub & Address keys for the given list of
|
// func (tc *TestContext) GenerateBlocks() []BlockData {
|
||||||
|
//
|
||||||
|
// 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 {
|
||||||
|
parser := NewParser(strings.NewReader(set))
|
||||||
|
parsedSet, err := parser.Parse()
|
||||||
|
require.Nil(tc.t, err)
|
||||||
|
|
||||||
|
tc.Instructions = parsedSet.Instructions
|
||||||
|
tc.accountsNames = parsedSet.Accounts
|
||||||
|
tc.TokenIDs = parsedSet.TokenIDs
|
||||||
|
|
||||||
|
tc.generateKeys(tc.accountsNames)
|
||||||
|
|
||||||
|
txs := []common.PoolL2Tx{}
|
||||||
|
for _, inst := range tc.Instructions {
|
||||||
|
switch inst.Type {
|
||||||
|
case common.TxTypeTransfer:
|
||||||
|
tc.accounts[idxTokenIDToString(inst.From, inst.TokenID)].Nonce++
|
||||||
|
// if account of receiver does not exist, don't use
|
||||||
|
// ToIdx, and use only ToEthAddr & ToBJJ
|
||||||
|
toIdx := new(common.Idx)
|
||||||
|
if _, ok := tc.l1CreatedAccounts[idxTokenIDToString(inst.To, inst.TokenID)]; !ok {
|
||||||
|
*toIdx = 0
|
||||||
|
} else {
|
||||||
|
*toIdx = tc.accounts[idxTokenIDToString(inst.To, inst.TokenID)].Idx
|
||||||
|
}
|
||||||
|
// TODO once common.L{x}Txs parameter pointers is undone, update this lines related to pointers usage
|
||||||
|
toEthAddr := new(ethCommon.Address)
|
||||||
|
*toEthAddr = tc.accounts[idxTokenIDToString(inst.To, inst.TokenID)].Addr
|
||||||
|
rqToEthAddr := new(ethCommon.Address)
|
||||||
|
*rqToEthAddr = tc.accounts[idxTokenIDToString(inst.To, inst.TokenID)].Addr
|
||||||
|
tx := common.PoolL2Tx{
|
||||||
|
FromIdx: tc.accounts[idxTokenIDToString(inst.From, inst.TokenID)].Idx,
|
||||||
|
ToIdx: toIdx,
|
||||||
|
ToEthAddr: toEthAddr,
|
||||||
|
ToBJJ: tc.accounts[idxTokenIDToString(inst.To, inst.TokenID)].BJJ.Public(),
|
||||||
|
TokenID: inst.TokenID,
|
||||||
|
Amount: big.NewInt(int64(inst.Amount)),
|
||||||
|
Fee: common.FeeSelector(inst.Fee),
|
||||||
|
Nonce: tc.accounts[idxTokenIDToString(inst.From, inst.TokenID)].Nonce,
|
||||||
|
State: common.PoolL2TxStatePending,
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
BatchNum: nil,
|
||||||
|
RqToEthAddr: rqToEthAddr,
|
||||||
|
RqToBJJ: tc.accounts[idxTokenIDToString(inst.To, inst.TokenID)].BJJ.Public(),
|
||||||
|
Type: common.TxTypeTransfer,
|
||||||
|
}
|
||||||
|
nTx, err := common.NewPoolL2Tx(&tx)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
tx = *nTx
|
||||||
|
// perform signature and set it to tx.Signature
|
||||||
|
toSign, err := tx.HashToSign()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
sig := tc.accounts[idxTokenIDToString(inst.To, inst.TokenID)].BJJ.SignPoseidon(toSign)
|
||||||
|
tx.Signature = sig
|
||||||
|
|
||||||
|
txs = append(txs, tx)
|
||||||
|
case common.TxTypeExit:
|
||||||
|
tc.accounts[idxTokenIDToString(inst.From, inst.TokenID)].Nonce++
|
||||||
|
// TODO once common.L{x}Txs parameter pointers is undone, update this lines related to pointers usage
|
||||||
|
toIdx := new(common.Idx)
|
||||||
|
*toIdx = common.Idx(1) // as is an Exit
|
||||||
|
tx := common.PoolL2Tx{
|
||||||
|
FromIdx: tc.accounts[idxTokenIDToString(inst.From, inst.TokenID)].Idx,
|
||||||
|
ToIdx: toIdx, // as is an Exit
|
||||||
|
TokenID: inst.TokenID,
|
||||||
|
Amount: big.NewInt(int64(inst.Amount)),
|
||||||
|
Nonce: tc.accounts[idxTokenIDToString(inst.From, inst.TokenID)].Nonce,
|
||||||
|
Type: common.TxTypeExit,
|
||||||
|
}
|
||||||
|
txs = append(txs, tx)
|
||||||
|
default:
|
||||||
|
log.Warnf("instruction type unrecognized: %s", inst.Type)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return txs
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateKeys generates BabyJubJub & Address keys for the given list of
|
||||||
// account names in a deterministic way. This means, that for the same given
|
// account names in a deterministic way. This means, that for the same given
|
||||||
// 'accNames' the keys will be always the same.
|
// 'accNames' in a certain order, the keys will be always the same.
|
||||||
func GenerateKeys(t *testing.T, accNames []string) map[string]*Account {
|
func (tc *TestContext) generateKeys(accNames []string) map[string]*Account {
|
||||||
acc := make(map[string]*Account)
|
acc := make(map[string]*Account)
|
||||||
for i := 1; i < len(accNames)+1; i++ {
|
for i := 1; i < len(accNames)+1; i++ {
|
||||||
|
if _, ok := tc.accounts[accNames[i-1]]; ok {
|
||||||
|
// account already created
|
||||||
|
continue
|
||||||
|
}
|
||||||
// babyjubjub key
|
// babyjubjub key
|
||||||
var sk babyjub.PrivateKey
|
var sk babyjub.PrivateKey
|
||||||
copy(sk[:], []byte(strconv.Itoa(i))) // only for testing
|
copy(sk[:], []byte(strconv.Itoa(i))) // only for testing
|
||||||
@@ -44,15 +156,16 @@ func GenerateKeys(t *testing.T, accNames []string) map[string]*Account {
|
|||||||
Addr: addr,
|
Addr: addr,
|
||||||
Nonce: 0,
|
Nonce: 0,
|
||||||
}
|
}
|
||||||
acc[accNames[i-1]] = &a
|
tc.accounts[accNames[i-1]] = &a
|
||||||
}
|
}
|
||||||
return acc
|
return acc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// GenerateTestTxs generates L1Tx & PoolL2Tx in a deterministic way for the
|
// GenerateTestTxs generates L1Tx & PoolL2Tx in a deterministic way for the
|
||||||
// given Instructions.
|
// given ParsedSet.
|
||||||
func GenerateTestTxs(t *testing.T, instructions Instructions) ([][]common.L1Tx, [][]common.L1Tx, [][]common.PoolL2Tx, []common.Token) {
|
func GenerateTestTxs(t *testing.T, parsedSet *ParsedSet) ([][]common.L1Tx, [][]common.L1Tx, [][]common.PoolL2Tx, []common.Token) {
|
||||||
accounts := GenerateKeys(t, instructions.Accounts)
|
accounts := generateKeys(t, parsedSet.Accounts)
|
||||||
l1CreatedAccounts := make(map[string]*Account)
|
l1CreatedAccounts := make(map[string]*Account)
|
||||||
|
|
||||||
var batchL1Txs []common.L1Tx
|
var batchL1Txs []common.L1Tx
|
||||||
@@ -62,7 +175,7 @@ func GenerateTestTxs(t *testing.T, instructions Instructions) ([][]common.L1Tx,
|
|||||||
var coordinatorL1Txs [][]common.L1Tx
|
var coordinatorL1Txs [][]common.L1Tx
|
||||||
var poolL2Txs [][]common.PoolL2Tx
|
var poolL2Txs [][]common.PoolL2Tx
|
||||||
idx := 256
|
idx := 256
|
||||||
for _, inst := range instructions.Instructions {
|
for _, inst := range parsedSet.Instructions {
|
||||||
switch inst.Type {
|
switch inst.Type {
|
||||||
case common.TxTypeCreateAccountDeposit:
|
case common.TxTypeCreateAccountDeposit:
|
||||||
tx := common.L1Tx{
|
tx := common.L1Tx{
|
||||||
@@ -176,8 +289,9 @@ func GenerateTestTxs(t *testing.T, instructions Instructions) ([][]common.L1Tx,
|
|||||||
// Instructions code
|
// Instructions code
|
||||||
func GenerateTestTxsFromSet(t *testing.T, set string) ([][]common.L1Tx, [][]common.L1Tx, [][]common.PoolL2Tx, []common.Token) {
|
func GenerateTestTxsFromSet(t *testing.T, set string) ([][]common.L1Tx, [][]common.L1Tx, [][]common.PoolL2Tx, []common.Token) {
|
||||||
parser := NewParser(strings.NewReader(set))
|
parser := NewParser(strings.NewReader(set))
|
||||||
instructions, err := parser.Parse()
|
parsedSet, err := parser.Parse()
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
return GenerateTestTxs(t, instructions)
|
return GenerateTestTxs(t, parsedSet)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|||||||
@@ -1,59 +1,46 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hermeznetwork/hermez-node/common"
|
"github.com/hermeznetwork/hermez-node/common"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGenerateTestL2Txs(t *testing.T) {
|
func TestGeneratePoolL2Txs(t *testing.T) {
|
||||||
s := `
|
set := `
|
||||||
A (1): 10
|
Transfer(1) A-B: 6 (1)
|
||||||
A (2): 20
|
Transfer(1) B-C: 3 (1)
|
||||||
B (1): 5
|
Transfer(1) C-A: 3 (1)
|
||||||
A-B (1): 6 1
|
Transfer(1) A-B: 1 (1)
|
||||||
B-C (1): 3 1
|
Transfer(2) A-B: 15 (1)
|
||||||
> advance batch
|
Transfer(1) User0-User1: 15 (1)
|
||||||
C-A (1): 3 1
|
Transfer(3) User1-User0: 15 (1)
|
||||||
A-B (1): 1 1
|
Transfer(2) B-D: 3 (1)
|
||||||
A-B (2): 15 1
|
Exit(1) A: 3
|
||||||
User0 (1): 20
|
|
||||||
User1 (3) : 20
|
|
||||||
User0-User1 (1): 15 1
|
|
||||||
User1-User0 (3): 15 1
|
|
||||||
B-D (2): 3 1
|
|
||||||
`
|
`
|
||||||
parser := NewParser(strings.NewReader(s))
|
tc := NewTestContext(t)
|
||||||
instructions, err := parser.Parse()
|
poolL2Txs := tc.GeneratePoolL2Txs(set)
|
||||||
assert.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)
|
||||||
|
assert.Equal(t, tc.accounts["B1"].Addr.Hex(), poolL2Txs[0].ToEthAddr.Hex())
|
||||||
|
assert.Equal(t, tc.accounts["B1"].BJJ.Public().String(), poolL2Txs[0].ToBJJ.String())
|
||||||
|
assert.Equal(t, tc.accounts["User11"].Addr.Hex(), poolL2Txs[5].ToEthAddr.Hex())
|
||||||
|
assert.Equal(t, tc.accounts["User11"].BJJ.Public().String(), poolL2Txs[5].ToBJJ.String())
|
||||||
|
|
||||||
l1txs, coordinatorL1txs, l2txs, _ := GenerateTestTxs(t, instructions)
|
assert.Equal(t, common.Nonce(1), poolL2Txs[0].Nonce)
|
||||||
assert.Equal(t, 2, len(l1txs))
|
assert.Equal(t, common.Nonce(2), poolL2Txs[3].Nonce)
|
||||||
assert.Equal(t, 3, len(l1txs[0]))
|
assert.Equal(t, common.Nonce(3), poolL2Txs[8].Nonce)
|
||||||
assert.Equal(t, 1, len(coordinatorL1txs[0]))
|
|
||||||
assert.Equal(t, 2, len(l2txs[0]))
|
|
||||||
assert.Equal(t, 2, len(l1txs[1]))
|
|
||||||
assert.Equal(t, 4, len(coordinatorL1txs[1]))
|
|
||||||
assert.Equal(t, 6, len(l2txs[1]))
|
|
||||||
|
|
||||||
accounts := GenerateKeys(t, instructions.Accounts)
|
// load another set in the same TestContext
|
||||||
|
set = `
|
||||||
// l1txs
|
Transfer(1) A-B: 6 (1)
|
||||||
assert.Equal(t, common.TxTypeCreateAccountDeposit, l1txs[0][0].Type)
|
Transfer(1) B-C: 3 (1)
|
||||||
assert.Equal(t, accounts["A1"].BJJ.Public().String(), l1txs[0][0].FromBJJ.String())
|
Transfer(1) A-C: 3 (1)
|
||||||
assert.Equal(t, accounts["A2"].BJJ.Public().String(), l1txs[0][1].FromBJJ.String())
|
`
|
||||||
assert.Equal(t, accounts["B1"].BJJ.Public().String(), l1txs[0][2].FromBJJ.String())
|
poolL2Txs = tc.GeneratePoolL2Txs(set)
|
||||||
assert.Equal(t, accounts["User13"].BJJ.Public().String(), l1txs[1][1].FromBJJ.String())
|
assert.Equal(t, common.Nonce(4), poolL2Txs[0].Nonce)
|
||||||
|
assert.Equal(t, common.Nonce(2), poolL2Txs[1].Nonce)
|
||||||
// l2txs
|
assert.Equal(t, common.Nonce(5), poolL2Txs[2].Nonce)
|
||||||
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, 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)
|
|
||||||
assert.Equal(t, common.Nonce(1), l2txs[1][1].Nonce)
|
|
||||||
assert.Equal(t, common.FeeSelector(1), l2txs[0][0].Fee)
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user