github.com/aergoio/aergo@v1.3.1/contract/vm_test.go (about) 1 package contract 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "math/big" 9 "strconv" 10 "strings" 11 "testing" 12 13 "github.com/aergoio/aergo/types" 14 ) 15 16 const ( 17 helloCode = `function hello(say) return "Hello " .. say end abi.register(hello)` 18 19 systemCode = `function testState() 20 system.setItem("key1", 999) 21 return system.getSender(), system.getTxhash(),system.getContractID(), system.getTimestamp(), system.getBlockheight(), system.getItem("key1") 22 end 23 abi.register(testState)` 24 25 queryCode = `function inc() 26 a = system.getItem("key1") 27 if (a == nil) then 28 system.setItem("key1", 1) 29 return 30 end 31 system.setItem("key1", a + 1) 32 end 33 function query(a) 34 return system.getItem(a) 35 end 36 abi.register(query) 37 abi.payable(inc)` 38 ) 39 40 func TestReturn(t *testing.T) { 41 bc, err := LoadDummyChain() 42 if err != nil { 43 t.Errorf("failed to create test database: %v", err) 44 } 45 defer bc.Release() 46 47 err = bc.ConnectBlock( 48 NewLuaTxAccount("ktlee", 100), 49 NewLuaTxDef("ktlee", "return_num", 0, "function return_num() return 10 end abi.register(return_num)"), 50 NewLuaTxCall("ktlee", "return_num", 0, `{"Name":"return_num", "Args":[]}`), 51 ) 52 if err != nil { 53 t.Error(err) 54 } 55 56 err = bc.Query("return_num", `{"Name":"return_num", "Args":[]}`, "", "10") 57 if err != nil { 58 t.Error(err) 59 } 60 61 foo := `function foo() 62 return {1,2,3} 63 end 64 function foo2(bar) 65 return bar 66 end 67 abi.register(foo,foo2)` 68 69 err = bc.ConnectBlock( 70 NewLuaTxDef("ktlee", "foo", 0, foo), 71 ) 72 if err != nil { 73 t.Error(err) 74 } 75 76 err = bc.Query("foo", `{"Name":"foo", "Args":[]}`, "", "[1,2,3]") 77 if err != nil { 78 t.Error(err) 79 } 80 err = bc.Query("foo", `{"Name":"foo2", "Args":["foo314"]}`, "", `"foo314"`) 81 if err != nil { 82 t.Error(err) 83 } 84 } 85 86 func TestContractHello(t *testing.T) { 87 bc, err := LoadDummyChain() 88 if err != nil { 89 t.Errorf("failed to create test database: %v", err) 90 } 91 defer bc.Release() 92 93 _ = bc.ConnectBlock( 94 NewLuaTxAccount("ktlee", 100), 95 ) 96 _ = bc.ConnectBlock( 97 NewLuaTxDef("ktlee", "hello", 0, helloCode), 98 ) 99 tx := NewLuaTxCall("ktlee", "hello", 0, `{"Name":"hello", "Args":["World"]}`) 100 _ = bc.ConnectBlock(tx) 101 receipt := bc.getReceipt(tx.hash()) 102 if receipt.GetRet() != `"Hello World"` { 103 t.Errorf("contract Call ret error :%s", receipt.GetRet()) 104 } 105 } 106 107 func TestContractSystem(t *testing.T) { 108 bc, err := LoadDummyChain() 109 if err != nil { 110 t.Errorf("failed to create test database: %v", err) 111 } 112 defer bc.Release() 113 114 _ = bc.ConnectBlock( 115 NewLuaTxAccount("ktlee", 100), 116 ) 117 _ = bc.ConnectBlock( 118 NewLuaTxDef("ktlee", "system", 0, systemCode), 119 ) 120 tx := NewLuaTxCall("ktlee", "system", 0, `{"Name":"testState", "Args":[]}`) 121 _ = bc.ConnectBlock(tx) 122 receipt := bc.getReceipt(tx.hash()) 123 exRv := fmt.Sprintf(`["Amg6nZWXKB6YpNgBPv9atcjdm6hnFvs5wMdRgb2e9DmaF5g9muF2","99NTyZ796bpvwLLhMmsfwo8J3Wu3rUioUQsHE9CSYQKz","AmhNNBNY7XFk4p5ym4CJf8nTcRTEHjWzAeXJfhP71244CjBCAQU3",%d,3,999]`, bc.cBlock.Header.Timestamp/1e9) 124 if receipt.GetRet() != exRv { 125 t.Errorf("expected: %s, but got: %s", exRv, receipt.GetRet()) 126 } 127 } 128 129 func TestGetABI(t *testing.T) { 130 bc, err := LoadDummyChain() 131 if err != nil { 132 t.Errorf("failed to create test database: %v", err) 133 } 134 defer bc.Release() 135 136 _ = bc.ConnectBlock( 137 NewLuaTxAccount("ktlee", 100), 138 NewLuaTxDef("ktlee", "hello", 0, 139 `state.var { 140 Say = state.value() 141 } 142 143 function hello(say) 144 return "Hello " .. say 145 end 146 147 abi.register(hello)`), 148 ) 149 abi, err := bc.GetABI("hello") 150 if err != nil { 151 t.Error(err) 152 } 153 b, err := json.Marshal(abi) 154 if err != nil { 155 t.Error(err) 156 } 157 if string(b) != `{"version":"0.2","language":"lua","functions":[{"name":"hello","arguments":[{"name":"say"}]}],"state_variables":[{"name":"Say","type":"value"}]}` { 158 t.Error(string(b)) 159 } 160 } 161 162 func TestContractQuery(t *testing.T) { 163 bc, err := LoadDummyChain() 164 if err != nil { 165 t.Errorf("failed to create test database: %v", err) 166 } 167 defer bc.Release() 168 169 _ = bc.ConnectBlock( 170 NewLuaTxAccount("ktlee", 100), 171 ) 172 _ = bc.ConnectBlock( 173 NewLuaTxDef("ktlee", "query", 0, queryCode), 174 NewLuaTxCall("ktlee", "query", 2, `{"Name":"inc", "Args":[]}`), 175 ) 176 177 ktlee, err := bc.GetAccountState("ktlee") 178 if err != nil { 179 t.Error(err) 180 } 181 if ktlee.GetBalanceBigInt().Uint64() != uint64(98) { 182 t.Error(ktlee.Balance) 183 } 184 query, err := bc.GetAccountState("query") 185 if err != nil { 186 t.Error(err) 187 } 188 if query.GetBalanceBigInt().Uint64() != uint64(2) { 189 t.Error(query.Balance) 190 } 191 192 err = bc.Query("query", `{"Name":"inc", "Args":[]}`, "set not permitted in query", "") 193 if err != nil { 194 t.Error(err) 195 } 196 197 err = bc.Query("query", `{"Name":"query", "Args":["key1"]}`, "", "1") 198 if err != nil { 199 t.Error(err) 200 } 201 } 202 203 func TestRollback(t *testing.T) { 204 bc, err := LoadDummyChain() 205 if err != nil { 206 t.Errorf("failed to create test database: %v", err) 207 } 208 defer bc.Release() 209 210 _ = bc.ConnectBlock( 211 NewLuaTxAccount("ktlee", 100), 212 ) 213 _ = bc.ConnectBlock( 214 NewLuaTxDef("ktlee", "query", 0, queryCode), 215 NewLuaTxCall("ktlee", "query", 0, `{"Name":"inc", "Args":[]}`), 216 ) 217 _ = bc.ConnectBlock( 218 NewLuaTxCall("ktlee", "query", 0, `{"Name":"inc", "Args":[]}`), 219 NewLuaTxCall("ktlee", "query", 0, `{"Name":"inc", "Args":[]}`), 220 ) 221 _ = bc.ConnectBlock( 222 NewLuaTxCall("ktlee", "query", 0, `{"Name":"inc", "Args":[]}`), 223 NewLuaTxCall("ktlee", "query", 0, `{"Name":"inc", "Args":[]}`), 224 ) 225 226 err = bc.Query("query", `{"Name":"query", "Args":["key1"]}`, "", "5") 227 if err != nil { 228 t.Error(err) 229 } 230 231 err = bc.DisConnectBlock() 232 if err != nil { 233 t.Error(err) 234 } 235 err = bc.Query("query", `{"Name":"query", "Args":["key1"]}`, "", "3") 236 if err != nil { 237 t.Error(err) 238 } 239 240 err = bc.DisConnectBlock() 241 if err != nil { 242 t.Error(err) 243 } 244 245 err = bc.Query("query", `{"Name":"query", "Args":["key1"]}`, "", "1") 246 if err != nil { 247 t.Error(err) 248 } 249 250 _ = bc.ConnectBlock( 251 NewLuaTxCall("ktlee", "query", 0, `{"Name":"inc", "Args":[]}`), 252 ) 253 254 err = bc.Query("query", `{"Name":"query", "Args":["key1"]}`, "", "2") 255 if err != nil { 256 t.Error(err) 257 } 258 } 259 260 func TestVote(t *testing.T) { 261 bc, err := LoadDummyChain() 262 if err != nil { 263 t.Errorf("failed to create test database: %v", err) 264 } 265 defer bc.Release() 266 267 definition := ` 268 function constructor() 269 system.setItem("owner", system.getSender()) 270 end 271 272 function addCandidate(name) 273 if system.getSender() ~= system.getItem("owner") then 274 return 275 end 276 277 if (system.getItem(name) ~= nil) then 278 return 279 end 280 281 local numCandidates; 282 if (system.getItem("numCandidates") == nil) then 283 numCandidates = 0; 284 else 285 numCandidates = tonumber(system.getItem("numCandidates")) 286 end 287 288 system.setItem("candidate_list_" .. numCandidates, name) 289 290 numCandidates = numCandidates + 1; 291 system.setItem("numCandidates", tostring(numCandidates)); 292 system.setItem(name, tostring(0)); 293 end 294 295 function getCandidates() 296 local numCandidates; 297 if (system.getItem("numCandidates") == nil) then 298 return {}; 299 else 300 numCandidates = tonumber(system.getItem("numCandidates")) 301 end 302 303 local candidates = {}; 304 local i = 0; 305 306 while true do 307 if (numCandidates == i) then 308 break; 309 end 310 local candidate = system.getItem("candidate_list_" .. i) 311 local count = system.getItem(candidate) 312 if count == nil then 313 count = 0 314 end 315 table.insert(candidates, {id = i, name = candidate, count = count}); 316 i = i + 1; 317 end 318 return candidates; 319 end 320 321 function registerVoter(address) 322 if system.getSender() ~= system.getItem("owner") then 323 return 324 end 325 326 system.setItem("voter_" .. address, "0"); 327 end 328 329 function vote(candidateID) 330 local totalVoted 331 local voter = system.getItem("voter_" .. system.getSender()) 332 if voter == nil then 333 return 334 end 335 totalVoted = tonumber(system.getItem("voter_" .. system.getSender())) 336 if totalVoted > 3 then 337 return 338 end 339 if system.getItem(candidateID) == nil then 340 return 341 end 342 local currentVotes; 343 if (system.getItem(candidateID) == nil) then 344 currentVotes = 0; 345 else 346 currentVotes = tonumber(system.getItem(candidateID)) 347 end 348 currentVotes = currentVotes + 1 349 350 system.setItem(candidateID, tostring(currentVotes)) 351 totalVoted = totalVoted + 1 352 system.setItem("voter_" .. system.getSender(), tostring(totalVoted)); 353 end 354 355 abi.register(addCandidate, getCandidates, registerVoter, vote)` 356 357 _ = bc.ConnectBlock( 358 NewLuaTxAccount("owner", 100), 359 NewLuaTxDef("owner", "vote", 0, definition), 360 NewLuaTxAccount("user1", 100), 361 ) 362 363 err = bc.ConnectBlock( 364 NewLuaTxCall( 365 "owner", 366 "vote", 367 0, 368 `{"Name":"addCandidate", "Args":["candidate1"]}`, 369 ), 370 NewLuaTxCall( 371 "owner", 372 "vote", 373 0, 374 `{"Name":"addCandidate", "Args":["candidate2"]}`, 375 ), 376 NewLuaTxCall( 377 "owner", 378 "vote", 379 0, 380 `{"Name":"addCandidate", "Args":["candidate3"]}`, 381 ), 382 ) 383 if err != nil { 384 t.Error(err) 385 } 386 387 err = bc.Query( 388 "vote", 389 `{"Name":"getCandidates"}`, 390 "", 391 `[{"count":"0","id":0,"name":"candidate1"},{"count":"0","id":1,"name":"candidate2"},{"count":"0","id":2,"name":"candidate3"}]`, 392 ) 393 if err != nil { 394 t.Error(err) 395 } 396 397 _ = bc.ConnectBlock( 398 NewLuaTxCall( 399 "user1", 400 "vote", 401 0, 402 `{"Name":"addCandidate", "Args":["candidate4"]}`, 403 ), 404 ) 405 err = bc.Query( 406 "vote", 407 `{"Name":"getCandidates"}`, 408 "", 409 `[{"count":"0","id":0,"name":"candidate1"},{"count":"0","id":1,"name":"candidate2"},{"count":"0","id":2,"name":"candidate3"}]`, 410 ) 411 if err != nil { 412 t.Error(err) 413 } 414 415 _ = bc.ConnectBlock( 416 // register voter 417 NewLuaTxCall( 418 "owner", 419 "vote", 420 0, 421 fmt.Sprintf(`{"Name":"registerVoter", "Args":["%s"]}`, types.EncodeAddress(strHash("user10"))), 422 ), 423 NewLuaTxCall( 424 "owner", 425 "vote", 426 0, 427 fmt.Sprintf(`{"Name":"registerVoter", "Args":["%s"]}`, types.EncodeAddress(strHash("user10"))), 428 ), 429 NewLuaTxCall( 430 "owner", 431 "vote", 432 0, 433 fmt.Sprintf(`{"Name":"registerVoter", "Args":["%s"]}`, types.EncodeAddress(strHash("user11"))), 434 ), 435 NewLuaTxCall( 436 "owner", 437 "vote", 438 0, 439 fmt.Sprintf(`{"Name":"registerVoter", "Args":["%s"]}`, types.EncodeAddress(strHash("user1"))), 440 ), 441 // vote 442 NewLuaTxCall( 443 "user1", 444 "vote", 445 0, 446 `{"Name":"vote", "Args":["user1"]}`, 447 ), 448 NewLuaTxCall( 449 "user1", 450 "vote", 451 0, 452 `{"Name":"vote", "Args":["user1"]}`, 453 ), 454 NewLuaTxCall( 455 "user1", 456 "vote", 457 0, 458 `{"Name":"vote", "Args":["user2"]}`, 459 ), 460 NewLuaTxCall( 461 "user1", 462 "vote", 463 0, 464 `{"Name":"vote", "Args":["user2"]}`, 465 ), 466 NewLuaTxCall( 467 "user1", 468 "vote", 469 0, 470 `{"Name":"vote", "Args":["user3"]}`, 471 ), 472 ) 473 474 err = bc.Query( 475 "vote", 476 `{"Name":"getCandidates"}`, 477 "", 478 `[{"count":"0","id":0,"name":"candidate1"},{"count":"0","id":1,"name":"candidate2"},{"count":"0","id":2,"name":"candidate3"}]`, 479 ) 480 if err != nil { 481 t.Error(err) 482 } 483 484 _ = bc.ConnectBlock( 485 NewLuaTxCall( 486 "user11", 487 "vote", 488 0, 489 `{"Name":"vote", "Args":["candidate1"]}`, 490 ), 491 NewLuaTxCall( 492 "user10", 493 "vote", 494 0, 495 `{"Name":"vote", "Args":["candidate1"]}`, 496 ), 497 ) 498 499 err = bc.Query( 500 "vote", 501 `{"Name":"getCandidates"}`, 502 "", 503 `[{"count":"2","id":0,"name":"candidate1"},{"count":"0","id":1,"name":"candidate2"},{"count":"0","id":2,"name":"candidate3"}]`, 504 ) 505 if err != nil { 506 t.Error(err) 507 } 508 } 509 510 func TestInfiniteLoop(t *testing.T) { 511 bc, err := LoadDummyChain() 512 if err != nil { 513 t.Errorf("failed to create test database: %v", err) 514 } 515 defer bc.Release() 516 517 definition := ` 518 function infiniteLoop() 519 local t = 0 520 while true do 521 t = t + 1 522 end 523 return t 524 end 525 function infiniteCall() 526 infiniteCall() 527 end 528 function catch() 529 return pcall(infiniteLoop) 530 end 531 abi.register(infiniteLoop, infiniteCall, catch)` 532 533 err = bc.ConnectBlock( 534 NewLuaTxAccount("ktlee", 100), 535 NewLuaTxDef("ktlee", "loop", 0, definition), 536 ) 537 if err != nil { 538 t.Error(err) 539 } 540 541 err = bc.ConnectBlock( 542 NewLuaTxCall( 543 "ktlee", 544 "loop", 545 0, 546 `{"Name":"infiniteLoop"}`, 547 ), 548 ) 549 errMsg := "exceeded the maximum instruction count" 550 if err == nil { 551 t.Errorf("expected: %s", errMsg) 552 } 553 if err != nil && !strings.Contains(err.Error(), errMsg) { 554 t.Error(err) 555 } 556 557 err = bc.ConnectBlock( 558 NewLuaTxCall( 559 "ktlee", 560 "loop", 561 0, 562 `{"Name":"catch"}`, 563 ), 564 ) 565 if err == nil { 566 t.Errorf("expected: %s", errMsg) 567 } 568 if err != nil && !strings.Contains(err.Error(), errMsg) { 569 t.Error(err) 570 } 571 572 err = bc.ConnectBlock( 573 NewLuaTxCall( 574 "ktlee", 575 "loop", 576 0, 577 `{"Name":"infiniteCall"}`, 578 ), 579 ) 580 errMsg = "stack overflow" 581 if err == nil { 582 t.Errorf("expected: %s", errMsg) 583 } 584 if err != nil && !strings.Contains(err.Error(), errMsg) { 585 t.Error(err) 586 } 587 588 } 589 590 func TestUpdateSize(t *testing.T) { 591 bc, err := LoadDummyChain() 592 if err != nil { 593 t.Errorf("failed to create test database: %v", err) 594 } 595 defer bc.Release() 596 597 definition := ` 598 function infiniteLoop() 599 for i = 1, 100000000000000 do 600 system.setItem("key_"..i, "value_"..i) 601 end 602 end 603 abi.register(infiniteLoop)` 604 605 err = bc.ConnectBlock( 606 NewLuaTxAccount("ktlee", 100), 607 NewLuaTxDef("ktlee", "loop", 0, definition), 608 NewLuaTxCall( 609 "ktlee", 610 "loop", 611 0, 612 `{"Name":"infiniteLoop"}`, 613 ), 614 ) 615 errMsg := "exceeded size of updates in the state database" 616 if err == nil { 617 t.Errorf("expected: %s", errMsg) 618 } 619 if err != nil && !strings.Contains(err.Error(), errMsg) { 620 t.Error(err) 621 } 622 } 623 624 func TestSqlVmSimple(t *testing.T) { 625 bc, err := LoadDummyChain() 626 if err != nil { 627 t.Errorf("failed to create test database: %v", err) 628 } 629 defer bc.Release() 630 631 definition := ` 632 function createAndInsert() 633 db.exec("create table if not exists dual(dummy char(1))") 634 db.exec("insert into dual values ('X')") 635 local insertYZ = db.prepare("insert into dual values (?),(?)") 636 insertYZ:exec("Y", "Z") 637 end 638 639 function insertRollbackData() 640 db.exec("insert into dual values ('A'),('B'),('C')") 641 end 642 643 function query() 644 local rt = {} 645 local stmt = db.prepare("select ?+1, round(?, 1), dummy || ? as col3 from dual order by col3") 646 local rs = stmt:query(1, 3.14, " Hello Blockchain") 647 while rs:next() do 648 local col1, col2, col3 = rs:get() 649 table.insert(rt, col1) 650 table.insert(rt, col2) 651 table.insert(rt, col3) 652 end 653 return rt 654 end 655 656 function count() 657 local rs = db.query("select count(*) from dual") 658 if rs:next() then 659 local n = rs:get() 660 --rs:next() 661 return n 662 else 663 return "error in count()" 664 end 665 end 666 667 function all() 668 local rt = {} 669 local rs = db.query("select dummy from dual order by 1") 670 while rs:next() do 671 local col = rs:get() 672 table.insert(rt, col) 673 end 674 return rt 675 end 676 677 abi.register(createAndInsert, insertRollbackData, query, count, all)` 678 679 _ = bc.ConnectBlock( 680 NewLuaTxAccount("ktlee", 100), 681 NewLuaTxDef("ktlee", "simple-query", 0, definition), 682 ) 683 _ = bc.ConnectBlock( 684 NewLuaTxCall("ktlee", "simple-query", 0, `{"Name": "createAndInsert", "Args":[]}`), 685 ) 686 err = bc.Query( 687 "simple-query", 688 `{"Name": "query", "Args":[]}`, 689 "", 690 `[2,3.1,"X Hello Blockchain",2,3.1,"Y Hello Blockchain",2,3.1,"Z Hello Blockchain"]`, 691 ) 692 if err != nil { 693 t.Error(err) 694 } 695 err = bc.Query( 696 "simple-query", 697 `{"Name": "count", "Args":[]}`, 698 "", 699 `3`, 700 ) 701 if err != nil { 702 t.Error(err) 703 } 704 705 _ = bc.ConnectBlock( 706 NewLuaTxCall("ktlee", "simple-query", 0, `{"Name": "createAndInsert", "Args":[]}`), 707 ) 708 err = bc.Query( 709 "simple-query", 710 `{"Name": "count", "Args":[]}`, 711 "", 712 `6`, 713 ) 714 if err != nil { 715 t.Error(err) 716 } 717 718 _ = bc.DisConnectBlock() 719 720 err = bc.Query( 721 "simple-query", 722 `{"Name": "count", "Args":[]}`, 723 "", 724 `3`, 725 ) 726 if err != nil { 727 t.Error(err) 728 } 729 730 err = bc.DisConnectBlock() 731 if err != nil { 732 t.Error(err) 733 } 734 err = bc.DisConnectBlock() 735 if err != nil { 736 t.Error(err) 737 } 738 739 // there is only a genesis block 740 err = bc.Query( 741 "simple-query", 742 `{"Name": "count", "Args":[]}`, 743 "not found contract", 744 "", 745 ) 746 if err != nil { 747 t.Error(err) 748 } 749 } 750 751 func TestSqlVmFail(t *testing.T) { 752 bc, err := LoadDummyChain() 753 if err != nil { 754 t.Errorf("failed to create test database: %v", err) 755 } 756 defer bc.Release() 757 758 definition := ` 759 function init() 760 db.exec("create table if not exists total(n int)") 761 db.exec("insert into total values (0)") 762 end 763 764 function add(n) 765 local stmt = db.prepare("update total set n = n + ?") 766 stmt:exec(n) 767 end 768 769 function addFail(n) 770 local stmt = db.prepare("update set n = n + ?") 771 stmt:exec(n) 772 end 773 774 function get() 775 local rs = db.query("select n from total") 776 rs:next() 777 n = rs:get() 778 return n 779 end 780 abi.register(init, add, addFail, get)` 781 782 _ = bc.ConnectBlock( 783 NewLuaTxAccount("ktlee", 100), 784 NewLuaTxDef("ktlee", "fail", 0, definition), 785 NewLuaTxCall("ktlee", "fail", 0, `{"Name":"init"}`), 786 ) 787 788 _ = bc.ConnectBlock( 789 NewLuaTxCall("ktlee", "fail", 0, `{"Name":"add", "Args":[1]}`), 790 ) 791 792 err = bc.ConnectBlock( 793 NewLuaTxCall("ktlee", "fail", 0, `{"Name":"add", "Args":[2]}`), 794 NewLuaTxCall("ktlee", "fail", 0, `{"Name":"addFail", "Args":[3]}`). 795 Fail(`near "set": syntax error`), 796 NewLuaTxCall("ktlee", "fail", 0, `{"Name":"add", "Args":[4]}`), 797 ) 798 if err != nil { 799 t.Error(err) 800 } 801 802 _ = bc.ConnectBlock( 803 NewLuaTxCall("ktlee", "fail", 0, `{"Name":"add", "Args":[5]}`), 804 ) 805 806 err = bc.Query("fail", `{"Name":"get"}`, "", "12") 807 if err != nil { 808 t.Error(err) 809 } 810 811 _ = bc.DisConnectBlock() 812 813 err = bc.Query("fail", `{"Name":"get"}`, "", "7") 814 if err != nil { 815 t.Error(err) 816 } 817 } 818 819 func TestSqlVmDateTime(t *testing.T) { 820 bc, err := LoadDummyChain() 821 if err != nil { 822 t.Errorf("failed to create test database: %v", err) 823 } 824 defer bc.Release() 825 826 definition := ` 827 function init() 828 db.exec("create table if not exists dt_test (n datetime, b bool)") 829 local n = db.exec("insert into dt_test values (?, ?),(date('2004-10-24', '+1 month', '-1 day'), 0)", 10000, 1) 830 assert(n == 2, "change count mismatch"); 831 end 832 833 function nowNull() 834 db.exec("insert into dt_test values (date('now'), 0)") 835 end 836 837 function localtimeNull() 838 db.exec("insert into dt_test values (datetime('2018-05-25', ?), 1)", 'localtime') 839 end 840 841 function get() 842 local rs = db.query("select n, b from dt_test order by 1, 2") 843 local r = {} 844 while rs:next() do 845 local d, b = rs:get() 846 table.insert(r, { date= d, bool= b }) 847 end 848 return r 849 end 850 abi.register(init, nowNull, localtimeNull, get)` 851 852 _ = bc.ConnectBlock( 853 NewLuaTxAccount("ktlee", 100), 854 NewLuaTxDef("ktlee", "datetime", 0, definition), 855 NewLuaTxCall("ktlee", "datetime", 0, `{"Name":"init"}`), 856 ) 857 858 _ = bc.ConnectBlock( 859 NewLuaTxCall("ktlee", "datetime", 0, `{"Name":"nowNull"}`), 860 ) 861 862 _ = bc.ConnectBlock( 863 NewLuaTxCall("ktlee", "datetime", 0, `{"Name":"localtimeNull"}`), 864 ) 865 866 err = bc.Query( 867 "datetime", 868 `{"Name":"get"}`, 869 "", 870 `[{"bool":0},{"bool":1},{"bool":1,"date":"1970-01-01 02:46:40"},{"bool":0,"date":"2004-11-23"}]`, 871 ) 872 if err != nil { 873 t.Error(err) 874 } 875 } 876 877 func TestSqlConstrains(t *testing.T) { 878 bc, err := LoadDummyChain() 879 if err != nil { 880 t.Errorf("failed to create test database: %v", err) 881 } 882 defer bc.Release() 883 884 definition := ` 885 function init() 886 db.exec([[create table if not exists r ( 887 id integer primary key 888 , n integer check(n >= 10) 889 , nonull text not null 890 , only integer unique) 891 ]]) 892 db.exec("insert into r values (1, 11, 'text', 1)") 893 db.exec("create table if not exists s (rid integer references r(id))") 894 end 895 896 function pkFail() 897 db.exec("insert into r values (1, 12, 'text', 2)") 898 end 899 900 function checkFail() 901 db.exec("insert into r values (2, 9, 'text', 3)") 902 end 903 904 function fkFail() 905 db.exec("insert into s values (2)") 906 end 907 908 function notNullFail() 909 db.exec("insert into r values (2, 13, null, 2)") 910 end 911 912 function uniqueFail() 913 db.exec("insert into r values (2, 13, 'text', 1)") 914 end 915 916 abi.register(init, pkFail, checkFail, fkFail, notNullFail, uniqueFail)` 917 918 err = bc.ConnectBlock( 919 NewLuaTxAccount( 920 "ktlee", 921 100, 922 ), 923 NewLuaTxDef( 924 "ktlee", 925 "constraint", 926 0, 927 definition, 928 ), 929 NewLuaTxCall( 930 "ktlee", 931 "constraint", 932 0, 933 `{"Name":"init"}`, 934 ), 935 NewLuaTxCall( 936 "ktlee", 937 "constraint", 938 0, 939 `{"Name":"pkFail"}`, 940 ).Fail("UNIQUE constraint failed: r.id"), 941 NewLuaTxCall( 942 "ktlee", 943 "constraint", 944 0, 945 `{"Name":"checkFail"}`, 946 ).Fail("CHECK constraint failed: r"), 947 NewLuaTxCall( 948 "ktlee", 949 "constraint", 950 0, 951 `{"Name":"fkFail"}`, 952 ).Fail("FOREIGN KEY constraint failed"), 953 NewLuaTxCall( 954 "ktlee", 955 "constraint", 956 0, 957 `{"Name":"notNullFail"}`, 958 ).Fail("NOT NULL constraint failed: r.nonull"), 959 NewLuaTxCall( 960 "ktlee", 961 "constraint", 962 0, 963 `{"Name":"uniqueFail"}`, 964 ).Fail("UNIQUE constraint failed: r.only"), 965 ) 966 if err != nil { 967 t.Error(err) 968 } 969 } 970 971 func TestSqlVmCustomer(t *testing.T) { 972 bc, err := LoadDummyChain() 973 if err != nil { 974 t.Errorf("failed to create test database: %v", err) 975 } 976 defer bc.Release() 977 978 definition := ` 979 function createTable() 980 db.exec([[create table if not exists customer( 981 id varchar(10), 982 passwd varchar(20), 983 name varchar(30), 984 birth char(8), 985 mobile varchar(20) 986 )]]) 987 end 988 989 function query(id) 990 local rt = {} 991 local rs = db.query("select * from customer where id like '%' || ? || '%'", id) 992 while rs:next() do 993 local col1, col2, col3, col4, col5 = rs:get() 994 local item = { 995 id = col1, 996 passwd = col2, 997 name = col3, 998 birth = col4, 999 mobile = col5 1000 } 1001 table.insert(rt, item) 1002 end 1003 return rt 1004 end 1005 1006 function insert(id , passwd, name, birth, mobile) 1007 local n = db.exec("insert into customer values (?,?,?,?,?)", id, passwd, name, birth, mobile) 1008 assert(n == 1, "insert count mismatch") 1009 end 1010 1011 function update(id , passwd) 1012 local n = db.exec("update customer set passwd =? where id =?", passwd, id) 1013 assert(n == 1, "update count mismatch") 1014 end 1015 1016 function delete(id) 1017 local n = db.exec("delete from customer where id =?", id) 1018 assert(n == 1, "delete count mismatch") 1019 end 1020 1021 function count() 1022 local rs = db.query("select count(*) from customer") 1023 if rs:next() then 1024 local n = rs:get() 1025 return n 1026 else 1027 return "error in count()" 1028 end 1029 end 1030 1031 abi.register(createTable, query, insert, update, delete, count)` 1032 1033 _ = bc.ConnectBlock( 1034 NewLuaTxAccount("ktlee", 100), 1035 NewLuaTxDef("ktlee", "customer", 0, definition), 1036 NewLuaTxCall( 1037 "ktlee", 1038 "customer", 1039 0, 1040 `{"Name":"createTable"}`, 1041 ), 1042 ) 1043 1044 _ = bc.ConnectBlock( 1045 NewLuaTxCall( 1046 "ktlee", 1047 "customer", 1048 0, 1049 `{"Name":"insert", "Args":["id1","passwd1","name1","20180524","010-1234-5678"]}`, 1050 ), 1051 ) 1052 1053 _ = bc.ConnectBlock( 1054 NewLuaTxCall( 1055 "ktlee", 1056 "customer", 1057 0, 1058 `{"Name":"insert", "Args":["id2","passwd2","name2","20180524","010-1234-5678"]}`, 1059 ), 1060 ) 1061 1062 _ = bc.ConnectBlock( 1063 NewLuaTxCall( 1064 "ktlee", 1065 "customer", 1066 0, 1067 `{"Name":"update", "Args":["id2","passwd3"]}`, 1068 ), 1069 ) 1070 1071 err = bc.Query("customer", `{"Name":"count"}`, "", "2") 1072 if err != nil { 1073 t.Error(err) 1074 } 1075 1076 _ = bc.DisConnectBlock() 1077 1078 err = bc.Query( 1079 "customer", 1080 `{"Name":"query", "Args":["id2"]}`, 1081 "", 1082 `[{"birth":"20180524","id":"id2","mobile":"010-1234-5678","name":"name2","passwd":"passwd2"}]`, 1083 ) 1084 if err != nil { 1085 t.Error(err) 1086 } 1087 1088 _ = bc.ConnectBlock( 1089 NewLuaTxCall( 1090 "ktlee", 1091 "customer", 1092 0, 1093 `{"Name":"delete", "Args":["id2"]}`, 1094 ), 1095 ) 1096 1097 err = bc.Query( 1098 "customer", 1099 `{"Name":"query", "Args":["id2"]}`, 1100 "", 1101 `{}`, 1102 ) 1103 if err != nil { 1104 t.Error(err) 1105 } 1106 } 1107 1108 func TestSqlVmDataType(t *testing.T) { 1109 bc, err := LoadDummyChain() 1110 if err != nil { 1111 t.Errorf("failed to create test database: %v", err) 1112 } 1113 defer bc.Release() 1114 1115 definition := ` 1116 function createDataTypeTable() 1117 db.exec([[create table if not exists datatype_table( 1118 var1 varchar(10), 1119 char1 char(10), 1120 int1 int(5), 1121 float1 float(6), 1122 blockheight1 long 1123 )]]) 1124 end 1125 1126 function dropDataTypeTable() 1127 db.exec("drop table datatype_table") 1128 end 1129 1130 function insertDataTypeTable() 1131 local stmt = db.prepare("insert into datatype_table values ('ABCD','fgh',1,3.14,?)") 1132 stmt:exec(system.getBlockheight()) 1133 end 1134 function queryOrderByDesc() 1135 local rt = {} 1136 local rs = db.query("select * from datatype_table order by blockheight1 desc") 1137 while rs:next() do 1138 local col1, col2, col3, col4, col5 = rs:get() 1139 item = { 1140 var1 = col1, 1141 char1 = col2, 1142 int1 = col3, 1143 float1 = col4, 1144 blockheight1 = col5 1145 } 1146 table.insert(rt, item) 1147 end 1148 return rt 1149 end 1150 1151 function queryGroupByBlockheight1() 1152 local rt = {} 1153 local rs = db.query("select blockheight1, count(*), sum(int1), avg(float1) from datatype_table group by blockheight1") 1154 while rs:next() do 1155 local col1, col2, col3, col4 = rs:get() 1156 item = { 1157 blockheight1 = col1, 1158 count1 = col2, 1159 sum_int1 = col3, 1160 avg_float1 =col4 1161 } 1162 table.insert(rt, item) 1163 end 1164 return rt 1165 end 1166 1167 abi.register(createDataTypeTable, dropDataTypeTable, insertDataTypeTable, queryOrderByDesc, queryGroupByBlockheight1)` 1168 1169 _ = bc.ConnectBlock( 1170 NewLuaTxAccount("ktlee", 100), 1171 NewLuaTxDef("ktlee", "datatype", 0, definition), 1172 NewLuaTxCall( 1173 "ktlee", 1174 "datatype", 1175 0, 1176 `{"Name":"createDataTypeTable"}`, 1177 ), 1178 ) 1179 1180 _ = bc.ConnectBlock( 1181 NewLuaTxCall( 1182 "ktlee", 1183 "datatype", 1184 0, 1185 `{"Name":"insertDataTypeTable"}`, 1186 ), 1187 NewLuaTxCall( 1188 "ktlee", 1189 "datatype", 1190 0, 1191 `{"Name":"insertDataTypeTable"}`, 1192 ), 1193 NewLuaTxCall( 1194 "ktlee", 1195 "datatype", 1196 0, 1197 `{"Name":"insertDataTypeTable"}`, 1198 ), 1199 ) 1200 1201 _ = bc.ConnectBlock( 1202 NewLuaTxCall( 1203 "ktlee", 1204 "datatype", 1205 0, 1206 `{"Name":"insertDataTypeTable"}`, 1207 ), 1208 ) 1209 1210 err = bc.Query( 1211 "datatype", 1212 `{"Name":"queryOrderByDesc"}`, 1213 "", 1214 `[{"blockheight1":3,"char1":"fgh","float1":3.14,"int1":1,"var1":"ABCD"},{"blockheight1":2,"char1":"fgh","float1":3.14,"int1":1,"var1":"ABCD"},{"blockheight1":2,"char1":"fgh","float1":3.14,"int1":1,"var1":"ABCD"},{"blockheight1":2,"char1":"fgh","float1":3.14,"int1":1,"var1":"ABCD"}]`, 1215 ) 1216 if err != nil { 1217 t.Error(err) 1218 } 1219 1220 err = bc.Query( 1221 "datatype", 1222 `{"Name":"queryGroupByBlockheight1"}`, 1223 "", 1224 `[{"avg_float1":3.14,"blockheight1":2,"count1":3,"sum_int1":3},{"avg_float1":3.14,"blockheight1":3,"count1":1,"sum_int1":1}]`, 1225 ) 1226 if err != nil { 1227 t.Error(err) 1228 } 1229 } 1230 1231 func TestSqlVmFunction(t *testing.T) { 1232 bc, err := LoadDummyChain() 1233 if err != nil { 1234 t.Errorf("failed to create test database: %v", err) 1235 } 1236 defer bc.Release() 1237 1238 definition := ` 1239 function sql_func() 1240 local rt = {} 1241 local rs = db.query("select round(3.14),min(1,2,3), max(4,5,6)") 1242 if rs:next() then 1243 local col1, col2, col3 = rs:get() 1244 table.insert(rt, col1) 1245 table.insert(rt, col2) 1246 table.insert(rt, col3) 1247 return rt 1248 else 1249 return "error in func()" 1250 end 1251 end 1252 1253 function abs_func() 1254 local rt = {} 1255 local rs = db.query("select abs(-1),abs(0), abs(1)") 1256 if rs:next() then 1257 local col1, col2, col3 = rs:get() 1258 table.insert(rt, col1) 1259 table.insert(rt, col2) 1260 table.insert(rt, col3) 1261 return rt 1262 else 1263 return "error in abs()" 1264 end 1265 end 1266 1267 function typeof_func() 1268 local rt = {} 1269 local rs = db.query("select typeof(-1), typeof('abc'), typeof(3.14), typeof(null)") 1270 if rs:next() then 1271 local col1, col2, col3, col4 = rs:get() 1272 table.insert(rt, col1) 1273 table.insert(rt, col2) 1274 table.insert(rt, col3) 1275 table.insert(rt, col4) 1276 return rt 1277 else 1278 return "error in typeof()" 1279 end 1280 end 1281 1282 abi.register(sql_func, abs_func, typeof_func)` 1283 1284 err = bc.ConnectBlock( 1285 NewLuaTxAccount("name", 100), 1286 NewLuaTxDef("ktlee", "fns", 0, definition), 1287 ) 1288 if err != nil { 1289 t.Error(err) 1290 } 1291 1292 err = bc.Query("fns", `{"Name":"sql_func"}`, "", `[3,1,6]`) 1293 if err != nil { 1294 t.Error(err) 1295 } 1296 1297 err = bc.Query("fns", `{"Name":"abs_func"}`, "", `[1,0,1]`) 1298 if err != nil { 1299 t.Error(err) 1300 } 1301 1302 err = bc.Query("fns", `{"Name":"typeof_func"}`, 1303 "", `["integer","text","real","null"]`, 1304 ) 1305 if err != nil { 1306 t.Error(err) 1307 } 1308 } 1309 1310 func TestSqlVmBook(t *testing.T) { 1311 bc, err := LoadDummyChain() 1312 if err != nil { 1313 t.Errorf("failed to create test database: %v", err) 1314 } 1315 defer bc.Release() 1316 1317 definition := ` 1318 function createTable() 1319 db.exec([[create table if not exists book ( 1320 page number, 1321 contents text 1322 )]]) 1323 1324 db.exec([[create table if not exists copy_book ( 1325 page number, 1326 contents text 1327 )]]) 1328 end 1329 1330 function makeBook() 1331 local stmt = db.prepare("insert into book values (?,?)") 1332 for i = 1, 100 do 1333 stmt:exec(i, "value=" .. i*i) 1334 end 1335 end 1336 1337 function copyBook() 1338 local rs = db.query("select page, contents from book order by page asc") 1339 while rs:next() do 1340 local col1, col2 = rs:get() 1341 local stmt_t = db.prepare("insert into copy_book values (?,?)") 1342 stmt_t:exec(col1, col2) 1343 end 1344 end 1345 1346 1347 function viewCopyBook() 1348 local rt = {} 1349 local rs = db.query("select max(page), min(contents) from copy_book") 1350 while rs:next() do 1351 local col1, col2 = rs:get() 1352 table.insert(rt, col1) 1353 table.insert(rt, col2) 1354 end 1355 return rt 1356 end 1357 1358 function viewJoinBook() 1359 local rt = {} 1360 local rs = db.query([[select c.page, b.page, c.contents 1361 from copy_book c, book b 1362 where c.page = b.page and c.page = 10 ]]) 1363 while rs:next() do 1364 local col1, col2, col3 = rs:get() 1365 table.insert(rt, col1) 1366 table.insert(rt, col2) 1367 table.insert(rt, col3) 1368 end 1369 return rt 1370 end 1371 1372 abi.register(createTable, makeBook, copyBook, viewCopyBook, viewJoinBook)` 1373 1374 err = bc.ConnectBlock( 1375 NewLuaTxAccount("ktlee", 100), 1376 NewLuaTxDef("ktlee", "book", 0, definition), 1377 NewLuaTxCall( 1378 "ktlee", 1379 "book", 1380 0, 1381 `{"Name":"createTable"}`, 1382 ), 1383 ) 1384 if err != nil { 1385 t.Error(err) 1386 } 1387 1388 err = bc.ConnectBlock( 1389 NewLuaTxCall( 1390 "ktlee", 1391 "book", 1392 0, 1393 `{"Name":"makeBook"}`, 1394 ), 1395 ) 1396 if err != nil { 1397 t.Error(err) 1398 } 1399 1400 err = bc.ConnectBlock( 1401 NewLuaTxCall( 1402 "ktlee", 1403 "book", 1404 0, 1405 `{"Name":"copyBook"}`, 1406 ), 1407 ) 1408 if err != nil { 1409 t.Error(err) 1410 } 1411 1412 err = bc.Query( 1413 "book", 1414 `{"Name":"viewCopyBook"}`, 1415 "", 1416 `[100,"value=1"]`, 1417 ) 1418 if err != nil { 1419 t.Error(err) 1420 } 1421 } 1422 1423 func TestSqlVmDateformat(t *testing.T) { 1424 bc, err := LoadDummyChain() 1425 if err != nil { 1426 t.Errorf("failed to create test database: %v", err) 1427 } 1428 defer bc.Release() 1429 1430 definition := ` 1431 function init() 1432 db.exec("drop table if exists dateformat_test") 1433 db.exec([[create table if not exists dateformat_test 1434 ( 1435 col1 date , 1436 col2 datetime , 1437 col3 text 1438 )]]) 1439 db.exec("insert into dateformat_test values (date('2004-10-24 11:11:11'), datetime('2004-10-24 11:11:11'),strftime('%Y%m%d%H%M%S','2004-10-24 11:11:11'))") 1440 db.exec("insert into dateformat_test values (date(1527504338,'unixepoch'), datetime(1527504338,'unixepoch'), strftime('%Y%m%d%H%M%S',1527504338,'unixepoch') )") 1441 end 1442 1443 function get() 1444 local rt = {} 1445 local rs = db.query([[select col1, col2, col3 1446 from dateformat_test ]]) 1447 while rs:next() do 1448 local col1, col2, col3 = rs:get() 1449 table.insert(rt, {col1,col2,col3} ) 1450 end 1451 return rt 1452 end 1453 1454 abi.register(init, get)` 1455 1456 err = bc.ConnectBlock( 1457 NewLuaTxAccount("ktlee", 100), 1458 NewLuaTxDef( 1459 "ktlee", 1460 "data_format", 1461 0, 1462 definition, 1463 ), 1464 NewLuaTxCall("ktlee", "data_format", 0, `{"Name":"init"}`), 1465 ) 1466 if err != nil { 1467 t.Error(err) 1468 } 1469 1470 err = bc.Query( 1471 "data_format", 1472 `{"Name":"get"}`, 1473 "", 1474 `[["2004-10-24","2004-10-24 11:11:11","20041024111111"],["2018-05-28","2018-05-28 10:45:38","20180528104538"]]`, 1475 ) 1476 if err != nil { 1477 t.Error(err) 1478 } 1479 } 1480 1481 func TestSqlVmRecursiveData(t *testing.T) { 1482 bc, err := LoadDummyChain() 1483 if err != nil { 1484 t.Errorf("failed to create test database: %v", err) 1485 } 1486 defer bc.Release() 1487 1488 definition := ` 1489 function r() 1490 local t = {} 1491 t["name"] = "ktlee" 1492 t["self"] = t 1493 return t 1494 end 1495 abi.register(r)` 1496 1497 tx := NewLuaTxCall("ktlee", "r", 0, `{"Name":"r"}`) 1498 err = bc.ConnectBlock( 1499 NewLuaTxAccount("ktlee", 100), 1500 NewLuaTxDef("ktlee", "r", 0, definition), 1501 tx, 1502 ) 1503 if err == nil { 1504 t.Error(err) 1505 } 1506 if err.Error() != `nested table error` { 1507 t.Errorf("contract Call ret error :%s", err.Error()) 1508 } 1509 } 1510 1511 func TestContractCall(t *testing.T) { 1512 definition1 := ` 1513 function constructor(init) 1514 system.setItem("count", init) 1515 end 1516 function inc() 1517 count = system.getItem("count") 1518 system.setItem("count", count + 1) 1519 return count 1520 end 1521 1522 function get() 1523 return system.getItem("count") 1524 end 1525 1526 function set(val) 1527 system.setItem("count", val) 1528 end 1529 abi.register(inc,get,set) 1530 ` 1531 1532 bc, err := LoadDummyChain() 1533 if err != nil { 1534 t.Errorf("failed to create test database: %v", err) 1535 } 1536 defer bc.Release() 1537 1538 err = bc.ConnectBlock( 1539 NewLuaTxAccount("ktlee", 100), 1540 NewLuaTxDef("ktlee", "counter", 0, definition1).Constructor("[1]"), 1541 NewLuaTxCall("ktlee", "counter", 0, `{"Name":"inc", "Args":[]}`), 1542 ) 1543 if err != nil { 1544 t.Error(err) 1545 } 1546 1547 err = bc.Query("counter", `{"Name":"get", "Args":[]}`, "", "2") 1548 if err != nil { 1549 t.Error(err) 1550 } 1551 1552 definition2 := ` 1553 function constructor(addr) 1554 system.setItem("count", 99) 1555 system.setItem("addr", addr) 1556 end 1557 function add(amount) 1558 return contract.call.value(amount)(system.getItem("addr"), "inc") 1559 end 1560 function dadd() 1561 return contract.delegatecall(system.getItem("addr"), "inc") 1562 end 1563 function get() 1564 addr = system.getItem("addr") 1565 a = contract.call(addr, "get") 1566 return a 1567 end 1568 function dget() 1569 addr = system.getItem("addr") 1570 a = contract.delegatecall(addr, "get") 1571 return a 1572 end 1573 function set(val) 1574 contract.call(system.getItem("addr"), "set", val) 1575 end 1576 function dset(val) 1577 contract.delegatecall(system.getItem("addr"), "set", val) 1578 end 1579 abi.register(add,dadd, get, dget, set, dset) 1580 ` 1581 err = bc.ConnectBlock( 1582 NewLuaTxDef("ktlee", "caller", 0, definition2). 1583 Constructor(fmt.Sprintf(`["%s"]`, types.EncodeAddress(strHash("counter")))), 1584 NewLuaTxCall("ktlee", "caller", 0, `{"Name":"add", "Args":[]}`), 1585 ) 1586 if err != nil { 1587 t.Error(err) 1588 } 1589 err = bc.Query("caller", `{"Name":"get", "Args":[]}`, "", "3") 1590 if err != nil { 1591 t.Error(err) 1592 } 1593 err = bc.Query("caller", `{"Name":"dget", "Args":[]}`, "", "99") 1594 if err != nil { 1595 t.Error(err) 1596 } 1597 tx := NewLuaTxCall("ktlee", "caller", 0, `{"Name":"dadd", "Args":[]}`) 1598 _ = bc.ConnectBlock(tx) 1599 receipt := bc.getReceipt(tx.hash()) 1600 if receipt.GetRet() != `99` { 1601 t.Errorf("contract Call ret error :%s", receipt.GetRet()) 1602 } 1603 tx = NewLuaTxCall("ktlee", "caller", 0, `{"Name":"dadd", "Args":[]}`) 1604 _ = bc.ConnectBlock(tx) 1605 receipt = bc.getReceipt(tx.hash()) 1606 if receipt.GetRet() != `100` { 1607 t.Errorf("contract Call ret error :%s", receipt.GetRet()) 1608 } 1609 err = bc.Query("caller", `{"Name":"get", "Args":[]}`, "", "3") 1610 if err != nil { 1611 t.Error(err) 1612 } 1613 } 1614 1615 func TestSparseTable(t *testing.T) { 1616 bc, err := LoadDummyChain() 1617 if err != nil { 1618 t.Errorf("failed to create test database: %v", err) 1619 } 1620 defer bc.Release() 1621 1622 definition := ` 1623 function is_table_equal(t1,t2,ignore_mt) 1624 local ty1 = type(t1) 1625 local ty2 = type(t2) 1626 if ty1 ~= ty2 then return false end 1627 -- non-table types can be directly compared 1628 if ty1 ~= 'table' and ty2 ~= 'table' then return t1 == t2 end 1629 -- as well as tables which have the metamethod __eq 1630 local mt = getmetatable(t1) 1631 if not ignore_mt and mt and mt.__eq then return t1 == t2 end 1632 for k1,v1 in pairs(t1) do 1633 local v2 = t2[k1] 1634 if v2 == nil or not is_table_equal(v1,v2) then return false end 1635 end 1636 for k2,v2 in pairs(t2) do 1637 local v1 = t1[k2] 1638 if v1 == nil or not is_table_equal(v1,v2) then return false end 1639 end 1640 return true 1641 end 1642 1643 function r() 1644 local t = {} 1645 t[10000] = "1234" 1646 system.setItem("k", t) 1647 k = system.getItem("k") 1648 if is_table_equal(t, k, false) then 1649 return 1 1650 end 1651 return 0 1652 end 1653 abi.register(r)` 1654 1655 tx := NewLuaTxCall("ktlee", "r", 0, `{"Name":"r"}`) 1656 err = bc.ConnectBlock( 1657 NewLuaTxAccount("ktlee", 100), 1658 NewLuaTxDef("ktlee", "r", 0, definition), 1659 tx, 1660 ) 1661 if err != nil { 1662 t.Error(err) 1663 } 1664 receipt := bc.getReceipt(tx.hash()) 1665 if receipt.GetRet() != `1` { 1666 t.Errorf("contract Call ret error :%s", receipt.GetRet()) 1667 } 1668 } 1669 1670 func TestKvstore(t *testing.T) { 1671 definition := ` 1672 state.var{ 1673 counts = state.map(), 1674 name = state.value() 1675 } 1676 1677 function inc(key) 1678 if counts[key] == nil then 1679 counts[key] = 0 1680 end 1681 counts[key] = counts[key] + 1 1682 end 1683 1684 function get(key) 1685 return counts[key] 1686 end 1687 1688 function set(key,val) 1689 counts[key] = val 1690 end 1691 1692 function setname(n) 1693 name:set(n) 1694 end 1695 1696 function getname() 1697 return name:get() 1698 end 1699 1700 abi.register(inc,get,set,setname,getname)` 1701 1702 bc, err := LoadDummyChain() 1703 if err != nil { 1704 t.Errorf("failed to create test database: %v", err) 1705 } 1706 defer bc.Release() 1707 1708 err = bc.ConnectBlock( 1709 NewLuaTxAccount("ktlee", 100), 1710 NewLuaTxDef("ktlee", "map", 0, definition), 1711 ) 1712 if err != nil { 1713 t.Error(err) 1714 } 1715 err = bc.ConnectBlock( 1716 NewLuaTxCall("ktlee", "map", 0, `{"Name":"inc", "Args":["ktlee"]}`), 1717 NewLuaTxCall("ktlee", "map", 0, `{"Name":"setname", "Args":["eve2adam"]}`), 1718 ) 1719 if err != nil { 1720 t.Error(err) 1721 } 1722 err = bc.ConnectBlock() 1723 if err != nil { 1724 t.Error(err) 1725 } 1726 1727 err = bc.Query("map", `{"Name":"get", "Args":["ktlee"]}`, "", "1") 1728 if err != nil { 1729 t.Error(err) 1730 } 1731 err = bc.Query("map", `{"Name":"get", "Args":["htwo"]}`, "", "{}") 1732 if err != nil { 1733 t.Error(err) 1734 } 1735 1736 err = bc.ConnectBlock( 1737 NewLuaTxCall("ktlee", "map", 0, `{"Name":"inc", "Args":["ktlee"]}`), 1738 NewLuaTxCall("ktlee", "map", 0, `{"Name":"inc", "Args":["htwo"]}`), 1739 NewLuaTxCall("ktlee", "map", 0, `{"Name":"set", "Args":["wook", 100]}`), 1740 ) 1741 if err != nil { 1742 t.Error(err) 1743 } 1744 1745 err = bc.Query("map", `{"Name":"get", "Args":["ktlee"]}`, "", "2") 1746 if err != nil { 1747 t.Error(err) 1748 } 1749 err = bc.Query("map", `{"Name":"get", "Args":["htwo"]}`, "", "1") 1750 if err != nil { 1751 t.Error(err) 1752 } 1753 err = bc.Query("map", `{"Name":"get", "Args":["wook"]}`, "", "100") 1754 if err != nil { 1755 t.Error(err) 1756 } 1757 err = bc.Query("map", `{"Name":"getname"}`, "", `"eve2adam"`) 1758 if err != nil { 1759 t.Error(err) 1760 } 1761 } 1762 1763 func TestJson(t *testing.T) { 1764 definition := ` 1765 state.var{ 1766 table = state.value() 1767 } 1768 1769 function set(val) 1770 table:set(json.decode(val)) 1771 end 1772 1773 function get() 1774 return table:get() 1775 end 1776 1777 function getenc() 1778 return json.encode(table:get()) 1779 end 1780 1781 function getlen() 1782 a = table:get() 1783 return a[1], string.len(a[1]) 1784 end 1785 1786 function getAmount() 1787 return system.getAmount() 1788 end 1789 1790 abi.register(set, get, getenc, getlen) 1791 abi.payable(getAmount)` 1792 1793 bc, err := LoadDummyChain() 1794 if err != nil { 1795 t.Errorf("failed to create test database: %v", err) 1796 } 1797 defer bc.Release() 1798 1799 err = bc.ConnectBlock( 1800 NewLuaTxAccount("ktlee", 100), 1801 NewLuaTxDef("ktlee", "json", 0, definition), 1802 ) 1803 if err != nil { 1804 t.Error(err) 1805 } 1806 err = bc.ConnectBlock( 1807 NewLuaTxCall("ktlee", "json", 0, `{"Name":"set", "Args":["[1,2,3]"]}`), 1808 ) 1809 if err != nil { 1810 t.Error(err) 1811 } 1812 err = bc.Query("json", `{"Name":"get", "Args":[]}`, "", "[1,2,3]") 1813 if err != nil { 1814 t.Error(err) 1815 } 1816 err = bc.Query("json", `{"Name":"getenc", "Args":[]}`, "", `"[1,2,3]"`) 1817 if err != nil { 1818 t.Error(err) 1819 } 1820 err = bc.ConnectBlock( 1821 NewLuaTxCall("ktlee", "json", 0, 1822 `{"Name":"set", "Args":["{\"key1\":[1,2,3], \"run\", \"key2\":5, [4,5,6]}"]}`), 1823 ) 1824 if err != nil { 1825 t.Error(err) 1826 } 1827 err = bc.Query("json", `{"Name":"get", "Args":[]}`, "", `{"1":"run","2":[4,5,6],"key1":[1,2,3],"key2":5}`) 1828 if err != nil { 1829 t.Error(err) 1830 } 1831 err = bc.Query("json", `{"Name":"getenc", "Args":[]}`, "", `"{\"1\":\"run\",\"2\":[4,5,6],\"key1\":[1,2,3],\"key2\":5}"`) 1832 if err != nil { 1833 t.Error(err) 1834 } 1835 err = bc.ConnectBlock( 1836 NewLuaTxCall("ktlee", "json", 0, 1837 `{"Name":"set", "Args":["{\"key1\":{\"arg1\": 1,\"arg2\":{}, \"arg3\":[]}, \"key2\":[5,4,3]}"]}`), 1838 ) 1839 if err != nil { 1840 t.Error(err) 1841 } 1842 err = bc.Query("json", `{"Name":"get", "Args":[]}`, "", `{"key1":{"arg1":1,"arg2":{},"arg3":{}},"key2":[5,4,3]}`) 1843 if err != nil { 1844 t.Error(err) 1845 } 1846 err = bc.Query("json", `{"Name":"getenc", "Args":[]}`, "", `"{\"key1\":{\"arg1\":1,\"arg2\":{},\"arg3\":{}},\"key2\":[5,4,3]}"`) 1847 if err != nil { 1848 t.Error(err) 1849 } 1850 err = bc.ConnectBlock( 1851 NewLuaTxCall("ktlee", "json", 0, 1852 `{"Name":"set", "Args":["{\"key1\":[1,2,3], \"key1\":5}"]}`), 1853 ) 1854 if err != nil { 1855 t.Error(err) 1856 } 1857 err = bc.Query("json", `{"Name":"get", "Args":[]}`, "", `{"key1":5}`) 1858 if err != nil { 1859 t.Error(err) 1860 } 1861 err = bc.ConnectBlock( 1862 NewLuaTxCall("ktlee", "json", 0, `{"Name":"set", "Args":["[\"\\\"hh\\t\",\"2\",3]"]}`), 1863 ) 1864 if err != nil { 1865 t.Error(err) 1866 } 1867 err = bc.Query("json", `{"Name":"get", "Args":[]}`, "", `["\"hh\u0009","2",3]`) 1868 if err != nil { 1869 t.Error(err) 1870 } 1871 err = bc.Query("json", `{"Name":"getlen", "Args":[]}`, "", `["\"hh\u0009",4]`) 1872 if err != nil { 1873 t.Error(err) 1874 } 1875 err = bc.Query("json", `{"Name":"getenc", "Args":[]}`, "", `"[\"\\\"hh\\u0009\",\"2\",3]"`) 1876 if err != nil { 1877 t.Error(err) 1878 } 1879 tx := NewLuaTxCall("ktlee", "json", 100, `{"Name":"getAmount"}`) 1880 err = bc.ConnectBlock(tx) 1881 if err != nil { 1882 t.Error(err) 1883 } 1884 receipt := bc.getReceipt(tx.hash()) 1885 if receipt.GetRet() != `"100"` { 1886 t.Errorf("contract Call ret error :%s", receipt.GetRet()) 1887 } 1888 err = bc.ConnectBlock( 1889 NewLuaTxCall("ktlee", "json", 0, 1890 `{"Name":"set", "Args":["{\"key1\":[1,2,3], \"key1\":5}}"]}`).Fail("not proper json format"), 1891 ) 1892 } 1893 1894 func TestArray(t *testing.T) { 1895 definition := ` 1896 state.var{ 1897 counts = state.array(10) 1898 } 1899 1900 function inc(key) 1901 if counts[key] == nil then 1902 counts[key] = 0 1903 end 1904 counts[key] = counts[key] + 1 1905 end 1906 1907 function get(key) 1908 return counts[key] 1909 end 1910 1911 function set(key,val) 1912 counts[key] = val 1913 end 1914 1915 function len() 1916 return counts:length() 1917 end 1918 1919 function iter() 1920 local rv = {} 1921 for i, v in counts:ipairs() do 1922 if v == nil then 1923 rv[i] = "nil" 1924 else 1925 rv[i] = v 1926 end 1927 end 1928 return rv 1929 end 1930 1931 abi.register(inc,get,set,len,iter)` 1932 1933 bc, err := LoadDummyChain() 1934 if err != nil { 1935 t.Errorf("failed to create test database: %v", err) 1936 } 1937 defer bc.Release() 1938 1939 err = bc.ConnectBlock( 1940 NewLuaTxAccount("ktlee", 100), 1941 NewLuaTxDef("ktlee", "array", 0, definition), 1942 ) 1943 if err != nil { 1944 t.Error(err) 1945 } 1946 err = bc.ConnectBlock( 1947 NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[1]}`), 1948 NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[0]}`).Fail("index out of range"), 1949 NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[1]}`), 1950 NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[1.00000001]}`).Fail("integer expected, got number"), 1951 NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":["1"]}`).Fail("integer expected, got string)"), 1952 NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[true]}`).Fail("integer expected, got boolean"), 1953 NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[[1, 2]]}`).Fail("integer expected, got table"), 1954 NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[null]}`).Fail("integer expected, got nil)"), 1955 NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[{}]}`).Fail("integer expected, got table)"), 1956 NewLuaTxCall("ktlee", "array", 0, `{"Name":"inc", "Args":[""]}`).Fail("integer expected, got string)"), 1957 NewLuaTxCall("ktlee", "array", 0, `{"Name":"set", "Args":[2,"ktlee"]}`), 1958 ) 1959 if err != nil { 1960 t.Error(err) 1961 } 1962 err = bc.Query("array", `{"Name":"get", "Args":[11]}`, "index out of range", "") 1963 if err != nil { 1964 t.Error(err) 1965 } 1966 err = bc.Query("array", `{"Name":"get", "Args":[1]}`, "", "2") 1967 if err != nil { 1968 t.Error(err) 1969 } 1970 err = bc.Query("array", `{"Name":"get", "Args":[2]}`, "", `"ktlee"`) 1971 if err != nil { 1972 t.Error(err) 1973 } 1974 err = bc.Query("array", `{"Name":"len"}`, "", `10`) 1975 if err != nil { 1976 t.Error(err) 1977 } 1978 err = bc.Query("array", `{"Name":"iter"}`, "", `[2,"ktlee","nil","nil","nil","nil","nil","nil","nil","nil"]`) 1979 if err != nil { 1980 t.Error(err) 1981 } 1982 overflow := ` 1983 state.var{ 1984 counts = state.array(1000000000000) 1985 } 1986 1987 function get() 1988 return "hello" 1989 end 1990 1991 abi.register(get) 1992 ` 1993 err = bc.ConnectBlock( 1994 NewLuaTxDef("ktlee", "overflow", 0, overflow), 1995 ) 1996 errMsg := "integer expected, got number" 1997 if err == nil { 1998 t.Errorf("expected: '%s', but got: nil", errMsg) 1999 } else if !strings.Contains(err.Error(), errMsg) { 2000 t.Errorf("expected: %s, but got: %s", errMsg, err.Error()) 2001 } 2002 } 2003 2004 func TestPcall(t *testing.T) { 2005 definition1 := ` 2006 function constructor(init) 2007 system.setItem("count", init) 2008 end 2009 2010 function init() 2011 db.exec([[create table if not exists r ( 2012 id integer primary key 2013 , n integer check(n >= 10) 2014 , nonull text not null 2015 , only integer unique) 2016 ]]) 2017 db.exec("insert into r values (1, 11, 'text', 1)") 2018 end 2019 2020 function pkins1() 2021 db.exec("insert into r values (3, 12, 'text', 2)") 2022 db.exec("insert into r values (1, 12, 'text', 2)") 2023 end 2024 2025 function pkins2() 2026 db.exec("insert into r values (4, 12, 'text', 2)") 2027 end 2028 2029 function pkget() 2030 local rs = db.query("select count(*) from r") 2031 if rs:next() then 2032 local n = rs:get() 2033 --rs:next() 2034 return n 2035 else 2036 return "error in count()" 2037 end 2038 end 2039 2040 function inc() 2041 count = system.getItem("count") 2042 system.setItem("count", count + 1) 2043 return count 2044 end 2045 2046 function get() 2047 return system.getItem("count") 2048 end 2049 2050 function getOrigin() 2051 return system.getOrigin() 2052 end 2053 2054 function set(val) 2055 system.setItem("count", val) 2056 end 2057 abi.register(inc,get,set, init, pkins1, pkins2, pkget, getOrigin) 2058 abi.payable(constructor, inc) 2059 ` 2060 2061 bc, err := LoadDummyChain() 2062 if err != nil { 2063 t.Errorf("failed to create test database: %v", err) 2064 } 2065 defer bc.Release() 2066 2067 err = bc.ConnectBlock( 2068 NewLuaTxAccount("ktlee", 100), 2069 NewLuaTxDef("ktlee", "counter", 10, definition1).Constructor("[0]"), 2070 NewLuaTxCall("ktlee", "counter", 15, `{"Name":"inc", "Args":[]}`), 2071 ) 2072 2073 err = bc.Query("counter", `{"Name":"get", "Args":[]}`, "", "1") 2074 if err != nil { 2075 t.Error(err) 2076 } 2077 2078 definition2 := ` 2079 function constructor(addr) 2080 system.setItem("count", 99) 2081 system.setItem("addr", addr) 2082 end 2083 function add(amount) 2084 first = contract.call.value(amount)(system.getItem("addr"), "inc") 2085 status, res = contract.pcall(contract.call.value(1000000), system.getItem("addr"), "inc") 2086 if status == false then 2087 return first 2088 end 2089 return res 2090 end 2091 function dadd() 2092 return contract.delegatecall(system.getItem("addr"), "inc") 2093 end 2094 function get() 2095 addr = system.getItem("addr") 2096 a = contract.call(addr, "get") 2097 return a 2098 end 2099 function dget() 2100 addr = system.getItem("addr") 2101 a = contract.delegatecall(addr, "get") 2102 return a 2103 end 2104 function send(addr, amount) 2105 contract.send(addr, amount) 2106 status, res = contract.pcall(contract.call.value(1000000000)(system.getItem("addr"), "inc")) 2107 return status 2108 end 2109 function sql() 2110 contract.call(system.getItem("addr"), "init") 2111 contract.pcall(contract.call, system.getItem("addr"), "pkins1") 2112 contract.call(system.getItem("addr"), "pkins2") 2113 end 2114 2115 function sqlget() 2116 return contract.call(system.getItem("addr"), "pkget") 2117 end 2118 2119 function getOrigin() 2120 return contract.call(system.getItem("addr"), "getOrigin") 2121 end 2122 abi.register(add, dadd, get, dget, send, sql, sqlget, getOrigin) 2123 abi.payable(constructor,add) 2124 ` 2125 err = bc.ConnectBlock( 2126 NewLuaTxDef("ktlee", "caller", 10, definition2). 2127 Constructor(fmt.Sprintf(`["%s"]`, types.EncodeAddress(strHash("counter")))), 2128 NewLuaTxCall("ktlee", "caller", 15, `{"Name":"add", "Args":[]}`), 2129 NewLuaTxCall("ktlee", "caller", 0, `{"Name":"sql", "Args":[]}`), 2130 ) 2131 if err != nil { 2132 t.Error(err) 2133 } 2134 err = bc.Query("caller", `{"Name":"get", "Args":[]}`, "", "2") 2135 if err != nil { 2136 t.Error(err) 2137 } 2138 err = bc.Query("caller", `{"Name":"sqlget", "Args":[]}`, "", "2") 2139 if err != nil { 2140 t.Error(err) 2141 } 2142 2143 tx := NewLuaTxCall("ktlee", "caller", 0, `{"Name":"getOrigin", "Args":[]}`) 2144 _ = bc.ConnectBlock(tx) 2145 receipt := bc.getReceipt(tx.hash()) 2146 if receipt.GetRet() != "\""+types.EncodeAddress(strHash("ktlee"))+"\"" { 2147 t.Errorf("contract Call ret error :%s", receipt.GetRet()) 2148 } 2149 2150 definition3 := ` 2151 function pass(addr) 2152 contract.send(addr, 1) 2153 end 2154 2155 function add(addr, a, b) 2156 system.setItem("arg", a) 2157 contract.pcall(pass, addr) 2158 return a+b 2159 end 2160 2161 function set(addr) 2162 contract.send(addr, 1) 2163 system.setItem("arg", 2) 2164 status, ret = contract.pcall(add, addr, 1, 2) 2165 end 2166 2167 function set2(addr) 2168 contract.send(addr, 1) 2169 system.setItem("arg", 2) 2170 status, ret = contract.pcall(add, addar, 1) 2171 end 2172 2173 function get() 2174 return system.getItem("arg") 2175 end 2176 2177 function getBalance() 2178 return contract.balance() 2179 end 2180 2181 abi.register(set, set2, get, getBalance) 2182 abi.payable(set, set2) 2183 ` 2184 2185 bc, err = LoadDummyChain() 2186 if err != nil { 2187 t.Errorf("failed to create test database: %v", err) 2188 } 2189 defer bc.Release() 2190 2191 err = bc.ConnectBlock( 2192 NewLuaTxAccount("ktlee", 100), 2193 NewLuaTxAccount("bong", 0), 2194 NewLuaTxDef("ktlee", "counter", 0, definition3), 2195 ) 2196 if err != nil { 2197 t.Error(err) 2198 } 2199 tx = NewLuaTxCall("ktlee", "counter", 20, 2200 fmt.Sprintf(`{"Name":"set", "Args":["%s"]}`, types.EncodeAddress(strHash("bong")))) 2201 err = bc.ConnectBlock(tx) 2202 if err != nil { 2203 t.Error(err) 2204 } 2205 err = bc.Query("counter", `{"Name":"get", "Args":[]}`, "", "1") 2206 if err != nil { 2207 t.Error(err) 2208 } 2209 err = bc.Query("counter", `{"Name":"getBalance", "Args":[]}`, "", "\"18\"") 2210 if err != nil { 2211 t.Error(err) 2212 } 2213 state, err := bc.GetAccountState("bong") 2214 if state.GetBalanceBigInt().Uint64() != 2 { 2215 t.Error("balance error") 2216 } 2217 tx = NewLuaTxCall("ktlee", "counter", 10, 2218 fmt.Sprintf(`{"Name":"set2", "Args":["%s"]}`, types.EncodeAddress(strHash("bong")))) 2219 err = bc.ConnectBlock(tx) 2220 if err != nil { 2221 t.Error(err) 2222 } 2223 err = bc.Query("counter", `{"Name":"get", "Args":[]}`, "", "2") 2224 if err != nil { 2225 t.Error(err) 2226 } 2227 state, err = bc.GetAccountState("bong") 2228 if state.GetBalanceBigInt().Uint64() != 3 { 2229 t.Error("balance error") 2230 } 2231 } 2232 2233 func TestPingpongCall(t *testing.T) { 2234 definition1 := ` 2235 function constructor() 2236 system.setItem("key", "empty") 2237 end 2238 function start(addr) 2239 system.setItem("key", "start") 2240 contract.call(addr, "called") 2241 end 2242 2243 function callback() 2244 system.setItem("key", "callback") 2245 end 2246 2247 function get() 2248 return system.getItem("key") 2249 end 2250 2251 abi.register(start, callback, get) 2252 ` 2253 2254 bc, err := LoadDummyChain() 2255 if err != nil { 2256 t.Errorf("failed to create test database: %v", err) 2257 } 2258 defer bc.Release() 2259 2260 err = bc.ConnectBlock( 2261 NewLuaTxAccount("ktlee", 100), 2262 NewLuaTxDef("ktlee", "a", 0, definition1), 2263 ) 2264 2265 definition2 := ` 2266 function constructor(addr) 2267 system.setItem("key", "empty") 2268 system.setItem("addr", addr) 2269 end 2270 2271 function called() 2272 system.setItem("key", "called") 2273 contract.call(system.getItem("addr"), "callback") 2274 end 2275 2276 function get() 2277 return system.getItem("key") 2278 end 2279 2280 abi.register(called, get) 2281 ` 2282 err = bc.ConnectBlock( 2283 NewLuaTxDef("ktlee", "b", 0, definition2). 2284 Constructor(fmt.Sprintf(`["%s"]`, types.EncodeAddress(strHash("a")))), 2285 ) 2286 if err != nil { 2287 t.Error(err) 2288 } 2289 tx := NewLuaTxCall("ktlee", "a", 0, 2290 fmt.Sprintf(`{"Name":"start", "Args":["%s"]}`, types.EncodeAddress(strHash("b")))) 2291 _ = bc.ConnectBlock(tx) 2292 err = bc.Query("a", `{"Name":"get", "Args":[]}`, "", `"callback"`) 2293 if err != nil { 2294 t.Error(err) 2295 } 2296 err = bc.Query("b", `{"Name":"get", "Args":[]}`, "", `"called"`) 2297 if err != nil { 2298 t.Error(err) 2299 } 2300 } 2301 2302 func TestArrayArg(t *testing.T) { 2303 definition1 := ` 2304 function copy(arr) 2305 assert(type(arr) == "table", "table expected") 2306 local rv = {} 2307 for i, v in ipairs(arr) do 2308 table.insert(rv, i, v) 2309 end 2310 return rv 2311 end 2312 function two_arr(arr1, arr2) 2313 assert(type(arr1) == "table", "table expected") 2314 assert(type(arr2) == "table", "table expected") 2315 local rv = {} 2316 table.insert(rv, 1, #arr1) 2317 table.insert(rv, 2, #arr2) 2318 return rv 2319 end 2320 function mixed_args(arr1, map1, n) 2321 assert(type(arr1) == "table", "table expected") 2322 assert(type(map1) == "table", "table expected") 2323 local rv = {} 2324 table.insert(rv, 1, arr1) 2325 table.insert(rv, 2, map1) 2326 table.insert(rv, 3, n) 2327 return rv 2328 end 2329 2330 abi.register(copy, two_arr, mixed_args) 2331 ` 2332 2333 bc, err := LoadDummyChain() 2334 if err != nil { 2335 t.Errorf("failed to create test database: %v", err) 2336 } 2337 defer bc.Release() 2338 2339 err = bc.ConnectBlock( 2340 NewLuaTxAccount("ktlee", 100), 2341 NewLuaTxDef("ktlee", "a", 0, definition1), 2342 ) 2343 if err != nil { 2344 t.Error(err) 2345 } 2346 err = bc.Query("a", `{"Name": "copy", "Args":[1, 2, 3]}`, "table expected", "") 2347 if err != nil { 2348 t.Error(err) 2349 } 2350 err = bc.Query("a", `{"Name": "copy", "Args":[[1, 2, 3]]}`, "", "[1,2,3]") 2351 if err != nil { 2352 t.Error(err) 2353 } 2354 err = bc.Query("a", `{"Name": "two_arr", "Args":[[1, 2, 3],[4, 5]]}`, "", "[3,2]") 2355 if err != nil { 2356 t.Error(err) 2357 } 2358 err = bc.Query("a", `{"Name": "mixed_args", "Args":[[1, 2, 3], {"name": "kslee", "age": 39}, 7]}`, 2359 "", 2360 `[[1,2,3],{"age":39,"name":"kslee"},7]`, 2361 ) 2362 if err != nil { 2363 t.Error(err) 2364 } 2365 err = bc.Query("a", `{"Name": "mixed_args", "Args":[ 2366 [[1, 2, 3],["first", "second"]], 2367 {"name": "kslee", "age": 39, "address": {"state": "XXX-do", "city": "YYY-si"}}, 2368 "end" 2369 ]}`, 2370 "", 2371 `[[[1,2,3],["first","second"]],{"address":{"city":"YYY-si","state":"XXX-do"},"age":39,"name":"kslee"},"end"]`, 2372 ) 2373 if err != nil { 2374 t.Error(err) 2375 } 2376 err = bc.Query("a", `{"Name": "mixed_args", "Args":[ 2377 [{"name": "wook", "age": 50}, {"name": "hook", "age": 42}], 2378 {"name": "kslee", "age": 39, "scores": [10, 20, 30, 40, 50]}, 2379 "hmm..." 2380 ]}`, 2381 "", 2382 `[[{"age":50,"name":"wook"},{"age":42,"name":"hook"}],{"age":39,"name":"kslee","scores":[10,20,30,40,50]},"hmm..."]`, 2383 ) 2384 if err != nil { 2385 t.Error(err) 2386 } 2387 } 2388 2389 func TestAbi(t *testing.T) { 2390 errMsg := "no exported functions" 2391 2392 noAbi := ` 2393 function dummy() 2394 system.print("dummy") 2395 end` 2396 2397 bc, err := LoadDummyChain() 2398 if err != nil { 2399 t.Errorf("failed to create test database: %v", err) 2400 } 2401 defer bc.Release() 2402 2403 err = bc.ConnectBlock( 2404 NewLuaTxAccount("ktlee", 100), 2405 NewLuaTxDef("ktlee", "a", 0, noAbi), 2406 ) 2407 if err == nil { 2408 t.Errorf("expected: %s, but got: nil", errMsg) 2409 } else if !strings.Contains(err.Error(), "no exported functions") { 2410 t.Errorf("expected: %s, but got: %s", errMsg, err.Error()) 2411 } 2412 2413 empty := ` 2414 function dummy() 2415 system.print("dummy") 2416 end 2417 abi.register()` 2418 2419 err = bc.ConnectBlock( 2420 NewLuaTxDef("ktlee", "a", 0, empty), 2421 ) 2422 if err == nil { 2423 t.Errorf("expected: %s, but got: nil", errMsg) 2424 } else if !strings.Contains(err.Error(), "no exported functions.") { 2425 t.Errorf("expected: %s, but got: %s", errMsg, err.Error()) 2426 } 2427 2428 localFunc := ` 2429 function dummy() 2430 system.print("dummy") 2431 end 2432 local function helper() 2433 system.print("helper") 2434 end 2435 abi.register(helper)` 2436 2437 err = bc.ConnectBlock( 2438 NewLuaTxDef("ktlee", "a", 0, localFunc), 2439 ) 2440 if err == nil { 2441 t.Errorf("expected: %s, but got: nil", errMsg) 2442 } else if !strings.Contains(err.Error(), "global function expected") { 2443 t.Errorf("expected: %s, but got: %s", errMsg, err.Error()) 2444 } 2445 } 2446 2447 func TestMapKey(t *testing.T) { 2448 definition := ` 2449 state.var{ 2450 counts = state.map() 2451 } 2452 function setCount(key, value) 2453 counts[key] = value 2454 end 2455 function getCount(key) 2456 return counts[key] 2457 end 2458 function delCount(key) 2459 counts:delete(key) 2460 end 2461 abi.register(setCount, getCount, delCount) 2462 ` 2463 bc, err := LoadDummyChain() 2464 if err != nil { 2465 t.Errorf("failed to create test database: %v", err) 2466 } 2467 defer bc.Release() 2468 2469 _ = bc.ConnectBlock( 2470 NewLuaTxAccount("ktlee", 100), 2471 NewLuaTxDef("ktlee", "a", 0, definition), 2472 ) 2473 2474 err = bc.Query("a", `{"Name":"getCount", "Args":[1]}`, "", "{}") 2475 if err != nil { 2476 t.Error(err) 2477 } 2478 2479 err = bc.ConnectBlock( 2480 NewLuaTxCall("ktlee", "a", 0, `{"Name":"setCount", "Args":[1, 10]}`), 2481 NewLuaTxCall("ktlee", "a", 0, `{"Name":"setCount", "Args":["1", 20]}`).Fail("(number expected, got string)"), 2482 NewLuaTxCall("ktlee", "a", 0, `{"Name":"setCount", "Args":[1.1, 30]}`), 2483 ) 2484 if err != nil { 2485 t.Error(err) 2486 } 2487 err = bc.Query("a", `{"Name":"getCount", "Args":["1"]}`, "(number expected, got string)", "") 2488 if err != nil { 2489 t.Error(err) 2490 } 2491 err = bc.Query("a", `{"Name":"getCount", "Args":[1]}`, "", "10") 2492 if err != nil { 2493 t.Error(err) 2494 } 2495 err = bc.Query("a", `{"Name":"getCount", "Args":[1.1]}`, "", "30") 2496 if err != nil { 2497 t.Error(err) 2498 } 2499 err = bc.ConnectBlock( 2500 NewLuaTxCall("ktlee", "a", 0, 2501 `{"Name":"setCount", "Args":[true, 40]}`, 2502 ).Fail(`invalid key type: 'boolean', state.map: 'counts'`), 2503 ) 2504 if err != nil { 2505 t.Error(err) 2506 } 2507 err = bc.ConnectBlock( 2508 NewLuaTxCall("ktlee", "a", 0, `{"Name":"delCount", "Args":[1.1]}`), 2509 ) 2510 if err != nil { 2511 t.Error(err) 2512 } 2513 err = bc.Query("a", `{"Name":"getCount", "Args":[1.1]}`, "", "{}") 2514 if err != nil { 2515 t.Error(err) 2516 } 2517 err = bc.Query("a", `{"Name":"getCount", "Args":[2]}`, "", "{}") 2518 if err != nil { 2519 t.Error(err) 2520 } 2521 2522 _ = bc.ConnectBlock( 2523 NewLuaTxDef("ktlee", "x", 0, definition), 2524 ) 2525 err = bc.ConnectBlock( 2526 NewLuaTxCall("ktlee", "x", 0, `{"Name":"setCount", "Args":["1", 10]}`), 2527 NewLuaTxCall("ktlee", "x", 0, `{"Name":"setCount", "Args":[1, 20]}`).Fail("string expected, got number)"), 2528 NewLuaTxCall("ktlee", "x", 0, `{"Name":"setCount", "Args":["third", 30]}`), 2529 ) 2530 if err != nil { 2531 t.Error(err) 2532 } 2533 err = bc.Query("x", `{"Name":"getCount", "Args":["1"]}`, "", "10") 2534 if err != nil { 2535 t.Error(err) 2536 } 2537 err = bc.Query("x", `{"Name":"getCount", "Args":["third"]}`, "", "30") 2538 if err != nil { 2539 t.Error(err) 2540 } 2541 } 2542 2543 func TestStateVarFieldUpdate(t *testing.T) { 2544 src := ` 2545 state.var{ 2546 Person = state.value() 2547 } 2548 2549 function constructor() 2550 Person:set({ name = "kslee", age = 38, address = "blahblah..." }) 2551 end 2552 2553 function InvalidUpdateAge(age) 2554 Person:get().age = age 2555 end 2556 2557 function ValidUpdateAge(age) 2558 local p = Person:get() 2559 p.age = age 2560 Person:set(p) 2561 end 2562 2563 function GetPerson() 2564 return Person:get() 2565 end 2566 2567 abi.register(InvalidUpdateAge, ValidUpdateAge, GetPerson) 2568 ` 2569 bc, err := LoadDummyChain() 2570 if err != nil { 2571 t.Errorf("failed to create test database: %v", err) 2572 } 2573 defer bc.Release() 2574 2575 err = bc.ConnectBlock( 2576 NewLuaTxAccount("ktlee", 100), 2577 NewLuaTxDef("ktlee", "c", 0, src), 2578 ) 2579 if err != nil { 2580 t.Error(err) 2581 } 2582 err = bc.ConnectBlock( 2583 NewLuaTxCall("ktlee", "c", 0, `{"Name":"InvalidUpdateAge", "Args":[10]}`), 2584 ) 2585 if err != nil { 2586 t.Error(err) 2587 } 2588 err = bc.Query("c", `{"Name":"GetPerson"}`, "", 2589 `{"address":"blahblah...","age":38,"name":"kslee"}`, 2590 ) 2591 if err != nil { 2592 t.Error(err) 2593 } 2594 err = bc.ConnectBlock( 2595 NewLuaTxCall("ktlee", "c", 0, `{"Name":"ValidUpdateAge", "Args":[10]}`), 2596 ) 2597 if err != nil { 2598 t.Error(err) 2599 } 2600 err = bc.Query("c", `{"Name":"GetPerson"}`, "", 2601 `{"address":"blahblah...","age":10,"name":"kslee"}`, 2602 ) 2603 if err != nil { 2604 t.Error(err) 2605 } 2606 } 2607 2608 func TestDatetime(t *testing.T) { 2609 src := ` 2610 state.var { 2611 cdate = state.value() 2612 } 2613 2614 function constructor() 2615 cdate:set(906000490) 2616 end 2617 2618 function CreateDate() 2619 return system.date("%c", cdate:get()) 2620 end 2621 2622 function Extract(fmt) 2623 return system.date(fmt, cdate:get()) 2624 end 2625 2626 function Difftime() 2627 system.print(system.date("%c", cdate:get())) 2628 s = system.date("*t", cdate:get()) 2629 system.print(s) 2630 s.hour = 2 2631 s.min = 0 2632 s.sec = 0 2633 system.print(system.date("*t", system.time(s))) 2634 return system.difftime(cdate:get(), system.time(s)) 2635 end 2636 2637 abi.register(CreateDate, Extract, Difftime) 2638 ` 2639 bc, err := LoadDummyChain() 2640 if err != nil { 2641 t.Errorf("failed to create test database: %v", err) 2642 } 2643 defer bc.Release() 2644 2645 err = bc.ConnectBlock( 2646 NewLuaTxAccount("ktlee", 100), 2647 NewLuaTxDef("ktlee", "datetime", 0, src), 2648 ) 2649 if err != nil { 2650 t.Error(err) 2651 } 2652 err = bc.Query("datetime", `{"Name": "CreateDate"}`, "", `"1998-09-17 02:48:10"`) 2653 if err != nil { 2654 t.Error(err) 2655 } 2656 err = bc.Query("datetime", `{"Name": "Extract", "Args":["%x"]}`, "", `"09/17/98"`) 2657 if err != nil { 2658 t.Error(err) 2659 } 2660 err = bc.Query("datetime", `{"Name": "Extract", "Args":["%X"]}`, "", `"02:48:10"`) 2661 if err != nil { 2662 t.Error(err) 2663 } 2664 err = bc.Query("datetime", `{"Name": "Extract", "Args":["%A"]}`, "", `"Thursday"`) 2665 if err != nil { 2666 t.Error(err) 2667 } 2668 err = bc.Query("datetime", `{"Name": "Extract", "Args":["%I:%M:%S %p"]}`, "", `"02:48:10 AM"`) 2669 if err != nil { 2670 t.Error(err) 2671 } 2672 err = bc.Query("datetime", `{"Name": "Difftime"}`, "", `2890`) 2673 if err != nil { 2674 t.Error(err) 2675 } 2676 } 2677 2678 func TestDynamicArray(t *testing.T) { 2679 zeroLen := ` 2680 state.var { 2681 fixedArray = state.array(0) 2682 } 2683 2684 function Length() 2685 return fixedArray:length() 2686 end 2687 2688 abi.register(Length) 2689 ` 2690 bc, err := LoadDummyChain() 2691 if err != nil { 2692 t.Errorf("failed to create test database: %v", err) 2693 } 2694 defer bc.Release() 2695 2696 _ = bc.ConnectBlock( 2697 NewLuaTxAccount("ktlee", 100), 2698 ) 2699 err = bc.ConnectBlock( 2700 NewLuaTxDef("ktlee", "zeroLen", 0, zeroLen), 2701 ) 2702 if err == nil { 2703 t.Error("expected: the array length must be greater than zero") 2704 } 2705 if !strings.Contains(err.Error(), "the array length must be greater than zero") { 2706 t.Errorf(err.Error()) 2707 } 2708 2709 dArr := ` 2710 state.var { 2711 dArr = state.array() 2712 } 2713 2714 function Append(val) 2715 dArr:append(val) 2716 end 2717 2718 function Get(idx) 2719 return dArr[idx] 2720 end 2721 2722 function Set(idx, val) 2723 dArr[idx] = val 2724 end 2725 2726 function Length() 2727 return dArr:length() 2728 end 2729 2730 abi.register(Append, Get, Set, Length) 2731 ` 2732 tx := NewLuaTxDef("ktlee", "dArr", 0, dArr) 2733 err = bc.ConnectBlock(tx) 2734 if err != nil { 2735 t.Error(err) 2736 } 2737 err = bc.Query("dArr", `{"Name": "Length"}`, "", "0") 2738 if err != nil { 2739 t.Error(err) 2740 } 2741 err = bc.ConnectBlock( 2742 NewLuaTxCall("ktlee", "dArr", 0, `{"Name": "Append", "Args": [10]}`), 2743 NewLuaTxCall("ktlee", "dArr", 0, `{"Name": "Append", "Args": [20]}`), 2744 ) 2745 if err != nil { 2746 t.Error(err) 2747 } 2748 err = bc.Query("dArr", `{"Name": "Get", "Args": [1]}`, "", "10") 2749 if err != nil { 2750 t.Error(err) 2751 } 2752 err = bc.Query("dArr", `{"Name": "Get", "Args": [2]}`, "", "20") 2753 if err != nil { 2754 t.Error(err) 2755 } 2756 err = bc.Query("dArr", `{"Name": "Get", "Args": [3]}`, "index out of range", "") 2757 if err != nil { 2758 t.Error(err) 2759 } 2760 err = bc.Query("dArr", `{"Name": "Length"}`, "", "2") 2761 if err != nil { 2762 t.Error(err) 2763 } 2764 err = bc.ConnectBlock( 2765 NewLuaTxCall("ktlee", "dArr", 0, `{"Name": "Append", "Args": [30]}`), 2766 NewLuaTxCall("ktlee", "dArr", 0, `{"Name": "Append", "Args": [40]}`), 2767 ) 2768 err = bc.Query("dArr", `{"Name": "Length"}`, "", "4") 2769 if err != nil { 2770 t.Error(err) 2771 } 2772 err = bc.ConnectBlock( 2773 NewLuaTxCall("ktlee", "dArr", 0, `{"Name": "Set", "Args": [3, 50]}`), 2774 ) 2775 err = bc.Query("dArr", `{"Name": "Get", "Args": [3]}`, "", "50") 2776 if err != nil { 2777 t.Error(err) 2778 } 2779 } 2780 2781 func TestDupVar(t *testing.T) { 2782 dupVar := ` 2783 state.var{ 2784 Var1 = state.value(), 2785 } 2786 function GetVar1() 2787 return Var1:get() 2788 end 2789 state.var{ 2790 Var1 = state.value(), 2791 } 2792 abi.register(GetVar1) 2793 ` 2794 bc, err := LoadDummyChain() 2795 if err != nil { 2796 t.Errorf("failed to create test database: %v", err) 2797 } 2798 defer bc.Release() 2799 2800 err = bc.ConnectBlock( 2801 NewLuaTxAccount("ktlee", 100), 2802 NewLuaTxDef("ktlee", "dupVar", 0, dupVar), 2803 ) 2804 if err == nil { 2805 t.Error("duplicated variable: 'Var1'") 2806 } 2807 if !strings.Contains(err.Error(), "duplicated variable: 'Var1'") { 2808 t.Error(err) 2809 } 2810 2811 dupVar = ` 2812 state.var{ 2813 Var1 = state.value(), 2814 } 2815 function GetVar1() 2816 return Var1:get() 2817 end 2818 function Work() 2819 state.var{ 2820 Var1 = state.value(), 2821 } 2822 end 2823 abi.register(GetVar1, Work) 2824 ` 2825 err = bc.ConnectBlock( 2826 NewLuaTxDef("ktlee", "dupVar1", 0, dupVar), 2827 ) 2828 if err != nil { 2829 t.Error(err) 2830 } 2831 err = bc.ConnectBlock( 2832 NewLuaTxCall("ktlee", "dupVar1", 0, `{"Name": "Work"}`).Fail("duplicated variable: 'Var1'"), 2833 ) 2834 2835 if err != nil { 2836 t.Error(err) 2837 } 2838 } 2839 2840 func TestCrypto(t *testing.T) { 2841 src := ` 2842 function get(a) 2843 return crypto.sha256(a) 2844 end 2845 2846 function checkEther() 2847 return crypto.ecverify("0xce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008", 2848 "0x90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc9301", 2849 "0xbcf9061f21320aa7e824b00d0152398b2d7a6e44") 2850 end 2851 2852 function checkAergo() 2853 return crypto.ecverify("11e96f2b58622a0ce815b81f94da04ae7a17ba17602feb1fd5afa4b9f2467960", 2854 "304402202e6d5664a87c2e29856bf8ff8b47caf44169a2a4a135edd459640be5b1b6ef8102200d8ea1f6f9ecdb7b520cdb3cc6816d773df47a1820d43adb4b74fb879fb27402", 2855 "AmPbWrQbtQrCaJqLWdMtfk2KiN83m2HFpBbQQSTxqqchVv58o82i") 2856 end 2857 2858 function keccak256(s) 2859 return crypto.keccak256(s) 2860 end 2861 2862 abi.register(get, checkEther, checkAergo, keccak256) 2863 ` 2864 bc, err := LoadDummyChain() 2865 if err != nil { 2866 t.Errorf("failed to create test database: %v", err) 2867 } 2868 defer bc.Release() 2869 2870 err = bc.ConnectBlock( 2871 NewLuaTxAccount("ktlee", 100), 2872 NewLuaTxDef("ktlee", "crypto", 0, src), 2873 ) 2874 err = bc.Query("crypto", `{"Name": "get", "Args" : ["ab\u0000\u442a"]}`, "", `"0xc58f6dca13e4bba90a326d8605042862fe87c63a64a9dd0e95608a2ee68dc6f0"`) 2875 if err != nil { 2876 t.Error(err) 2877 } 2878 err = bc.Query("crypto", `{"Name": "get", "Args" : ["0x616200e490aa"]}`, "", `"0xc58f6dca13e4bba90a326d8605042862fe87c63a64a9dd0e95608a2ee68dc6f0"`) 2879 if err != nil { 2880 t.Error(err) 2881 } 2882 err = bc.Query("crypto", `{"Name": "checkEther", "Args" : []}`, "", `true`) 2883 if err != nil { 2884 t.Error(err) 2885 } 2886 2887 err = bc.Query("crypto", `{"Name": "checkAergo", "Args" : []}`, "", `true`) 2888 if err != nil { 2889 t.Error(err) 2890 } 2891 2892 err = bc.Query( 2893 "crypto", 2894 `{"Name": "keccak256", "Args" : ["0x616263"]}`, 2895 "", 2896 `"0x4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45"`) 2897 if err != nil { 2898 t.Error(err) 2899 } 2900 2901 err = bc.Query( 2902 "crypto", 2903 `{"Name": "keccak256", "Args" : ["0x616572676F"]}`, 2904 "", 2905 `"0xe98bb03ab37161f8bbfe131f711dcccf3002a9cd9ec31bbd52edf181f7ab09a0"`) 2906 if err != nil { 2907 t.Error(err) 2908 } 2909 } 2910 2911 func TestPayable(t *testing.T) { 2912 src := ` 2913 state.var { 2914 Data = state.value() 2915 } 2916 function save(data) 2917 Data:set(data) 2918 end 2919 function load() 2920 return Data:get() 2921 end 2922 2923 abi.register(load) 2924 abi.payable(save) 2925 ` 2926 bc, err := LoadDummyChain() 2927 if err != nil { 2928 t.Errorf("failed to create test database: %v", err) 2929 } 2930 defer bc.Release() 2931 2932 err = bc.ConnectBlock( 2933 NewLuaTxAccount("ktlee", 100), 2934 ) 2935 2936 err = bc.ConnectBlock( 2937 NewLuaTxDef("ktlee", "payable", 1, src), 2938 ) 2939 if err == nil { 2940 t.Error("expected: 'constructor' is not payable") 2941 } else { 2942 if !strings.Contains(err.Error(), "'constructor' is not payable") { 2943 t.Error(err) 2944 } 2945 } 2946 err = bc.ConnectBlock( 2947 NewLuaTxCall("ktlee", "payable", 0, `{"Name":"save", "Args": ["blahblah"]}`).Fail("not found contract"), 2948 ) 2949 if err != nil { 2950 t.Error(err) 2951 } 2952 err = bc.ConnectBlock( 2953 NewLuaTxDef("ktlee", "payable", 0, src), 2954 NewLuaTxCall("ktlee", "payable", 0, `{"Name":"save", "Args": ["blahblah"]}`), 2955 ) 2956 if err != nil { 2957 t.Error(err) 2958 } 2959 err = bc.Query("payable", `{"Name":"load"}`, "", `"blahblah"`) 2960 if err != nil { 2961 t.Error(err) 2962 } 2963 err = bc.ConnectBlock( 2964 NewLuaTxCall("ktlee", "payable", 1, `{"Name":"save", "Args": ["payed"]}`), 2965 ) 2966 if err != nil { 2967 t.Error(err) 2968 } 2969 err = bc.Query("payable", `{"Name":"load"}`, "", `"payed"`) 2970 if err != nil { 2971 t.Error(err) 2972 } 2973 } 2974 2975 func TestDefault(t *testing.T) { 2976 src := ` 2977 function default() 2978 return "default" 2979 end 2980 abi.register(default) 2981 ` 2982 bc, err := LoadDummyChain() 2983 if err != nil { 2984 t.Errorf("failed to create test database: %v", err) 2985 } 2986 defer bc.Release() 2987 2988 err = bc.ConnectBlock( 2989 NewLuaTxAccount("ktlee", 100), 2990 NewLuaTxDef("ktlee", "default", 0, src), 2991 ) 2992 if err != nil { 2993 t.Error(err) 2994 } 2995 tx := NewLuaTxCall("ktlee", "default", 0, "") 2996 err = bc.ConnectBlock(tx) 2997 receipt := bc.getReceipt(tx.hash()) 2998 if receipt.GetRet() != `"default"` { 2999 t.Errorf("contract Call ret error :%s", receipt.GetRet()) 3000 } 3001 err = bc.ConnectBlock( 3002 NewLuaTxCall("ktlee", "default", 1, "").Fail(`'default' is not payable`), 3003 ) 3004 if err != nil { 3005 t.Error(err) 3006 } 3007 err = bc.Query("default", `{"Name":"a"}`, "not found function: a", "") 3008 if err != nil { 3009 t.Error(err) 3010 } 3011 } 3012 3013 func TestBignum(t *testing.T) { 3014 bigNum := ` 3015 function test(addr) 3016 bal = contract.balance() 3017 contract.send(addr, bal / 2) 3018 return contract.balance() 3019 end 3020 3021 function sendS(addr) 3022 contract.send(addr, "1 gaer 99999") 3023 return contract.balance() 3024 end 3025 3026 function testBignum() 3027 bg = bignum.number("999999999999999999999999999999") 3028 system.setItem("big", bg) 3029 bi = system.getItem("big") 3030 return tostring(bi) 3031 end 3032 3033 function argBignum(a) 3034 b = a + 1 3035 return tostring(b) 3036 end 3037 3038 function calladdBignum(addr, a) 3039 return tostring(contract.call(addr, "add", a, 2) + 3) 3040 end 3041 3042 function checkBignum() 3043 a = 1 3044 b = bignum.number(1) 3045 3046 return bignum.isbignum(a), bignum.isbignum(b), bignum.isbignum("2333") 3047 end 3048 function calcBignum() 3049 bg1 = bignum.number("999999999999999999999999999999") 3050 bg2 = bignum.number("999999999999999999999999999999") 3051 bg3 = bg1 + bg2 3052 bg4 = bg1 * 2 3053 bg5 = 2 * bg1 3054 n1 = 999999999999999 3055 system.print(n1) 3056 bg6 = bignum.number(n1) 3057 assert (bg3 == bg4 and bg4 == bg5) 3058 bg5 = bg1 - bg3 3059 assert (bignum.isneg(bg5) and bg5 == bignum.neg(bg1)) 3060 system.print(bg3, bg5, bg6) 3061 bg6 = bignum.number(1) 3062 assert (bg6 > bg5) 3063 a = bignum.number(2) 3064 b = bignum.number(8) 3065 pow = a ^ b 3066 system.print(pow, a, b) 3067 assert(pow == bignum.number(256) and a == bignum.number(2) and b == bignum.number(8)) 3068 assert(bignum.compare(bg6, 1) == 0) 3069 system.print((bg6 == 1), bignum.isbignum(pow)) 3070 div1 = bignum.number(3)/2 3071 assert(bignum.compare(div1, 1) == 0) 3072 div = bg6 / 0 3073 end 3074 3075 function negativeBignum() 3076 bg1 = bignum.number("-2") 3077 bg2 = bignum.sqrt(bg1) 3078 end 3079 3080 function byteBignum() 3081 state.var { 3082 value = state.value() 3083 } 3084 value = bignum.tobyte(bignum.number("177")) 3085 return bignum.frombyte(value) 3086 end 3087 3088 function constructor() 3089 end 3090 3091 abi.register(test, sendS, testBignum, argBignum, calladdBignum, checkBignum, calcBignum, negativeBignum, byteBignum) 3092 abi.payable(constructor) 3093 ` 3094 callee := ` 3095 function add(a, b) 3096 return a + b 3097 end 3098 abi.register(add) 3099 ` 3100 3101 bc, err := LoadDummyChain() 3102 if err != nil { 3103 t.Errorf("failed to create test database: %v", err) 3104 } 3105 defer bc.Release() 3106 3107 err = bc.ConnectBlock( 3108 NewLuaTxAccount("ktlee", 1000000000000), 3109 NewLuaTxDef("ktlee", "bigNum", 50000000000, bigNum), 3110 NewLuaTxDef("ktlee", "add", 0, callee), 3111 ) 3112 if err != nil { 3113 t.Error(err) 3114 } 3115 tx := NewLuaTxCall("ktlee", "bigNum", 0, fmt.Sprintf(`{"Name":"test", "Args":["%s"]}`, types.EncodeAddress(strHash("ktlee")))) 3116 err = bc.ConnectBlock(tx) 3117 if err != nil { 3118 t.Error(err) 3119 } 3120 receipt := bc.getReceipt(tx.hash()) 3121 if receipt.GetRet() != `"25000000000"` { 3122 t.Errorf("contract Call ret error :%s", receipt.GetRet()) 3123 } 3124 tx = NewLuaTxCall("ktlee", "bigNum", 0, fmt.Sprintf(`{"Name":"sendS", "Args":["%s"]}`, types.EncodeAddress(strHash("ktlee")))) 3125 err = bc.ConnectBlock(tx) 3126 if err != nil { 3127 t.Error(err) 3128 } 3129 receipt = bc.getReceipt(tx.hash()) 3130 if receipt.GetRet() != `"23999900001"` { 3131 t.Errorf("contract Call ret error :%s", receipt.GetRet()) 3132 } 3133 tx = NewLuaTxCall("ktlee", "bigNum", 0, `{"Name":"testBignum", "Args":[]}`) 3134 err = bc.ConnectBlock(tx) 3135 if err != nil { 3136 t.Error(err) 3137 } 3138 receipt = bc.getReceipt(tx.hash()) 3139 if receipt.GetRet() != `"999999999999999999999999999999"` { 3140 t.Errorf("contract Call ret error :%s", receipt.GetRet()) 3141 } 3142 err = bc.Query("bigNum", `{"Name":"argBignum", "Args":[{"_bignum":"99999999999999999999999999"}]}`, "", `"100000000000000000000000000"`) 3143 if err != nil { 3144 t.Error(err) 3145 } 3146 err = bc.Query("bigNum", fmt.Sprintf(`{"Name":"calladdBignum", "Args":["%s", {"_bignum":"999999999999999999"}]}`, types.EncodeAddress(strHash("add"))), "", `"1000000000000000004"`) 3147 if err != nil { 3148 t.Error(err) 3149 } 3150 err = bc.Query("bigNum", `{"Name":"checkBignum"}`, "", `[false,true,false]`) 3151 if err != nil { 3152 t.Error(err) 3153 } 3154 err = bc.Query("bigNum", `{"Name":"calcBignum"}`, "bignum divide by zero", "") 3155 if err != nil { 3156 t.Error(err) 3157 } 3158 err = bc.Query("bigNum", `{"Name":"negativeBignum"}`, "bignum not allowed negative value", "") 3159 if err != nil { 3160 t.Error(err) 3161 } 3162 err = bc.Query("bigNum", `{"Name":"byteBignum"}`, "", `{"_bignum":"177"}`) 3163 if err != nil { 3164 t.Error(err) 3165 } 3166 } 3167 3168 func TestDeploy(t *testing.T) { 3169 deploy := ` 3170 function hello() 3171 hello = [[ 3172 function hello(say) 3173 return "Hello " .. say 3174 end 3175 3176 local type_check = {} 3177 function type_check.isValidAddress(address) 3178 -- check existence of invalid alphabets 3179 if nil ~= string.match(address, '[^123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]') then 3180 return false 3181 end 3182 -- check lenght is in range 3183 if 52 ~= string.len(address) then 3184 return false 3185 end 3186 -- TODO add checksum verification? 3187 return true 3188 end 3189 function type_check.isValidNumber(value) 3190 if nil ~= string.match(value, '[^0123456789]') then 3191 return false 3192 end 3193 return true 3194 end 3195 3196 -- The a bridge token is a mintable and burnable token controlled by 3197 -- the bridge contract. It represents all tokens locked on the other side of the 3198 -- bridge with a 1:1 ratio. 3199 -- This contract is depoyed by the merkle bridge when a new type of token 3200 -- is transfered 3201 state.var { 3202 Symbol = state.value(), 3203 Name = state.value(), 3204 Decimals = state.value(), 3205 TotalSupply = state.value(), 3206 Balances = state.map(), 3207 Nonces = state.map(), 3208 -- Contract ID is a unique id that cannot be shared by another contract, even one on a sidechain 3209 -- This is neeeded for replay protection of signed transfer, because users might have the same private key 3210 -- on different sidechains 3211 ContractID = state.value(), 3212 Owner = state.value(), 3213 } 3214 3215 function constructor() 3216 Symbol:set("TOKEN") 3217 Name:set("Standard Token on Aergo") 3218 Decimals:set(18) 3219 TotalSupply:set(bignum.number(0)) 3220 Owner:set(system.getSender()) 3221 -- contractID is the hash of system.getContractID (prevent replay between contracts on the same chain) and system.getPrevBlockHash (prevent replay between sidechains). 3222 -- take the first 16 bytes to save size of signed message 3223 local id = crypto.sha256(system.getContractID()..system.getPrevBlockHash()) 3224 id = string.sub(id, 3, 32) 3225 ContractID:set(id) 3226 return true 3227 end 3228 3229 --------------------------------------- 3230 -- Transfer sender's token to target 'to' 3231 -- @type call 3232 -- @param to a target address 3233 -- @param value string amount of tokens to send 3234 -- @return success 3235 --------------------------------------- 3236 function transfer(to, value) 3237 assert(type_check.isValidNumber(value), "invalid value format (must be string)") 3238 assert(type_check.isValidAddress(to), "invalid address format: " .. to) 3239 local from = system.getSender() 3240 local bvalue = bignum.number(value) 3241 local b0 = bignum.number(0) 3242 assert(bvalue > b0, "invalid value") 3243 assert(to ~= from, "same sender and receiver") 3244 assert(Balances[from] and bvalue <= Balances[from], "not enough balance") 3245 Balances[from] = Balances[from] - bvalue 3246 Nonces[from] = (Nonces[from] or 0) + 1 3247 Balances[to] = (Balances[to] or b0) + bvalue 3248 -- TODO event notification 3249 return true 3250 end 3251 3252 --------------------------------------- 3253 -- Transfer tokens according to signed data from the owner 3254 -- @type call 3255 -- @param from sender's address 3256 -- @param to receiver's address 3257 -- @param value string amount of token to send in aer 3258 -- @param nonce nonce of the sender to prevent replay 3259 -- @param fee string fee given to the tx broadcaster 3260 -- @param deadline block number before which the tx can be executed 3261 -- @param signature signature proving sender's consent 3262 -- @return success 3263 --------------------------------------- 3264 function signed_transfer(from, to, value, nonce, signature, fee, deadline) 3265 assert(type_check.isValidNumber(value), "invalid value format (must be string)") 3266 assert(type_check.isValidNumber(fee), "invalid fee format (must be string)") 3267 local bfee = bignum.number(fee) 3268 local bvalue = bignum.number(value) 3269 local b0 = bignum.number(0) 3270 -- check addresses 3271 assert(type_check.isValidAddress(to), "invalid address format: " .. to) 3272 assert(type_check.isValidAddress(from), "invalid address format: " .. from) 3273 assert(to ~= from, "same sender and receiver") 3274 -- check amounts, fee 3275 assert(bfee >= b0, "fee must be positive") 3276 assert(bvalue >= b0, "value must be positive") 3277 assert(Balances[from] and (bvalue+bfee) <= Balances[from], "not enough balance") 3278 -- check deadline 3279 assert(deadline == 0 or system.getBlockheight() < deadline, "deadline has passed") 3280 -- check nonce 3281 if Nonces[from] == nil then Nonces[from] = 0 end 3282 assert(Nonces[from] == nonce, "nonce is invalid or already spent") 3283 -- construct signed transfer and verifiy signature 3284 data = crypto.sha256(to..bignum.tostring(bvalue)..tostring(nonce)..bignum.tostring(bfee)..tostring(deadline)..ContractID:get()) 3285 assert(crypto.ecverify(data, signature, from), "signature of signed transfer is invalid") 3286 -- execute transfer 3287 Balances[from] = Balances[from] - bvalue - bfee 3288 Balances[to] = (Balances[to] or b0) + bvalue 3289 Balances[system.getOrigin()] = (Balances[system.getOrigin()] or b0) + bfee 3290 Nonces[from] = Nonces[from] + 1 3291 -- TODO event notification 3292 return true 3293 end 3294 3295 3296 --------------------------------------- 3297 -- mint, burn and signed_burn are specific to the token contract controlled by 3298 -- the merkle bridge contract and representing transfered assets. 3299 --------------------------------------- 3300 3301 --------------------------------------- 3302 -- Mint tokens to 'to' 3303 -- @type call 3304 -- @param to a target address 3305 -- @param value string amount of token to mint 3306 -- @return success 3307 --------------------------------------- 3308 function mint(to, value) 3309 assert(system.getSender() == Owner:get(), "Only bridge contract can mint") 3310 assert(type_check.isValidNumber(value), "invalid value format (must be string)") 3311 local bvalue = bignum.number(value) 3312 local b0 = bignum.number(0) 3313 assert(type_check.isValidAddress(to), "invalid address format: " .. to) 3314 local new_total = TotalSupply:get() + bvalue 3315 TotalSupply:set(new_total) 3316 Balances[to] = (Balances[to] or b0) + bvalue; 3317 -- TODO event notification 3318 return true 3319 end 3320 3321 --------------------------------------- 3322 -- burn the tokens of 'from' 3323 -- @type call 3324 -- @param from a target address 3325 -- @param value an amount of token to send 3326 -- @return success 3327 --------------------------------------- 3328 function burn(from, value) 3329 assert(system.getSender() == Owner:get(), "Only bridge contract can burn") 3330 assert(type_check.isValidNumber(value), "invalid value format (must be string)") 3331 local bvalue = bignum.number(value) 3332 local b0 = bignum.number(0) 3333 assert(type_check.isValidAddress(from), "invalid address format: " ..from) 3334 assert(Balances[from] and bvalue <= Balances[from], "Not enough funds to burn") 3335 new_total = TotalSupply:get() - bvalue 3336 TotalSupply:set(new_total) 3337 Balances[from] = Balances[from] - bvalue 3338 -- TODO event notification 3339 return true 3340 end 3341 3342 --------------------------------------- 3343 -- signed_burn the tokens of 'from' according to signed data from the owner 3344 -- @type call 3345 -- @param from a target address 3346 -- @param value an amount of token to send 3347 -- @param nonce nonce of the sender to prevent replay 3348 -- @param fee string fee given to the tx broadcaster 3349 -- @param deadline block number before which the tx can be executed 3350 -- @param signature signature proving sender's consent 3351 -- @return success 3352 --------------------------------------- 3353 function signed_burn(from, value, nonce, signature, fee, deadline) 3354 assert(system.getSender() == Owner:get(), "Only bridge contract can burn") 3355 assert(type_check.isValidNumber(value), "invalid value format (must be string)") 3356 assert(type_check.isValidNumber(fee), "invalid fee format (must be string)") 3357 local bfee = bignum.number(fee) 3358 local bvalue = bignum.number(value) 3359 local b0 = bignum.number(0) 3360 -- check addresses 3361 assert(type_check.isValidAddress(from), "invalid address format: " .. from) 3362 -- check amounts, fee 3363 assert(bfee >= b0, "fee must be positive") 3364 assert(bvalue >= b0, "value must be positive") 3365 assert(Balances[from] and (bvalue+bfee) <= Balances[from], "not enough balance") 3366 -- check deadline 3367 assert(deadline == 0 or system.getBlockheight() < deadline, "deadline has passed") 3368 -- check nonce 3369 if Nonces[from] == nil then Nonces[from] = 0 end 3370 assert(Nonces[from] == nonce, "nonce is invalid or already spent") 3371 -- construct signed transfer and verifiy signature 3372 data = crypto.sha256(system.getSender()..bignum.tostring(bvalue)..tostring(nonce)..bignum.tostring(bfee)..tostring(deadline)..ContractID:get()) 3373 assert(crypto.ecverify(data, signature, from), "signature of signed transfer is invalid") 3374 -- execute burn 3375 new_total = TotalSupply:get() - bvalue 3376 TotalSupply:set(new_total) 3377 Balances[from] = Balances[from] - bvalue - bfee 3378 Balances[system.getOrigin()] = (Balances[system.getOrigin()] or b0) + bfee 3379 Nonces[from] = Nonces[from] + 1 3380 -- TODO event notification 3381 return true 3382 end 3383 3384 3385 -- register functions to abi 3386 abi.register(transfer, signed_transfer, mint, burn, signed_burn, hello) 3387 ]] 3388 addr = contract.deploy(hello) 3389 ret = contract.call(addr, "hello", "world") 3390 return addr, ret 3391 end 3392 3393 function helloQuery(addr) 3394 return contract.call(addr, "hello", "world") 3395 end 3396 3397 function testConst() 3398 src = [[ 3399 function hello(say, key) 3400 return "Hello " .. say .. system.getItem(key) 3401 end 3402 function constructor(key, item) 3403 system.setItem(key, item) 3404 return key, item 3405 end 3406 abi.register(hello) 3407 abi.payable(constructor) 3408 ]] 3409 addr, key, item = contract.deploy.value(100)(src, "key", 2) 3410 ret = contract.call(addr, "hello", "world", "key") 3411 return addr, ret 3412 end 3413 3414 function testFail() 3415 src = [[ 3416 function hello(say, key) 3417 return "Hello " .. say .. system.getItem(key) 3418 end 3419 function constructor() 3420 end 3421 abi.register(hello) 3422 ]] 3423 addr = contract.deploy.value(100)(src) 3424 return addr 3425 end 3426 3427 paddr = nil 3428 function deploy() 3429 src = [[ 3430 function hello(say, key) 3431 return "Hello " .. say .. system.getItem(key) 3432 end 3433 function getcre() 3434 return system.getCreator() 3435 end 3436 function constructor() 3437 end 3438 abi.register(hello, getcre) 3439 ]] 3440 paddr = contract.deploy(src) 3441 system.print("addr :", paddr) 3442 ret = contract.call(paddr, "hello", "world", "key") 3443 end 3444 3445 function testPcall() 3446 ret = contract.pcall(deploy) 3447 return contract.call(paddr, "getcre") 3448 end 3449 function constructor() 3450 end 3451 3452 abi.register(hello, helloQuery, testConst, testFail, testPcall) 3453 abi.payable(constructor) 3454 ` 3455 bc, err := LoadDummyChain() 3456 if err != nil { 3457 t.Errorf("failed to create test database: %v", err) 3458 } 3459 defer bc.Release() 3460 3461 err = bc.ConnectBlock( 3462 NewLuaTxAccount("ktlee", 1000000000000), 3463 NewLuaTxDef("ktlee", "deploy", 50000000000, deploy), 3464 ) 3465 if err != nil { 3466 t.Error(err) 3467 } 3468 tx := NewLuaTxCall("ktlee", "deploy", 0, `{"Name":"hello"}`) 3469 err = bc.ConnectBlock(tx) 3470 if err != nil { 3471 t.Error(err) 3472 } 3473 receipt := bc.getReceipt(tx.hash()) 3474 if receipt.GetRet() != `["AmgKtCaGjH4XkXwny2Jb1YH5gdsJGJh78ibWEgLmRWBS5LMfQuTf","Hello world"]` { 3475 t.Errorf("contract Call ret error :%s", receipt.GetRet()) 3476 } 3477 err = bc.Query("deploy", `{"Name":"helloQuery", "Args":["AmgKtCaGjH4XkXwny2Jb1YH5gdsJGJh78ibWEgLmRWBS5LMfQuTf"]}`, "", `"Hello world"`) 3478 if err != nil { 3479 t.Error(err) 3480 } 3481 tx = NewLuaTxCall("ktlee", "deploy", 0, `{"Name":"testConst"}`) 3482 err = bc.ConnectBlock(tx) 3483 receipt = bc.getReceipt(tx.hash()) 3484 if receipt.GetRet() != `["Amhmj6kKZz7mPstBAPJWRe1e8RHP7bZ5pV35XatqTHMWeAVSyMkc","Hello world2"]` { 3485 t.Errorf("contract Call ret error :%s", receipt.GetRet()) 3486 } 3487 deployAcc, err := bc.GetAccountState("deploy") 3488 if err != nil { 3489 t.Error(err) 3490 } 3491 if deployAcc.GetBalanceBigInt().Uint64() != uint64(49999999900) { 3492 t.Error(deployAcc.GetBalanceBigInt().Uint64()) 3493 } 3494 tx = NewLuaTxCall("ktlee", "deploy", 0, `{"Name":"testFail"}`) 3495 err = bc.ConnectBlock(tx) 3496 deployAcc, err = bc.GetAccountState("deploy") 3497 if err != nil && deployAcc.Nonce == 2 { 3498 t.Error(err) 3499 } 3500 tx = NewLuaTxCall("ktlee", "deploy", 0, `{"Name":"testPcall"}`) 3501 err = bc.ConnectBlock(tx) 3502 deployAcc, err = bc.GetAccountState("deploy") 3503 if err != nil && deployAcc.Nonce == 2 { 3504 t.Error(err) 3505 } 3506 receipt = bc.getReceipt(tx.hash()) 3507 if receipt.GetRet() != `` { 3508 t.Errorf("contract Call ret error :%s", receipt.GetRet()) 3509 } 3510 } 3511 3512 func TestSqlVmPubNet(t *testing.T) { 3513 flushLState := func() { 3514 for i := 0; i <= MAX_LSTATE_SIZE; i++ { 3515 s := GetLState() 3516 FreeLState(s) 3517 } 3518 } 3519 PubNet = true 3520 flushLState() 3521 defer func() { 3522 PubNet = false 3523 flushLState() 3524 }() 3525 3526 bc, err := LoadDummyChain() 3527 if err != nil { 3528 t.Errorf("failed to create test database: %v", err) 3529 } 3530 defer bc.Release() 3531 3532 definition := ` 3533 function createAndInsert() 3534 db.exec("create table if not exists dual(dummy char(1))") 3535 db.exec("insert into dual values ('X')") 3536 local insertYZ = db.prepare("insert into dual values (?),(?)") 3537 insertYZ:exec("Y", "Z") 3538 end 3539 abi.register(createAndInsert)` 3540 3541 err = bc.ConnectBlock( 3542 NewLuaTxAccount("ktlee", 100), 3543 NewLuaTxDef("ktlee", "simple-query", 0, definition), 3544 ) 3545 if err != nil { 3546 t.Error(err) 3547 } 3548 3549 err = bc.ConnectBlock( 3550 NewLuaTxCall("ktlee", "simple-query", 0, `{"Name": "createAndInsert", "Args":[]}`).Fail(`attempt to index global 'db'`), 3551 ) 3552 if err != nil { 3553 t.Error(err) 3554 } 3555 } 3556 3557 func TestReturnUData(t *testing.T) { 3558 bc, err := LoadDummyChain() 3559 if err != nil { 3560 t.Errorf("failed to create test database: %v", err) 3561 } 3562 defer bc.Release() 3563 3564 definition := ` 3565 function test_die() 3566 return contract.call(system.getContractID(), "return_object") 3567 end 3568 function return_object() 3569 return db.query("select 1") 3570 end 3571 abi.register(test_die, return_object)` 3572 3573 err = bc.ConnectBlock( 3574 NewLuaTxAccount("ktlee", 100), 3575 NewLuaTxDef("ktlee", "rs-return", 0, definition), 3576 ) 3577 if err != nil { 3578 t.Error(err) 3579 } 3580 3581 err = bc.ConnectBlock( 3582 NewLuaTxCall("ktlee", "rs-return", 0, `{"Name": "test_die", "Args":[]}`).Fail(`unsupport type: userdata`), 3583 ) 3584 if err != nil { 3585 t.Error(err) 3586 } 3587 } 3588 3589 func checkRandomIntValue(v string, min, max int) error { 3590 n, _ := strconv.Atoi(v) 3591 if n < min || n > max { 3592 return errors.New("out of range") 3593 } 3594 return nil 3595 } 3596 3597 func TestRandom(t *testing.T) { 3598 bc, err := LoadDummyChain() 3599 if err != nil { 3600 t.Errorf("failed to create test database: %v", err) 3601 } 3602 defer bc.Release() 3603 3604 random := ` 3605 function random(...) 3606 return system.random(...) 3607 end 3608 abi.register(random)` 3609 3610 err = bc.ConnectBlock( 3611 NewLuaTxAccount("ktlee", 100), 3612 NewLuaTxDef("ktlee", "random", 0, random), 3613 ) 3614 if err != nil { 3615 t.Error(err) 3616 } 3617 err = bc.ConnectBlock( 3618 NewLuaTxCall("ktlee", "random", 0, `{"Name": "random", "Args":[]}`).Fail( 3619 "1 or 2 arguments required", 3620 ), 3621 ) 3622 if err != nil { 3623 t.Error(err) 3624 } 3625 3626 err = bc.ConnectBlock( 3627 NewLuaTxCall( 3628 "ktlee", 3629 "random", 3630 0, 3631 `{"Name": "random", "Args":[0]}`).Fail("the maximum value must be greater than zero"), 3632 ) 3633 if err != nil { 3634 t.Error(err) 3635 } 3636 3637 tx := NewLuaTxCall("ktlee", "random", 0, `{"Name": "random", "Args":[3]}`) 3638 err = bc.ConnectBlock(tx) 3639 if err != nil { 3640 t.Error(err) 3641 } 3642 receipt := bc.getReceipt(tx.hash()) 3643 err = checkRandomIntValue(receipt.GetRet(), 1, 3) 3644 if err != nil { 3645 t.Errorf("error: %s, return value: %s", err.Error(), receipt.GetRet()) 3646 } 3647 3648 tx = NewLuaTxCall("ktlee", "random", 0, `{"Name": "random", "Args":[3, 10]}`) 3649 err = bc.ConnectBlock(tx) 3650 receipt = bc.getReceipt(tx.hash()) 3651 err = checkRandomIntValue(receipt.GetRet(), 3, 10) 3652 if err != nil { 3653 t.Errorf("error: %s, return value: %s", err.Error(), receipt.GetRet()) 3654 } 3655 3656 err = bc.Query("random", `{"Name": "random", "Args":[1]}`, "", "1") 3657 if err != nil { 3658 t.Error(err) 3659 } 3660 err = bc.Query("random", `{"Name": "random", "Args":[4,4]}`, "", "4") 3661 if err != nil { 3662 t.Error(err) 3663 } 3664 err = bc.Query("random", `{"Name": "random", "Args":[0,4]}`, "system.random: the minimum value must be greater than zero", "") 3665 if err != nil { 3666 t.Error(err) 3667 } 3668 err = bc.Query("random", `{"Name": "random", "Args":[3,1]}`, "system.random: the maximum value must be greater than the minimum value", "") 3669 if err != nil { 3670 t.Error(err) 3671 } 3672 } 3673 3674 func TestBigTable(t *testing.T) { 3675 bc, err := LoadDummyChain() 3676 if err != nil { 3677 t.Errorf("failed to create test database: %v", err) 3678 } 3679 defer bc.Release() 3680 3681 bigSrc := ` 3682 function constructor() 3683 db.exec("create table if not exists table1 (cid integer PRIMARY KEY, rgtime datetime)") 3684 db.exec("insert into table1 (rgtime) values (datetime('2018-10-30 16:00:00'))") 3685 end 3686 3687 function inserts(n) 3688 for i = 1, n do 3689 db.exec("insert into table1 (rgtime) select rgtime from table1") 3690 end 3691 end 3692 3693 abi.register(inserts) 3694 ` 3695 3696 err = bc.ConnectBlock( 3697 NewLuaTxAccount("ktlee", 100), 3698 NewLuaTxDef("ktlee", "big", 0, bigSrc), 3699 ) 3700 if err != nil { 3701 t.Error(err) 3702 } 3703 3704 // About 900MB 3705 err = bc.ConnectBlock( 3706 NewLuaTxCall("ktlee", "big", 0, `{"Name": "inserts", "Args":[25]}`), 3707 ) 3708 if err != nil { 3709 t.Error(err) 3710 } 3711 3712 SetStateSQLMaxDBSize(20) 3713 3714 bigSrc = ` 3715 function constructor() 3716 db.exec("create table if not exists aergojdbc001 (name text, yyyymmdd text)") 3717 db.exec("insert into aergojdbc001 values ('홍길동', '20191007')") 3718 db.exec("insert into aergojdbc001 values ('홍길동', '20191007')") 3719 db.exec("insert into aergojdbc001 values ('홍길동', '20191007')") 3720 end 3721 3722 function inserts() 3723 db.exec("insert into aergojdbc001 select * from aergojdbc001") 3724 end 3725 3726 abi.register(inserts) 3727 ` 3728 3729 err = bc.ConnectBlock( 3730 NewLuaTxAccount("ktlee", 100), 3731 NewLuaTxDef("ktlee", "big20", 0, bigSrc), 3732 ) 3733 if err != nil { 3734 t.Error(err) 3735 } 3736 3737 for i := 0; i < 17; i++ { 3738 err = bc.ConnectBlock( 3739 NewLuaTxCall("ktlee", "big20", 0, `{"Name": "inserts"}`), 3740 ) 3741 if err != nil { 3742 t.Error(err) 3743 } 3744 } 3745 err = bc.ConnectBlock( 3746 NewLuaTxCall("ktlee", "big20", 0, `{"Name": "inserts"}`).Fail("database or disk is full"), 3747 ) 3748 if err != nil { 3749 t.Error(err) 3750 } 3751 } 3752 3753 func TestEvent(t *testing.T) { 3754 bc, err := LoadDummyChain() 3755 if err != nil { 3756 t.Errorf("failed to create test database: %v", err) 3757 } 3758 defer bc.Release() 3759 3760 definition := ` 3761 function test_ev() 3762 contract.event("ev1", 1,"local", 2, "form") 3763 contract.event("ev1", 3,"local", 4, "form") 3764 end 3765 abi.register(test_ev)` 3766 3767 err = bc.ConnectBlock( 3768 NewLuaTxAccount("ktlee", 100), 3769 NewLuaTxDef("ktlee", "event", 0, definition), 3770 ) 3771 if err != nil { 3772 t.Error(err) 3773 } 3774 err = bc.ConnectBlock( 3775 NewLuaTxCall("ktlee", "event", 0, `{"Name": "test_ev", "Args":[]}`), 3776 ) 3777 if err != nil { 3778 t.Error(err) 3779 } 3780 } 3781 3782 func TestView(t *testing.T) { 3783 bc, err := LoadDummyChain() 3784 if err != nil { 3785 t.Errorf("failed to create test database: %v", err) 3786 } 3787 defer bc.Release() 3788 3789 definition := ` 3790 function test_view() 3791 contract.event("ev1", 1,"local", 2, "form") 3792 contract.event("ev1", 3,"local", 4, "form") 3793 end 3794 function k() 3795 return 10 3796 end 3797 function tx_in_view_function() 3798 k2() 3799 end 3800 function k2() 3801 test_view() 3802 end 3803 function tx_after_view_function() 3804 k() 3805 contract.event("ev1", 1,"local", 2, "form") 3806 end 3807 abi.register(test_view, tx_after_view_function) 3808 abi.register_view(test_view, k, tx_in_view_function) 3809 ` 3810 3811 err = bc.ConnectBlock( 3812 NewLuaTxAccount("ktlee", 100), 3813 NewLuaTxDef("ktlee", "view", 0, definition), 3814 ) 3815 if err != nil { 3816 t.Error(err) 3817 } 3818 err = bc.ConnectBlock( 3819 NewLuaTxCall("ktlee", "view", 0, `{"Name": "test_view", "Args":[]}`).Fail("[Contract.Event] event not permitted in query"), 3820 ) 3821 if err != nil { 3822 t.Error(err) 3823 } 3824 err = bc.Query("view", `{"Name":"k", "Args":[]}`, "", "10") 3825 if err != nil { 3826 t.Error(err) 3827 } 3828 err = bc.ConnectBlock( 3829 NewLuaTxCall("ktlee", "view", 0, `{"Name": "tx_in_view_function", "Args":[]}`).Fail("[Contract.Event] event not permitted in query"), 3830 ) 3831 if err != nil { 3832 t.Error(err) 3833 } 3834 err = bc.ConnectBlock( 3835 NewLuaTxCall("ktlee", "view", 0, `{"Name": "tx_after_view_function", "Args":[]}`), 3836 ) 3837 if err != nil { 3838 t.Error(err) 3839 } 3840 } 3841 3842 func TestNsec(t *testing.T) { 3843 bc, err := LoadDummyChain() 3844 if err != nil { 3845 t.Errorf("failed to create test database: %v", err) 3846 } 3847 defer bc.Release() 3848 3849 definition := ` 3850 function test_nsec() 3851 system.print(nsec()) 3852 end 3853 abi.register(test_nsec)` 3854 3855 err = bc.ConnectBlock( 3856 NewLuaTxAccount("ktlee", 100), 3857 NewLuaTxDef("ktlee", "nsec", 0, definition), 3858 ) 3859 err = bc.ConnectBlock( 3860 NewLuaTxCall("ktlee", "nsec", 0, `{"Name": "test_nsec"}`).Fail(`attempt to call global 'nsec' (a nil value)`), 3861 ) 3862 if err != nil { 3863 t.Error(err) 3864 } 3865 } 3866 3867 func TestGovernance(t *testing.T) { 3868 bc, err := LoadDummyChain() 3869 if err != nil { 3870 t.Errorf("failed to create test database: %v", err) 3871 } 3872 defer bc.Release() 3873 3874 definition := ` 3875 function test_gov() 3876 contract.stake("10000 aergo") 3877 contract.vote("16Uiu2HAm2gtByd6DQu95jXURJXnS59Dyb9zTe16rDrcwKQaxma4p") 3878 end 3879 3880 function error_case() 3881 contract.stake("10000 aergo") 3882 assert(false) 3883 end 3884 3885 function test_pcall() 3886 return contract.pcall(error_case) 3887 end 3888 3889 abi.register(test_gov, test_pcall, error_case) 3890 abi.payable(test_gov, test_pcall) 3891 ` 3892 3893 err = bc.ConnectBlock( 3894 NewLuaTxAccount("ktlee", 100), 3895 NewLuaTxDef("ktlee", "gov", 0, definition), 3896 ) 3897 if err != nil { 3898 t.Error(err) 3899 } 3900 amount, _ := new(big.Int).SetString("10000000000000000000000", 10) 3901 err = bc.ConnectBlock( 3902 NewLuaTxCallBig("ktlee", "gov", amount, `{"Name": "test_gov", "Args":[]}`), 3903 ) 3904 if err != nil { 3905 t.Error(err) 3906 } 3907 oldstaking, err := bc.GetStaking("gov") 3908 if err != nil { 3909 t.Error(err) 3910 } 3911 oldgov, err := bc.GetAccountState("gov") 3912 if err != nil { 3913 t.Error(err) 3914 } 3915 tx := NewLuaTxCall("ktlee", "gov", 0, `{"Name": "test_pcall", "Args":[]}`) 3916 err = bc.ConnectBlock(tx) 3917 if err != nil { 3918 t.Error(err) 3919 } 3920 staking, err := bc.GetStaking("gov") 3921 if err != nil { 3922 t.Error(err) 3923 } 3924 gov, err := bc.GetAccountState("gov") 3925 if err != nil { 3926 t.Error(err) 3927 } 3928 3929 if bytes.Equal(oldstaking.Amount, staking.Amount) == false || 3930 bytes.Equal(oldgov.GetBalance(), gov.GetBalance()) == false { 3931 t.Error("pcall error") 3932 } 3933 tx = NewLuaTxCall("ktlee", "gov", 0, `{"Name": "error_case", "Args":[]}`) 3934 _ = bc.ConnectBlock(tx) 3935 newstaking, err := bc.GetStaking("gov") 3936 if err != nil { 3937 t.Error(err) 3938 } 3939 newgov, err := bc.GetAccountState("gov") 3940 if err != nil { 3941 t.Error(err) 3942 } 3943 if bytes.Equal(oldstaking.Amount, newstaking.Amount) == false || 3944 bytes.Equal(oldgov.GetBalance(), newgov.GetBalance()) == false { 3945 fmt.Println(new(big.Int).SetBytes(newstaking.Amount).String(), newgov.GetBalanceBigInt().String()) 3946 t.Error("pcall error") 3947 } 3948 } 3949 3950 func TestContractSend(t *testing.T) { 3951 bc, err := LoadDummyChain() 3952 if err != nil { 3953 t.Errorf("failed to create test database: %v", err) 3954 } 3955 defer bc.Release() 3956 3957 definition := ` 3958 function constructor() 3959 end 3960 function send(addr) 3961 contract.send(addr,1) 3962 end 3963 abi.register(send, constructor) 3964 abi.payable(constructor) 3965 ` 3966 definition2 := ` 3967 function default() 3968 system.print("default called") 3969 end 3970 abi.register(default) 3971 abi.payable(default) 3972 ` 3973 definition3 := ` 3974 function test() 3975 end 3976 abi.register(test) 3977 ` 3978 definition4 := ` 3979 function default() 3980 end 3981 abi.register(default) 3982 ` 3983 err = bc.ConnectBlock( 3984 NewLuaTxAccount("ktlee", 100), 3985 NewLuaTxDef("ktlee", "test1", 50, definition), 3986 NewLuaTxDef("ktlee", "test2", 0, definition2), 3987 NewLuaTxDef("ktlee", "test3", 0, definition3), 3988 NewLuaTxDef("ktlee", "test4", 0, definition4), 3989 ) 3990 if err != nil { 3991 t.Error(err) 3992 } 3993 err = bc.ConnectBlock( 3994 NewLuaTxCall("ktlee", "test1", 0, fmt.Sprintf(`{"Name":"send", "Args":["%s"]}`, types.EncodeAddress(strHash("test2")))), 3995 ) 3996 if err != nil { 3997 t.Error(err) 3998 } 3999 err = bc.ConnectBlock( 4000 NewLuaTxCall("ktlee", "test1", 0, fmt.Sprintf(`{"Name":"send", "Args":["%s"]}`, types.EncodeAddress(strHash("test3")))).Fail(`[Contract.LuaSendAmount] newExecutor error: not found function: default`), 4001 ) 4002 if err != nil { 4003 t.Error(err) 4004 } 4005 err = bc.ConnectBlock( 4006 NewLuaTxCall("ktlee", "test1", 0, fmt.Sprintf(`{"Name":"send", "Args":["%s"]}`, types.EncodeAddress(strHash("test4")))).Fail(`[Contract.LuaSendAmount] newExecutor error: 'default' is not payable`), 4007 ) 4008 if err != nil { 4009 t.Error(err) 4010 } 4011 4012 err = bc.ConnectBlock( 4013 NewLuaTxCall("ktlee", "test1", 0, fmt.Sprintf(`{"Name":"send", "Args":["%s"]}`, types.EncodeAddress(strHash("ktlee")))), 4014 ) 4015 if err != nil { 4016 t.Error(err) 4017 } 4018 } 4019 4020 func TestMaxMemSize(t *testing.T) { 4021 bc, err := LoadDummyChain() 4022 if err != nil { 4023 t.Errorf("failed to create test database: %v", err) 4024 } 4025 defer bc.Release() 4026 4027 definition := ` 4028 function oom() 4029 local s = "hello" 4030 4031 while 1 do 4032 s = s .. s 4033 end 4034 end 4035 4036 function p() 4037 pcall(oom) 4038 end 4039 4040 function cp() 4041 contract.pcall(oom) 4042 end 4043 abi.register(oom, p, cp)` 4044 4045 err = bc.ConnectBlock( 4046 NewLuaTxAccount("ktlee", 100), 4047 NewLuaTxDef("ktlee", "oom", 0, definition), 4048 ) 4049 err = bc.ConnectBlock( 4050 NewLuaTxCall( 4051 "ktlee", 4052 "oom", 4053 0, 4054 `{"Name":"oom"}`, 4055 ), 4056 ) 4057 errMsg := "not enough memory" 4058 if err == nil { 4059 t.Errorf("expected: %s", errMsg) 4060 } 4061 if err != nil && !strings.Contains(err.Error(), errMsg) { 4062 t.Error(err) 4063 } 4064 err = bc.ConnectBlock( 4065 NewLuaTxCall( 4066 "ktlee", 4067 "oom", 4068 0, 4069 `{"Name":"p"}`, 4070 ).Fail(errMsg), 4071 ) 4072 if err != nil { 4073 t.Error(err) 4074 } 4075 err = bc.ConnectBlock( 4076 NewLuaTxCall( 4077 "ktlee", 4078 "oom", 4079 0, 4080 `{"Name":"cp"}`, 4081 ).Fail(errMsg), 4082 ) 4083 if err != nil { 4084 t.Error(err) 4085 } 4086 } 4087 4088 func TestDeploy2(t *testing.T) { 4089 deploy := ` 4090 function hello() 4091 src = [[ 4092 state.var{ 4093 counts = state.array(10) 4094 } 4095 4096 counts[1] = 10 4097 function inc(key) 4098 if counts[key] == nil then 4099 counts[key] = 0 4100 end 4101 counts[key] = counts[key] + 1 4102 end 4103 4104 function get(key) 4105 return counts[key] 4106 end 4107 4108 function set(key,val) 4109 counts[key] = val 4110 end 4111 4112 function len() 4113 return counts:length() 4114 end 4115 4116 function iter() 4117 local rv = {} 4118 for i, v in counts:ipairs() do 4119 if v == nil then 4120 rv[i] = "nil" 4121 else 4122 rv[i] = v 4123 end 4124 end 4125 return rv 4126 end 4127 4128 abi.register(inc,get,set,len,iter) 4129 ]] 4130 paddr = contract.deploy(src) 4131 system.print("addr :", paddr) 4132 ret = contract.call(paddr, "hello", "world", "key") 4133 end 4134 4135 function constructor() 4136 end 4137 4138 abi.register(hello) 4139 abi.payable(constructor) 4140 ` 4141 bc, err := LoadDummyChain() 4142 if err != nil { 4143 t.Errorf("failed to create test database: %v", err) 4144 } 4145 defer bc.Release() 4146 4147 err = bc.ConnectBlock( 4148 NewLuaTxAccount("ktlee", 1000000000000), 4149 NewLuaTxDef("ktlee", "deploy", 50000000000, deploy), 4150 ) 4151 if err != nil { 4152 t.Error(err) 4153 } 4154 tx := NewLuaTxCall("ktlee", "deploy", 0, `{"Name":"hello"}`).Fail(`[Contract.LuaDeployContract]newExecutor Error :not permitted state referencing at global scope`) 4155 err = bc.ConnectBlock(tx) 4156 if err != nil { 4157 t.Error(err) 4158 } 4159 } 4160 4161 func TestInvalidKey(t *testing.T) { 4162 src := ` 4163 state.var { 4164 h = state.map(), 4165 arr = state.array(10), 4166 v = state.value() 4167 } 4168 4169 t = {} 4170 4171 function key_table() 4172 local k = {} 4173 t[k] = "table" 4174 end 4175 4176 function key_func() 4177 t[key_table] = "function" 4178 end 4179 4180 function key_statemap(key) 4181 t[h] = "state.map" 4182 end 4183 4184 function key_statearray(key) 4185 t[arr] = "state.array" 4186 end 4187 4188 function key_statevalue(key) 4189 t[v] = "state.value" 4190 end 4191 4192 function key_upval(key) 4193 local k = {} 4194 local f = function() 4195 t[k] = "upval" 4196 end 4197 f() 4198 end 4199 4200 function key_nil(key) 4201 h[nil] = "nil" 4202 end 4203 4204 abi.register(key_table, key_func, key_statemap, key_statearray, key_statevalue, key_upval, key_nil) 4205 ` 4206 bc, err := LoadDummyChain() 4207 if err != nil { 4208 t.Errorf("failed to create test database: %v", err) 4209 } 4210 defer bc.Release() 4211 4212 err = bc.ConnectBlock( 4213 NewLuaTxAccount("ktlee", 100), 4214 NewLuaTxDef("ktlee", "invalidkey", 0, src), 4215 ) 4216 if err != nil { 4217 t.Error(err) 4218 } 4219 4220 err = bc.ConnectBlock( 4221 NewLuaTxCall("ktlee", "invalidkey", 0, `{"Name":"key_table"}`).Fail( 4222 "cannot use 'table' as a key", 4223 ), 4224 ) 4225 if err != nil { 4226 t.Error(err) 4227 } 4228 err = bc.ConnectBlock( 4229 NewLuaTxCall("ktlee", "invalidkey", 0, `{"Name":"key_func"}`).Fail( 4230 "cannot use 'function' as a key", 4231 ), 4232 ) 4233 if err != nil { 4234 t.Error(err) 4235 } 4236 err = bc.ConnectBlock( 4237 NewLuaTxCall("ktlee", "invalidkey", 0, `{"Name":"key_statemap"}`).Fail( 4238 "cannot use 'userdata' as a key", 4239 ), 4240 ) 4241 if err != nil { 4242 t.Error(err) 4243 } 4244 err = bc.ConnectBlock( 4245 NewLuaTxCall("ktlee", "invalidkey", 0, `{"Name":"key_statearray"}`).Fail( 4246 "cannot use 'userdata' as a key", 4247 ), 4248 ) 4249 if err != nil { 4250 t.Error(err) 4251 } 4252 err = bc.ConnectBlock( 4253 NewLuaTxCall("ktlee", "invalidkey", 0, `{"Name":"key_statevalue"}`).Fail( 4254 "cannot use 'userdata' as a key", 4255 ), 4256 ) 4257 if err != nil { 4258 t.Error(err) 4259 } 4260 err = bc.ConnectBlock( 4261 NewLuaTxCall("ktlee", "invalidkey", 0, `{"Name":"key_upval"}`).Fail( 4262 "cannot use 'table' as a key", 4263 ), 4264 ) 4265 if err != nil { 4266 t.Error(err) 4267 } 4268 err = bc.ConnectBlock( 4269 NewLuaTxCall("ktlee", "invalidkey", 0, `{"Name":"key_nil"}`).Fail( 4270 "invalid key type: 'nil', state.map: 'h'", 4271 ), 4272 ) 4273 if err != nil { 4274 t.Error(err) 4275 } 4276 } 4277 4278 func TestPcallRollback(t *testing.T) { 4279 definition1 := ` 4280 function constructor(init) 4281 system.setItem("count", init) 4282 end 4283 4284 function init() 4285 db.exec([[create table if not exists r ( 4286 id integer primary key 4287 , n integer check(n >= 10) 4288 , nonull text not null 4289 , only integer unique) 4290 ]]) 4291 db.exec("insert into r values (1, 11, 'text', 1)") 4292 end 4293 4294 function pkins1() 4295 db.exec("insert into r values (3, 12, 'text', 2)") 4296 db.exec("insert into r values (1, 12, 'text', 2)") 4297 end 4298 4299 function pkins2() 4300 db.exec("insert into r values (4, 12, 'text', 2)") 4301 end 4302 4303 function pkget() 4304 local rs = db.query("select count(*) from r") 4305 if rs:next() then 4306 local n = rs:get() 4307 --rs:next() 4308 return n 4309 else 4310 return "error in count()" 4311 end 4312 end 4313 4314 function inc() 4315 count = system.getItem("count") 4316 system.setItem("count", count + 1) 4317 return count 4318 end 4319 4320 function get() 4321 return system.getItem("count") 4322 end 4323 4324 function getOrigin() 4325 return system.getOrigin() 4326 end 4327 4328 function set(val) 4329 system.setItem("count", val) 4330 end 4331 abi.register(inc,get,set, init, pkins1, pkins2, pkget, getOrigin) 4332 abi.payable(constructor, inc) 4333 ` 4334 4335 bc, err := LoadDummyChain() 4336 if err != nil { 4337 t.Errorf("failed to create test database: %v", err) 4338 } 4339 defer bc.Release() 4340 4341 err = bc.ConnectBlock( 4342 NewLuaTxAccount("ktlee", 100), 4343 NewLuaTxDef("ktlee", "counter", 10, definition1).Constructor("[0]"), 4344 NewLuaTxCall("ktlee", "counter", 15, `{"Name":"inc", "Args":[]}`), 4345 ) 4346 4347 err = bc.Query("counter", `{"Name":"get", "Args":[]}`, "", "1") 4348 if err != nil { 4349 t.Error(err) 4350 } 4351 4352 definition2 := ` 4353 function constructor(addr) 4354 system.setItem("count", 99) 4355 system.setItem("addr", addr) 4356 end 4357 function add(amount) 4358 first = contract.call.value(amount)(system.getItem("addr"), "inc") 4359 status, res = pcall(contract.call.value(1000000), system.getItem("addr"), "inc") 4360 if status == false then 4361 return first 4362 end 4363 return res 4364 end 4365 function dadd() 4366 return contract.delegatecall(system.getItem("addr"), "inc") 4367 end 4368 function get() 4369 addr = system.getItem("addr") 4370 a = contract.call(addr, "get") 4371 return a 4372 end 4373 function dget() 4374 addr = system.getItem("addr") 4375 a = contract.delegatecall(addr, "get") 4376 return a 4377 end 4378 function send(addr, amount) 4379 contract.send(addr, amount) 4380 status, res = pcall(contract.call.value(1000000000)(system.getItem("addr"), "inc")) 4381 return status 4382 end 4383 function sql() 4384 contract.call(system.getItem("addr"), "init") 4385 pcall(contract.call, system.getItem("addr"), "pkins1") 4386 contract.call(system.getItem("addr"), "pkins2") 4387 return status 4388 end 4389 4390 function sqlget() 4391 return contract.call(system.getItem("addr"), "pkget") 4392 end 4393 4394 function getOrigin() 4395 return contract.call(system.getItem("addr"), "getOrigin") 4396 end 4397 abi.register(add, dadd, get, dget, send, sql, sqlget, getOrigin) 4398 abi.payable(constructor,add) 4399 ` 4400 err = bc.ConnectBlock( 4401 NewLuaTxDef("ktlee", "caller", 10, definition2). 4402 Constructor(fmt.Sprintf(`["%s"]`, types.EncodeAddress(strHash("counter")))), 4403 NewLuaTxCall("ktlee", "caller", 15, `{"Name":"add", "Args":[]}`), 4404 ) 4405 if err != nil { 4406 t.Error(err) 4407 } 4408 4409 err = bc.ConnectBlock( 4410 NewLuaTxCall("ktlee", "caller", 0, `{"Name":"sql", "Args":[]}`), 4411 ) 4412 if err != nil { 4413 t.Error(err) 4414 } 4415 err = bc.Query("caller", `{"Name":"get", "Args":[]}`, "", "2") 4416 if err != nil { 4417 t.Error(err) 4418 } 4419 err = bc.Query("caller", `{"Name":"sqlget", "Args":[]}`, "", "2") 4420 if err != nil { 4421 t.Error(err) 4422 } 4423 4424 tx := NewLuaTxCall("ktlee", "caller", 0, `{"Name":"getOrigin", "Args":[]}`) 4425 _ = bc.ConnectBlock(tx) 4426 receipt := bc.getReceipt(tx.hash()) 4427 if receipt.GetRet() != "\""+types.EncodeAddress(strHash("ktlee"))+"\"" { 4428 t.Errorf("contract Call ret error :%s", receipt.GetRet()) 4429 } 4430 4431 definition3 := ` 4432 function pass(addr) 4433 contract.send(addr, 1) 4434 end 4435 4436 function add(addr, a, b) 4437 system.setItem("arg", a) 4438 contract.pcall(pass, addr) 4439 return a+b 4440 end 4441 4442 function set(addr) 4443 contract.send(addr, 1) 4444 system.setItem("arg", 2) 4445 status, ret = contract.pcall(add, addr, 1, 2) 4446 end 4447 4448 function set2(addr) 4449 contract.send(addr, 1) 4450 system.setItem("arg", 2) 4451 status, ret = contract.pcall(add, addar, 1) 4452 end 4453 4454 function get() 4455 return system.getItem("arg") 4456 end 4457 4458 function getBalance() 4459 return contract.balance() 4460 end 4461 4462 abi.register(set, set2, get, getBalance) 4463 abi.payable(set, set2) 4464 ` 4465 4466 bc, err = LoadDummyChain() 4467 if err != nil { 4468 t.Errorf("failed to create test database: %v", err) 4469 } 4470 defer bc.Release() 4471 4472 err = bc.ConnectBlock( 4473 NewLuaTxAccount("ktlee", 100), 4474 NewLuaTxAccount("bong", 0), 4475 NewLuaTxDef("ktlee", "counter", 0, definition3), 4476 ) 4477 if err != nil { 4478 t.Error(err) 4479 } 4480 tx = NewLuaTxCall("ktlee", "counter", 20, 4481 fmt.Sprintf(`{"Name":"set", "Args":["%s"]}`, types.EncodeAddress(strHash("bong")))) 4482 err = bc.ConnectBlock(tx) 4483 if err != nil { 4484 t.Error(err) 4485 } 4486 err = bc.Query("counter", `{"Name":"get", "Args":[]}`, "", "1") 4487 if err != nil { 4488 t.Error(err) 4489 } 4490 err = bc.Query("counter", `{"Name":"getBalance", "Args":[]}`, "", "\"18\"") 4491 if err != nil { 4492 t.Error(err) 4493 } 4494 state, err := bc.GetAccountState("bong") 4495 if state.GetBalanceBigInt().Uint64() != 2 { 4496 t.Error("balance error") 4497 } 4498 tx = NewLuaTxCall("ktlee", "counter", 10, 4499 fmt.Sprintf(`{"Name":"set2", "Args":["%s"]}`, types.EncodeAddress(strHash("bong")))) 4500 err = bc.ConnectBlock(tx) 4501 if err != nil { 4502 t.Error(err) 4503 } 4504 err = bc.Query("counter", `{"Name":"get", "Args":[]}`, "", "2") 4505 if err != nil { 4506 t.Error(err) 4507 } 4508 state, err = bc.GetAccountState("bong") 4509 if state.GetBalanceBigInt().Uint64() != 3 { 4510 t.Error("balance error") 4511 } 4512 } 4513 4514 func TestNestedPcall(t *testing.T) { 4515 definition1 := ` 4516 state.var { 4517 Map = state.map(), 4518 } 4519 function map(a) 4520 return Map[a] 4521 end 4522 function constructor() 4523 end 4524 function pcall3(to) 4525 contract.send(to, "1 aergo") 4526 end 4527 function pcall2(addr, to) 4528 status = pcall(contract.call, addr, "pcall3", to) 4529 system.print(status) 4530 assert(false) 4531 end 4532 function pcall1(addr, to) 4533 status = pcall(contract.call, addr, "pcall2", addr, to) 4534 system.print(status) 4535 Map[addr] = 2 4536 status = pcall(contract.call, addr, "pcall3", to) 4537 system.print(status) 4538 status = pcall(contract.call, addr, "pcall2", addr, to) 4539 system.print(status) 4540 end 4541 function default() 4542 end 4543 abi.register(map, pcall1, pcall2, pcall3, default) 4544 abi.payable(pcall1, default, constructor) 4545 ` 4546 4547 bc, err := LoadDummyChain() 4548 if err != nil { 4549 t.Errorf("failed to create test database: %v", err) 4550 } 4551 defer bc.Release() 4552 4553 err = bc.ConnectBlock( 4554 NewLuaTxAccount("ktlee", 100), 4555 NewLuaTxAccount("bong", 0), 4556 NewLuaTxDef("ktlee", "pcall", 10000000000000000000, definition1), 4557 ) 4558 if err != nil { 4559 t.Error(err) 4560 } 4561 err = bc.ConnectBlock( 4562 NewLuaTxCall("ktlee", "pcall", 0, 4563 fmt.Sprintf(`{"Name":"pcall1", "Args":["%s", "%s"]}`, 4564 types.EncodeAddress(strHash("pcall")), types.EncodeAddress(strHash("bong")))), 4565 ) 4566 if err != nil { 4567 t.Error(err) 4568 } 4569 err = bc.Query("pcall", fmt.Sprintf(`{"Name":"map", "Args":["%s"]}`, 4570 types.EncodeAddress(strHash("pcall"))), "", "2") 4571 if err != nil { 4572 t.Error(err) 4573 } 4574 state, err := bc.GetAccountState("bong") 4575 if state.GetBalanceBigInt().Uint64() != 1000000000000000000 { 4576 t.Error("balance error", state.GetBalanceBigInt().Uint64()) 4577 } 4578 } 4579 4580 func TestSnapshot(t *testing.T) { 4581 bc, err := LoadDummyChain() 4582 if err != nil { 4583 t.Errorf("failed to create test database: %v", err) 4584 } 4585 defer bc.Release() 4586 4587 definition := ` 4588 state.var{ 4589 counts = state.map(), 4590 data = state.value(), 4591 array = state.array(10) 4592 } 4593 4594 function inc() 4595 a = system.getItem("key1") 4596 if (a == nil) then 4597 system.setItem("key1", 1) 4598 return 4599 end 4600 system.setItem("key1", a + 1) 4601 counts["key1"] = a + 1 4602 data:set(a+1) 4603 array[1] = a + 1 4604 end 4605 function query(a) 4606 return system.getItem("key1", a), state.getsnap(counts, "key1", a), state.getsnap(data,a), state.getsnap(array, 1, a) 4607 end 4608 function query2() 4609 return state.getsnap(array, 1) 4610 end 4611 abi.register(inc, query, query2) 4612 abi.payable(inc)` 4613 4614 err = bc.ConnectBlock( 4615 NewLuaTxAccount("ktlee", 100), 4616 NewLuaTxDef("ktlee", "snap", 0, definition), 4617 ) 4618 if err != nil { 4619 t.Error(err) 4620 } 4621 err = bc.ConnectBlock( 4622 NewLuaTxCall("ktlee", "snap", 0, `{"Name": "inc", "Args":[]}`), 4623 ) 4624 if err != nil { 4625 t.Error(err) 4626 } 4627 err = bc.ConnectBlock( 4628 NewLuaTxCall("ktlee", "snap", 0, `{"Name": "inc", "Args":[]}`), 4629 ) 4630 if err != nil { 4631 t.Error(err) 4632 } 4633 err = bc.ConnectBlock( 4634 NewLuaTxCall("ktlee", "snap", 0, `{"Name": "inc", "Args":[]}`), 4635 ) 4636 if err != nil { 4637 t.Error(err) 4638 } 4639 err = bc.Query("snap", `{"Name":"query"}`, "", "[3,3,3,3]") 4640 if err != nil { 4641 t.Error(err) 4642 } 4643 err = bc.Query("snap", `{"Name":"query", "Args":[2]}`, "", "[1,{},{},{}]") 4644 if err != nil { 4645 t.Error(err) 4646 } 4647 err = bc.Query("snap", `{"Name":"query", "Args":[3]}`, "", "[2,2,2,2]") 4648 if err != nil { 4649 t.Error(err) 4650 } 4651 err = bc.Query("snap", `{"Name":"query2", "Args":[]}`, 4652 "invalid argument at getsnap, need (state.array, index, blockheight)", "") 4653 if err != nil { 4654 t.Error(err) 4655 } 4656 } 4657 4658 func TestByteKey(t *testing.T) { 4659 bk := ` 4660 state.var { 4661 c = state.map(), 4662 } 4663 4664 function constructor() 4665 c[fromhex('00')] = "kk" 4666 c[fromhex('61')] = "kk" 4667 system.setItem(fromhex('00'), "kk") 4668 end 4669 4670 function fromhex(str) 4671 return (str:gsub('..', function (cc) 4672 return string.char(tonumber(cc, 16)) 4673 end)) 4674 end 4675 function get() 4676 return c[fromhex('00')], system.getItem(fromhex('00')), system.getItem(fromhex('0000')) 4677 end 4678 function getcre() 4679 return system.getCreator() 4680 end 4681 abi.register(get, getcre) 4682 ` 4683 bc, err := LoadDummyChain() 4684 if err != nil { 4685 t.Errorf("failed to create test database: %v", err) 4686 } 4687 defer bc.Release() 4688 4689 err = bc.ConnectBlock( 4690 NewLuaTxAccount("ktlee", 100000), 4691 NewLuaTxDef("ktlee", "bk", 0, bk), 4692 ) 4693 if err != nil { 4694 t.Error(err) 4695 } 4696 err = bc.Query("bk", `{"Name":"get"}`, "", `["kk","kk"]`) 4697 if err != nil { 4698 t.Error(err) 4699 } 4700 err = bc.Query("bk", `{"Name":"getcre"}`, "", `"Amg6nZWXKB6YpNgBPv9atcjdm6hnFvs5wMdRgb2e9DmaF5g9muF2"`) 4701 if err != nil { 4702 t.Error(err) 4703 } 4704 } 4705 4706 func TestUtf(t *testing.T) { 4707 bc, err := LoadDummyChain() 4708 if err != nil { 4709 t.Errorf("failed to create test database: %v", err) 4710 } 4711 defer bc.Release() 4712 4713 definition := ` 4714 function string.tohex(str) 4715 return (str:gsub('.', function (c) 4716 return string.format('%02X', string.byte(c)) 4717 end)) 4718 end 4719 4720 function query() 4721 assert (utf8.char(256) == json.decode('"\\u0100"'), "test1") 4722 a = utf8.char(256,128) 4723 b = utf8.char(256,10000,45) 4724 assert(string.len(a) == 4 and utf8.len(a) == 2, "test2") 4725 4726 for p,c in utf8.codes(a) do 4727 if p == 1 then 4728 assert(c == 256, "test11") 4729 else 4730 assert(c == 128, "test12") 4731 end 4732 end 4733 assert(utf8.offset(b,1)==1, "test3") 4734 assert(utf8.offset(b,2)==3, "test4") 4735 assert(utf8.offset(b,3)==6, "test5") 4736 4737 assert(utf8.codepoint(b,1)==256, "test6") 4738 4739 k1, k2, k3 = utf8.codepoint(b,1,3) 4740 assert(k1 == 256 and k2 == 10000 and k3 == nil, "test7" .. k1 .. k2) 4741 4742 k1, k2, k3 = utf8.codepoint(b,1,6) 4743 assert(k1 == 256 and k2 == 10000 and k3 == 45, "test7" .. k1 .. k2 .. k3) 4744 end 4745 4746 function query2() 4747 a = bignum.number(1000000000000) 4748 b = bignum.number(0) 4749 return (bignum.tobyte(a)):tohex(), (bignum.tobyte(b)):tohex() 4750 end 4751 4752 function query3() 4753 a = bignum.number(-1) 4754 return (bignum.tobyte(a)):tohex() 4755 end 4756 abi.register(query, query2, query3) 4757 ` 4758 4759 err = bc.ConnectBlock( 4760 NewLuaTxAccount("ktlee", 100), 4761 NewLuaTxDef("ktlee", "utf", 0, definition), 4762 ) 4763 if err != nil { 4764 t.Error(err) 4765 } 4766 4767 err = bc.Query("utf", `{"Name":"query"}`, "", "") 4768 if err != nil { 4769 t.Error(err) 4770 } 4771 err = bc.Query("utf", `{"Name":"query2"}`, "", `["E8D4A51000","00"]`) 4772 if err != nil { 4773 t.Error(err) 4774 } 4775 err = bc.Query("utf", `{"Name":"query3"}`, "bignum not allowed negative value", "") 4776 if err != nil { 4777 t.Error(err) 4778 } 4779 } 4780 4781 func TestLuaCryptoVerifyProof(t *testing.T) { 4782 bc, err := LoadDummyChain() 4783 if err != nil { 4784 t.Errorf("failed to create test database: %v", err) 4785 } 4786 defer bc.Release() 4787 4788 definition := ` 4789 function hextobytes(str) 4790 return (str:gsub('..', function (cc) 4791 return string.char(tonumber(cc, 16)) 4792 end)) 4793 end 4794 4795 function verifyProofRaw(data) 4796 local k = "a6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49" 4797 local v = "2710" 4798 local p0 = "f871a0379a71a6fb36a75e085aff02beec9f5934b9648d24e2901da307492219608b3780a006a684f73e33f5c18739fd1339977f6fe328eb5cbe64239244b0cec88744355180808080a023866491ea0336f72e659c2a7daf61285de093b04fa353c48069a807c2ba845f808080808080808080" 4799 local p1 = "e5a03eb5be412f275a18f6e4d622aee4ff40b21467c926224771b782d4c095d1444b83822710" 4800 local b = crypto.verifyProof(hextobytes(k), hextobytes(v), crypto.keccak256(hextobytes(p0)), hextobytes(p0), hextobytes(p1)) 4801 return b 4802 end 4803 4804 function verifyProofHex(data) 4805 local k = "0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49" 4806 local v = "0x2710" 4807 local p0 = "0xf871a0379a71a6fb36a75e085aff02beec9f5934b9648d24e2901da307492219608b3780a006a684f73e33f5c18739fd1339977f6fe328eb5cbe64239244b0cec88744355180808080a023866491ea0336f72e659c2a7daf61285de093b04fa353c48069a807c2ba845f808080808080808080" 4808 local p1 = "0xe5a03eb5be412f275a18f6e4d622aee4ff40b21467c926224771b782d4c095d1444b83822710" 4809 local b = crypto.verifyProof(k, v, crypto.keccak256(p0), p0, p1) 4810 return b 4811 end 4812 4813 abi.register(verifyProofRaw, verifyProofHex)` 4814 4815 err = bc.ConnectBlock( 4816 NewLuaTxAccount("ktlee", 100), 4817 NewLuaTxDef("ktlee", "eth", 0, definition), 4818 ) 4819 if err != nil { 4820 t.Error(err) 4821 } 4822 4823 err = bc.Query("eth", `{"Name":"verifyProofRaw"}`, "", `true`) 4824 if err != nil { 4825 t.Error(err) 4826 } 4827 4828 err = bc.Query("eth", `{"Name":"verifyProofHex"}`, "", `true`) 4829 if err != nil { 4830 t.Error(err) 4831 } 4832 } 4833 4834 func TestMultiArray(t *testing.T) { 4835 bc, err := LoadDummyChain() 4836 if err != nil { 4837 t.Errorf("failed to create test database: %v", err) 4838 } 4839 defer bc.Release() 4840 4841 definition := ` 4842 state.var{ 4843 mcounts = state.map(2), 4844 array = state.array(10, 11), 4845 tcounts = state.map(3) 4846 } 4847 4848 function inc() 4849 a = system.getItem("key1") 4850 if (a == nil) then 4851 system.setItem("key1", 1) 4852 return 4853 end 4854 system.setItem("key1", a + 1) 4855 mcounts[system.getSender()]["key1"] = a + 1 4856 array[1][10] = "k" 4857 array[10][5] = "l" 4858 tcounts[0][0][0] = 2 4859 end 4860 function query(a) 4861 return system.getItem("key1"), mcounts[a]["key1"], tcounts[0][0][0], tcounts[1][2][3], array:length(), array[1]:length() 4862 end 4863 function del() 4864 tcounts[0][0]:delete(0) 4865 tcounts[1][2]:delete(3) 4866 end 4867 function iter(a) 4868 local rv = {} 4869 for i, x in array:ipairs() do 4870 for j, y in x:ipairs() do 4871 if y ~= nil then 4872 rv[i..","..j] = y 4873 end 4874 end 4875 end 4876 return rv 4877 end 4878 4879 function seterror() 4880 rv, err = pcall(function () mcounts[1]["k2y1"] = 4 end) 4881 assert(rv == false and string.find(err, "string expected, got number")) 4882 rv, err = pcall(function () mcounts["middle"] = 4 end) 4883 assert(rv == false and string.find(err, "not permitted to set intermediate dimension of map")) 4884 rv, err = pcall(function () array[1] = 4 end) 4885 assert(rv == false and string.find(err, "not permitted to set intermediate dimension of array")) 4886 rv, err = pcall(function () tcounts[0]:delete(0) end) 4887 assert(rv == false and string.find(err, "not permitted to set intermediate dimension of map")) 4888 rv, err = pcall(function () tcounts[0][1]:delete() end) 4889 assert(rv == false and string.find(err, "invalid key type: 'no value', state.map: 'tcounts'")) 4890 rv, err = pcall(function () array[0]:append(2) end) 4891 assert(rv == false and string.find(err, "the fixed array cannot use 'append' method")) 4892 rv, err = pcall(function () state.var {k = state.map(6)} end) 4893 assert(rv == false and string.find(err, "dimension over max limit"), err) 4894 rv, err = pcall(function () state.var {k = state.array(1,2,3,4,5,6)} end) 4895 assert(rv == false and string.find(err, "dimension over max limit"), err) 4896 end 4897 4898 abi.register(inc, query, iter, seterror, del) 4899 abi.payable(inc)` 4900 4901 err = bc.ConnectBlock( 4902 NewLuaTxAccount("ktlee", 100), 4903 NewLuaTxDef("ktlee", "ma", 0, definition), 4904 ) 4905 if err != nil { 4906 t.Error(err) 4907 } 4908 err = bc.ConnectBlock( 4909 NewLuaTxCall("ktlee", "ma", 0, `{"Name": "inc", "Args":[]}`), 4910 ) 4911 if err != nil { 4912 t.Error(err) 4913 } 4914 err = bc.ConnectBlock( 4915 NewLuaTxCall("ktlee", "ma", 0, `{"Name": "inc", "Args":[]}`), 4916 ) 4917 if err != nil { 4918 t.Error(err) 4919 } 4920 err = bc.Query("ma", fmt.Sprintf(`{"Name":"query", "Args":["%s"]}`, 4921 types.EncodeAddress(strHash("ktlee"))), "", "[2,2,2,{},10,11]") 4922 if err != nil { 4923 t.Error(err) 4924 } 4925 err = bc.ConnectBlock( 4926 NewLuaTxCall("ktlee", "ma", 0, `{"Name": "del", "Args":[]}`), 4927 ) 4928 if err != nil { 4929 t.Error(err) 4930 } 4931 err = bc.Query("ma", fmt.Sprintf(`{"Name":"query", "Args":["%s"]}`, 4932 types.EncodeAddress(strHash("ktlee"))), "", "[2,2,{},{},10,11]") 4933 if err != nil { 4934 t.Error(err) 4935 } 4936 err = bc.Query("ma", `{"Name":"iter"}`, "", `{"1,10":"k","10,5":"l"}`) 4937 if err != nil { 4938 t.Error(err) 4939 } 4940 err = bc.Query("ma", `{"Name":"seterror"}`, "", ``) 4941 if err != nil { 4942 t.Error(err) 4943 } 4944 definition2 := ` 4945 state.var { 4946 -- global map 4947 alpha = state.map(2), 4948 beta = state.map(2), 4949 } 4950 4951 function constructor() 4952 4953 local d = alpha["dict"] 4954 d["a"] = "A" 4955 alpha["dict"]["b"] = "B" 4956 4957 assert(alpha["dict"]["a"]=="A" and alpha["dict"]["b"]=="B") 4958 4959 -- with local variable 4960 local d2 = beta["dict"] 4961 d2["a"] = "A" 4962 d2["value"] = "v0" 4963 beta["dict"]["b"] = "B" 4964 beta["dict"]["value"] = "v1" 4965 assert(beta["dict"]["a"]=="A" and beta["dict"]["b"]=="B" and beta["dict"]["value"]=="v1") 4966 end 4967 4968 function abc() 4969 local d = alpha["dict"] 4970 d["c"] = "C" 4971 alpha["dict"]["d"] = "D" 4972 4973 local d = beta["dict"] 4974 d["a"] = "A" 4975 d["value"] = "v2" 4976 beta["dict"]["b"] = "B" 4977 beta["dict"]["value"] = "v3" 4978 return alpha["dict"]["c"], alpha["dict"]["d"], beta["dict"]["a"], beta["dict"]["b"], beta["dict"]["value"] 4979 end 4980 4981 function query() 4982 return alpha["dict"]["a"], alpha["dict"]["b"], alpha["dict"]["c"], alpha["dict"]["d"], 4983 beta["dict"]["a"], beta["dict"]["b"], beta["dict"]["value"] 4984 end 4985 4986 abi.register(abc, query) 4987 ` 4988 err = bc.ConnectBlock( 4989 NewLuaTxAccount("ktlee", 100), 4990 NewLuaTxDef("ktlee", "ma", 0, definition2), 4991 ) 4992 err = bc.Query("ma", `{"Name":"query", "Args":[]}`, 4993 "", `["A","B",{},{},"A","B","v1"]`) 4994 if err != nil { 4995 t.Error(err) 4996 } 4997 tx := NewLuaTxCall("ktlee", "ma", 0, `{"Name": "abc", "Args":[]}`) 4998 err = bc.ConnectBlock(tx) 4999 if err != nil { 5000 t.Error(err) 5001 } 5002 receipt := bc.getReceipt(tx.hash()) 5003 if receipt.GetRet() != `["C","D","A","B","v3"]` { 5004 t.Errorf("contract Call ret error :%s", receipt.GetRet()) 5005 } 5006 err = bc.Query("ma", `{"Name":"query", "Args":[]}`, 5007 "", `["A","B","C","D","A","B","v3"]`) 5008 if err != nil { 5009 t.Error(err) 5010 } 5011 } 5012 5013 func TestNDeploy(t *testing.T) { 5014 bc, err := LoadDummyChain() 5015 if err != nil { 5016 t.Errorf("failed to create test database: %v", err) 5017 } 5018 defer bc.Release() 5019 5020 definition := ` 5021 function constructor() 5022 testall() 5023 end 5024 5025 function testall() 5026 deploytest() 5027 sendtest() 5028 end 5029 5030 function deploytest() 5031 src = [[ 5032 function default() 5033 contract.send(system.getSender(), system.getAmount()) 5034 end 5035 5036 function getargs(...) 5037 tb = {...} 5038 end 5039 5040 abi.payable(default) 5041 abi.register(getargs) 5042 ]] 5043 5044 addr = contract.deploy(src) 5045 id = 'deploy_src'; system.setItem(id, addr) 5046 system.print(id, system.getItem(id)) 5047 5048 korean_char_src = [[ 5049 function 함수() 5050 변수 = 1 5051 결과 = 변수 + 3 5052 system.print('결과', 결과) 5053 end 5054 5055 abi.register(함수) 5056 ]] 5057 5058 5059 korean_char_src222 = [[ 5060 function default() 5061 contract.send(system.getSender(), system.getAmount()) 5062 end 5063 5064 function getargs(...) 5065 tb = {...} 5066 end 5067 5068 function x() 5069 end 5070 5071 abi.payable(default) 5072 abi.register(getargs) 5073 ]] 5074 5075 korean_addr = contract.deploy(korean_char_src) 5076 id = 'korean_char_src'; system.setItem(id, korean_addr) 5077 system.print(id, system.getItem(id)) 5078 end 5079 5080 function sendtest() 5081 addr = system.getItem("deploy_src") 5082 system.print('ADDRESS', addr, system.getAmount()) 5083 5084 id = 's01'; system.setItem(id,{pcall(function() contract.send(addr, system.getAmount()) end)}) 5085 system.print(id, system.getItem(id)) 5086 end 5087 5088 function default() 5089 -- do nothing 5090 end 5091 5092 abi.payable(constructor, default) 5093 abi.register(testall) 5094 ` 5095 5096 err = bc.ConnectBlock( 5097 NewLuaTxAccount("ktlee", 100), 5098 NewLuaTxDef("ktlee", "n-deploy", 0, definition), 5099 ) 5100 if err != nil { 5101 t.Error(err) 5102 } 5103 } 5104 5105 func TestJdbcSql(t *testing.T) { 5106 bc, err := LoadDummyChain() 5107 if err != nil { 5108 t.Errorf("failed to create test database: %v", err) 5109 } 5110 defer bc.Release() 5111 5112 definition := ` 5113 function init() 5114 db.exec("create table if not exists total(a int, b int, c text)") 5115 db.exec("insert into total(a,c) values (1,2)") 5116 db.exec("insert into total values (2,2,3)") 5117 db.exec("insert into total values (3,2,3)") 5118 db.exec("insert into total values (4,2,3)") 5119 db.exec("insert into total values (5,2,3)") 5120 db.exec("insert into total values (6,2,3)") 5121 db.exec("insert into total values (7,2,3)") 5122 end 5123 5124 function exec(sql, ...) 5125 local stmt = db.prepare(sql) 5126 stmt:exec(...) 5127 end 5128 5129 function query(sql, ...) 5130 local stmt = db.prepare(sql) 5131 local rs = stmt:query(...) 5132 local r = {} 5133 local colcnt = rs:colcnt() 5134 local colmetas 5135 while rs:next() do 5136 if colmetas == nil then 5137 colmetas = stmt:column_info() 5138 end 5139 5140 local k = {rs:get()} 5141 for i = 1, colcnt do 5142 if k[i] == nil then 5143 k[i] = {} 5144 end 5145 end 5146 table.insert(r, k) 5147 end 5148 -- if (#r == 0) then 5149 -- return {"colcnt":0, "rowcnt":0} 5150 -- end 5151 5152 return {snap=db.getsnap(), colcnt=colcnt, rowcnt=#r, data=r, colmetas=colmetas} 5153 end 5154 5155 function queryS(snap, sql, ...) 5156 db.open_with_snapshot(snap) 5157 5158 local stmt = db.prepare(sql) 5159 local rs = stmt:query(...) 5160 local r = {} 5161 local colcnt = rs:colcnt() 5162 local colmetas 5163 while rs:next() do 5164 if colmetas == nil then 5165 colmetas = stmt:column_info() 5166 end 5167 5168 local k = {rs:get()} 5169 for i = 1, colcnt do 5170 if k[i] == nil then 5171 k[i] = {} 5172 end 5173 end 5174 table.insert(r, k) 5175 end 5176 -- if (#r == 0) then 5177 -- return {"colcnt":0, "rowcnt":0} 5178 -- end 5179 5180 return {snap=db.getsnap(), colcnt=colcnt, rowcnt=#r, data=r, colmetas=colmetas} 5181 end 5182 function getmeta(sql) 5183 local stmt = db.prepare(sql) 5184 5185 return stmt:column_info(), stmt:bind_param_cnt() 5186 end 5187 abi.register(init, exec, query, getmeta, queryS)` 5188 5189 _ = bc.ConnectBlock( 5190 NewLuaTxAccount("ktlee", 100000000000000000), 5191 NewLuaTxDef("ktlee", "jdbc", 0, definition), 5192 NewLuaTxCall("ktlee", "jdbc", 0, `{"Name":"init"}`), 5193 ) 5194 5195 err = bc.Query("jdbc", `{"Name":"query", "Args":["select a,b,c from total"]}`, "", 5196 `{"colcnt":3,"colmetas":{"colcnt":3,"decltypes":["int","int","text"],"names":["a","b","c"]},"data":[[1,{},"2"],[2,2,"3"],[3,2,"3"],[4,2,"3"],[5,2,"3"],[6,2,"3"],[7,2,"3"]],"rowcnt":7,"snap":"2"}`) 5197 if err != nil { 5198 t.Error(err) 5199 } 5200 err = bc.Query("jdbc", `{"Name":"getmeta", "Args":["select a,b,?+1 from total"]}`, "", 5201 `[{"colcnt":3,"decltypes":["int","int",""],"names":["a","b","?+1"]},1]`) 5202 if err != nil { 5203 t.Error(err) 5204 } 5205 err = bc.ConnectBlock( 5206 NewLuaTxCall("ktlee", "jdbc", 0, `{"Name": "exec", "Args":["insert into total values (3,4,5)"]}`), 5207 ) 5208 if err != nil { 5209 t.Error(err) 5210 } 5211 err = bc.Query("jdbc", `{"Name":"query", "Args":["select a,b,c from total"]}`, "", 5212 `{"colcnt":3,"colmetas":{"colcnt":3,"decltypes":["int","int","text"],"names":["a","b","c"]},"data":[[1,{},"2"],[2,2,"3"],[3,2,"3"],[4,2,"3"],[5,2,"3"],[6,2,"3"],[7,2,"3"],[3,4,"5"]],"rowcnt":8,"snap":"3"}`) 5213 if err != nil { 5214 t.Error(err) 5215 } 5216 err = bc.Query("jdbc", `{"Name":"queryS", "Args":["2", "select a,b,c from total"]}`, "", 5217 `{"colcnt":3,"colmetas":{"colcnt":3,"decltypes":["int","int","text"],"names":["a","b","c"]},"data":[[1,{},"2"],[2,2,"3"],[3,2,"3"],[4,2,"3"],[5,2,"3"],[6,2,"3"],[7,2,"3"]],"rowcnt":7,"snap":"3"}`) 5218 if err != nil { 5219 t.Error(err) 5220 } 5221 } 5222 5223 // end of test-cases