hermez-node/common/account_test.go
common/account_test.goRaw
1package common
2
3import (
4 "encoding/hex"
5 "fmt"
6 "math"
7 "math/big"
8 "testing"
9
10 ethCommon "github.com/ethereum/go-ethereum/common"
11 ethCrypto "github.com/ethereum/go-ethereum/crypto"
12 "github.com/iden3/go-iden3-crypto/babyjub"
13 cryptoConstants "github.com/iden3/go-iden3-crypto/constants"
14 "github.com/iden3/go-iden3-crypto/poseidon"
15 cryptoUtils "github.com/iden3/go-iden3-crypto/utils"
16 "github.com/stretchr/testify/assert"
17 "github.com/stretchr/testify/require"
18)
19
20func TestIdxParser(t *testing.T) {
21 i := Idx(1)
22 iBytes, err := i.Bytes()
23 assert.Nil(t, err)
24 assert.Equal(t, 6, len(iBytes))
25 assert.Equal(t, "000000000001", hex.EncodeToString(iBytes[:]))
26 i2, err := IdxFromBytes(iBytes[:])
27 assert.Nil(t, err)
28 assert.Equal(t, i, i2)
29
30 i = Idx(100)
31 assert.Equal(t, big.NewInt(100), i.BigInt())
32
33 // value before overflow
34 i = Idx(281474976710655)
35 iBytes, err = i.Bytes()
36 assert.Nil(t, err)
37 assert.Equal(t, 6, len(iBytes))
38 assert.Equal(t, "ffffffffffff", hex.EncodeToString(iBytes[:]))
39 i2, err = IdxFromBytes(iBytes[:])
40 assert.Nil(t, err)
41 assert.Equal(t, i, i2)
42
43 // expect value overflow
44 i = Idx(281474976710656)
45 iBytes, err = i.Bytes()
46 assert.NotNil(t, err)
47 assert.Equal(t, ErrIdxOverflow, err)
48}
49
50func TestNonceParser(t *testing.T) {
51 n := Nonce(1)
52 nBytes, err := n.Bytes()
53 assert.Nil(t, err)
54 assert.Equal(t, 5, len(nBytes))
55 assert.Equal(t, "0000000001", hex.EncodeToString(nBytes[:]))
56 n2 := NonceFromBytes(nBytes)
57 assert.Equal(t, n, n2)
58
59 // value before overflow
60 n = Nonce(1099511627775)
61 nBytes, err = n.Bytes()
62 assert.Nil(t, err)
63 assert.Equal(t, 5, len(nBytes))
64 assert.Equal(t, "ffffffffff", hex.EncodeToString(nBytes[:]))
65 n2 = NonceFromBytes(nBytes)
66 assert.Equal(t, n, n2)
67
68 // expect value overflow
69 n = Nonce(1099511627776)
70 nBytes, err = n.Bytes()
71 assert.NotNil(t, err)
72 assert.Equal(t, ErrNonceOverflow, err)
73}
74
75func TestAccount(t *testing.T) {
76 var sk babyjub.PrivateKey
77 _, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
78 assert.Nil(t, err)
79 pk := sk.Public()
80
81 account := &Account{
82 TokenID: TokenID(1),
83 Nonce: Nonce(1234),
84 Balance: big.NewInt(1000),
85 PublicKey: pk,
86 EthAddr: ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),
87 }
88 b, err := account.Bytes()
89 assert.Nil(t, err)
90 assert.Equal(t, byte(1), b[22])
91 a1, err := AccountFromBytes(b)
92 assert.Nil(t, err)
93 assert.Equal(t, account, a1)
94
95 e, err := account.BigInts()
96 assert.Nil(t, err)
97 assert.True(t, cryptoUtils.CheckBigIntInField(e[0]))
98 assert.True(t, cryptoUtils.CheckBigIntInField(e[1]))
99 assert.True(t, cryptoUtils.CheckBigIntInField(e[2]))
100 assert.True(t, cryptoUtils.CheckBigIntInField(e[3]))
101
102 assert.Equal(t, "1000", e[1].String())
103 assert.Equal(t, pk.Y.String(), e[2].String())
104 assert.Equal(t, new(big.Int).SetBytes(account.EthAddr.Bytes()).String(), e[3].String())
105
106 a2, err := AccountFromBigInts(e)
107 assert.Nil(t, err)
108 assert.Equal(t, account, a2)
109 assert.Equal(t, a1, a2)
110}
111
112func TestAccountLoop(t *testing.T) {
113 // check that for different deterministic BabyJubJub keys & random Address there is no problem
114 for i := 0; i < 256; i++ {
115 var sk babyjub.PrivateKey
116 _, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
117 assert.Nil(t, err)
118 pk := sk.Public()
119
120 key, err := ethCrypto.GenerateKey()
121 assert.Nil(t, err)
122 address := ethCrypto.PubkeyToAddress(key.PublicKey)
123
124 account := &Account{
125 TokenID: TokenID(i),
126 Nonce: Nonce(i),
127 Balance: big.NewInt(1000),
128 PublicKey: pk,
129 EthAddr: address,
130 }
131 b, err := account.Bytes()
132 assert.Nil(t, err)
133 a1, err := AccountFromBytes(b)
134 assert.Nil(t, err)
135 assert.Equal(t, account, a1)
136
137 e, err := account.BigInts()
138 assert.Nil(t, err)
139 assert.True(t, cryptoUtils.CheckBigIntInField(e[0]))
140 assert.True(t, cryptoUtils.CheckBigIntInField(e[1]))
141 assert.True(t, cryptoUtils.CheckBigIntInField(e[2]))
142 assert.True(t, cryptoUtils.CheckBigIntInField(e[3]))
143
144 a2, err := AccountFromBigInts(e)
145 assert.Nil(t, err)
146 assert.Equal(t, account, a2)
147 }
148}
149
150func TestAccountLoopRandom(t *testing.T) {
151 // check that for different random Address & BabyJubJub keys there is
152 // no problem
153 for i := 0; i < 256; i++ {
154 sk := babyjub.NewRandPrivKey()
155 pk := sk.Public()
156
157 key, err := ethCrypto.GenerateKey()
158 assert.Nil(t, err)
159 address := ethCrypto.PubkeyToAddress(key.PublicKey)
160
161 account := &Account{
162 TokenID: TokenID(i),
163 Nonce: Nonce(i),
164 Balance: big.NewInt(1000),
165 PublicKey: pk,
166 EthAddr: address,
167 }
168 b, err := account.Bytes()
169 assert.Nil(t, err)
170 a1, err := AccountFromBytes(b)
171 assert.Nil(t, err)
172 assert.Equal(t, account, a1)
173
174 e, err := account.BigInts()
175 assert.Nil(t, err)
176 assert.True(t, cryptoUtils.CheckBigIntInField(e[0]))
177 assert.True(t, cryptoUtils.CheckBigIntInField(e[1]))
178 assert.True(t, cryptoUtils.CheckBigIntInField(e[2]))
179 assert.True(t, cryptoUtils.CheckBigIntInField(e[3]))
180
181 a2, err := AccountFromBigInts(e)
182 assert.Nil(t, err)
183 assert.Equal(t, account, a2)
184 }
185}
186
187func bigFromStr(h string, u int) *big.Int {
188 b, ok := new(big.Int).SetString(h, u)
189 if !ok {
190 panic("bigFromStr err")
191 }
192 return b
193}
194
195func TestAccountHashValue(t *testing.T) {
196 var sk babyjub.PrivateKey
197 _, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
198 assert.Nil(t, err)
199 pk := sk.Public()
200
201 account := &Account{
202 TokenID: TokenID(1),
203 Nonce: Nonce(1234),
204 Balance: big.NewInt(1000),
205 PublicKey: pk,
206 EthAddr: ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),
207 }
208 v, err := account.HashValue()
209 assert.Nil(t, err)
210 assert.Equal(t, "16297758255249203915951182296472515138555043617458222397753168518282206850764", v.String())
211}
212
213func TestAccountHashValueTestVectors(t *testing.T) {
214 // values from js test vectors
215 ay := new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(253), nil), big.NewInt(1))
216 assert.Equal(t, "1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", (hex.EncodeToString(ay.Bytes())))
217 bjj, err := babyjub.PointFromSignAndY(true, ay)
218 require.Nil(t, err)
219
220 account := &Account{
221 Idx: 1,
222 TokenID: 0xFFFFFFFF,
223 PublicKey: (*babyjub.PublicKey)(bjj),
224 EthAddr: ethCommon.HexToAddress("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
225 Nonce: Nonce(0xFFFFFFFFFF),
226 Balance: bigFromStr("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16),
227 }
228
229 e, err := account.BigInts()
230 assert.Nil(t, err)
231 assert.Equal(t, "9444732965739290427391", e[0].String())
232 assert.Equal(t, "6277101735386680763835789423207666416102355444464034512895", e[1].String())
233 assert.Equal(t, "14474011154664524427946373126085988481658748083205070504932198000989141204991", e[2].String())
234 assert.Equal(t, "1461501637330902918203684832716283019655932542975", e[3].String())
235
236 h, err := poseidon.Hash(e[:])
237 assert.Nil(t, err)
238 assert.Equal(t, "4550823210217540218403400309533329186487982452461145263910122718498735057257", h.String())
239
240 v, err := account.HashValue()
241 assert.Nil(t, err)
242 assert.Equal(t, "4550823210217540218403400309533329186487982452461145263910122718498735057257", v.String())
243
244 // second account
245 ay = big.NewInt(0)
246 bjj, err = babyjub.PointFromSignAndY(false, ay)
247 require.Nil(t, err)
248 account = &Account{
249 TokenID: 0,
250 PublicKey: (*babyjub.PublicKey)(bjj),
251 EthAddr: ethCommon.HexToAddress("0x00"),
252 Nonce: Nonce(0),
253 Balance: big.NewInt(0),
254 }
255 v, err = account.HashValue()
256 assert.Nil(t, err)
257 assert.Equal(t, "7750253361301235345986002241352365187241910378619330147114280396816709365657", v.String())
258
259 // third account
260 ay = bigFromStr("21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d7", 16)
261 bjj, err = babyjub.PointFromSignAndY(false, ay)
262 require.Nil(t, err)
263 account = &Account{
264 TokenID: 3,
265 PublicKey: (*babyjub.PublicKey)(bjj),
266 EthAddr: ethCommon.HexToAddress("0xA3C88ac39A76789437AED31B9608da72e1bbfBF9"),
267 Nonce: Nonce(129),
268 Balance: bigFromStr("42000000000000000000", 10),
269 }
270 e, err = account.BigInts()
271 assert.Nil(t, err)
272 assert.Equal(t, "554050781187", e[0].String())
273 assert.Equal(t, "42000000000000000000", e[1].String())
274 assert.Equal(t, "15238403086306505038849621710779816852318505119327426213168494964113886299863", e[2].String())
275 assert.Equal(t, "935037732739828347587684875151694054123613453305", e[3].String())
276 v, err = account.HashValue()
277 assert.Nil(t, err)
278 assert.Equal(t, "10565754214047872850889045989683221123564392137456000481397520902594455245517", v.String())
279}
280
281func TestAccountErrNotInFF(t *testing.T) {
282 z := big.NewInt(0)
283
284 // Q-1 should not give error
285 r := new(big.Int).Sub(cryptoConstants.Q, big.NewInt(1))
286 e := [NLeafElems]*big.Int{z, z, r, r}
287 _, err := AccountFromBigInts(e)
288 assert.Nil(t, err)
289
290 // Q should give error
291 r = cryptoConstants.Q
292 e = [NLeafElems]*big.Int{z, z, r, r}
293 _, err = AccountFromBigInts(e)
294 assert.NotNil(t, err)
295 assert.Equal(t, ErrNotInFF, err)
296
297 // Q+1 should give error
298 r = new(big.Int).Add(cryptoConstants.Q, big.NewInt(1))
299 e = [NLeafElems]*big.Int{z, z, r, r}
300 _, err = AccountFromBigInts(e)
301 assert.NotNil(t, err)
302 assert.Equal(t, ErrNotInFF, err)
303}
304
305func TestAccountErrNumOverflowNonce(t *testing.T) {
306 var sk babyjub.PrivateKey
307 _, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
308 assert.Nil(t, err)
309 pk := sk.Public()
310
311 // check limit
312 account := &Account{
313 TokenID: TokenID(1),
314 Nonce: Nonce(math.Pow(2, 40) - 1),
315 Balance: big.NewInt(1000),
316 PublicKey: pk,
317 EthAddr: ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),
318 }
319 _, err = account.Bytes()
320 assert.Nil(t, err)
321
322 // force value overflow
323 account.Nonce = Nonce(math.Pow(2, 40))
324 b, err := account.Bytes()
325 assert.NotNil(t, err)
326 assert.Equal(t, fmt.Errorf("%s Nonce", ErrNumOverflow), err)
327
328 _, err = AccountFromBytes(b)
329 assert.Nil(t, err)
330}
331
332func TestAccountErrNumOverflowBalance(t *testing.T) {
333 var sk babyjub.PrivateKey
334 _, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
335 assert.Nil(t, err)
336 pk := sk.Public()
337
338 // check limit
339 account := &Account{
340 TokenID: TokenID(1),
341 Nonce: Nonce(math.Pow(2, 40) - 1),
342 Balance: new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(192), nil), big.NewInt(1)),
343 PublicKey: pk,
344 EthAddr: ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),
345 }
346 assert.Equal(t, "6277101735386680763835789423207666416102355444464034512895", account.Balance.String())
347
348 _, err = account.Bytes()
349 assert.Nil(t, err)
350
351 // force value overflow
352 account.Balance = new(big.Int).Exp(big.NewInt(2), big.NewInt(192), nil)
353 assert.Equal(t, "6277101735386680763835789423207666416102355444464034512896", account.Balance.String())
354 b, err := account.Bytes()
355 assert.NotNil(t, err)
356 assert.Equal(t, fmt.Errorf("%s Balance", ErrNumOverflow), err)
357
358 _, err = AccountFromBytes(b)
359 assert.Nil(t, err)
360
361 b[39] = 1
362 _, err = AccountFromBytes(b)
363 assert.NotNil(t, err)
364 assert.Equal(t, fmt.Errorf("%s Balance", ErrNumOverflow), err)
365}