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