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