mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 11:26:44 +01:00
Implement initial version of test.Client
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
gotest.sh
|
||||
@@ -171,6 +171,26 @@ type AuctionEvents struct { //nolint:structcheck
|
||||
HEZClaimed []AuctionEventHEZClaimed
|
||||
}
|
||||
|
||||
// NewAuctionEvents creates an empty AuctionEvents with the slices initialized.
|
||||
func NewAuctionEvents() AuctionEvents {
|
||||
return AuctionEvents{
|
||||
NewBid: make([]AuctionEventNewBid, 0),
|
||||
NewSlotDeadline: make([]AuctionEventNewSlotDeadline, 0),
|
||||
NewClosedAuctionSlots: make([]AuctionEventNewClosedAuctionSlots, 0),
|
||||
NewOutbidding: make([]AuctionEventNewOutbidding, 0),
|
||||
NewDonationAddress: make([]AuctionEventNewDonationAddress, 0),
|
||||
NewBootCoordinator: make([]AuctionEventNewBootCoordinator, 0),
|
||||
NewOpenAuctionSlots: make([]AuctionEventNewOpenAuctionSlots, 0),
|
||||
NewAllocationRatio: make([]AuctionEventNewAllocationRatio, 0),
|
||||
NewCoordinator: make([]AuctionEventNewCoordinator, 0),
|
||||
CoordinatorUpdated: make([]AuctionEventCoordinatorUpdated, 0),
|
||||
NewForgeAllocated: make([]AuctionEventNewForgeAllocated, 0),
|
||||
NewMinBidEpoch: make([]AuctionEventNewMinBidEpoch, 0),
|
||||
NewForge: make([]AuctionEventNewForge, 0),
|
||||
HEZClaimed: make([]AuctionEventHEZClaimed, 0),
|
||||
}
|
||||
}
|
||||
|
||||
// AuctionInterface is the inteface to to Auction Smart Contract
|
||||
type AuctionInterface interface {
|
||||
//
|
||||
|
||||
@@ -18,9 +18,9 @@ import (
|
||||
|
||||
// EthereumInterface is the interface to Ethereum
|
||||
type EthereumInterface interface {
|
||||
EthCurrentBlock() (*big.Int, error)
|
||||
EthHeaderByNumber(context.Context, *big.Int) (*types.Header, error)
|
||||
EthBlockByNumber(context.Context, *big.Int) (*common.Block, error)
|
||||
EthCurrentBlock() (int64, error)
|
||||
// EthHeaderByNumber(context.Context, *big.Int) (*types.Header, error)
|
||||
EthBlockByNumber(context.Context, int64) (*common.Block, error)
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -214,29 +214,33 @@ func (c *EthereumClient) waitReceipt(ctx context.Context, tx *types.Transaction,
|
||||
}
|
||||
|
||||
// EthCurrentBlock returns the current block number in the blockchain
|
||||
func (c *EthereumClient) EthCurrentBlock() (*big.Int, error) {
|
||||
func (c *EthereumClient) EthCurrentBlock() (int64, error) {
|
||||
ctx, cancel := context.WithTimeout(context.TODO(), 1*time.Second)
|
||||
defer cancel()
|
||||
header, err := c.client.HeaderByNumber(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return 0, err
|
||||
}
|
||||
return header.Number, nil
|
||||
return header.Number.Int64(), nil
|
||||
}
|
||||
|
||||
// EthHeaderByNumber internally calls ethclient.Client HeaderByNumber
|
||||
func (c *EthereumClient) EthHeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
|
||||
return c.client.HeaderByNumber(ctx, number)
|
||||
}
|
||||
// func (c *EthereumClient) EthHeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
|
||||
// return c.client.HeaderByNumber(ctx, number)
|
||||
// }
|
||||
|
||||
// EthBlockByNumber internally calls ethclient.Client BlockByNumber and returns *common.Block
|
||||
func (c *EthereumClient) EthBlockByNumber(ctx context.Context, number *big.Int) (*common.Block, error) {
|
||||
block, err := c.client.BlockByNumber(ctx, number)
|
||||
func (c *EthereumClient) EthBlockByNumber(ctx context.Context, number int64) (*common.Block, error) {
|
||||
blockNum := big.NewInt(number)
|
||||
if number == 0 {
|
||||
blockNum = nil
|
||||
}
|
||||
block, err := c.client.BlockByNumber(ctx, blockNum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := &common.Block{
|
||||
EthBlockNum: block.Number().Uint64(),
|
||||
EthBlockNum: block.Number().Int64(),
|
||||
Timestamp: time.Unix(int64(block.Time()), 0),
|
||||
Hash: block.Hash(),
|
||||
}
|
||||
|
||||
@@ -5,10 +5,19 @@ import (
|
||||
|
||||
ethCommon "github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/hermeznetwork/hermez-node/common"
|
||||
"github.com/hermeznetwork/hermez-node/utils"
|
||||
"github.com/iden3/go-iden3-crypto/babyjub"
|
||||
)
|
||||
|
||||
const (
|
||||
// FeeIdxCoordinatorLen is the number of tokens the coordinator can use
|
||||
// to collect fees (determines the number of tokens that the
|
||||
// coordinator can collect fees from). This value is determined by the
|
||||
// circuit.
|
||||
FeeIdxCoordinatorLen = 64
|
||||
)
|
||||
|
||||
// RollupConstants are the constants of the Rollup Smart Contract
|
||||
type RollupConstants struct {
|
||||
// Maxim Deposit allowed
|
||||
@@ -41,21 +50,28 @@ type RollupVariables struct {
|
||||
// QueueStruct is the queue of L1Txs for a batch
|
||||
//nolint:structcheck
|
||||
type QueueStruct struct {
|
||||
L1TxQueue [][]byte
|
||||
CurrentIndex int64
|
||||
L1TxQueue []common.L1Tx
|
||||
TotalL1TxFee *big.Int
|
||||
}
|
||||
|
||||
// NewQueueStruct creates a new clear QueueStruct.
|
||||
func NewQueueStruct() *QueueStruct {
|
||||
return &QueueStruct{
|
||||
L1TxQueue: make([]common.L1Tx, 0),
|
||||
TotalL1TxFee: big.NewInt(0),
|
||||
}
|
||||
}
|
||||
|
||||
// RollupState represents the state of the Rollup in the Smart Contract
|
||||
//nolint:structcheck,unused
|
||||
type RollupState struct {
|
||||
StateRoot *big.Int
|
||||
ExitRoots []*big.Int
|
||||
ExiNullifierMap map[[256 / 8]byte]bool
|
||||
ExitNullifierMap map[[256 / 8]byte]bool
|
||||
TokenList []ethCommon.Address
|
||||
TokenMap map[ethCommon.Address]bool
|
||||
mapL1TxQueue map[int64]QueueStruct
|
||||
LastLTxBatch int64
|
||||
MapL1TxQueue map[int64]*QueueStruct
|
||||
LastL1L2Batch int64
|
||||
CurrentToForgeL1TxsNum int64
|
||||
LastToForgeL1TxsNum int64
|
||||
CurrentIdx int64
|
||||
@@ -63,9 +79,7 @@ type RollupState struct {
|
||||
|
||||
// RollupEventL1UserTx is an event of the Rollup Smart Contract
|
||||
type RollupEventL1UserTx struct {
|
||||
L1UserTx []byte
|
||||
ToForgeL1TxsNum int64
|
||||
Position int
|
||||
L1Tx common.L1Tx
|
||||
}
|
||||
|
||||
// RollupEventAddToken is an event of the Rollup Smart Contract
|
||||
@@ -76,7 +90,8 @@ type RollupEventAddToken struct {
|
||||
|
||||
// RollupEventForgeBatch is an event of the Rollup Smart Contract
|
||||
type RollupEventForgeBatch struct {
|
||||
BatchNum int64
|
||||
BatchNum int64
|
||||
EthTxHash ethCommon.Hash
|
||||
}
|
||||
|
||||
// RollupEventUpdateForgeL1Timeout is an event of the Rollup Smart Contract
|
||||
@@ -117,21 +132,35 @@ type RollupEvents struct { //nolint:structcheck
|
||||
Withdraw []RollupEventWithdraw
|
||||
}
|
||||
|
||||
// NewRollupEvents creates an empty RollupEvents with the slices initialized.
|
||||
func NewRollupEvents() RollupEvents {
|
||||
return RollupEvents{
|
||||
L1UserTx: make([]RollupEventL1UserTx, 0),
|
||||
AddToken: make([]RollupEventAddToken, 0),
|
||||
ForgeBatch: make([]RollupEventForgeBatch, 0),
|
||||
UpdateForgeL1Timeout: make([]RollupEventUpdateForgeL1Timeout, 0),
|
||||
UpdateFeeL1UserTx: make([]RollupEventUpdateFeeL1UserTx, 0),
|
||||
UpdateFeeAddToken: make([]RollupEventUpdateFeeAddToken, 0),
|
||||
UpdateTokenHez: make([]RollupEventUpdateTokenHez, 0),
|
||||
Withdraw: make([]RollupEventWithdraw, 0),
|
||||
}
|
||||
}
|
||||
|
||||
// RollupForgeBatchArgs are the arguments to the ForgeBatch function in the Rollup Smart Contract
|
||||
//nolint:structcheck,unused
|
||||
type RollupForgeBatchArgs struct {
|
||||
proofA [2]*big.Int
|
||||
proofB [2][2]*big.Int
|
||||
proofC [2]*big.Int
|
||||
newLastIdx int64
|
||||
newStRoot *big.Int
|
||||
newExitRoot *big.Int
|
||||
// TODO: Replace compressedL1CoordinatorTx, l2TxsData, feeIdxCoordinator for vectors
|
||||
compressedL1CoordinatorTx []byte
|
||||
l2TxsData []byte
|
||||
feeIdxCoordinator []byte
|
||||
verifierIdx int64
|
||||
l1Batch bool
|
||||
ProofA [2]*big.Int
|
||||
ProofB [2][2]*big.Int
|
||||
ProofC [2]*big.Int
|
||||
NewLastIdx int64
|
||||
NewStRoot *big.Int
|
||||
NewExitRoot *big.Int
|
||||
L1CoordinatorTxs []*common.L1Tx
|
||||
L2Txs []*common.L2Tx
|
||||
FeeIdxCoordinator []common.Idx
|
||||
// Circuit selector
|
||||
VerifierIdx int64
|
||||
L1Batch bool
|
||||
}
|
||||
|
||||
// RollupInterface is the inteface to to Rollup Smart Contract
|
||||
@@ -176,7 +205,7 @@ type RollupInterface interface {
|
||||
|
||||
RollupConstants() (*RollupConstants, error)
|
||||
RollupEventsByBlock(blockNum int64) (*RollupEvents, *ethCommon.Hash, error)
|
||||
RollupForgeBatchArgs(*types.Transaction) (*RollupForgeBatchArgs, error)
|
||||
RollupForgeBatchArgs(ethCommon.Hash) (*RollupForgeBatchArgs, error)
|
||||
}
|
||||
|
||||
//
|
||||
@@ -293,6 +322,11 @@ func (c *RollupClient) RollupEventsByBlock(blockNum int64) (*RollupEvents, *ethC
|
||||
}
|
||||
|
||||
// RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the Rollup Smart Contract in the given transaction
|
||||
func (c *RollupClient) RollupForgeBatchArgs(transaction *types.Transaction) (*RollupForgeBatchArgs, error) {
|
||||
func (c *RollupClient) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*RollupForgeBatchArgs, error) {
|
||||
// tx := client.TransactionByHash(ethTxHash) -> types.Transaction
|
||||
// txData := types.Transaction -> Data()
|
||||
// m := abi.MethodById(txData) -> Method
|
||||
// m.Inputs.Unpack(txData) -> Args
|
||||
// client.TransactionReceipt()?
|
||||
return nil, errTODO
|
||||
}
|
||||
|
||||
1
go.mod
1
go.mod
@@ -13,6 +13,7 @@ require (
|
||||
github.com/jinzhu/gorm v1.9.15
|
||||
github.com/jmoiron/sqlx v1.2.0
|
||||
github.com/lib/pq v1.8.0
|
||||
github.com/mitchellh/copystructure v1.0.0
|
||||
github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351
|
||||
github.com/russross/meddler v1.0.0
|
||||
github.com/stretchr/testify v1.6.1
|
||||
|
||||
2
go.sum
2
go.sum
@@ -399,6 +399,7 @@ github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
@@ -408,6 +409,7 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.3.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"math/big"
|
||||
"sync"
|
||||
|
||||
ethCommon "github.com/ethereum/go-ethereum/common"
|
||||
@@ -50,7 +49,7 @@ type BlockData struct {
|
||||
|
||||
// Status is returned by the Status method
|
||||
type Status struct {
|
||||
CurrentBlock uint64
|
||||
CurrentBlock int64
|
||||
CurrentBatch common.BatchNum
|
||||
CurrentForgerAddr ethCommon.Address
|
||||
NextForgerAddr ethCommon.Address
|
||||
@@ -82,15 +81,15 @@ func (s *Synchronizer) Sync() error {
|
||||
s.mux.Lock()
|
||||
defer s.mux.Unlock()
|
||||
|
||||
var lastStoredForgeL1TxsNum uint64
|
||||
var lastStoredForgeL1TxsNum int64
|
||||
|
||||
// TODO: Get this information from ethClient once it's implemented
|
||||
// for the moment we will get the latestblock - 20 as firstSavedBlock
|
||||
latestBlock, err := s.ethClient.EthBlockByNumber(context.Background(), nil)
|
||||
latestBlock, err := s.ethClient.EthBlockByNumber(context.Background(), 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.firstSavedBlock, err = s.ethClient.EthBlockByNumber(context.Background(), big.NewInt(int64(latestBlock.EthBlockNum-blocksToSync)))
|
||||
s.firstSavedBlock, err = s.ethClient.EthBlockByNumber(context.Background(), latestBlock.EthBlockNum-blocksToSync)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -107,7 +106,7 @@ func (s *Synchronizer) Sync() error {
|
||||
lastSavedBlock = s.firstSavedBlock
|
||||
} else {
|
||||
// Get the latest block we have in History DB from blockchain to detect a reorg
|
||||
ethBlock, err := s.ethClient.EthBlockByNumber(context.Background(), big.NewInt(int64(lastSavedBlock.EthBlockNum)))
|
||||
ethBlock, err := s.ethClient.EthBlockByNumber(context.Background(), lastSavedBlock.EthBlockNum)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -135,10 +134,10 @@ func (s *Synchronizer) Sync() error {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("Blocks to sync: %v (lastSavedBlock: %v, latestBlock: %v)", latestBlockNum.Uint64()-lastSavedBlock.EthBlockNum, lastSavedBlock.EthBlockNum, latestBlockNum)
|
||||
log.Debugf("Blocks to sync: %v (lastSavedBlock: %v, latestBlock: %v)", latestBlockNum-lastSavedBlock.EthBlockNum, lastSavedBlock.EthBlockNum, latestBlockNum)
|
||||
|
||||
for lastSavedBlock.EthBlockNum < latestBlockNum.Uint64() {
|
||||
ethBlock, err := s.ethClient.EthBlockByNumber(context.Background(), big.NewInt(int64(lastSavedBlock.EthBlockNum+1)))
|
||||
for lastSavedBlock.EthBlockNum < latestBlockNum {
|
||||
ethBlock, err := s.ethClient.EthBlockByNumber(context.Background(), lastSavedBlock.EthBlockNum+1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -181,7 +180,7 @@ func (s *Synchronizer) reorg(uncleBlock *common.Block) error {
|
||||
|
||||
// Iterate History DB and the blokchain looking for the latest valid block
|
||||
for !found && blockNum > s.firstSavedBlock.EthBlockNum {
|
||||
header, err := s.ethClient.EthHeaderByNumber(context.Background(), big.NewInt(int64(blockNum)))
|
||||
ethBlock, err := s.ethClient.EthBlockByNumber(context.Background(), blockNum)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -190,7 +189,7 @@ func (s *Synchronizer) reorg(uncleBlock *common.Block) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if block.Hash == header.Hash() {
|
||||
if block.Hash == ethBlock.Hash {
|
||||
found = true
|
||||
log.Debugf("Found valid block: %v", blockNum)
|
||||
} else {
|
||||
@@ -255,12 +254,12 @@ func (s *Synchronizer) Status() (*Status, error) {
|
||||
// TODO: Get CurrentForgerAddr & NextForgerAddr
|
||||
|
||||
// Check if Synchronizer is synchronized
|
||||
status.Synchronized = status.CurrentBlock == latestBlockNum.Uint64()
|
||||
status.Synchronized = status.CurrentBlock == latestBlockNum
|
||||
return status, nil
|
||||
}
|
||||
|
||||
// rollupSync gets information from the Rollup Contract
|
||||
func (s *Synchronizer) rollupSync(block *common.Block, lastStoredForgeL1TxsNum uint64) (*BlockData, []*BatchData, error) {
|
||||
func (s *Synchronizer) rollupSync(block *common.Block, lastStoredForgeL1TxsNum int64) (*BlockData, []*BatchData, error) {
|
||||
// To be implemented
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
@@ -13,67 +15,273 @@ import (
|
||||
"github.com/hermeznetwork/hermez-node/log"
|
||||
"github.com/hermeznetwork/hermez-node/utils"
|
||||
"github.com/iden3/go-iden3-crypto/babyjub"
|
||||
"github.com/mitchellh/copystructure"
|
||||
)
|
||||
|
||||
// RollupBlock stores all the data related to the Rollup SC from an ethereum block
|
||||
type RollupBlock struct {
|
||||
State eth.RollupState
|
||||
Vars eth.RollupVariables
|
||||
Events eth.RollupEvents
|
||||
}
|
||||
|
||||
// AuctionBlock stores all the data related to the Auction SC from an ethereum block
|
||||
type AuctionBlock struct {
|
||||
State eth.AuctionState
|
||||
Vars eth.AuctionVariables
|
||||
Events eth.AuctionEvents
|
||||
}
|
||||
|
||||
// EthereumBlock stores all the generic data related to the an ethereum block
|
||||
type EthereumBlock struct {
|
||||
BlockNum int64
|
||||
Time int64
|
||||
Hash ethCommon.Hash
|
||||
ParentHash ethCommon.Hash
|
||||
// state ethState
|
||||
}
|
||||
|
||||
// Block represents a ethereum block
|
||||
type Block struct {
|
||||
Rollup *RollupBlock
|
||||
Auction *AuctionBlock
|
||||
Eth *EthereumBlock
|
||||
}
|
||||
|
||||
// type ethState struct {
|
||||
// blockNum int64
|
||||
// }
|
||||
|
||||
// type state struct {
|
||||
// rollupState eth.RollupState
|
||||
// rollupVars eth.RollupVariables
|
||||
// auctionState eth.AuctionState
|
||||
// auctionVars eth.AuctionVariables
|
||||
// eth ethState
|
||||
// }
|
||||
|
||||
// ClientSetup is used to initialize the constants of the Smart Contracts and
|
||||
// other details of the test Client
|
||||
type ClientSetup struct {
|
||||
RollupConstants *eth.RollupConstants
|
||||
RollupVariables *eth.RollupVariables
|
||||
AuctionConstants *eth.AuctionConstants
|
||||
AuctionVariables *eth.AuctionVariables
|
||||
VerifyProof bool
|
||||
}
|
||||
|
||||
// Timer is an interface to simulate a source of time, useful to advance time
|
||||
// virtually.
|
||||
type Timer interface {
|
||||
Time() int64
|
||||
}
|
||||
|
||||
// type forgeBatchArgs struct {
|
||||
// ethTx *types.Transaction
|
||||
// blockNum int64
|
||||
// blockHash ethCommon.Hash
|
||||
// }
|
||||
|
||||
// Client implements the eth.ClientInterface interface, allowing to manipulate the
|
||||
// values for testing, working with deterministic results.
|
||||
type Client struct {
|
||||
log bool
|
||||
blockNum *big.Int
|
||||
log bool
|
||||
rollupConstants *eth.RollupConstants
|
||||
auctionConstants *eth.AuctionConstants
|
||||
blocks map[int64]*Block
|
||||
// state state
|
||||
blockNum int64 // last mined block num
|
||||
maxBlockNum int64 // highest block num calculated
|
||||
timer Timer
|
||||
hasher hasher
|
||||
|
||||
forgeBatchArgsPending map[ethCommon.Hash]*eth.RollupForgeBatchArgs
|
||||
forgeBatchArgs map[ethCommon.Hash]*eth.RollupForgeBatchArgs
|
||||
}
|
||||
|
||||
// NewClient returns a new test Client that implements the eth.IClient
|
||||
// interface, at the given initialBlockNumber.
|
||||
func NewClient(l bool, initialBlockNumber int64) *Client {
|
||||
func NewClient(l bool, timer Timer, setup *ClientSetup) *Client {
|
||||
blocks := make(map[int64]*Block)
|
||||
blockNum := int64(0)
|
||||
|
||||
hasher := hasher{}
|
||||
// Add ethereum genesis block
|
||||
mapL1TxQueue := make(map[int64]*eth.QueueStruct)
|
||||
mapL1TxQueue[0] = eth.NewQueueStruct()
|
||||
mapL1TxQueue[1] = eth.NewQueueStruct()
|
||||
blockCurrent := Block{
|
||||
Rollup: &RollupBlock{
|
||||
State: eth.RollupState{
|
||||
StateRoot: big.NewInt(0),
|
||||
ExitRoots: make([]*big.Int, 0),
|
||||
ExitNullifierMap: make(map[[256 / 8]byte]bool),
|
||||
TokenList: make([]ethCommon.Address, 0),
|
||||
TokenMap: make(map[ethCommon.Address]bool),
|
||||
MapL1TxQueue: mapL1TxQueue,
|
||||
LastL1L2Batch: 0,
|
||||
CurrentToForgeL1TxsNum: 0,
|
||||
LastToForgeL1TxsNum: 1,
|
||||
CurrentIdx: 0,
|
||||
},
|
||||
Vars: *setup.RollupVariables,
|
||||
Events: eth.NewRollupEvents(),
|
||||
},
|
||||
Auction: &AuctionBlock{
|
||||
State: eth.AuctionState{
|
||||
Slots: make(map[int64]eth.SlotState),
|
||||
PendingBalances: make(map[ethCommon.Address]*big.Int),
|
||||
Coordinators: make(map[ethCommon.Address]eth.Coordinator),
|
||||
},
|
||||
Vars: *setup.AuctionVariables,
|
||||
Events: eth.NewAuctionEvents(),
|
||||
},
|
||||
Eth: &EthereumBlock{
|
||||
BlockNum: blockNum,
|
||||
Time: timer.Time(),
|
||||
Hash: hasher.Next(),
|
||||
ParentHash: ethCommon.Hash{},
|
||||
},
|
||||
}
|
||||
blocks[blockNum] = &blockCurrent
|
||||
blockNextRaw, err := copystructure.Copy(&blockCurrent)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
blockNext := blockNextRaw.(*Block)
|
||||
blocks[blockNum+1] = blockNext
|
||||
|
||||
return &Client{
|
||||
log: l,
|
||||
blockNum: big.NewInt(initialBlockNumber),
|
||||
log: l,
|
||||
rollupConstants: setup.RollupConstants,
|
||||
auctionConstants: setup.AuctionConstants,
|
||||
blocks: blocks,
|
||||
timer: timer,
|
||||
hasher: hasher,
|
||||
forgeBatchArgsPending: make(map[ethCommon.Hash]*eth.RollupForgeBatchArgs),
|
||||
forgeBatchArgs: make(map[ethCommon.Hash]*eth.RollupForgeBatchArgs),
|
||||
}
|
||||
}
|
||||
|
||||
// Advance moves one block forward
|
||||
func (c *Client) Advance() {
|
||||
c.blockNum = c.blockNum.Add(c.blockNum, big.NewInt(1))
|
||||
//
|
||||
// Mock Control
|
||||
//
|
||||
|
||||
// Debugf calls log.Debugf if c.log is true
|
||||
func (c *Client) Debugf(template string, args ...interface{}) {
|
||||
if c.log {
|
||||
log.Debugf("TestEthClient blockNum advanced: %d", c.blockNum)
|
||||
log.Debugf(template, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// SetBlockNum sets the Client.blockNum to the given blockNum
|
||||
func (c *Client) SetBlockNum(blockNum *big.Int) {
|
||||
c.blockNum = blockNum
|
||||
// Debugw calls log.Debugw if c.log is true
|
||||
func (c *Client) Debugw(template string, kv ...interface{}) {
|
||||
if c.log {
|
||||
log.Debugf("TestEthClient blockNum set to: %d", c.blockNum)
|
||||
log.Debugw(template, kv...)
|
||||
}
|
||||
}
|
||||
|
||||
type hasher struct {
|
||||
counter uint64
|
||||
}
|
||||
|
||||
// Next returns the next hash
|
||||
func (h *hasher) Next() ethCommon.Hash {
|
||||
var hash ethCommon.Hash
|
||||
binary.LittleEndian.PutUint64(hash[:], h.counter)
|
||||
h.counter++
|
||||
return hash
|
||||
}
|
||||
|
||||
func (c *Client) nextBlock() *Block {
|
||||
return c.blocks[c.blockNum+1]
|
||||
}
|
||||
|
||||
// CtlMineBlock moves one block forward
|
||||
func (c *Client) CtlMineBlock() {
|
||||
blockCurrent := c.nextBlock()
|
||||
c.blockNum++
|
||||
c.maxBlockNum = c.blockNum
|
||||
blockCurrent.Eth = &EthereumBlock{
|
||||
BlockNum: c.blockNum,
|
||||
Time: c.timer.Time(),
|
||||
Hash: c.hasher.Next(),
|
||||
ParentHash: blockCurrent.Eth.Hash,
|
||||
}
|
||||
for ethTxHash, forgeBatchArgs := range c.forgeBatchArgsPending {
|
||||
c.forgeBatchArgs[ethTxHash] = forgeBatchArgs
|
||||
}
|
||||
c.forgeBatchArgsPending = make(map[ethCommon.Hash]*eth.RollupForgeBatchArgs)
|
||||
|
||||
blockNextRaw, err := copystructure.Copy(blockCurrent)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
blockNext := blockNextRaw.(*Block)
|
||||
blockNext.Rollup.Events = eth.NewRollupEvents()
|
||||
blockNext.Auction.Events = eth.NewAuctionEvents()
|
||||
c.blocks[c.blockNum+1] = blockNext
|
||||
c.Debugw("TestClient mined block", "blockNum", c.blockNum)
|
||||
}
|
||||
|
||||
// CtlRollback discards the last mined block. Use this to replace a mined
|
||||
// block to simulate reorgs.
|
||||
func (c *Client) CtlRollback() {
|
||||
if c.blockNum == 0 {
|
||||
panic("Can't rollback at blockNum = 0")
|
||||
}
|
||||
delete(c.blocks, c.blockNum+1) // delete next block
|
||||
delete(c.blocks, c.blockNum) // delete current block
|
||||
c.blockNum--
|
||||
blockCurrent := c.blocks[c.blockNum]
|
||||
blockNextRaw, err := copystructure.Copy(blockCurrent)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
blockNext := blockNextRaw.(*Block)
|
||||
blockNext.Rollup.Events = eth.NewRollupEvents()
|
||||
blockNext.Auction.Events = eth.NewAuctionEvents()
|
||||
c.blocks[c.blockNum+1] = blockNext
|
||||
}
|
||||
|
||||
//
|
||||
// Ethereum
|
||||
//
|
||||
|
||||
// EthCurrentBlock returns the current blockNum
|
||||
func (c *Client) EthCurrentBlock() (*big.Int, error) {
|
||||
func (c *Client) EthCurrentBlock() (int64, error) {
|
||||
if c.blockNum < c.maxBlockNum {
|
||||
panic("blockNum has decreased. " +
|
||||
"After a rollback you must mine to reach the same or higher blockNum")
|
||||
}
|
||||
return c.blockNum, nil
|
||||
}
|
||||
|
||||
func newHeader(number *big.Int) *types.Header {
|
||||
return &types.Header{
|
||||
Number: number,
|
||||
Time: uint64(number.Int64()),
|
||||
}
|
||||
}
|
||||
// func newHeader(number *big.Int) *types.Header {
|
||||
// return &types.Header{
|
||||
// Number: number,
|
||||
// Time: uint64(number.Int64()),
|
||||
// }
|
||||
// }
|
||||
|
||||
// EthHeaderByNumber returns the *types.Header for the given block number in a
|
||||
// deterministic way.
|
||||
func (c *Client) EthHeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
|
||||
return newHeader(number), nil
|
||||
}
|
||||
// func (c *Client) EthHeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
|
||||
// return newHeader(number), nil
|
||||
// }
|
||||
|
||||
// EthBlockByNumber returns the *common.Block for the given block number in a
|
||||
// deterministic way.
|
||||
func (c *Client) EthBlockByNumber(ctx context.Context, number *big.Int) (*common.Block, error) {
|
||||
header := newHeader(number)
|
||||
|
||||
func (c *Client) EthBlockByNumber(ctx context.Context, blockNum int64) (*common.Block, error) {
|
||||
block, ok := c.blocks[blockNum]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("block not found")
|
||||
}
|
||||
return &common.Block{
|
||||
EthBlockNum: uint64(number.Int64()),
|
||||
Timestamp: time.Unix(number.Int64(), 0),
|
||||
Hash: header.Hash(),
|
||||
EthBlockNum: blockNum,
|
||||
Timestamp: time.Unix(block.Eth.Time, 0),
|
||||
Hash: block.Eth.Hash,
|
||||
ParentHash: block.Eth.ParentHash,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -83,14 +291,78 @@ var errTODO = fmt.Errorf("TODO: Not implemented yet")
|
||||
// Rollup
|
||||
//
|
||||
|
||||
// CtlAddL1TxUser adds an L1TxUser to the L1UserTxs queue of the Rollup
|
||||
func (c *Client) CtlAddL1TxUser(l1Tx *common.L1Tx) {
|
||||
nextBlock := c.nextBlock()
|
||||
r := nextBlock.Rollup
|
||||
queue := r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
|
||||
if len(queue.L1TxQueue) >= c.rollupConstants.MaxL1UserTx {
|
||||
r.State.LastToForgeL1TxsNum++
|
||||
r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
|
||||
queue = r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum]
|
||||
}
|
||||
if int64(l1Tx.FromIdx) > r.State.CurrentIdx {
|
||||
panic("l1Tx.FromIdx > r.State.CurrentIdx")
|
||||
}
|
||||
if int(l1Tx.TokenID)+1 > len(r.State.TokenList) {
|
||||
panic("l1Tx.TokenID + 1 > len(r.State.TokenList)")
|
||||
}
|
||||
queue.L1TxQueue = append(queue.L1TxQueue, *l1Tx)
|
||||
r.Events.L1UserTx = append(r.Events.L1UserTx, eth.RollupEventL1UserTx{L1Tx: *l1Tx})
|
||||
}
|
||||
|
||||
func (c *Client) newTransaction(name string, value interface{}) *types.Transaction {
|
||||
data, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return types.NewTransaction(0, ethCommon.Address{}, nil, 0, nil,
|
||||
data)
|
||||
}
|
||||
|
||||
// RollupForgeBatch is the interface to call the smart contract function
|
||||
func (c *Client) RollupForgeBatch(*eth.RollupForgeBatchArgs) (*types.Transaction, error) {
|
||||
return nil, errTODO
|
||||
}
|
||||
|
||||
// CtlAddBatch adds forged batch to the Rollup, without checking any ZKProof
|
||||
func (c *Client) CtlAddBatch(args *eth.RollupForgeBatchArgs) {
|
||||
nextBlock := c.nextBlock()
|
||||
r := nextBlock.Rollup
|
||||
r.State.StateRoot = args.NewStRoot
|
||||
if args.NewLastIdx < r.State.CurrentIdx {
|
||||
panic("args.NewLastIdx < r.State.CurrentIdx")
|
||||
}
|
||||
r.State.CurrentIdx = args.NewLastIdx
|
||||
r.State.ExitRoots = append(r.State.ExitRoots, args.NewExitRoot)
|
||||
if args.L1Batch {
|
||||
r.State.CurrentToForgeL1TxsNum++
|
||||
if r.State.CurrentToForgeL1TxsNum == r.State.LastToForgeL1TxsNum {
|
||||
r.State.LastToForgeL1TxsNum++
|
||||
r.State.MapL1TxQueue[r.State.LastToForgeL1TxsNum] = eth.NewQueueStruct()
|
||||
}
|
||||
}
|
||||
ethTx := c.newTransaction("forgebatch", args)
|
||||
c.forgeBatchArgsPending[ethTx.Hash()] = args
|
||||
r.Events.ForgeBatch = append(r.Events.ForgeBatch, eth.RollupEventForgeBatch{
|
||||
BatchNum: int64(len(r.State.ExitRoots)),
|
||||
EthTxHash: ethTx.Hash(),
|
||||
})
|
||||
}
|
||||
|
||||
// RollupAddToken is the interface to call the smart contract function
|
||||
func (c *Client) RollupAddToken(tokenAddress ethCommon.Address) (*types.Transaction, error) {
|
||||
return nil, errTODO
|
||||
nextBlock := c.nextBlock()
|
||||
r := nextBlock.Rollup
|
||||
if _, ok := r.State.TokenMap[tokenAddress]; ok {
|
||||
return nil, fmt.Errorf("Token %v already registered", tokenAddress)
|
||||
}
|
||||
|
||||
r.State.TokenMap[tokenAddress] = true
|
||||
r.State.TokenList = append(r.State.TokenList, tokenAddress)
|
||||
r.Events.AddToken = append(r.Events.AddToken, eth.RollupEventAddToken{Address: tokenAddress,
|
||||
TokenID: uint32(len(r.State.TokenList) - 1)})
|
||||
return c.newTransaction("addtoken", tokenAddress), nil
|
||||
}
|
||||
|
||||
// RollupWithdrawSNARK is the interface to call the smart contract function
|
||||
@@ -185,12 +457,20 @@ func (c *Client) RollupConstants() (*eth.RollupConstants, error) {
|
||||
|
||||
// RollupEventsByBlock returns the events in a block that happened in the Rollup Smart Contract
|
||||
func (c *Client) RollupEventsByBlock(blockNum int64) (*eth.RollupEvents, *ethCommon.Hash, error) {
|
||||
return nil, nil, errTODO
|
||||
block, ok := c.blocks[blockNum]
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("Block %v doesn't exist", blockNum)
|
||||
}
|
||||
return &block.Rollup.Events, &block.Eth.Hash, nil
|
||||
}
|
||||
|
||||
// RollupForgeBatchArgs returns the arguments used in a ForgeBatch call in the Rollup Smart Contract in the given transaction
|
||||
func (c *Client) RollupForgeBatchArgs(transaction *types.Transaction) (*eth.RollupForgeBatchArgs, error) {
|
||||
return nil, errTODO
|
||||
func (c *Client) RollupForgeBatchArgs(ethTxHash ethCommon.Hash) (*eth.RollupForgeBatchArgs, error) {
|
||||
forgeBatchArgs, ok := c.forgeBatchArgs[ethTxHash]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("transaction not found")
|
||||
}
|
||||
return forgeBatchArgs, nil
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -2,45 +2,219 @@ package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"encoding/binary"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
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/eth"
|
||||
"github.com/iden3/go-iden3-crypto/babyjub"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var clientSetup *ClientSetup
|
||||
|
||||
func init() {
|
||||
rollupConstants := ð.RollupConstants{}
|
||||
rollupVariables := ð.RollupVariables{
|
||||
MaxTxVerifiers: make([]int, 0),
|
||||
TokenHEZ: ethCommon.Address{},
|
||||
GovernanceAddress: ethCommon.Address{},
|
||||
SafetyBot: ethCommon.Address{},
|
||||
ConsensusContract: ethCommon.Address{},
|
||||
WithdrawalContract: ethCommon.Address{},
|
||||
FeeAddToken: big.NewInt(1),
|
||||
ForgeL1Timeout: 16,
|
||||
FeeL1UserTx: big.NewInt(2),
|
||||
}
|
||||
auctionConstants := ð.AuctionConstants{}
|
||||
auctionVariables := ð.AuctionVariables{
|
||||
DonationAddress: ethCommon.Address{},
|
||||
BootCoordinator: ethCommon.Address{},
|
||||
MinBidEpoch: [6]*big.Int{
|
||||
big.NewInt(10), big.NewInt(11), big.NewInt(12),
|
||||
big.NewInt(13), big.NewInt(14), big.NewInt(15)},
|
||||
ClosedAuctionSlots: 0,
|
||||
OpenAuctionSlots: 0,
|
||||
AllocationRatio: [3]uint8{},
|
||||
Outbidding: 0,
|
||||
SlotDeadline: 0,
|
||||
}
|
||||
clientSetup = &ClientSetup{
|
||||
RollupConstants: rollupConstants,
|
||||
RollupVariables: rollupVariables,
|
||||
AuctionConstants: auctionConstants,
|
||||
AuctionVariables: auctionVariables,
|
||||
}
|
||||
}
|
||||
|
||||
type timer struct {
|
||||
time int64
|
||||
}
|
||||
|
||||
func (t *timer) Time() int64 {
|
||||
currentTime := t.time
|
||||
t.time++
|
||||
return currentTime
|
||||
}
|
||||
|
||||
func TestClientInterface(t *testing.T) {
|
||||
var c eth.ClientInterface
|
||||
client := NewClient(true, 1000)
|
||||
var timer timer
|
||||
client := NewClient(true, &timer, clientSetup)
|
||||
c = client
|
||||
require.NotNil(t, c)
|
||||
}
|
||||
|
||||
func TestEthClient(t *testing.T) {
|
||||
c := NewClient(true, 1000)
|
||||
token1Addr := ethCommon.HexToAddress("0x6b175474e89094c44da98b954eedeac495271d0f")
|
||||
|
||||
block, err := c.EthBlockByNumber(context.TODO(), big.NewInt(3))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, uint64(3), block.EthBlockNum)
|
||||
assert.Equal(t, time.Unix(3, 0), block.Timestamp)
|
||||
assert.Equal(t, "0x6b0ab5a7a0ebf5f05cef3b49bc7a9739de06469a4e05557d802ee828fdf5187e", block.Hash.Hex())
|
||||
var timer timer
|
||||
c := NewClient(true, &timer, clientSetup)
|
||||
blockNum, err := c.EthCurrentBlock()
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, int64(0), blockNum)
|
||||
|
||||
header, err := c.EthHeaderByNumber(context.TODO(), big.NewInt(4))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, big.NewInt(4), header.Number)
|
||||
assert.Equal(t, uint64(4), header.Time)
|
||||
assert.Equal(t, "0x66cdb12322040a5a345ad29cea66ca97c14d6142b53987010947c8c008e26913", header.Hash().Hex())
|
||||
block, err := c.EthBlockByNumber(context.TODO(), 0)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, int64(0), block.EthBlockNum)
|
||||
assert.Equal(t, time.Unix(0, 0), block.Timestamp)
|
||||
assert.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000000", block.Hash.Hex())
|
||||
assert.Equal(t, int64(0), c.blockNum)
|
||||
|
||||
assert.Equal(t, big.NewInt(1000), c.blockNum)
|
||||
c.Advance()
|
||||
assert.Equal(t, big.NewInt(1001), c.blockNum)
|
||||
c.Advance()
|
||||
assert.Equal(t, big.NewInt(1002), c.blockNum)
|
||||
// Mine some empty blocks
|
||||
|
||||
c.SetBlockNum(big.NewInt(5000))
|
||||
assert.Equal(t, big.NewInt(5000), c.blockNum)
|
||||
c.Advance()
|
||||
assert.Equal(t, big.NewInt(5001), c.blockNum)
|
||||
c.CtlMineBlock()
|
||||
assert.Equal(t, int64(1), c.blockNum)
|
||||
c.CtlMineBlock()
|
||||
assert.Equal(t, int64(2), c.blockNum)
|
||||
|
||||
block, err = c.EthBlockByNumber(context.TODO(), 2)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, int64(2), block.EthBlockNum)
|
||||
assert.Equal(t, time.Unix(2, 0), block.Timestamp)
|
||||
|
||||
// Add a token
|
||||
|
||||
tx, err := c.RollupAddToken(token1Addr)
|
||||
require.Nil(t, err)
|
||||
assert.NotNil(t, tx)
|
||||
|
||||
// Add some L1UserTxs
|
||||
// Create Accounts
|
||||
|
||||
const N = 16
|
||||
var keys [N]*keys
|
||||
for i := 0; i < N; i++ {
|
||||
keys[i] = genKeys(int64(i))
|
||||
l1UserTx := common.L1Tx{
|
||||
FromIdx: common.Idx(0),
|
||||
FromEthAddr: keys[i].Addr,
|
||||
FromBJJ: keys[i].BJJPublicKey,
|
||||
TokenID: common.TokenID(0),
|
||||
LoadAmount: big.NewInt(10 + int64(i)),
|
||||
}
|
||||
c.CtlAddL1TxUser(&l1UserTx)
|
||||
}
|
||||
c.CtlMineBlock()
|
||||
|
||||
blockNum, err = c.EthCurrentBlock()
|
||||
require.Nil(t, err)
|
||||
rollupEvents, _, err := c.RollupEventsByBlock(blockNum)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, N, len(rollupEvents.L1UserTx))
|
||||
assert.Equal(t, 1, len(rollupEvents.AddToken))
|
||||
|
||||
// Forge a batch
|
||||
|
||||
c.CtlAddBatch(ð.RollupForgeBatchArgs{
|
||||
NewLastIdx: 0,
|
||||
NewStRoot: big.NewInt(1),
|
||||
NewExitRoot: big.NewInt(100),
|
||||
L1CoordinatorTxs: []*common.L1Tx{},
|
||||
L2Txs: []*common.L2Tx{},
|
||||
FeeIdxCoordinator: make([]common.Idx, eth.FeeIdxCoordinatorLen),
|
||||
VerifierIdx: 0,
|
||||
L1Batch: true,
|
||||
})
|
||||
c.CtlMineBlock()
|
||||
|
||||
blockNumA, err := c.EthCurrentBlock()
|
||||
require.Nil(t, err)
|
||||
rollupEvents, hashA, err := c.RollupEventsByBlock(blockNumA)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 0, len(rollupEvents.L1UserTx))
|
||||
assert.Equal(t, 0, len(rollupEvents.AddToken))
|
||||
assert.Equal(t, 1, len(rollupEvents.ForgeBatch))
|
||||
|
||||
// Simulate reorg discarding last mined block
|
||||
|
||||
c.CtlRollback()
|
||||
c.CtlMineBlock()
|
||||
|
||||
blockNumB, err := c.EthCurrentBlock()
|
||||
require.Nil(t, err)
|
||||
rollupEvents, hashB, err := c.RollupEventsByBlock(blockNumA)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 0, len(rollupEvents.L1UserTx))
|
||||
assert.Equal(t, 0, len(rollupEvents.AddToken))
|
||||
assert.Equal(t, 0, len(rollupEvents.ForgeBatch))
|
||||
|
||||
assert.Equal(t, blockNumA, blockNumB)
|
||||
assert.NotEqual(t, hashA, hashB)
|
||||
|
||||
// Forge again
|
||||
rollupForgeBatchArgs0 := ð.RollupForgeBatchArgs{
|
||||
NewLastIdx: 0,
|
||||
NewStRoot: big.NewInt(1),
|
||||
NewExitRoot: big.NewInt(100),
|
||||
L1CoordinatorTxs: []*common.L1Tx{},
|
||||
L2Txs: []*common.L2Tx{},
|
||||
FeeIdxCoordinator: make([]common.Idx, eth.FeeIdxCoordinatorLen),
|
||||
VerifierIdx: 0,
|
||||
L1Batch: true,
|
||||
}
|
||||
c.CtlAddBatch(rollupForgeBatchArgs0)
|
||||
c.CtlMineBlock()
|
||||
|
||||
// Retrieve ForgeBatchArguments starting from the events
|
||||
|
||||
blockNum, err = c.EthCurrentBlock()
|
||||
require.Nil(t, err)
|
||||
rollupEvents, _, err = c.RollupEventsByBlock(blockNum)
|
||||
require.Nil(t, err)
|
||||
|
||||
rollupForgeBatchArgs1, err := c.RollupForgeBatchArgs(rollupEvents.ForgeBatch[0].EthTxHash)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, rollupForgeBatchArgs0, rollupForgeBatchArgs1)
|
||||
}
|
||||
|
||||
type keys struct {
|
||||
BJJSecretKey *babyjub.PrivateKey
|
||||
BJJPublicKey *babyjub.PublicKey
|
||||
Addr ethCommon.Address
|
||||
}
|
||||
|
||||
func genKeys(i int64) *keys {
|
||||
i++ // i = 0 doesn't work for the ecdsa key generation
|
||||
var sk babyjub.PrivateKey
|
||||
binary.LittleEndian.PutUint64(sk[:], uint64(i))
|
||||
|
||||
// eth address
|
||||
var key ecdsa.PrivateKey
|
||||
key.D = big.NewInt(i) // only for testing
|
||||
key.PublicKey.X, key.PublicKey.Y = ethCrypto.S256().ScalarBaseMult(key.D.Bytes())
|
||||
key.Curve = ethCrypto.S256()
|
||||
addr := ethCrypto.PubkeyToAddress(key.PublicKey)
|
||||
|
||||
return &keys{
|
||||
BJJSecretKey: &sk,
|
||||
BJJPublicKey: sk.Public(),
|
||||
Addr: addr,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user