cheque_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. // Copyright 2016 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package chequebook
  17. import (
  18. "crypto/ecdsa"
  19. "math/big"
  20. "os"
  21. "path/filepath"
  22. "testing"
  23. "time"
  24. "github.com/ethereum/go-ethereum/accounts/abi/bind"
  25. "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
  26. "github.com/ethereum/go-ethereum/common"
  27. "github.com/ethereum/go-ethereum/contracts/chequebook/contract"
  28. "github.com/ethereum/go-ethereum/core"
  29. "github.com/ethereum/go-ethereum/crypto"
  30. )
  31. var (
  32. key0, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  33. key1, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
  34. key2, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
  35. addr0 = crypto.PubkeyToAddress(key0.PublicKey)
  36. addr1 = crypto.PubkeyToAddress(key1.PublicKey)
  37. addr2 = crypto.PubkeyToAddress(key2.PublicKey)
  38. )
  39. func newTestBackend() *backends.SimulatedBackend {
  40. return backends.NewSimulatedBackend(
  41. core.GenesisAccount{Address: addr0, Balance: big.NewInt(1000000000)},
  42. core.GenesisAccount{Address: addr1, Balance: big.NewInt(1000000000)},
  43. core.GenesisAccount{Address: addr2, Balance: big.NewInt(1000000000)},
  44. )
  45. }
  46. func deploy(prvKey *ecdsa.PrivateKey, amount *big.Int, backend *backends.SimulatedBackend) (common.Address, error) {
  47. deployTransactor := bind.NewKeyedTransactor(prvKey)
  48. deployTransactor.Value = amount
  49. addr, _, _, err := contract.DeployChequebook(deployTransactor, backend)
  50. if err != nil {
  51. return common.Address{}, err
  52. }
  53. backend.Commit()
  54. return addr, nil
  55. }
  56. func TestIssueAndReceive(t *testing.T) {
  57. path := filepath.Join(os.TempDir(), "chequebook-test.json")
  58. backend := newTestBackend()
  59. addr0, err := deploy(key0, big.NewInt(0), backend)
  60. if err != nil {
  61. t.Fatalf("deploy contract: expected no error, got %v", err)
  62. }
  63. chbook, err := NewChequebook(path, addr0, key0, backend)
  64. if err != nil {
  65. t.Fatalf("expected no error, got %v", err)
  66. }
  67. chbook.sent[addr1] = new(big.Int).SetUint64(42)
  68. amount := common.Big1
  69. if _, err = chbook.Issue(addr1, amount); err == nil {
  70. t.Fatalf("expected insufficient funds error, got none")
  71. }
  72. chbook.balance = new(big.Int).Set(common.Big1)
  73. if chbook.Balance().Cmp(common.Big1) != 0 {
  74. t.Fatalf("expected: %v, got %v", "0", chbook.Balance())
  75. }
  76. ch, err := chbook.Issue(addr1, amount)
  77. if err != nil {
  78. t.Fatalf("expected no error, got %v", err)
  79. }
  80. if chbook.Balance().Cmp(common.Big0) != 0 {
  81. t.Errorf("expected: %v, got %v", "0", chbook.Balance())
  82. }
  83. chbox, err := NewInbox(key1, addr0, addr1, &key0.PublicKey, backend)
  84. if err != nil {
  85. t.Fatalf("expected no error, got %v", err)
  86. }
  87. received, err := chbox.Receive(ch)
  88. if err != nil {
  89. t.Fatalf("expected no error, got %v", err)
  90. }
  91. if received.Cmp(big.NewInt(43)) != 0 {
  92. t.Errorf("expected: %v, got %v", "43", received)
  93. }
  94. }
  95. func TestCheckbookFile(t *testing.T) {
  96. path := filepath.Join(os.TempDir(), "chequebook-test.json")
  97. backend := newTestBackend()
  98. chbook, err := NewChequebook(path, addr0, key0, backend)
  99. if err != nil {
  100. t.Fatalf("expected no error, got %v", err)
  101. }
  102. chbook.sent[addr1] = new(big.Int).SetUint64(42)
  103. chbook.balance = new(big.Int).Set(common.Big1)
  104. chbook.Save()
  105. chbook, err = LoadChequebook(path, key0, backend, false)
  106. if err != nil {
  107. t.Fatalf("expected no error, got %v", err)
  108. }
  109. if chbook.Balance().Cmp(common.Big1) != 0 {
  110. t.Errorf("expected: %v, got %v", "0", chbook.Balance())
  111. }
  112. var ch *Cheque
  113. if ch, err = chbook.Issue(addr1, common.Big1); err != nil {
  114. t.Fatalf("expected no error, got %v", err)
  115. }
  116. if ch.Amount.Cmp(new(big.Int).SetUint64(43)) != 0 {
  117. t.Errorf("expected: %v, got %v", "0", ch.Amount)
  118. }
  119. err = chbook.Save()
  120. if err != nil {
  121. t.Fatalf("expected no error, got %v", err)
  122. }
  123. }
  124. func TestVerifyErrors(t *testing.T) {
  125. path0 := filepath.Join(os.TempDir(), "chequebook-test-0.json")
  126. backend := newTestBackend()
  127. contr0, err := deploy(key0, common.Big2, backend)
  128. if err != nil {
  129. t.Errorf("expected no error, got %v", err)
  130. }
  131. chbook0, err := NewChequebook(path0, contr0, key0, backend)
  132. if err != nil {
  133. t.Errorf("expected no error, got %v", err)
  134. }
  135. path1 := filepath.Join(os.TempDir(), "chequebook-test-1.json")
  136. contr1, _ := deploy(key1, common.Big2, backend)
  137. chbook1, err := NewChequebook(path1, contr1, key1, backend)
  138. if err != nil {
  139. t.Errorf("expected no error, got %v", err)
  140. }
  141. chbook0.sent[addr1] = new(big.Int).SetUint64(42)
  142. chbook0.balance = new(big.Int).Set(common.Big2)
  143. chbook1.balance = new(big.Int).Set(common.Big1)
  144. amount := common.Big1
  145. ch0, err := chbook0.Issue(addr1, amount)
  146. if err != nil {
  147. t.Fatalf("expected no error, got %v", err)
  148. }
  149. time.Sleep(5)
  150. chbox, err := NewInbox(key1, contr0, addr1, &key0.PublicKey, backend)
  151. if err != nil {
  152. t.Fatalf("expected no error, got %v", err)
  153. }
  154. received, err := chbox.Receive(ch0)
  155. if err != nil {
  156. t.Fatalf("expected no error, got %v", err)
  157. }
  158. if received.Cmp(big.NewInt(43)) != 0 {
  159. t.Errorf("expected: %v, got %v", "43", received)
  160. }
  161. ch1, err := chbook0.Issue(addr2, amount)
  162. if err != nil {
  163. t.Fatalf("expected no error, got %v", err)
  164. }
  165. received, err = chbox.Receive(ch1)
  166. t.Logf("correct error: %v", err)
  167. if err == nil {
  168. t.Fatalf("expected receiver error, got none")
  169. }
  170. ch2, err := chbook1.Issue(addr1, amount)
  171. if err != nil {
  172. t.Fatalf("expected no error, got %v", err)
  173. }
  174. received, err = chbox.Receive(ch2)
  175. t.Logf("correct error: %v", err)
  176. if err == nil {
  177. t.Fatalf("expected sender error, got none")
  178. }
  179. _, err = chbook1.Issue(addr1, new(big.Int).SetInt64(-1))
  180. t.Logf("correct error: %v", err)
  181. if err == nil {
  182. t.Fatalf("expected incorrect amount error, got none")
  183. }
  184. received, err = chbox.Receive(ch0)
  185. t.Logf("correct error: %v", err)
  186. if err == nil {
  187. t.Fatalf("expected incorrect amount error, got none")
  188. }
  189. }
  190. func TestDeposit(t *testing.T) {
  191. path0 := filepath.Join(os.TempDir(), "chequebook-test-0.json")
  192. backend := newTestBackend()
  193. contr0, _ := deploy(key0, new(big.Int), backend)
  194. chbook, err := NewChequebook(path0, contr0, key0, backend)
  195. if err != nil {
  196. t.Errorf("expected no error, got %v", err)
  197. }
  198. balance := new(big.Int).SetUint64(42)
  199. chbook.Deposit(balance)
  200. backend.Commit()
  201. if chbook.balance.Cmp(balance) != 0 {
  202. t.Fatalf("expected balance %v, got %v", balance, chbook.balance)
  203. }
  204. amount := common.Big1
  205. _, err = chbook.Issue(addr1, amount)
  206. if err != nil {
  207. t.Fatalf("expected no error, got %v", err)
  208. }
  209. backend.Commit()
  210. exp := new(big.Int).SetUint64(41)
  211. if chbook.balance.Cmp(exp) != 0 {
  212. t.Fatalf("expected balance %v, got %v", exp, chbook.balance)
  213. }
  214. // autodeposit on each issue
  215. chbook.AutoDeposit(0, balance, balance)
  216. _, err = chbook.Issue(addr1, amount)
  217. if err != nil {
  218. t.Fatalf("expected no error, got %v", err)
  219. }
  220. backend.Commit()
  221. _, err = chbook.Issue(addr1, amount)
  222. if err != nil {
  223. t.Fatalf("expected no error, got %v", err)
  224. }
  225. backend.Commit()
  226. if chbook.balance.Cmp(balance) != 0 {
  227. t.Fatalf("expected balance %v, got %v", balance, chbook.balance)
  228. }
  229. // autodeposit off
  230. chbook.AutoDeposit(0, common.Big0, balance)
  231. _, err = chbook.Issue(addr1, amount)
  232. if err != nil {
  233. t.Fatalf("expected no error, got %v", err)
  234. }
  235. backend.Commit()
  236. _, err = chbook.Issue(addr1, amount)
  237. if err != nil {
  238. t.Fatalf("expected no error, got %v", err)
  239. }
  240. backend.Commit()
  241. exp = new(big.Int).SetUint64(40)
  242. if chbook.balance.Cmp(exp) != 0 {
  243. t.Fatalf("expected balance %v, got %v", exp, chbook.balance)
  244. }
  245. // autodeposit every 10ms if new cheque issued
  246. interval := 30 * time.Millisecond
  247. chbook.AutoDeposit(interval, common.Big1, balance)
  248. _, err = chbook.Issue(addr1, amount)
  249. if err != nil {
  250. t.Fatalf("expected no error, got %v", err)
  251. }
  252. backend.Commit()
  253. _, err = chbook.Issue(addr1, amount)
  254. if err != nil {
  255. t.Fatalf("expected no error, got %v", err)
  256. }
  257. backend.Commit()
  258. exp = new(big.Int).SetUint64(38)
  259. if chbook.balance.Cmp(exp) != 0 {
  260. t.Fatalf("expected balance %v, got %v", exp, chbook.balance)
  261. }
  262. time.Sleep(3 * interval)
  263. backend.Commit()
  264. if chbook.balance.Cmp(balance) != 0 {
  265. t.Fatalf("expected balance %v, got %v", balance, chbook.balance)
  266. }
  267. exp = new(big.Int).SetUint64(40)
  268. chbook.AutoDeposit(4*interval, exp, balance)
  269. _, err = chbook.Issue(addr1, amount)
  270. if err != nil {
  271. t.Fatalf("expected no error, got %v", err)
  272. }
  273. backend.Commit()
  274. _, err = chbook.Issue(addr1, amount)
  275. if err != nil {
  276. t.Fatalf("expected no error, got %v", err)
  277. }
  278. time.Sleep(3 * interval)
  279. backend.Commit()
  280. if chbook.balance.Cmp(exp) != 0 {
  281. t.Fatalf("expected balance %v, got %v", exp, chbook.balance)
  282. }
  283. _, err = chbook.Issue(addr1, amount)
  284. if err != nil {
  285. t.Fatalf("expected no error, got %v", err)
  286. }
  287. time.Sleep(1 * interval)
  288. backend.Commit()
  289. if chbook.balance.Cmp(balance) != 0 {
  290. t.Fatalf("expected balance %v, got %v", balance, chbook.balance)
  291. }
  292. chbook.AutoDeposit(1*interval, common.Big0, balance)
  293. chbook.Stop()
  294. _, err = chbook.Issue(addr1, common.Big1)
  295. if err != nil {
  296. t.Fatalf("expected no error, got %v", err)
  297. }
  298. backend.Commit()
  299. _, err = chbook.Issue(addr1, common.Big2)
  300. if err != nil {
  301. t.Fatalf("expected no error, got %v", err)
  302. }
  303. time.Sleep(1 * interval)
  304. backend.Commit()
  305. exp = new(big.Int).SetUint64(39)
  306. if chbook.balance.Cmp(exp) != 0 {
  307. t.Fatalf("expected balance %v, got %v", exp, chbook.balance)
  308. }
  309. }
  310. func TestCash(t *testing.T) {
  311. path := filepath.Join(os.TempDir(), "chequebook-test.json")
  312. backend := newTestBackend()
  313. contr0, _ := deploy(key0, common.Big2, backend)
  314. chbook, err := NewChequebook(path, contr0, key0, backend)
  315. if err != nil {
  316. t.Errorf("expected no error, got %v", err)
  317. }
  318. chbook.sent[addr1] = new(big.Int).SetUint64(42)
  319. amount := common.Big1
  320. chbook.balance = new(big.Int).Set(common.Big1)
  321. ch, err := chbook.Issue(addr1, amount)
  322. if err != nil {
  323. t.Fatalf("expected no error, got %v", err)
  324. }
  325. backend.Commit()
  326. chbox, err := NewInbox(key1, contr0, addr1, &key0.PublicKey, backend)
  327. if err != nil {
  328. t.Fatalf("expected no error, got %v", err)
  329. }
  330. // cashing latest cheque
  331. if _, err = chbox.Receive(ch); err != nil {
  332. t.Fatalf("expected no error, got %v", err)
  333. }
  334. if _, err = ch.Cash(chbook.session); err != nil {
  335. t.Fatal("Cash failed:", err)
  336. }
  337. backend.Commit()
  338. chbook.balance = new(big.Int).Set(common.Big3)
  339. ch0, err := chbook.Issue(addr1, amount)
  340. if err != nil {
  341. t.Fatalf("expected no error, got %v", err)
  342. }
  343. backend.Commit()
  344. ch1, err := chbook.Issue(addr1, amount)
  345. if err != nil {
  346. t.Fatalf("expected no error, got %v", err)
  347. }
  348. backend.Commit()
  349. interval := 10 * time.Millisecond
  350. // setting autocash with interval of 10ms
  351. chbox.AutoCash(interval, nil)
  352. _, err = chbox.Receive(ch0)
  353. if err != nil {
  354. t.Fatalf("expected no error, got %v", err)
  355. }
  356. _, err = chbox.Receive(ch1)
  357. if err != nil {
  358. t.Fatalf("expected no error, got %v", err)
  359. }
  360. backend.Commit()
  361. // expBalance := big.NewInt(2)
  362. // gotBalance := backend.BalanceAt(addr1)
  363. // if gotBalance.Cmp(expBalance) != 0 {
  364. // t.Fatalf("expected beneficiary balance %v, got %v", expBalance, gotBalance)
  365. // }
  366. // after 3x interval time and 2 cheques received, exactly one cashing tx is sent
  367. time.Sleep(4 * interval)
  368. backend.Commit()
  369. // expBalance = big.NewInt(4)
  370. // gotBalance = backend.BalanceAt(addr1)
  371. // if gotBalance.Cmp(expBalance) != 0 {
  372. // t.Fatalf("expected beneficiary balance %v, got %v", expBalance, gotBalance)
  373. // }
  374. // after stopping autocash no more tx are sent
  375. ch2, err := chbook.Issue(addr1, amount)
  376. if err != nil {
  377. t.Fatalf("expected no error, got %v", err)
  378. }
  379. chbox.Stop()
  380. _, err = chbox.Receive(ch2)
  381. if err != nil {
  382. t.Fatalf("expected no error, got %v", err)
  383. }
  384. time.Sleep(2 * interval)
  385. backend.Commit()
  386. // expBalance = big.NewInt(4)
  387. // gotBalance = backend.BalanceAt(addr1)
  388. // if gotBalance.Cmp(expBalance) != 0 {
  389. // t.Fatalf("expected beneficiary balance %v, got %v", expBalance, gotBalance)
  390. // }
  391. // autocash below 1
  392. chbook.balance = big.NewInt(2)
  393. chbox.AutoCash(0, common.Big1)
  394. ch3, err := chbook.Issue(addr1, amount)
  395. if err != nil {
  396. t.Fatalf("expected no error, got %v", err)
  397. }
  398. backend.Commit()
  399. // expBalance = big.NewInt(4)
  400. // gotBalance = backend.BalanceAt(addr1)
  401. // if gotBalance.Cmp(expBalance) != 0 {
  402. // t.Fatalf("expected beneficiary balance %v, got %v", expBalance, gotBalance)
  403. // }
  404. ch4, err := chbook.Issue(addr1, amount)
  405. if err != nil {
  406. t.Fatalf("expected no error, got %v", err)
  407. }
  408. backend.Commit()
  409. _, err = chbox.Receive(ch3)
  410. if err != nil {
  411. t.Fatalf("expected no error, got %v", err)
  412. }
  413. backend.Commit()
  414. _, err = chbox.Receive(ch4)
  415. if err != nil {
  416. t.Fatalf("expected no error, got %v", err)
  417. }
  418. backend.Commit()
  419. // 2 checks of amount 1 received, exactly 1 tx is sent
  420. // expBalance = big.NewInt(6)
  421. // gotBalance = backend.BalanceAt(addr1)
  422. // if gotBalance.Cmp(expBalance) != 0 {
  423. // t.Fatalf("expected beneficiary balance %v, got %v", expBalance, gotBalance)
  424. // }
  425. // autochash on receipt when maxUncashed is 0
  426. chbook.balance = new(big.Int).Set(common.Big2)
  427. chbox.AutoCash(0, common.Big0)
  428. ch5, err := chbook.Issue(addr1, amount)
  429. if err != nil {
  430. t.Fatalf("expected no error, got %v", err)
  431. }
  432. backend.Commit()
  433. // expBalance = big.NewInt(5)
  434. // gotBalance = backend.BalanceAt(addr1)
  435. // if gotBalance.Cmp(expBalance) != 0 {
  436. // t.Fatalf("expected beneficiary balance %v, got %v", expBalance, gotBalance)
  437. // }
  438. ch6, err := chbook.Issue(addr1, amount)
  439. if err != nil {
  440. t.Fatalf("expected no error, got %v", err)
  441. }
  442. _, err = chbox.Receive(ch5)
  443. if err != nil {
  444. t.Fatalf("expected no error, got %v", err)
  445. }
  446. backend.Commit()
  447. // expBalance = big.NewInt(4)
  448. // gotBalance = backend.BalanceAt(addr1)
  449. // if gotBalance.Cmp(expBalance) != 0 {
  450. // t.Fatalf("expected beneficiary balance %v, got %v", expBalance, gotBalance)
  451. // }
  452. _, err = chbox.Receive(ch6)
  453. if err != nil {
  454. t.Fatalf("expected no error, got %v", err)
  455. }
  456. backend.Commit()
  457. // expBalance = big.NewInt(6)
  458. // gotBalance = backend.BalanceAt(addr1)
  459. // if gotBalance.Cmp(expBalance) != 0 {
  460. // t.Fatalf("expected beneficiary balance %v, got %v", expBalance, gotBalance)
  461. // }
  462. }