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	"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}