cheque_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  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(core.GenesisAlloc{
  41. addr0: {Balance: big.NewInt(1000000000)},
  42. addr1: {Balance: big.NewInt(1000000000)},
  43. 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().Sign() != 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. chbox, err := NewInbox(key1, contr0, addr1, &key0.PublicKey, backend)
  150. if err != nil {
  151. t.Fatalf("expected no error, got %v", err)
  152. }
  153. received, err := chbox.Receive(ch0)
  154. if err != nil {
  155. t.Fatalf("expected no error, got %v", err)
  156. }
  157. if received.Cmp(big.NewInt(43)) != 0 {
  158. t.Errorf("expected: %v, got %v", "43", received)
  159. }
  160. ch1, err := chbook0.Issue(addr2, amount)
  161. if err != nil {
  162. t.Fatalf("expected no error, got %v", err)
  163. }
  164. received, err = chbox.Receive(ch1)
  165. t.Logf("correct error: %v", err)
  166. if err == nil {
  167. t.Fatalf("expected receiver error, got none and value %v", received)
  168. }
  169. ch2, err := chbook1.Issue(addr1, amount)
  170. if err != nil {
  171. t.Fatalf("expected no error, got %v", err)
  172. }
  173. received, err = chbox.Receive(ch2)
  174. t.Logf("correct error: %v", err)
  175. if err == nil {
  176. t.Fatalf("expected sender error, got none and value %v", received)
  177. }
  178. _, err = chbook1.Issue(addr1, new(big.Int).SetInt64(-1))
  179. t.Logf("correct error: %v", err)
  180. if err == nil {
  181. t.Fatalf("expected incorrect amount error, got none")
  182. }
  183. received, err = chbox.Receive(ch0)
  184. t.Logf("correct error: %v", err)
  185. if err == nil {
  186. t.Fatalf("expected incorrect amount error, got none and value %v", received)
  187. }
  188. }
  189. func TestDeposit(t *testing.T) {
  190. path0 := filepath.Join(os.TempDir(), "chequebook-test-0.json")
  191. backend := newTestBackend()
  192. contr0, _ := deploy(key0, new(big.Int), backend)
  193. chbook, err := NewChequebook(path0, contr0, key0, backend)
  194. if err != nil {
  195. t.Errorf("expected no error, got %v", err)
  196. }
  197. balance := new(big.Int).SetUint64(42)
  198. chbook.Deposit(balance)
  199. backend.Commit()
  200. if chbook.Balance().Cmp(balance) != 0 {
  201. t.Fatalf("expected balance %v, got %v", balance, chbook.Balance())
  202. }
  203. amount := common.Big1
  204. _, err = chbook.Issue(addr1, amount)
  205. if err != nil {
  206. t.Fatalf("expected no error, got %v", err)
  207. }
  208. backend.Commit()
  209. exp := new(big.Int).SetUint64(41)
  210. if chbook.Balance().Cmp(exp) != 0 {
  211. t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
  212. }
  213. // autodeposit on each issue
  214. chbook.AutoDeposit(0, balance, balance)
  215. _, err = chbook.Issue(addr1, amount)
  216. if err != nil {
  217. t.Fatalf("expected no error, got %v", err)
  218. }
  219. backend.Commit()
  220. _, err = chbook.Issue(addr1, amount)
  221. if err != nil {
  222. t.Fatalf("expected no error, got %v", err)
  223. }
  224. backend.Commit()
  225. if chbook.Balance().Cmp(balance) != 0 {
  226. t.Fatalf("expected balance %v, got %v", balance, chbook.Balance())
  227. }
  228. // autodeposit off
  229. chbook.AutoDeposit(0, common.Big0, balance)
  230. _, err = chbook.Issue(addr1, amount)
  231. if err != nil {
  232. t.Fatalf("expected no error, got %v", err)
  233. }
  234. backend.Commit()
  235. _, err = chbook.Issue(addr1, amount)
  236. if err != nil {
  237. t.Fatalf("expected no error, got %v", err)
  238. }
  239. backend.Commit()
  240. exp = new(big.Int).SetUint64(40)
  241. if chbook.Balance().Cmp(exp) != 0 {
  242. t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
  243. }
  244. // autodeposit every 200ms if new cheque issued
  245. interval := 200 * time.Millisecond
  246. chbook.AutoDeposit(interval, common.Big1, balance)
  247. _, err = chbook.Issue(addr1, amount)
  248. if err != nil {
  249. t.Fatalf("expected no error, got %v", err)
  250. }
  251. backend.Commit()
  252. _, err = chbook.Issue(addr1, amount)
  253. if err != nil {
  254. t.Fatalf("expected no error, got %v", err)
  255. }
  256. backend.Commit()
  257. exp = new(big.Int).SetUint64(38)
  258. if chbook.Balance().Cmp(exp) != 0 {
  259. t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
  260. }
  261. time.Sleep(3 * interval)
  262. backend.Commit()
  263. if chbook.Balance().Cmp(balance) != 0 {
  264. t.Fatalf("expected balance %v, got %v", balance, chbook.Balance())
  265. }
  266. exp = new(big.Int).SetUint64(40)
  267. chbook.AutoDeposit(4*interval, exp, balance)
  268. _, err = chbook.Issue(addr1, amount)
  269. if err != nil {
  270. t.Fatalf("expected no error, got %v", err)
  271. }
  272. backend.Commit()
  273. _, err = chbook.Issue(addr1, amount)
  274. if err != nil {
  275. t.Fatalf("expected no error, got %v", err)
  276. }
  277. time.Sleep(3 * interval)
  278. backend.Commit()
  279. if chbook.Balance().Cmp(exp) != 0 {
  280. t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
  281. }
  282. _, err = chbook.Issue(addr1, amount)
  283. if err != nil {
  284. t.Fatalf("expected no error, got %v", err)
  285. }
  286. time.Sleep(1 * interval)
  287. backend.Commit()
  288. if chbook.Balance().Cmp(balance) != 0 {
  289. t.Fatalf("expected balance %v, got %v", balance, chbook.Balance())
  290. }
  291. chbook.AutoDeposit(1*interval, common.Big0, balance)
  292. chbook.Stop()
  293. _, err = chbook.Issue(addr1, common.Big1)
  294. if err != nil {
  295. t.Fatalf("expected no error, got %v", err)
  296. }
  297. backend.Commit()
  298. _, err = chbook.Issue(addr1, common.Big2)
  299. if err != nil {
  300. t.Fatalf("expected no error, got %v", err)
  301. }
  302. time.Sleep(1 * interval)
  303. backend.Commit()
  304. exp = new(big.Int).SetUint64(39)
  305. if chbook.Balance().Cmp(exp) != 0 {
  306. t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
  307. }
  308. }
  309. func TestCash(t *testing.T) {
  310. path := filepath.Join(os.TempDir(), "chequebook-test.json")
  311. backend := newTestBackend()
  312. contr0, _ := deploy(key0, common.Big2, backend)
  313. chbook, err := NewChequebook(path, contr0, key0, backend)
  314. if err != nil {
  315. t.Errorf("expected no error, got %v", err)
  316. }
  317. chbook.sent[addr1] = new(big.Int).SetUint64(42)
  318. amount := common.Big1
  319. chbook.balance = new(big.Int).Set(common.Big1)
  320. ch, err := chbook.Issue(addr1, amount)
  321. if err != nil {
  322. t.Fatalf("expected no error, got %v", err)
  323. }
  324. backend.Commit()
  325. chbox, err := NewInbox(key1, contr0, addr1, &key0.PublicKey, backend)
  326. if err != nil {
  327. t.Fatalf("expected no error, got %v", err)
  328. }
  329. // cashing latest cheque
  330. if _, err = chbox.Receive(ch); err != nil {
  331. t.Fatalf("expected no error, got %v", err)
  332. }
  333. if _, err = ch.Cash(chbook.session); err != nil {
  334. t.Fatal("Cash failed:", err)
  335. }
  336. backend.Commit()
  337. chbook.balance = new(big.Int).Set(common.Big3)
  338. ch0, err := chbook.Issue(addr1, amount)
  339. if err != nil {
  340. t.Fatalf("expected no error, got %v", err)
  341. }
  342. backend.Commit()
  343. ch1, err := chbook.Issue(addr1, amount)
  344. if err != nil {
  345. t.Fatalf("expected no error, got %v", err)
  346. }
  347. backend.Commit()
  348. interval := 10 * time.Millisecond
  349. // setting autocash with interval of 10ms
  350. chbox.AutoCash(interval, nil)
  351. _, err = chbox.Receive(ch0)
  352. if err != nil {
  353. t.Fatalf("expected no error, got %v", err)
  354. }
  355. _, err = chbox.Receive(ch1)
  356. if err != nil {
  357. t.Fatalf("expected no error, got %v", err)
  358. }
  359. backend.Commit()
  360. // after 3x interval time and 2 cheques received, exactly one cashing tx is sent
  361. time.Sleep(4 * interval)
  362. backend.Commit()
  363. // after stopping autocash no more tx are sent
  364. ch2, err := chbook.Issue(addr1, amount)
  365. if err != nil {
  366. t.Fatalf("expected no error, got %v", err)
  367. }
  368. chbox.Stop()
  369. _, err = chbox.Receive(ch2)
  370. if err != nil {
  371. t.Fatalf("expected no error, got %v", err)
  372. }
  373. time.Sleep(2 * interval)
  374. backend.Commit()
  375. // autocash below 1
  376. chbook.balance = big.NewInt(2)
  377. chbox.AutoCash(0, common.Big1)
  378. ch3, err := chbook.Issue(addr1, amount)
  379. if err != nil {
  380. t.Fatalf("expected no error, got %v", err)
  381. }
  382. backend.Commit()
  383. ch4, err := chbook.Issue(addr1, amount)
  384. if err != nil {
  385. t.Fatalf("expected no error, got %v", err)
  386. }
  387. backend.Commit()
  388. _, err = chbox.Receive(ch3)
  389. if err != nil {
  390. t.Fatalf("expected no error, got %v", err)
  391. }
  392. backend.Commit()
  393. _, err = chbox.Receive(ch4)
  394. if err != nil {
  395. t.Fatalf("expected no error, got %v", err)
  396. }
  397. backend.Commit()
  398. // autochash on receipt when maxUncashed is 0
  399. chbook.balance = new(big.Int).Set(common.Big2)
  400. chbox.AutoCash(0, common.Big0)
  401. ch5, err := chbook.Issue(addr1, amount)
  402. if err != nil {
  403. t.Fatalf("expected no error, got %v", err)
  404. }
  405. backend.Commit()
  406. ch6, err := chbook.Issue(addr1, amount)
  407. if err != nil {
  408. t.Fatalf("expected no error, got %v", err)
  409. }
  410. _, err = chbox.Receive(ch5)
  411. if err != nil {
  412. t.Fatalf("expected no error, got %v", err)
  413. }
  414. backend.Commit()
  415. _, err = chbox.Receive(ch6)
  416. if err != nil {
  417. t.Fatalf("expected no error, got %v", err)
  418. }
  419. backend.Commit()
  420. }