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.

373 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[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
  70. assert.NoError(t, err)
  71. pk := sk.Public()
  72. account := &Account{
  73. TokenID: TokenID(1),
  74. Nonce: Nonce(1234),
  75. Balance: big.NewInt(1000),
  76. BJJ: pk.Compress(),
  77. EthAddr: ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),
  78. }
  79. b, err := account.Bytes()
  80. assert.NoError(t, err)
  81. assert.Equal(t, byte(1), b[22])
  82. a1, err := AccountFromBytes(b)
  83. assert.NoError(t, err)
  84. assert.Equal(t, account, a1)
  85. e, err := account.BigInts()
  86. assert.NoError(t, err)
  87. assert.True(t, cryptoUtils.CheckBigIntInField(e[0]))
  88. assert.True(t, cryptoUtils.CheckBigIntInField(e[1]))
  89. assert.True(t, cryptoUtils.CheckBigIntInField(e[2]))
  90. assert.True(t, cryptoUtils.CheckBigIntInField(e[3]))
  91. assert.Equal(t, "1000", e[1].String())
  92. assert.Equal(t, pk.Y.String(), e[2].String())
  93. assert.Equal(t, new(big.Int).SetBytes(account.EthAddr.Bytes()).String(), e[3].String())
  94. a2, err := AccountFromBigInts(e)
  95. assert.NoError(t, err)
  96. assert.Equal(t, account, a2)
  97. assert.Equal(t, a1, a2)
  98. }
  99. func TestAccountLoop(t *testing.T) {
  100. // check that for different deterministic BabyJubJub keys & random Address there is no problem
  101. for i := 0; i < 256; i++ {
  102. var sk babyjub.PrivateKey
  103. _, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
  104. assert.NoError(t, err)
  105. pk := sk.Public()
  106. key, err := ethCrypto.GenerateKey()
  107. assert.NoError(t, err)
  108. address := ethCrypto.PubkeyToAddress(key.PublicKey)
  109. account := &Account{
  110. TokenID: TokenID(i),
  111. Nonce: Nonce(i),
  112. Balance: big.NewInt(1000),
  113. BJJ: pk.Compress(),
  114. EthAddr: address,
  115. }
  116. b, err := account.Bytes()
  117. assert.NoError(t, err)
  118. a1, err := AccountFromBytes(b)
  119. assert.NoError(t, err)
  120. assert.Equal(t, account, a1)
  121. e, err := account.BigInts()
  122. assert.NoError(t, err)
  123. assert.True(t, cryptoUtils.CheckBigIntInField(e[0]))
  124. assert.True(t, cryptoUtils.CheckBigIntInField(e[1]))
  125. assert.True(t, cryptoUtils.CheckBigIntInField(e[2]))
  126. assert.True(t, cryptoUtils.CheckBigIntInField(e[3]))
  127. a2, err := AccountFromBigInts(e)
  128. assert.NoError(t, err)
  129. assert.Equal(t, account, a2)
  130. }
  131. }
  132. func TestAccountLoopRandom(t *testing.T) {
  133. // check that for different random Address & BabyJubJub keys there is
  134. // no problem
  135. for i := 0; i < 256; i++ {
  136. sk := babyjub.NewRandPrivKey()
  137. pk := sk.Public()
  138. key, err := ethCrypto.GenerateKey()
  139. assert.NoError(t, err)
  140. address := ethCrypto.PubkeyToAddress(key.PublicKey)
  141. account := &Account{
  142. TokenID: TokenID(i),
  143. Nonce: Nonce(i),
  144. Balance: big.NewInt(1000),
  145. BJJ: pk.Compress(),
  146. EthAddr: address,
  147. }
  148. b, err := account.Bytes()
  149. assert.NoError(t, err)
  150. a1, err := AccountFromBytes(b)
  151. assert.NoError(t, err)
  152. assert.Equal(t, account, a1)
  153. e, err := account.BigInts()
  154. assert.NoError(t, err)
  155. assert.True(t, cryptoUtils.CheckBigIntInField(e[0]))
  156. assert.True(t, cryptoUtils.CheckBigIntInField(e[1]))
  157. assert.True(t, cryptoUtils.CheckBigIntInField(e[2]))
  158. assert.True(t, cryptoUtils.CheckBigIntInField(e[3]))
  159. a2, err := AccountFromBigInts(e)
  160. assert.NoError(t, err)
  161. assert.Equal(t, account, a2)
  162. }
  163. }
  164. func bigFromStr(h string, u int) *big.Int {
  165. if u == 16 {
  166. h = strings.TrimPrefix(h, "0x")
  167. }
  168. b, ok := new(big.Int).SetString(h, u)
  169. if !ok {
  170. panic("bigFromStr err")
  171. }
  172. return b
  173. }
  174. func TestAccountHashValue(t *testing.T) {
  175. var sk babyjub.PrivateKey
  176. _, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
  177. assert.NoError(t, err)
  178. pk := sk.Public()
  179. account := &Account{
  180. TokenID: TokenID(1),
  181. Nonce: Nonce(1234),
  182. Balance: big.NewInt(1000),
  183. BJJ: pk.Compress(),
  184. EthAddr: ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),
  185. }
  186. v, err := account.HashValue()
  187. assert.NoError(t, err)
  188. assert.Equal(t, "16297758255249203915951182296472515138555043617458222397753168518282206850764", v.String())
  189. }
  190. func TestAccountHashValueTestVectors(t *testing.T) {
  191. // values from js test vectors
  192. ay := new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(253), nil), big.NewInt(1))
  193. assert.Equal(t, "1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", (hex.EncodeToString(ay.Bytes())))
  194. bjjPoint, err := babyjub.PointFromSignAndY(true, ay)
  195. require.NoError(t, err)
  196. bjj := babyjub.PublicKey(*bjjPoint)
  197. account := &Account{
  198. Idx: 1,
  199. TokenID: 0xFFFFFFFF,
  200. BJJ: bjj.Compress(),
  201. EthAddr: ethCommon.HexToAddress("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
  202. Nonce: Nonce(0xFFFFFFFFFF),
  203. Balance: bigFromStr("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16),
  204. }
  205. e, err := account.BigInts()
  206. assert.NoError(t, err)
  207. assert.Equal(t, "9444732965739290427391", e[0].String())
  208. assert.Equal(t, "6277101735386680763835789423207666416102355444464034512895", e[1].String())
  209. assert.Equal(t, "14474011154664524427946373126085988481658748083205070504932198000989141204991", e[2].String())
  210. assert.Equal(t, "1461501637330902918203684832716283019655932542975", e[3].String())
  211. h, err := poseidon.Hash(e[:])
  212. assert.NoError(t, err)
  213. assert.Equal(t, "4550823210217540218403400309533329186487982452461145263910122718498735057257", h.String())
  214. v, err := account.HashValue()
  215. assert.NoError(t, err)
  216. assert.Equal(t, "4550823210217540218403400309533329186487982452461145263910122718498735057257", v.String())
  217. // second account
  218. ay = big.NewInt(0)
  219. bjjPoint, err = babyjub.PointFromSignAndY(false, ay)
  220. require.NoError(t, err)
  221. bjj = babyjub.PublicKey(*bjjPoint)
  222. account = &Account{
  223. TokenID: 0,
  224. BJJ: bjj.Compress(),
  225. EthAddr: ethCommon.HexToAddress("0x00"),
  226. Nonce: Nonce(0),
  227. Balance: big.NewInt(0),
  228. }
  229. v, err = account.HashValue()
  230. assert.NoError(t, err)
  231. assert.Equal(t, "7750253361301235345986002241352365187241910378619330147114280396816709365657", v.String())
  232. // third account
  233. ay = bigFromStr("21b0a1688b37f77b1d1d5539ec3b826db5ac78b2513f574a04c50a7d4f8246d7", 16)
  234. bjjPoint, err = babyjub.PointFromSignAndY(false, ay)
  235. require.NoError(t, err)
  236. bjj = babyjub.PublicKey(*bjjPoint)
  237. account = &Account{
  238. TokenID: 3,
  239. BJJ: bjj.Compress(),
  240. EthAddr: ethCommon.HexToAddress("0xA3C88ac39A76789437AED31B9608da72e1bbfBF9"),
  241. Nonce: Nonce(129),
  242. Balance: bigFromStr("42000000000000000000", 10),
  243. }
  244. e, err = account.BigInts()
  245. assert.NoError(t, err)
  246. assert.Equal(t, "554050781187", e[0].String())
  247. assert.Equal(t, "42000000000000000000", e[1].String())
  248. assert.Equal(t, "15238403086306505038849621710779816852318505119327426213168494964113886299863", e[2].String())
  249. assert.Equal(t, "935037732739828347587684875151694054123613453305", e[3].String())
  250. v, err = account.HashValue()
  251. assert.NoError(t, err)
  252. assert.Equal(t, "10565754214047872850889045989683221123564392137456000481397520902594455245517", v.String())
  253. }
  254. func TestAccountErrNotInFF(t *testing.T) {
  255. z := big.NewInt(0)
  256. // Q-1 should not give error
  257. r := new(big.Int).Sub(cryptoConstants.Q, big.NewInt(1))
  258. e := [NLeafElems]*big.Int{z, z, r, r}
  259. _, err := AccountFromBigInts(e)
  260. assert.NoError(t, err)
  261. // Q should give error
  262. r = cryptoConstants.Q
  263. e = [NLeafElems]*big.Int{z, z, r, r}
  264. _, err = AccountFromBigInts(e)
  265. assert.NotNil(t, err)
  266. assert.Equal(t, ErrNotInFF, tracerr.Unwrap(err))
  267. // Q+1 should give error
  268. r = new(big.Int).Add(cryptoConstants.Q, big.NewInt(1))
  269. e = [NLeafElems]*big.Int{z, z, r, r}
  270. _, err = AccountFromBigInts(e)
  271. assert.NotNil(t, err)
  272. assert.Equal(t, ErrNotInFF, tracerr.Unwrap(err))
  273. }
  274. func TestAccountErrNumOverflowNonce(t *testing.T) {
  275. var sk babyjub.PrivateKey
  276. _, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
  277. assert.NoError(t, err)
  278. pk := sk.Public()
  279. // check limit
  280. account := &Account{
  281. TokenID: TokenID(1),
  282. Nonce: Nonce(math.Pow(2, 40) - 1),
  283. Balance: big.NewInt(1000),
  284. BJJ: pk.Compress(),
  285. EthAddr: ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),
  286. }
  287. _, err = account.Bytes()
  288. assert.NoError(t, err)
  289. // force value overflow
  290. account.Nonce = Nonce(math.Pow(2, 40))
  291. b, err := account.Bytes()
  292. assert.NotNil(t, err)
  293. assert.Equal(t, fmt.Errorf("%s Nonce", ErrNumOverflow), tracerr.Unwrap(err))
  294. _, err = AccountFromBytes(b)
  295. assert.NoError(t, err)
  296. }
  297. func TestAccountErrNumOverflowBalance(t *testing.T) {
  298. var sk babyjub.PrivateKey
  299. _, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
  300. assert.NoError(t, err)
  301. pk := sk.Public()
  302. // check limit
  303. account := &Account{
  304. TokenID: TokenID(1),
  305. Nonce: Nonce(math.Pow(2, 40) - 1),
  306. Balance: new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(192), nil), big.NewInt(1)),
  307. BJJ: pk.Compress(),
  308. EthAddr: ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),
  309. }
  310. assert.Equal(t, "6277101735386680763835789423207666416102355444464034512895", account.Balance.String())
  311. _, err = account.Bytes()
  312. assert.NoError(t, err)
  313. // force value overflow
  314. account.Balance = new(big.Int).Exp(big.NewInt(2), big.NewInt(192), nil)
  315. assert.Equal(t, "6277101735386680763835789423207666416102355444464034512896", account.Balance.String())
  316. b, err := account.Bytes()
  317. assert.NotNil(t, err)
  318. assert.Equal(t, fmt.Errorf("%s Balance", ErrNumOverflow), tracerr.Unwrap(err))
  319. _, err = AccountFromBytes(b)
  320. assert.NoError(t, err)
  321. b[39] = 1
  322. _, err = AccountFromBytes(b)
  323. assert.NotNil(t, err)
  324. assert.Equal(t, fmt.Errorf("%s Balance", ErrNumOverflow), tracerr.Unwrap(err))
  325. }