@ -49,7 +49,7 @@ type contextExtra struct {
// Context contains the data of the test
// Context contains the data of the test
type Context struct {
type Context struct {
Instructions [ ] i nstruction
instructions [ ] I nstruction
userNames [ ] string
userNames [ ] string
Users map [ string ] * User // Name -> *User
Users map [ string ] * User // Name -> *User
UsersByIdx map [ int ] * User
UsersByIdx map [ int ] * User
@ -146,7 +146,7 @@ type L2Tx struct {
L2Tx common . L2Tx
L2Tx common . L2Tx
}
}
// GenerateBlocks returns an array of BlockData for a given set. It uses the
// GenerateBlocks returns an array of BlockData for a given set made of a string . It uses the
// users (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 ) )
@ -154,34 +154,60 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) {
if err != nil {
if err != nil {
return nil , tracerr . Wrap ( err )
return nil , tracerr . Wrap ( err )
}
}
if parsedSet . typ != s etTypeBlockchain {
return nil , tracerr . Wrap ( fmt . Errorf ( "Expected set type: %s, found: %s" , s etTypeBlockchain, parsedSet . typ ) )
if parsedSet . typ != S etTypeBlockchain {
return nil , tracerr . Wrap ( fmt . Errorf ( "Expected set type: %s, found: %s" , S etTypeBlockchain, parsedSet . typ ) )
}
}
tc . I nstructions = parsedSet . instructions
tc . i nstructions = parsedSet . instructions
tc . userNames = parsedSet . users
tc . userNames = parsedSet . users
return tc . generateBlocks ( )
}
// GenerateBlocksFromInstructions returns an array of BlockData for a given set made of instructions. It uses the
// users (keys & nonces) of the Context.
func ( tc * Context ) GenerateBlocksFromInstructions ( set [ ] Instruction ) ( [ ] common . BlockData , error ) {
userNames := [ ] string { }
addedNames := make ( map [ string ] bool )
for _ , inst := range set {
if _ , ok := addedNames [ inst . From ] ; ! ok {
// If the name wasn't already added
userNames = append ( userNames , inst . From )
addedNames [ inst . From ] = true
}
if _ , ok := addedNames [ inst . To ] ; ! ok {
// If the name wasn't already added
userNames = append ( userNames , inst . To )
addedNames [ inst . To ] = true
}
}
tc . userNames = userNames
tc . instructions = set
return tc . generateBlocks ( )
}
func ( tc * Context ) generateBlocks ( ) ( [ ] common . BlockData , error ) {
tc . generateKeys ( tc . userNames )
tc . generateKeys ( tc . userNames )
var blocks [ ] common . BlockData
var blocks [ ] common . BlockData
for _ , inst := range parsedSet . instructions {
switch inst . typ {
case txTypeCreateAccountDepositCoordinator : // tx source: L1CoordinatorTx
for _ , inst := range tc . instructions {
switch inst . T yp {
case T xTypeCreateAccountDepositCoordinator: // tx source: L1CoordinatorTx
if err := tc . checkIfTokenIsRegistered ( inst ) ; err != nil {
if err := tc . checkIfTokenIsRegistered ( inst ) ; err != nil {
log . Error ( err )
log . Error ( err )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . lineNum , err . Error ( ) ) )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . L ineNum, err . Error ( ) ) )
}
}
tx := common . L1Tx {
tx := common . L1Tx {
FromEthAddr : tc . Users [ inst . from ] . Addr ,
FromBJJ : tc . Users [ inst . from ] . BJJ . Public ( ) ,
TokenID : inst . tokenID ,
FromEthAddr : tc . Users [ inst . F rom] . Addr ,
FromBJJ : tc . Users [ inst . F rom] . BJJ . Public ( ) ,
TokenID : inst . T okenID,
Amount : big . NewInt ( 0 ) ,
Amount : big . NewInt ( 0 ) ,
LoadAmount : big . NewInt ( 0 ) ,
LoadAmount : big . NewInt ( 0 ) ,
Type : common . TxTypeCreateAccountDeposit , // as txTypeCreateAccountDepositCoordinator is not valid oustide Til package
Type : common . TxTypeCreateAccountDeposit , // as T xTypeCreateAccountDepositCoordinator is not valid oustide Til package
}
}
testTx := L1Tx {
testTx := L1Tx {
lineNum : inst . lineNum ,
fromIdxName : inst . from ,
lineNum : inst . L ineNum,
fromIdxName : inst . F rom,
L1Tx : tx ,
L1Tx : tx ,
}
}
@ -189,23 +215,23 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) {
case common . TxTypeCreateAccountDeposit , common . TxTypeCreateAccountDepositTransfer : // tx source: L1UserTx
case common . TxTypeCreateAccountDeposit , common . TxTypeCreateAccountDepositTransfer : // tx source: L1UserTx
if err := tc . checkIfTokenIsRegistered ( inst ) ; err != nil {
if err := tc . checkIfTokenIsRegistered ( inst ) ; err != nil {
log . Error ( err )
log . Error ( err )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . l ineNum, err . Error ( ) ) )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . L ineNum, err . Error ( ) ) )
}
}
tx := common . L1Tx {
tx := common . L1Tx {
FromEthAddr : tc . Users [ inst . f rom] . Addr ,
FromBJJ : tc . Users [ inst . f rom] . BJJ . Public ( ) ,
TokenID : inst . t okenID,
FromEthAddr : tc . Users [ inst . F rom] . Addr ,
FromBJJ : tc . Users [ inst . F rom] . BJJ . Public ( ) ,
TokenID : inst . T okenID,
Amount : big . NewInt ( 0 ) ,
Amount : big . NewInt ( 0 ) ,
LoadAmount : inst . l oadAmount,
Type : inst . t yp,
LoadAmount : inst . L oadAmount,
Type : inst . T yp,
}
}
if inst . t yp == common . TxTypeCreateAccountDepositTransfer {
tx . Amount = inst . a mount
if inst . T yp == common . TxTypeCreateAccountDepositTransfer {
tx . Amount = inst . A mount
}
}
testTx := L1Tx {
testTx := L1Tx {
lineNum : inst . l ineNum,
fromIdxName : inst . f rom,
toIdxName : inst . t o,
lineNum : inst . L ineNum,
fromIdxName : inst . F rom,
toIdxName : inst . T o,
L1Tx : tx ,
L1Tx : tx ,
}
}
if err := tc . addToL1UserQueue ( testTx ) ; err != nil {
if err := tc . addToL1UserQueue ( testTx ) ; err != nil {
@ -214,25 +240,25 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) {
case common . TxTypeDeposit , common . TxTypeDepositTransfer : // tx source: L1UserTx
case common . TxTypeDeposit , common . TxTypeDepositTransfer : // tx source: L1UserTx
if err := tc . checkIfTokenIsRegistered ( inst ) ; err != nil {
if err := tc . checkIfTokenIsRegistered ( inst ) ; err != nil {
log . Error ( err )
log . Error ( err )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . l ineNum, err . Error ( ) ) )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . L ineNum, err . Error ( ) ) )
}
}
if err := tc . checkIfAccountExists ( inst . f rom, inst ) ; err != nil {
if err := tc . checkIfAccountExists ( inst . F rom, inst ) ; err != nil {
log . Error ( err )
log . Error ( err )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . l ineNum, err . Error ( ) ) )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . L ineNum, err . Error ( ) ) )
}
}
tx := common . L1Tx {
tx := common . L1Tx {
TokenID : inst . t okenID,
TokenID : inst . T okenID,
Amount : big . NewInt ( 0 ) ,
Amount : big . NewInt ( 0 ) ,
LoadAmount : inst . l oadAmount,
Type : inst . t yp,
LoadAmount : inst . L oadAmount,
Type : inst . T yp,
}
}
if inst . t yp == common . TxTypeDepositTransfer {
tx . Amount = inst . a mount
if inst . T yp == common . TxTypeDepositTransfer {
tx . Amount = inst . A mount
}
}
testTx := L1Tx {
testTx := L1Tx {
lineNum : inst . l ineNum,
fromIdxName : inst . f rom,
toIdxName : inst . t o,
lineNum : inst . L ineNum,
fromIdxName : inst . F rom,
toIdxName : inst . T o,
L1Tx : tx ,
L1Tx : tx ,
}
}
if err := tc . addToL1UserQueue ( testTx ) ; err != nil {
if err := tc . addToL1UserQueue ( testTx ) ; err != nil {
@ -241,38 +267,38 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) {
case common . TxTypeTransfer : // L2Tx
case common . TxTypeTransfer : // L2Tx
if err := tc . checkIfTokenIsRegistered ( inst ) ; err != nil {
if err := tc . checkIfTokenIsRegistered ( inst ) ; err != nil {
log . Error ( err )
log . Error ( err )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . l ineNum, err . Error ( ) ) )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . L ineNum, err . Error ( ) ) )
}
}
tx := common . L2Tx {
tx := common . L2Tx {
Amount : inst . a mount,
Fee : common . FeeSelector ( inst . f ee) ,
Amount : inst . A mount,
Fee : common . FeeSelector ( inst . F ee) ,
Type : common . TxTypeTransfer ,
Type : common . TxTypeTransfer ,
EthBlockNum : tc . blockNum ,
EthBlockNum : tc . blockNum ,
}
}
tx . BatchNum = common . BatchNum ( tc . currBatchNum ) // when converted to PoolL2Tx BatchNum parameter is lost
tx . BatchNum = common . BatchNum ( tc . currBatchNum ) // when converted to PoolL2Tx BatchNum parameter is lost
testTx := L2Tx {
testTx := L2Tx {
lineNum : inst . l ineNum,
fromIdxName : inst . f rom,
toIdxName : inst . t o,
tokenID : inst . t okenID,
lineNum : inst . L ineNum,
fromIdxName : inst . F rom,
toIdxName : inst . T o,
tokenID : inst . T okenID,
L2Tx : tx ,
L2Tx : tx ,
}
}
tc . currBatchTest . l2Txs = append ( tc . currBatchTest . l2Txs , testTx )
tc . currBatchTest . l2Txs = append ( tc . currBatchTest . l2Txs , testTx )
case common . TxTypeForceTransfer : // tx source: L1UserTx
case common . TxTypeForceTransfer : // tx source: L1UserTx
if err := tc . checkIfTokenIsRegistered ( inst ) ; err != nil {
if err := tc . checkIfTokenIsRegistered ( inst ) ; err != nil {
log . Error ( err )
log . Error ( err )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . l ineNum, err . Error ( ) ) )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . L ineNum, err . Error ( ) ) )
}
}
tx := common . L1Tx {
tx := common . L1Tx {
TokenID : inst . t okenID,
Amount : inst . a mount,
TokenID : inst . T okenID,
Amount : inst . A mount,
LoadAmount : big . NewInt ( 0 ) ,
LoadAmount : big . NewInt ( 0 ) ,
Type : common . TxTypeForceTransfer ,
Type : common . TxTypeForceTransfer ,
}
}
testTx := L1Tx {
testTx := L1Tx {
lineNum : inst . l ineNum,
fromIdxName : inst . f rom,
toIdxName : inst . t o,
lineNum : inst . L ineNum,
fromIdxName : inst . F rom,
toIdxName : inst . T o,
L1Tx : tx ,
L1Tx : tx ,
}
}
if err := tc . addToL1UserQueue ( testTx ) ; err != nil {
if err := tc . addToL1UserQueue ( testTx ) ; err != nil {
@ -281,63 +307,63 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) {
case common . TxTypeExit : // tx source: L2Tx
case common . TxTypeExit : // tx source: L2Tx
if err := tc . checkIfTokenIsRegistered ( inst ) ; err != nil {
if err := tc . checkIfTokenIsRegistered ( inst ) ; err != nil {
log . Error ( err )
log . Error ( err )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . l ineNum, err . Error ( ) ) )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . L ineNum, err . Error ( ) ) )
}
}
tx := common . L2Tx {
tx := common . L2Tx {
ToIdx : common . Idx ( 1 ) , // as is an Exit
ToIdx : common . Idx ( 1 ) , // as is an Exit
Fee : common . FeeSelector ( inst . f ee) ,
Amount : inst . a mount,
Fee : common . FeeSelector ( inst . F ee) ,
Amount : inst . A mount,
Type : common . TxTypeExit ,
Type : common . TxTypeExit ,
EthBlockNum : tc . blockNum ,
EthBlockNum : tc . blockNum ,
}
}
tx . BatchNum = common . BatchNum ( tc . currBatchNum ) // when converted to PoolL2Tx BatchNum parameter is lost
tx . BatchNum = common . BatchNum ( tc . currBatchNum ) // when converted to PoolL2Tx BatchNum parameter is lost
testTx := L2Tx {
testTx := L2Tx {
lineNum : inst . l ineNum,
fromIdxName : inst . f rom,
toIdxName : inst . t o,
tokenID : inst . t okenID,
lineNum : inst . L ineNum,
fromIdxName : inst . F rom,
toIdxName : inst . T o,
tokenID : inst . T okenID,
L2Tx : tx ,
L2Tx : tx ,
}
}
tc . currBatchTest . l2Txs = append ( tc . currBatchTest . l2Txs , testTx )
tc . currBatchTest . l2Txs = append ( tc . currBatchTest . l2Txs , testTx )
case common . TxTypeForceExit : // tx source: L1UserTx
case common . TxTypeForceExit : // tx source: L1UserTx
if err := tc . checkIfTokenIsRegistered ( inst ) ; err != nil {
if err := tc . checkIfTokenIsRegistered ( inst ) ; err != nil {
log . Error ( err )
log . Error ( err )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . l ineNum, err . Error ( ) ) )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . L ineNum, err . Error ( ) ) )
}
}
tx := common . L1Tx {
tx := common . L1Tx {
ToIdx : common . Idx ( 1 ) , // as is an Exit
ToIdx : common . Idx ( 1 ) , // as is an Exit
TokenID : inst . t okenID,
Amount : inst . a mount,
TokenID : inst . T okenID,
Amount : inst . A mount,
LoadAmount : big . NewInt ( 0 ) ,
LoadAmount : big . NewInt ( 0 ) ,
Type : common . TxTypeForceExit ,
Type : common . TxTypeForceExit ,
}
}
testTx := L1Tx {
testTx := L1Tx {
lineNum : inst . l ineNum,
fromIdxName : inst . f rom,
toIdxName : inst . t o,
lineNum : inst . L ineNum,
fromIdxName : inst . F rom,
toIdxName : inst . T o,
L1Tx : tx ,
L1Tx : tx ,
}
}
if err := tc . addToL1UserQueue ( testTx ) ; err != nil {
if err := tc . addToL1UserQueue ( testTx ) ; err != nil {
return nil , tracerr . Wrap ( err )
return nil , tracerr . Wrap ( err )
}
}
case t ypeNewBatch:
if err = tc . calculateIdxForL1Txs ( true , tc . currBatchTest . l1CoordinatorTxs ) ; err != nil {
case T ypeNewBatch:
if err : = tc . calculateIdxForL1Txs ( true , tc . currBatchTest . l1CoordinatorTxs ) ; err != nil {
return nil , tracerr . Wrap ( err )
return nil , tracerr . Wrap ( err )
}
}
if err = tc . setIdxs ( ) ; err != nil {
if err : = tc . setIdxs ( ) ; err != nil {
log . Error ( err )
log . Error ( err )
return nil , tracerr . Wrap ( err )
return nil , tracerr . Wrap ( err )
}
}
case t ypeNewBatchL1:
case T ypeNewBatchL1:
// for each L1UserTx of the Queues[ToForgeNum], calculate the Idx
// for each L1UserTx of the Queues[ToForgeNum], calculate the Idx
if err = tc . calculateIdxForL1Txs ( false , tc . Queues [ tc . ToForgeNum ] ) ; err != nil {
if err : = tc . calculateIdxForL1Txs ( false , tc . Queues [ tc . ToForgeNum ] ) ; err != nil {
return nil , tracerr . Wrap ( err )
return nil , tracerr . Wrap ( err )
}
}
if err = tc . calculateIdxForL1Txs ( true , tc . currBatchTest . l1CoordinatorTxs ) ; err != nil {
if err : = tc . calculateIdxForL1Txs ( true , tc . currBatchTest . l1CoordinatorTxs ) ; err != nil {
return nil , tracerr . Wrap ( err )
return nil , tracerr . Wrap ( err )
}
}
tc . currBatch . L1Batch = true
tc . currBatch . L1Batch = true
if err = tc . setIdxs ( ) ; err != nil {
if err : = tc . setIdxs ( ) ; err != nil {
log . Error ( err )
log . Error ( err )
return nil , tracerr . Wrap ( err )
return nil , tracerr . Wrap ( err )
}
}
@ -350,26 +376,26 @@ func (tc *Context) GenerateBlocks(set string) ([]common.BlockData, error) {
newQueue := [ ] L1Tx { }
newQueue := [ ] L1Tx { }
tc . Queues = append ( tc . Queues , newQueue )
tc . Queues = append ( tc . Queues , newQueue )
}
}
case t ypeNewBlock:
case T ypeNewBlock:
blocks = append ( blocks , tc . currBlock )
blocks = append ( blocks , tc . currBlock )
tc . blockNum ++
tc . blockNum ++
tc . currBlock = newBlock ( tc . blockNum )
tc . currBlock = newBlock ( tc . blockNum )
case t ypeAddToken:
case T ypeAddToken:
newToken := common . Token {
newToken := common . Token {
EthAddr : ethCommon . BigToAddress ( big . NewInt ( int64 ( inst . t okenID * 100 ) ) ) , //nolint:gomnd
// Name: fmt.Sprintf("Token %d", inst.t okenID),
// Symbol: fmt.Sprintf("TK%d", inst.t okenID),
EthAddr : ethCommon . BigToAddress ( big . NewInt ( int64 ( inst . T okenID * 100 ) ) ) , //nolint:gomnd
// Name: fmt.Sprintf("Token %d", inst.T okenID),
// Symbol: fmt.Sprintf("TK%d", inst.T okenID),
// Decimals: 18,
// Decimals: 18,
TokenID : inst . t okenID,
TokenID : inst . T okenID,
EthBlockNum : tc . blockNum ,
EthBlockNum : tc . blockNum ,
}
}
if inst . t okenID != tc . LastRegisteredTokenID + 1 {
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: AddToken TokenID should be sequential, expected TokenID: %d, defined TokenID: %d" , inst . l ineNum, tc . LastRegisteredTokenID + 1 , inst . t okenID) )
if inst . T okenID != tc . LastRegisteredTokenID + 1 {
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: AddToken TokenID should be sequential, expected TokenID: %d, defined TokenID: %d" , inst . L ineNum, tc . LastRegisteredTokenID + 1 , inst . T okenID) )
}
}
tc . LastRegisteredTokenID ++
tc . LastRegisteredTokenID ++
tc . currBlock . Rollup . AddedTokens = append ( tc . currBlock . Rollup . AddedTokens , newToken )
tc . currBlock . Rollup . AddedTokens = append ( tc . currBlock . Rollup . AddedTokens , newToken )
default :
default :
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: Unexpected type: %s" , inst . l ineNum, inst . t yp) )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: Unexpected type: %s" , inst . L ineNum, inst . T yp) )
}
}
}
}
@ -497,20 +523,21 @@ func (tc *Context) addToL1UserQueue(tx L1Tx) error {
return nil
return nil
}
}
func ( tc * Context ) checkIfAccountExists ( tf string , inst i nstruction) error {
if tc . Users [ tf ] . Accounts [ inst . t okenID] == nil {
return tracerr . Wrap ( fmt . Errorf ( "%s at User: %s, for TokenID: %d, while account not created yet" , inst . t yp, tf , inst . t okenID) )
func ( tc * Context ) checkIfAccountExists ( tf string , inst I nstruction) error {
if tc . Users [ tf ] . Accounts [ inst . T okenID] == nil {
return tracerr . Wrap ( fmt . Errorf ( "%s at User: %s, for TokenID: %d, while account not created yet" , inst . T yp, tf , inst . T okenID) )
}
}
return nil
return nil
}
}
func ( tc * Context ) checkIfTokenIsRegistered ( inst instruction ) error {
if inst . tokenID > tc . LastRegisteredTokenID {
return tracerr . Wrap ( fmt . Errorf ( "Can not process %s: TokenID %d not registered, last registered TokenID: %d" , inst . typ , inst . tokenID , tc . LastRegisteredTokenID ) )
func ( tc * Context ) checkIfTokenIsRegistered ( inst Instruction ) error {
if inst . TokenID > tc . LastRegisteredTokenID {
return tracerr . Wrap ( fmt . Errorf ( "Can not process %s: TokenID %d not registered, last registered TokenID: %d" , inst . Typ , inst . TokenID , tc . LastRegisteredTokenID ) )
}
}
return nil
return nil
}
}
// GeneratePoolL2Txs returns an array of common.PoolL2Tx from a given set. It
// GeneratePoolL2Txs returns an array of common.PoolL2Tx from a given set made of a string . It
// uses the users (keys) 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 ) )
@ -518,98 +545,125 @@ func (tc *Context) GeneratePoolL2Txs(set string) ([]common.PoolL2Tx, error) {
if err != nil {
if err != nil {
return nil , tracerr . Wrap ( err )
return nil , tracerr . Wrap ( err )
}
}
if parsedSet . typ != s etTypePoolL2 {
return nil , tracerr . Wrap ( fmt . Errorf ( "Expected set type: %s, found: %s" , s etTypePoolL2, parsedSet . typ ) )
if parsedSet . typ != S etTypePoolL2 {
return nil , tracerr . Wrap ( fmt . Errorf ( "Expected set type: %s, found: %s" , S etTypePoolL2, parsedSet . typ ) )
}
}
tc . I nstructions = parsedSet . instructions
tc . i nstructions = parsedSet . instructions
tc . userNames = parsedSet . users
tc . userNames = parsedSet . users
return tc . generatePoolL2Txs ( )
}
// GeneratePoolL2TxsFromInstructions returns an array of common.PoolL2Tx from a given set made of instructions. It
// uses the users (keys) of the Context.
func ( tc * Context ) GeneratePoolL2TxsFromInstructions ( set [ ] Instruction ) ( [ ] common . PoolL2Tx , error ) {
userNames := [ ] string { }
addedNames := make ( map [ string ] bool )
for _ , inst := range set {
if _ , ok := addedNames [ inst . From ] ; ! ok {
// If the name wasn't already added
userNames = append ( userNames , inst . From )
addedNames [ inst . From ] = true
}
if _ , ok := addedNames [ inst . To ] ; ! ok {
// If the name wasn't already added
userNames = append ( userNames , inst . To )
addedNames [ inst . To ] = true
}
}
tc . userNames = userNames
tc . instructions = set
return tc . generatePoolL2Txs ( )
}
func ( tc * Context ) generatePoolL2Txs ( ) ( [ ] common . PoolL2Tx , error ) {
tc . generateKeys ( tc . userNames )
tc . generateKeys ( tc . userNames )
txs := [ ] common . PoolL2Tx { }
txs := [ ] common . PoolL2Tx { }
for _ , inst := range tc . Instructions {
switch inst . typ {
for _ , inst := range tc . i nstructions {
switch inst . T yp {
case common . TxTypeTransfer , common . TxTypeTransferToEthAddr , common . TxTypeTransferToBJJ :
case common . TxTypeTransfer , common . TxTypeTransferToEthAddr , common . TxTypeTransferToBJJ :
if err := tc . checkIfAccountExists ( inst . from , inst ) ; err != nil {
if err := tc . checkIfAccountExists ( inst . F rom, inst ) ; err != nil {
log . Error ( err )
log . Error ( err )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . lineNum , err . Error ( ) ) )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . L ineNum, err . Error ( ) ) )
}
}
if inst . typ == common . TxTypeTransfer {
if inst . T yp == common . TxTypeTransfer {
// if TxTypeTransfer, need to exist the ToIdx account
// if TxTypeTransfer, need to exist the ToIdx account
if err := tc . checkIfAccountExists ( inst . to , inst ) ; err != nil {
if err := tc . checkIfAccountExists ( inst . T o, inst ) ; err != nil {
log . Error ( err )
log . Error ( err )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . lineNum , err . Error ( ) ) )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . L ineNum, err . Error ( ) ) )
}
}
}
}
tc . Users [ inst . from ] . Accounts [ inst . tokenID ] . Nonce ++
tc . Users [ inst . F rom] . Accounts [ inst . T okenID] . 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 ,
TokenID : inst . tokenID ,
Amount : inst . amount ,
Fee : common . FeeSelector ( inst . fee ) ,
Nonce : tc . Users [ inst . from ] . Accounts [ inst . tokenID ] . Nonce ,
FromIdx : tc . Users [ inst . F rom] . Accounts [ inst . T okenID] . Idx ,
TokenID : inst . T okenID,
Amount : inst . A mount,
Fee : common . FeeSelector ( inst . F ee) ,
Nonce : tc . Users [ inst . F rom] . Accounts [ inst . T okenID] . Nonce ,
State : common . PoolL2TxStatePending ,
State : common . PoolL2TxStatePending ,
Timestamp : time . Now ( ) ,
Timestamp : time . Now ( ) ,
RqToEthAddr : common . EmptyAddr ,
RqToEthAddr : common . EmptyAddr ,
RqToBJJ : nil ,
RqToBJJ : nil ,
Type : inst . t yp,
Type : inst . T yp,
}
}
if tx . Type == common . TxTypeTransfer {
if tx . Type == common . TxTypeTransfer {
tx . ToIdx = tc . Users [ inst . t o] . Accounts [ inst . t okenID] . Idx
tx . ToEthAddr = tc . Users [ inst . t o] . Addr
tx . ToBJJ = tc . Users [ inst . t o] . BJJ . Public ( )
tx . ToIdx = tc . Users [ inst . T o] . Accounts [ inst . T okenID] . Idx
tx . ToEthAddr = tc . Users [ inst . T o] . Addr
tx . ToBJJ = tc . Users [ inst . T o] . BJJ . Public ( )
} else if tx . Type == common . TxTypeTransferToEthAddr {
} else if tx . Type == common . TxTypeTransferToEthAddr {
tx . ToIdx = common . Idx ( 0 )
tx . ToIdx = common . Idx ( 0 )
tx . ToEthAddr = tc . Users [ inst . t o] . Addr
tx . ToEthAddr = tc . Users [ inst . T o] . Addr
} else if tx . Type == common . TxTypeTransferToBJJ {
} else if tx . Type == common . TxTypeTransferToBJJ {
tx . ToIdx = common . Idx ( 0 )
tx . ToIdx = common . Idx ( 0 )
tx . ToEthAddr = common . FFAddr
tx . ToEthAddr = common . FFAddr
tx . ToBJJ = tc . Users [ inst . t o] . BJJ . Public ( )
tx . ToBJJ = tc . Users [ inst . T o] . BJJ . Public ( )
}
}
nTx , err := common . NewPoolL2Tx ( & tx )
nTx , err := common . NewPoolL2Tx ( & tx )
if err != nil {
if err != nil {
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . l ineNum, err . Error ( ) ) )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . L ineNum, err . Error ( ) ) )
}
}
tx = * nTx
tx = * nTx
// perform signature and set it to tx.Signature
// perform signature and set it to tx.Signature
toSign , err := tx . HashToSign ( )
toSign , err := tx . HashToSign ( )
if err != nil {
if err != nil {
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . l ineNum, err . Error ( ) ) )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . L ineNum, err . Error ( ) ) )
}
}
sig := tc . Users [ inst . f rom] . BJJ . SignPoseidon ( toSign )
sig := tc . Users [ inst . F rom] . BJJ . SignPoseidon ( toSign )
tx . Signature = sig . Compress ( )
tx . Signature = sig . Compress ( )
txs = append ( txs , tx )
txs = append ( txs , tx )
case common . TxTypeExit :
case common . TxTypeExit :
tc . Users [ inst . f rom] . Accounts [ inst . t okenID] . Nonce ++
tc . Users [ inst . F rom] . Accounts [ inst . T okenID] . Nonce ++
tx := common . PoolL2Tx {
tx := common . PoolL2Tx {
FromIdx : tc . Users [ inst . f rom] . Accounts [ inst . t okenID] . Idx ,
FromIdx : tc . Users [ inst . F rom] . Accounts [ inst . T okenID] . Idx ,
ToIdx : common . Idx ( 1 ) , // as is an Exit
ToIdx : common . Idx ( 1 ) , // as is an Exit
Fee : common . FeeSelector ( inst . f ee) ,
TokenID : inst . t okenID,
Amount : inst . a mount,
Nonce : tc . Users [ inst . f rom] . Accounts [ inst . t okenID] . Nonce ,
Fee : common . FeeSelector ( inst . F ee) ,
TokenID : inst . T okenID,
Amount : inst . A mount,
Nonce : tc . Users [ inst . F rom] . Accounts [ inst . T okenID] . Nonce ,
State : common . PoolL2TxStatePending ,
State : common . PoolL2TxStatePending ,
Type : common . TxTypeExit ,
Type : common . TxTypeExit ,
}
}
nTx , err := common . NewPoolL2Tx ( & tx )
nTx , err := common . NewPoolL2Tx ( & tx )
if err != nil {
if err != nil {
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . l ineNum, err . Error ( ) ) )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . L ineNum, err . Error ( ) ) )
}
}
tx = * nTx
tx = * nTx
// perform signature and set it to tx.Signature
// perform signature and set it to tx.Signature
toSign , err := tx . HashToSign ( )
toSign , err := tx . HashToSign ( )
if err != nil {
if err != nil {
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . l ineNum, err . Error ( ) ) )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: %s" , inst . L ineNum, err . Error ( ) ) )
}
}
sig := tc . Users [ inst . f rom] . BJJ . SignPoseidon ( toSign )
sig := tc . Users [ inst . F rom] . BJJ . SignPoseidon ( toSign )
tx . Signature = sig . Compress ( )
tx . Signature = sig . Compress ( )
txs = append ( txs , tx )
txs = append ( txs , tx )
default :
default :
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: instruction type unrecognized: %s" , inst . l ineNum, inst . t yp) )
return nil , tracerr . Wrap ( fmt . Errorf ( "Line %d: instruction type unrecognized: %s" , inst . L ineNum, inst . T yp) )
}
}
}
}