arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/test/ethclient_test.go
test/ethclient_test.goRaw
  1package test
  2
  3import (
  4	"context"
  5	"crypto/ecdsa"
  6	"encoding/binary"
  7	"math/big"
  8	"testing"
  9	"time"
 10
 11	ethCommon "github.com/ethereum/go-ethereum/common"
 12	ethCrypto "github.com/ethereum/go-ethereum/crypto"
 13	"github.com/hermeznetwork/hermez-node/common"
 14	"github.com/hermeznetwork/hermez-node/eth"
 15	"github.com/hermeznetwork/tracerr"
 16	"github.com/iden3/go-iden3-crypto/babyjub"
 17	"github.com/stretchr/testify/assert"
 18	"github.com/stretchr/testify/require"
 19)
 20
 21type timer struct {
 22	time int64
 23}
 24
 25func (t *timer) Time() int64 {
 26	currentTime := t.time
 27	t.time++
 28	return currentTime
 29}
 30
 31func TestClientInterface(t *testing.T) {
 32	var c eth.ClientInterface
 33	var timer timer
 34	clientSetup := NewClientSetupExample()
 35	client := NewClient(true, &timer, &ethCommon.Address{}, clientSetup)
 36	c = client
 37	require.NotNil(t, c)
 38}
 39
 40func TestClientEth(t *testing.T) {
 41	var timer timer
 42	clientSetup := NewClientSetupExample()
 43	c := NewClient(true, &timer, &ethCommon.Address{}, clientSetup)
 44	blockNum, err := c.EthLastBlock()
 45	require.Nil(t, err)
 46	assert.Equal(t, int64(1), blockNum)
 47
 48	block, err := c.EthBlockByNumber(context.TODO(), 0)
 49	require.Nil(t, err)
 50	assert.Equal(t, int64(0), block.Num)
 51	assert.Equal(t, time.Unix(0, 0), block.Timestamp)
 52	assert.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000000", block.Hash.Hex())
 53
 54	// Mine some empty blocks
 55
 56	assert.Equal(t, int64(1), c.blockNum)
 57	c.CtlMineBlock()
 58	assert.Equal(t, int64(2), c.blockNum)
 59	c.CtlMineBlock()
 60	assert.Equal(t, int64(3), c.blockNum)
 61
 62	block, err = c.EthBlockByNumber(context.TODO(), 2)
 63	require.Nil(t, err)
 64	assert.Equal(t, int64(2), block.Num)
 65	assert.Equal(t, time.Unix(2, 0), block.Timestamp)
 66
 67	// Add a token
 68	tokenAddr := ethCommon.HexToAddress("0x44021007485550008e0f9f1f7b506c7d970ad8ce")
 69	constants := eth.ERC20Consts{
 70		Name:     "FooBar",
 71		Symbol:   "FOO",
 72		Decimals: 4,
 73	}
 74	c.CtlAddERC20(tokenAddr, constants)
 75	c.CtlMineBlock()
 76	tokenConstants, err := c.EthERC20Consts(tokenAddr)
 77	require.Nil(t, err)
 78	assert.Equal(t, constants, *tokenConstants)
 79}
 80
 81func TestClientAuction(t *testing.T) {
 82	addrBidder1 := ethCommon.HexToAddress("0x6b175474e89094c44da98b954eedeac495271d0f")
 83	addrBidder2 := ethCommon.HexToAddress("0xc27cadc437d067a6ec869502cc9f7F834cFc087a")
 84	addrForge := ethCommon.HexToAddress("0xCfAA413eEb796f328620a3630Ae39124cabcEa92")
 85	addrForge2 := ethCommon.HexToAddress("0x1fCb4ac309428feCc61B1C8cA5823C15A5e1a800")
 86
 87	var timer timer
 88	clientSetup := NewClientSetupExample()
 89	clientSetup.AuctionVariables.ClosedAuctionSlots = 2
 90	clientSetup.AuctionVariables.OpenAuctionSlots = 4320
 91	clientSetup.AuctionVariables.DefaultSlotSetBid = [6]*big.Int{
 92		big.NewInt(1000), big.NewInt(1100), big.NewInt(1200),
 93		big.NewInt(1300), big.NewInt(1400), big.NewInt(1500)}
 94	c := NewClient(true, &timer, &addrBidder1, clientSetup)
 95
 96	// Check several cases in which bid doesn't succed, and also do 2 successful bids.
 97
 98	_, err := c.AuctionBidSimple(0, big.NewInt(1))
 99	assert.Equal(t, errBidClosed, tracerr.Unwrap(err))
100
101	_, err = c.AuctionBidSimple(4323, big.NewInt(1))
102	assert.Equal(t, errBidNotOpen, tracerr.Unwrap(err))
103
104	// 101 % 6 = 5;  defaultSlotSetBid[5] = 1500;  1500 + 10% = 1650
105	_, err = c.AuctionBidSimple(101, big.NewInt(1650))
106	assert.Equal(t, errCoordNotReg, tracerr.Unwrap(err))
107
108	_, err = c.AuctionSetCoordinator(addrForge, "https://foo.bar")
109	assert.Nil(t, err)
110
111	_, err = c.AuctionBidSimple(3, big.NewInt(1))
112	assert.Equal(t, errBidBelowMin, tracerr.Unwrap(err))
113
114	_, err = c.AuctionBidSimple(3, big.NewInt(1650))
115	assert.Nil(t, err)
116
117	c.CtlSetAddr(addrBidder2)
118	_, err = c.AuctionSetCoordinator(addrForge2, "https://foo2.bar")
119	assert.Nil(t, err)
120
121	_, err = c.AuctionBidSimple(3, big.NewInt(16))
122	assert.Equal(t, errBidBelowMin, tracerr.Unwrap(err))
123
124	// 1650 + 10% = 1815
125	_, err = c.AuctionBidSimple(3, big.NewInt(1815))
126	assert.Nil(t, err)
127
128	c.CtlMineBlock()
129
130	blockNum, err := c.EthLastBlock()
131	require.Nil(t, err)
132
133	auctionEvents, err := c.AuctionEventsByBlock(blockNum, nil)
134	require.Nil(t, err)
135	assert.Equal(t, 2, len(auctionEvents.NewBid))
136}
137
138func TestClientRollup(t *testing.T) {
139	token1Addr := ethCommon.HexToAddress("0x6b175474e89094c44da98b954eedeac495271d0f")
140
141	var timer timer
142	clientSetup := NewClientSetupExample()
143	c := NewClient(true, &timer, &ethCommon.Address{}, clientSetup)
144
145	// Add a token
146
147	tx, err := c.RollupAddTokenSimple(token1Addr, clientSetup.RollupVariables.FeeAddToken)
148	require.Nil(t, err)
149	assert.NotNil(t, tx)
150
151	// Add some L1UserTxs
152	// Create Accounts
153
154	const N = 16
155	var keys [N]*keys
156	for i := 0; i < N; i++ {
157		keys[i] = genKeys(int64(i))
158		tx := common.L1Tx{
159			FromIdx:       0,
160			FromEthAddr:   keys[i].Addr,
161			FromBJJ:       keys[i].BJJPublicKey.Compress(),
162			TokenID:       common.TokenID(0),
163			Amount:        big.NewInt(0),
164			DepositAmount: big.NewInt(10 + int64(i)),
165		}
166		_, err := c.RollupL1UserTxERC20ETH(tx.FromBJJ, int64(tx.FromIdx), tx.DepositAmount,
167			tx.Amount, uint32(tx.TokenID), int64(tx.ToIdx))
168		require.Nil(t, err)
169	}
170	c.CtlMineBlock()
171
172	blockNum, err := c.EthLastBlock()
173	require.Nil(t, err)
174	rollupEvents, err := c.RollupEventsByBlock(blockNum, nil)
175	require.Nil(t, err)
176	assert.Equal(t, N, len(rollupEvents.L1UserTx))
177	assert.Equal(t, 1, len(rollupEvents.AddToken))
178
179	// Forge a batch
180
181	c.CtlAddBatch(&eth.RollupForgeBatchArgs{
182		NewLastIdx:        0,
183		NewStRoot:         big.NewInt(1),
184		NewExitRoot:       big.NewInt(100),
185		L1CoordinatorTxs:  []common.L1Tx{},
186		L2TxsData:         []common.L2Tx{},
187		FeeIdxCoordinator: []common.Idx{},
188		VerifierIdx:       0,
189		L1Batch:           true,
190	})
191	c.CtlMineBlock()
192
193	blockNumA, err := c.EthLastBlock()
194	require.Nil(t, err)
195	rollupEvents, err = c.RollupEventsByBlock(blockNumA, nil)
196	require.Nil(t, err)
197	assert.Equal(t, 0, len(rollupEvents.L1UserTx))
198	assert.Equal(t, 0, len(rollupEvents.AddToken))
199	assert.Equal(t, 1, len(rollupEvents.ForgeBatch))
200
201	// Simulate reorg discarding last mined block
202
203	c.CtlRollback()
204	c.CtlMineBlock()
205
206	blockNumB, err := c.EthLastBlock()
207	require.Nil(t, err)
208	rollupEventsB, err := c.RollupEventsByBlock(blockNumA, nil)
209	require.Nil(t, err)
210	assert.Equal(t, 0, len(rollupEventsB.L1UserTx))
211	assert.Equal(t, 0, len(rollupEventsB.AddToken))
212	assert.Equal(t, 0, len(rollupEventsB.ForgeBatch))
213
214	assert.Equal(t, blockNumA, blockNumB)
215	assert.NotEqual(t, rollupEvents, rollupEventsB)
216
217	// Forge again
218	rollupForgeBatchArgs0 := &eth.RollupForgeBatchArgs{
219		NewLastIdx:        0,
220		NewStRoot:         big.NewInt(1),
221		NewExitRoot:       big.NewInt(100),
222		L1CoordinatorTxs:  []common.L1Tx{},
223		L2TxsData:         []common.L2Tx{},
224		FeeIdxCoordinator: []common.Idx{},
225		VerifierIdx:       0,
226		L1Batch:           true,
227	}
228	c.CtlAddBatch(rollupForgeBatchArgs0)
229	c.CtlMineBlock()
230
231	// Retrieve ForgeBatchArguments starting from the events
232
233	blockNum, err = c.EthLastBlock()
234	require.Nil(t, err)
235	rollupEvents, err = c.RollupEventsByBlock(blockNum, nil)
236	require.Nil(t, err)
237
238	rollupForgeBatchArgs1, sender, err := c.RollupForgeBatchArgs(rollupEvents.ForgeBatch[0].EthTxHash,
239		rollupEvents.ForgeBatch[0].L1UserTxsLen)
240	require.Nil(t, err)
241	assert.Equal(t, *c.addr, *sender)
242	assert.Equal(t, rollupForgeBatchArgs0, rollupForgeBatchArgs1)
243}
244
245type keys struct {
246	BJJSecretKey *babyjub.PrivateKey
247	BJJPublicKey *babyjub.PublicKey
248	Addr         ethCommon.Address
249}
250
251func genKeys(i int64) *keys {
252	i++ // i = 0 doesn't work for the ecdsa key generation
253	var sk babyjub.PrivateKey
254	binary.LittleEndian.PutUint64(sk[:], uint64(i))
255
256	// eth address
257	var key ecdsa.PrivateKey
258	key.D = big.NewInt(i) // only for testing
259	key.PublicKey.X, key.PublicKey.Y = ethCrypto.S256().ScalarBaseMult(key.D.Bytes())
260	key.Curve = ethCrypto.S256()
261	addr := ethCrypto.PubkeyToAddress(key.PublicKey)
262
263	return &keys{
264		BJJSecretKey: &sk,
265		BJJPublicKey: sk.Public(),
266		Addr:         addr,
267	}
268}