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