You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

396 lines
12 KiB

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