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	tx := L1Tx{
 54		FromIdx: 2,
 55		ToIdx:   3,
 56		Amount:  big.NewInt(4),
 57		TokenID: 5,
 58	}
 59	chainID := uint16(0)
 60	txCompressedData, err := tx.TxCompressedData(chainID)
 61	assert.NoError(t, err)
 62
 63	// test vector value generated from javascript implementation
 64	expectedStr := "7307597389635308713748674793997299267459594577423"
 65	assert.Equal(t, expectedStr, txCompressedData.String())
 66	assert.Equal(t, "0500040000000000030000000000020000c60be60f", hex.EncodeToString(txCompressedData.Bytes()))
 67}
 68
 69func TestBytesDataAvailability(t *testing.T) {
 70	tx := L1Tx{
 71		FromIdx: 2,
 72		ToIdx:   3,
 73		Amount:  big.NewInt(4),
 74		TokenID: 5,
 75	}
 76	txCompressedData, err := tx.BytesDataAvailability(32)
 77	assert.NoError(t, err)
 78	assert.Equal(t, "0000000200000003000000", hex.EncodeToString(txCompressedData))
 79
 80	tx = L1Tx{
 81		FromIdx:         2,
 82		ToIdx:           3,
 83		EffectiveAmount: big.NewInt(4),
 84		TokenID:         5,
 85	}
 86	txCompressedData, err = tx.BytesDataAvailability(32)
 87	assert.NoError(t, err)
 88	assert.Equal(t, "0000000200000003000400", hex.EncodeToString(txCompressedData))
 89}
 90
 91func TestL1TxFromDataAvailability(t *testing.T) {
 92	tx := L1Tx{
 93		FromIdx: 2,
 94		ToIdx:   3,
 95		Amount:  big.NewInt(4),
 96	}
 97	txCompressedData, err := tx.BytesDataAvailability(32)
 98	assert.NoError(t, err)
 99	l1tx, err := L1TxFromDataAvailability(txCompressedData, 32)
100	require.NoError(t, err)
101	assert.Equal(t, tx.FromIdx, l1tx.FromIdx)
102	assert.Equal(t, tx.ToIdx, l1tx.ToIdx)
103
104	tx = L1Tx{
105		FromIdx:         2,
106		ToIdx:           3,
107		EffectiveAmount: big.NewInt(4),
108	}
109	txCompressedData, err = tx.BytesDataAvailability(32)
110	assert.NoError(t, err)
111	l1tx, err = L1TxFromDataAvailability(txCompressedData, 32)
112	require.NoError(t, err)
113	assert.Equal(t, tx.FromIdx, l1tx.FromIdx)
114	assert.Equal(t, tx.ToIdx, l1tx.ToIdx)
115	assert.Equal(t, tx.EffectiveAmount, l1tx.EffectiveAmount)
116}
117
118func TestL1userTxByteParsers(t *testing.T) {
119	var pkComp babyjub.PublicKeyComp
120	pkCompL := []byte("0x56ca90f80d7c374ae7485e9bcc47d4ac399460948da6aeeb899311097925a72c")
121	err := pkComp.UnmarshalText(pkCompL)
122	require.NoError(t, err)
123
124	l1Tx := &L1Tx{
125		UserOrigin:    true,
126		ToIdx:         3,
127		TokenID:       5,
128		Amount:        big.NewInt(1),
129		DepositAmount: big.NewInt(2),
130		FromIdx:       2,
131		FromBJJ:       pkComp,
132		FromEthAddr:   ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),
133	}
134
135	encodedData, err := l1Tx.BytesUser()
136	require.NoError(t, err)
137	decodedData, err := L1UserTxFromBytes(encodedData)
138	require.NoError(t, err)
139	assert.Equal(t, l1Tx, decodedData)
140	encodedData2, err := decodedData.BytesUser()
141	require.NoError(t, err)
142	assert.Equal(t, encodedData, encodedData2)
143
144	// expect error if length!=68
145	_, err = L1UserTxFromBytes(encodedData[:66])
146	require.NotNil(t, err)
147	_, err = L1UserTxFromBytes([]byte{})
148	require.NotNil(t, err)
149	_, err = L1UserTxFromBytes(nil)
150	require.NotNil(t, err)
151}
152
153func TestL1TxByteParsersCompatibility(t *testing.T) {
154	// Data from compatibility test
155	var pkComp babyjub.PublicKeyComp
156	pkCompB, err := hex.DecodeString("0dd02deb2c81068e7a0f7e327df80b4ab79ee1f41a7def613e73a20c32eece5a")
157	require.NoError(t, err)
158	pkCompL := SwapEndianness(pkCompB)
159	err = pkComp.UnmarshalText([]byte(hex.EncodeToString(pkCompL)))
160	require.NoError(t, err)
161
162	depositAmount := new(big.Int)
163	depositAmount.SetString("100000000000000000000", 10)
164	l1Tx := &L1Tx{
165		ToIdx:         87865485,
166		TokenID:       2098076,
167		Amount:        big.NewInt(2400000000000000000),
168		DepositAmount: depositAmount,
169		FromIdx:       Idx(29767899),
170		FromBJJ:       pkComp,
171		FromEthAddr:   ethCommon.HexToAddress("0x85dab5b9e2e361d0c208d77be90efcc0439b0a53"),
172		UserOrigin:    true,
173	}
174
175	expected, err := utils.HexDecode("85dab5b9e2e361d0c208d77be90efcc0439b0a530dd02deb2c81068e7a0f7e327df80b4ab79ee1f41a7def613e73a20c32eece5a000001c638db8be880f00020039c0000053cb88d")
176	require.NoError(t, err)
177
178	encodedData, err := l1Tx.BytesUser()
179	require.NoError(t, err)
180	assert.Equal(t, expected, encodedData)
181}
182
183func TestL1CoordinatorTxByteParsers(t *testing.T) {
184	hermezAddress := ethCommon.HexToAddress("0xD6C850aeBFDC46D7F4c207e445cC0d6B0919BDBe")
185	chainID := big.NewInt(1337)
186	chainIDBytes := ethCommon.LeftPadBytes(chainID.Bytes(), 2)
187
188	privateKey, err := crypto.HexToECDSA("fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19")
189	require.NoError(t, err)
190
191	publicKey := privateKey.Public()
192	publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
193	if !ok {
194		log.Fatal("error casting public key to ECDSA")
195	}
196	publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)
197	pubKey, err := crypto.UnmarshalPubkey(publicKeyBytes)
198	require.NoError(t, err)
199	fromEthAddr := crypto.PubkeyToAddress(*pubKey)
200	var pkComp babyjub.PublicKeyComp
201	pkCompL := []byte("56ca90f80d7c374ae7485e9bcc47d4ac399460948da6aeeb899311097925a72c")
202	err = pkComp.UnmarshalText(pkCompL)
203	require.NoError(t, err)
204	bytesMessage1 := []byte("\x19Ethereum Signed Message:\n120")
205	bytesMessage2 := []byte("I authorize this babyjubjub key for hermez rollup account creation")
206
207	babyjubB := SwapEndianness(pkComp[:])
208	var data []byte
209	data = append(data, bytesMessage1...)
210	data = append(data, bytesMessage2...)
211	data = append(data, babyjubB[:]...)
212	data = append(data, chainIDBytes...)
213	data = append(data, hermezAddress.Bytes()...)
214	hash := crypto.Keccak256Hash(data)
215	signature, err := crypto.Sign(hash.Bytes(), privateKey)
216	require.NoError(t, err)
217	// Ethereum adds 27 to v
218	v := int(signature[64])
219	signature[64] = byte(v + 27)
220
221	l1Tx := &L1Tx{
222		TokenID:       231,
223		FromBJJ:       pkComp,
224		FromEthAddr:   fromEthAddr,
225		Amount:        big.NewInt(0),
226		DepositAmount: big.NewInt(0),
227	}
228
229	bytesCoordinatorL1, err := l1Tx.BytesCoordinatorTx(signature)
230	require.NoError(t, err)
231	l1txDecoded, err := L1CoordinatorTxFromBytes(bytesCoordinatorL1, chainID, hermezAddress)
232	require.NoError(t, err)
233	assert.Equal(t, l1Tx, l1txDecoded)
234	bytesCoordinatorL12, err := l1txDecoded.BytesCoordinatorTx(signature)
235	require.NoError(t, err)
236	assert.Equal(t, bytesCoordinatorL1, bytesCoordinatorL12)
237
238	// expect error if length!=68
239	_, err = L1CoordinatorTxFromBytes(bytesCoordinatorL1[:66], chainID, hermezAddress)
240	require.NotNil(t, err)
241	_, err = L1CoordinatorTxFromBytes([]byte{}, chainID, hermezAddress)
242	require.NotNil(t, err)
243	_, err = L1CoordinatorTxFromBytes(nil, chainID, hermezAddress)
244	require.NotNil(t, err)
245}
246
247func TestL1CoordinatorTxByteParsersCompatibility(t *testing.T) {
248	// Data from compatibility test
249	var signature []byte
250	r, err := hex.DecodeString("da71e5eb097e115405d84d1e7b464009b434b32c014a2df502d1f065ced8bc3b")
251	require.NoError(t, err)
252	s, err := hex.DecodeString("186d7122ff7f654cfed3156719774898d573900c86599a885a706dbdffe5ea8c")
253	require.NoError(t, err)
254	v, err := hex.DecodeString("1b")
255	require.NoError(t, err)
256
257	signature = append(signature, r[:]...)
258	signature = append(signature, s[:]...)
259	signature = append(signature, v[:]...)
260
261	var pkComp babyjub.PublicKeyComp
262	pkCompB, err := hex.DecodeString("a2c2807ee39c3b3378738cff85a46a9465bb8fcf44ea597c33da9719be7c259c")
263	require.NoError(t, err)
264	pkCompL := SwapEndianness(pkCompB)
265	err = pkComp.UnmarshalText([]byte(hex.EncodeToString(pkCompL)))
266	require.NoError(t, err)
267	// Data from the compatibility test
268	require.NoError(t, err)
269	l1Tx := &L1Tx{
270		TokenID: 231,
271		FromBJJ: pkComp,
272	}
273
274	encodeData, err := l1Tx.BytesCoordinatorTx(signature)
275	require.NoError(t, err)
276
277	expected, err := utils.HexDecode("1b186d7122ff7f654cfed3156719774898d573900c86599a885a706dbdffe5ea8cda71e5eb097e115405d84d1e7b464009b434b32c014a2df502d1f065ced8bc3ba2c2807ee39c3b3378738cff85a46a9465bb8fcf44ea597c33da9719be7c259c000000e7")
278	require.NoError(t, err)
279
280	assert.Equal(t, expected, encodeData)
281}
282
283func TestL1TxID(t *testing.T) {
284	// L1UserTx
285	i64_1 := int64(1)
286	i64_2 := int64(2)
287	tx0 := L1Tx{
288		UserOrigin:      true,
289		ToForgeL1TxsNum: &i64_1,
290		Position:        1,
291	}
292	err := tx0.SetID()
293	require.NoError(t, err)
294	assert.Equal(t, TxIDPrefixL1UserTx, tx0.TxID[0])
295
296	// differ ToForgeL1TxsNum
297	tx1 := L1Tx{
298		UserOrigin:      true,
299		ToForgeL1TxsNum: &i64_2,
300		Position:        1,
301	}
302	err = tx1.SetID()
303	require.NoError(t, err)
304	assert.NotEqual(t, tx0.TxID, tx1.TxID)
305
306	// differ Position
307	tx1 = L1Tx{
308		UserOrigin:      true,
309		ToForgeL1TxsNum: &i64_1,
310		Position:        2,
311	}
312	err = tx1.SetID()
313	require.NoError(t, err)
314	assert.NotEqual(t, tx0.TxID, tx1.TxID)
315
316	// L1CoordinatorTx
317	bn1 := BatchNum(1)
318	bn2 := BatchNum(2)
319	tx0 = L1Tx{
320		UserOrigin: false,
321		BatchNum:   &bn1,
322		Position:   1,
323	}
324	err = tx0.SetID()
325	require.NoError(t, err)
326	assert.Equal(t, TxIDPrefixL1CoordTx, tx0.TxID[0])
327
328	// differ BatchNum
329	tx1 = L1Tx{
330		UserOrigin: false,
331		BatchNum:   &bn2,
332		Position:   1,
333	}
334	err = tx1.SetID()
335	require.NoError(t, err)
336	assert.NotEqual(t, tx0.TxID, tx1.TxID)
337
338	// differ Position
339	tx1 = L1Tx{
340		UserOrigin: false,
341		BatchNum:   &bn1,
342		Position:   2,
343	}
344	err = tx1.SetID()
345	require.NoError(t, err)
346	assert.NotEqual(t, tx0.TxID, tx1.TxID)
347}