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.

395 lines
11 KiB

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