arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/common/l1tx_test.go
common/l1tx_test.goRaw
  1package common
  2
  3import (
  4	"crypto/ecdsa"
  5	"encoding/hex"
  6	"log"
  7	"math/big"
  8	"testing"
  9
 10	ethCommon "github.com/ethereum/go-ethereum/common"
 11	"github.com/ethereum/go-ethereum/crypto"
 12	"github.com/iden3/go-iden3-crypto/babyjub"
 13	"github.com/iden3/go-iden3-crypto/utils"
 14	"github.com/stretchr/testify/assert"
 15	"github.com/stretchr/testify/require"
 16)
 17
 18func TestNewL1UserTx(t *testing.T) {
 19	toForge := int64(123456)
 20	l1Tx := &L1Tx{
 21		ToForgeL1TxsNum: &toForge,
 22		Position:        71,
 23		UserOrigin:      true,
 24		ToIdx:           301,
 25		TokenID:         5,
 26		Amount:          big.NewInt(1),
 27		DepositAmount:   big.NewInt(2),
 28		FromIdx:         Idx(300),
 29	}
 30	l1Tx, err := NewL1Tx(l1Tx)
 31	assert.NoError(t, err)
 32	assert.Equal(t, "0x00a6cbae3b8661fb75b0919ca6605a02cfb04d9c6dd16870fa0fcdf01befa32768", l1Tx.TxID.String())
 33}
 34
 35func TestNewL1CoordinatorTx(t *testing.T) {
 36	batchNum := BatchNum(51966)
 37	l1Tx := &L1Tx{
 38		Position:      88,
 39		UserOrigin:    false,
 40		ToIdx:         301,
 41		TokenID:       5,
 42		Amount:        big.NewInt(1),
 43		DepositAmount: big.NewInt(2),
 44		FromIdx:       Idx(300),
 45		BatchNum:      &batchNum,
 46	}
 47	l1Tx, err := NewL1Tx(l1Tx)
 48	assert.NoError(t, err)
 49	assert.Equal(t, "0x01274482d73df4dab34a1b6740adfca347a462513aa14e82f27b12f818d1b68c84", l1Tx.TxID.String())
 50}
 51
 52func TestL1TxCompressedData(t *testing.T) {
 53	// test vectors values generated from javascript implementation (using
 54	// PoolL2Tx values)
 55	amount, ok := new(big.Int).SetString("343597383670000000000000000000000000000000", 10)
 56	require.True(t, ok)
 57	tx := L1Tx{
 58		FromIdx: (1 << 48) - 1,
 59		ToIdx:   (1 << 48) - 1,
 60		Amount:  amount,
 61		TokenID: (1 << 32) - 1,
 62	}
 63	txCompressedData, err := tx.TxCompressedData(uint16((1 << 16) - 1))
 64	assert.NoError(t, err)
 65	expectedStr := "ffffffffffffffffffffffffffffffffffffc60be60f"
 66	assert.Equal(t, expectedStr, hex.EncodeToString(txCompressedData.Bytes()))
 67
 68	tx = L1Tx{
 69		FromIdx: 0,
 70		ToIdx:   0,
 71		Amount:  big.NewInt(0),
 72		TokenID: 0,
 73	}
 74	txCompressedData, err = tx.TxCompressedData(uint16(0))
 75	assert.NoError(t, err)
 76	expectedStr = "c60be60f"
 77	assert.Equal(t, expectedStr, hex.EncodeToString(txCompressedData.Bytes()))
 78
 79	amount, ok = new(big.Int).SetString("63000000000000000", 10)
 80	require.True(t, ok)
 81	tx = L1Tx{
 82		FromIdx: 324,
 83		ToIdx:   256,
 84		Amount:  amount,
 85		TokenID: 123,
 86	}
 87	txCompressedData, err = tx.TxCompressedData(uint16(1))
 88	assert.NoError(t, err)
 89	expectedStr = "7b0000000001000000000001440001c60be60f"
 90	assert.Equal(t, expectedStr, hex.EncodeToString(txCompressedData.Bytes()))
 91
 92	tx = L1Tx{
 93		FromIdx: 1,
 94		ToIdx:   2,
 95		TokenID: 3,
 96	}
 97	txCompressedData, err = tx.TxCompressedData(uint16(0))
 98	assert.NoError(t, err)
 99	expectedStr = "030000000000020000000000010000c60be60f"
100	assert.Equal(t, expectedStr, hex.EncodeToString(txCompressedData.Bytes()))
101}
102
103func TestBytesDataAvailability(t *testing.T) {
104	// test vectors values generated from javascript implementation
105	amount, ok := new(big.Int).SetString("343597383670000000000000000000000000000000", 10)
106	require.True(t, ok)
107	tx := L1Tx{
108		ToIdx:           (1 << 16) - 1,
109		FromIdx:         (1 << 16) - 1,
110		EffectiveAmount: amount,
111	}
112	txCompressedData, err := tx.BytesDataAvailability(16)
113	assert.NoError(t, err)
114	assert.Equal(t, "ffffffffffffffffff00", hex.EncodeToString(txCompressedData))
115	l1tx, err := L1TxFromDataAvailability(txCompressedData, 16)
116	require.NoError(t, err)
117	assert.Equal(t, tx.FromIdx, l1tx.FromIdx)
118	assert.Equal(t, tx.ToIdx, l1tx.ToIdx)
119	assert.Equal(t, tx.EffectiveAmount, l1tx.EffectiveAmount)
120
121	tx = L1Tx{
122		ToIdx:           (1 << 32) - 1,
123		FromIdx:         (1 << 32) - 1,
124		EffectiveAmount: amount,
125	}
126	txCompressedData, err = tx.BytesDataAvailability(32)
127	assert.NoError(t, err)
128	assert.Equal(t, "ffffffffffffffffffffffffff00", hex.EncodeToString(txCompressedData))
129	l1tx, err = L1TxFromDataAvailability(txCompressedData, 32)
130	require.NoError(t, err)
131	assert.Equal(t, tx.FromIdx, l1tx.FromIdx)
132	assert.Equal(t, tx.ToIdx, l1tx.ToIdx)
133	assert.Equal(t, tx.EffectiveAmount, l1tx.EffectiveAmount)
134
135	tx = L1Tx{
136		ToIdx:           0,
137		FromIdx:         0,
138		EffectiveAmount: big.NewInt(0),
139	}
140	txCompressedData, err = tx.BytesDataAvailability(32)
141	assert.NoError(t, err)
142	assert.Equal(t, "0000000000000000000000000000", hex.EncodeToString(txCompressedData))
143	l1tx, err = L1TxFromDataAvailability(txCompressedData, 32)
144	require.NoError(t, err)
145	assert.Equal(t, tx.FromIdx, l1tx.FromIdx)
146	assert.Equal(t, tx.ToIdx, l1tx.ToIdx)
147	assert.Equal(t, tx.EffectiveAmount, l1tx.EffectiveAmount)
148
149	tx = L1Tx{
150		ToIdx:           635,
151		FromIdx:         296,
152		EffectiveAmount: big.NewInt(1000000000000000000),
153	}
154	txCompressedData, err = tx.BytesDataAvailability(32)
155	assert.NoError(t, err)
156	assert.Equal(t, "000001280000027b42540be40000", hex.EncodeToString(txCompressedData))
157	l1tx, err = L1TxFromDataAvailability(txCompressedData, 32)
158	require.NoError(t, err)
159	assert.Equal(t, tx.FromIdx, l1tx.FromIdx)
160	assert.Equal(t, tx.ToIdx, l1tx.ToIdx)
161	assert.Equal(t, tx.EffectiveAmount, l1tx.EffectiveAmount)
162}
163
164func TestL1userTxByteParsers(t *testing.T) {
165	var pkComp babyjub.PublicKeyComp
166	pkCompL := []byte("0x56ca90f80d7c374ae7485e9bcc47d4ac399460948da6aeeb899311097925a72c")
167	err := pkComp.UnmarshalText(pkCompL)
168	require.NoError(t, err)
169
170	l1Tx := &L1Tx{
171		UserOrigin:    true,
172		ToIdx:         3,
173		TokenID:       5,
174		Amount:        big.NewInt(1),
175		DepositAmount: big.NewInt(2),
176		FromIdx:       2,
177		FromBJJ:       pkComp,
178		FromEthAddr:   ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),
179	}
180
181	encodedData, err := l1Tx.BytesUser()
182	require.NoError(t, err)
183	decodedData, err := L1UserTxFromBytes(encodedData)
184	require.NoError(t, err)
185	assert.Equal(t, l1Tx, decodedData)
186	encodedData2, err := decodedData.BytesUser()
187	require.NoError(t, err)
188	assert.Equal(t, encodedData, encodedData2)
189
190	// expect error if length!=68
191	_, err = L1UserTxFromBytes(encodedData[:66])
192	require.NotNil(t, err)
193	_, err = L1UserTxFromBytes([]byte{})
194	require.NotNil(t, err)
195	_, err = L1UserTxFromBytes(nil)
196	require.NotNil(t, err)
197}
198
199func TestL1TxByteParsersCompatibility(t *testing.T) {
200	// Data from compatibility test
201	var pkComp babyjub.PublicKeyComp
202	pkCompB, err := hex.DecodeString("0dd02deb2c81068e7a0f7e327df80b4ab79ee1f41a7def613e73a20c32eece5a")
203	require.NoError(t, err)
204	pkCompL := SwapEndianness(pkCompB)
205	err = pkComp.UnmarshalText([]byte(hex.EncodeToString(pkCompL)))
206	require.NoError(t, err)
207
208	depositAmount := new(big.Int)
209	depositAmount.SetString("100000000000000000000", 10)
210	l1Tx := &L1Tx{
211		ToIdx:         87865485,
212		TokenID:       2098076,
213		Amount:        big.NewInt(2400000000000000000),
214		DepositAmount: depositAmount,
215		FromIdx:       Idx(29767899),
216		FromBJJ:       pkComp,
217		FromEthAddr:   ethCommon.HexToAddress("0x85dab5b9e2e361d0c208d77be90efcc0439b0a53"),
218		UserOrigin:    true,
219	}
220
221	encodedData, err := l1Tx.BytesUser()
222	require.NoError(t, err)
223	expected := "85dab5b9e2e361d0c208d77be90efcc0439b0a530dd02deb2c81068e7a0f7e327df80b4ab79ee1f41a7def613e73a20c32eece5a000001c638db52540be400459682f0000020039c0000053cb88d"
224	assert.Equal(t, expected, hex.EncodeToString(encodedData))
225}
226
227func TestL1CoordinatorTxByteParsers(t *testing.T) {
228	hermezAddress := ethCommon.HexToAddress("0xD6C850aeBFDC46D7F4c207e445cC0d6B0919BDBe")
229	chainID := big.NewInt(1337)
230
231	privateKey, err := crypto.HexToECDSA("fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19")
232	require.NoError(t, err)
233
234	publicKey := privateKey.Public()
235	publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
236	if !ok {
237		log.Fatal("error casting public key to ECDSA")
238	}
239	publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)
240	pubKey, err := crypto.UnmarshalPubkey(publicKeyBytes)
241	require.NoError(t, err)
242	fromEthAddr := crypto.PubkeyToAddress(*pubKey)
243	var pkComp babyjub.PublicKeyComp
244	pkCompL := []byte("56ca90f80d7c374ae7485e9bcc47d4ac399460948da6aeeb899311097925a72c")
245	err = pkComp.UnmarshalText(pkCompL)
246	require.NoError(t, err)
247
248	accCreationAuth := AccountCreationAuth{
249		EthAddr: fromEthAddr,
250		BJJ:     pkComp,
251	}
252
253	h, err := accCreationAuth.HashToSign(uint16(chainID.Uint64()), hermezAddress)
254	require.NoError(t, err)
255
256	signature, err := crypto.Sign(h, privateKey)
257	require.NoError(t, err)
258	// Ethereum adds 27 to v
259	v := int(signature[64])
260	signature[64] = byte(v + 27)
261
262	l1Tx := &L1Tx{
263		TokenID:       231,
264		FromBJJ:       pkComp,
265		FromEthAddr:   fromEthAddr,
266		Amount:        big.NewInt(0),
267		DepositAmount: big.NewInt(0),
268	}
269
270	bytesCoordinatorL1, err := l1Tx.BytesCoordinatorTx(signature)
271	require.NoError(t, err)
272	l1txDecoded, err := L1CoordinatorTxFromBytes(bytesCoordinatorL1, chainID, hermezAddress)
273	require.NoError(t, err)
274	assert.Equal(t, l1Tx, l1txDecoded)
275	bytesCoordinatorL12, err := l1txDecoded.BytesCoordinatorTx(signature)
276	require.NoError(t, err)
277	assert.Equal(t, bytesCoordinatorL1, bytesCoordinatorL12)
278
279	// expect error if length!=68
280	_, err = L1CoordinatorTxFromBytes(bytesCoordinatorL1[:66], chainID, hermezAddress)
281	require.NotNil(t, err)
282	_, err = L1CoordinatorTxFromBytes([]byte{}, chainID, hermezAddress)
283	require.NotNil(t, err)
284	_, err = L1CoordinatorTxFromBytes(nil, chainID, hermezAddress)
285	require.NotNil(t, err)
286}
287
288func TestL1CoordinatorTxByteParsersCompatibility(t *testing.T) {
289	// Data from compatibility test
290	var signature []byte
291	r, err := hex.DecodeString("da71e5eb097e115405d84d1e7b464009b434b32c014a2df502d1f065ced8bc3b")
292	require.NoError(t, err)
293	s, err := hex.DecodeString("186d7122ff7f654cfed3156719774898d573900c86599a885a706dbdffe5ea8c")
294	require.NoError(t, err)
295	v, err := hex.DecodeString("1b")
296	require.NoError(t, err)
297
298	signature = append(signature, r[:]...)
299	signature = append(signature, s[:]...)
300	signature = append(signature, v[:]...)
301
302	var pkComp babyjub.PublicKeyComp
303	pkCompB, err := hex.DecodeString("a2c2807ee39c3b3378738cff85a46a9465bb8fcf44ea597c33da9719be7c259c")
304	require.NoError(t, err)
305	pkCompL := SwapEndianness(pkCompB)
306	err = pkComp.UnmarshalText([]byte(hex.EncodeToString(pkCompL)))
307	require.NoError(t, err)
308	// Data from the compatibility test
309	require.NoError(t, err)
310	l1Tx := &L1Tx{
311		TokenID: 231,
312		FromBJJ: pkComp,
313	}
314
315	encodeData, err := l1Tx.BytesCoordinatorTx(signature)
316	require.NoError(t, err)
317
318	expected, err := utils.HexDecode("1b186d7122ff7f654cfed3156719774898d573900c86599a885a706dbdffe5ea8cda71e5eb097e115405d84d1e7b464009b434b32c014a2df502d1f065ced8bc3ba2c2807ee39c3b3378738cff85a46a9465bb8fcf44ea597c33da9719be7c259c000000e7")
319	require.NoError(t, err)
320
321	assert.Equal(t, expected, encodeData)
322}
323
324func TestL1TxID(t *testing.T) {
325	// L1UserTx
326	i64_1 := int64(1)
327	i64_2 := int64(2)
328	tx0 := L1Tx{
329		UserOrigin:      true,
330		ToForgeL1TxsNum: &i64_1,
331		Position:        1,
332	}
333	err := tx0.SetID()
334	require.NoError(t, err)
335	assert.Equal(t, TxIDPrefixL1UserTx, tx0.TxID[0])
336
337	// differ ToForgeL1TxsNum
338	tx1 := L1Tx{
339		UserOrigin:      true,
340		ToForgeL1TxsNum: &i64_2,
341		Position:        1,
342	}
343	err = tx1.SetID()
344	require.NoError(t, err)
345	assert.NotEqual(t, tx0.TxID, tx1.TxID)
346
347	// differ Position
348	tx1 = L1Tx{
349		UserOrigin:      true,
350		ToForgeL1TxsNum: &i64_1,
351		Position:        2,
352	}
353	err = tx1.SetID()
354	require.NoError(t, err)
355	assert.NotEqual(t, tx0.TxID, tx1.TxID)
356
357	// L1CoordinatorTx
358	bn1 := BatchNum(1)
359	bn2 := BatchNum(2)
360	tx0 = L1Tx{
361		UserOrigin: false,
362		BatchNum:   &bn1,
363		Position:   1,
364	}
365	err = tx0.SetID()
366	require.NoError(t, err)
367	assert.Equal(t, TxIDPrefixL1CoordTx, tx0.TxID[0])
368
369	// differ BatchNum
370	tx1 = L1Tx{
371		UserOrigin: false,
372		BatchNum:   &bn2,
373		Position:   1,
374	}
375	err = tx1.SetID()
376	require.NoError(t, err)
377	assert.NotEqual(t, tx0.TxID, tx1.TxID)
378
379	// differ Position
380	tx1 = L1Tx{
381		UserOrigin: false,
382		BatchNum:   &bn1,
383		Position:   2,
384	}
385	err = tx1.SetID()
386	require.NoError(t, err)
387	assert.NotEqual(t, tx0.TxID, tx1.TxID)
388}