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, ðCommon.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, ðCommon.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, ðCommon.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(ð.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 := ð.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}