├── README.md ├── build └── contracts │ ├── ECCMath_noconflict.json │ ├── LocalCrypto.json │ ├── Migrations.json │ └── Secp256k1_noconflict.json ├── contracts ├── LocalCrypto.sol └── Migrations.sol ├── migrations ├── 1_initial_migration.js └── 2_deploy_contracts.js ├── test ├── TestLocalCrypto.sol └── TestLocalCrypto2.sol └── truffle.js /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonecoldpat/localcrypto/75b013514f1a7ed5fe43f16080198186f7ee9098/README.md -------------------------------------------------------------------------------- /build/contracts/ECCMath_noconflict.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "ECCMath_noconflict", 3 | "abi": [], 4 | "unlinked_binary": "0x60606040523415600b57fe5b5b60338060196000396000f30060606040525bfe00a165627a7a723058206e0dc5c67aa7ba180740de77dd8521457eb7f29d860cd0a29acd0722e457b8150029", 5 | "networks": {}, 6 | "schema_version": "0.0.5", 7 | "updated_at": 1502021271204 8 | } -------------------------------------------------------------------------------- /build/contracts/LocalCrypto.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "LocalCrypto", 3 | "abi": [ 4 | { 5 | "constant": false, 6 | "inputs": [ 7 | { 8 | "name": "r", 9 | "type": "uint256" 10 | } 11 | ], 12 | "name": "createPubKeyWithY", 13 | "outputs": [ 14 | { 15 | "name": "key", 16 | "type": "uint256[2]" 17 | } 18 | ], 19 | "payable": false, 20 | "type": "function" 21 | }, 22 | { 23 | "constant": false, 24 | "inputs": [], 25 | "name": "getG", 26 | "outputs": [ 27 | { 28 | "name": "", 29 | "type": "uint256[2]" 30 | } 31 | ], 32 | "payable": false, 33 | "type": "function" 34 | }, 35 | { 36 | "constant": false, 37 | "inputs": [], 38 | "name": "getY", 39 | "outputs": [ 40 | { 41 | "name": "", 42 | "type": "uint256[2]" 43 | } 44 | ], 45 | "payable": false, 46 | "type": "function" 47 | }, 48 | { 49 | "constant": false, 50 | "inputs": [ 51 | { 52 | "name": "params", 53 | "type": "uint256[4]" 54 | }, 55 | { 56 | "name": "xG", 57 | "type": "uint256[2]" 58 | }, 59 | { 60 | "name": "yG", 61 | "type": "uint256[2]" 62 | }, 63 | { 64 | "name": "y", 65 | "type": "uint256[2]" 66 | }, 67 | { 68 | "name": "a1", 69 | "type": "uint256[2]" 70 | }, 71 | { 72 | "name": "b1", 73 | "type": "uint256[2]" 74 | }, 75 | { 76 | "name": "a2", 77 | "type": "uint256[2]" 78 | }, 79 | { 80 | "name": "b2", 81 | "type": "uint256[2]" 82 | } 83 | ], 84 | "name": "commitToVote", 85 | "outputs": [ 86 | { 87 | "name": "", 88 | "type": "bytes32" 89 | } 90 | ], 91 | "payable": false, 92 | "type": "function" 93 | }, 94 | { 95 | "constant": false, 96 | "inputs": [ 97 | { 98 | "name": "xG", 99 | "type": "uint256[2]" 100 | }, 101 | { 102 | "name": "yG", 103 | "type": "uint256[2]" 104 | }, 105 | { 106 | "name": "w", 107 | "type": "uint256" 108 | }, 109 | { 110 | "name": "r2", 111 | "type": "uint256" 112 | }, 113 | { 114 | "name": "d2", 115 | "type": "uint256" 116 | }, 117 | { 118 | "name": "x", 119 | "type": "uint256" 120 | } 121 | ], 122 | "name": "create1outof2ZKPNoVote", 123 | "outputs": [ 124 | { 125 | "name": "res", 126 | "type": "uint256[10]" 127 | }, 128 | { 129 | "name": "res2", 130 | "type": "uint256[4]" 131 | } 132 | ], 133 | "payable": false, 134 | "type": "function" 135 | }, 136 | { 137 | "constant": false, 138 | "inputs": [ 139 | { 140 | "name": "r1", 141 | "type": "uint256" 142 | }, 143 | { 144 | "name": "r2", 145 | "type": "uint256" 146 | }, 147 | { 148 | "name": "r3", 149 | "type": "uint256" 150 | }, 151 | { 152 | "name": "c1", 153 | "type": "uint256[2]" 154 | }, 155 | { 156 | "name": "c2", 157 | "type": "uint256[2]" 158 | } 159 | ], 160 | "name": "createEqualityProof", 161 | "outputs": [ 162 | { 163 | "name": "t", 164 | "type": "uint256[2]" 165 | }, 166 | { 167 | "name": "n", 168 | "type": "uint256" 169 | } 170 | ], 171 | "payable": false, 172 | "type": "function" 173 | }, 174 | { 175 | "constant": false, 176 | "inputs": [ 177 | { 178 | "name": "n", 179 | "type": "uint256" 180 | }, 181 | { 182 | "name": "c1", 183 | "type": "uint256[2]" 184 | }, 185 | { 186 | "name": "c2", 187 | "type": "uint256[2]" 188 | }, 189 | { 190 | "name": "t", 191 | "type": "uint256[2]" 192 | } 193 | ], 194 | "name": "verifyEqualityProof", 195 | "outputs": [ 196 | { 197 | "name": "", 198 | "type": "bool" 199 | } 200 | ], 201 | "payable": false, 202 | "type": "function" 203 | }, 204 | { 205 | "constant": false, 206 | "inputs": [ 207 | { 208 | "name": "coef", 209 | "type": "uint256[]" 210 | }, 211 | { 212 | "name": "available", 213 | "type": "uint256" 214 | } 215 | ], 216 | "name": "createShares", 217 | "outputs": [ 218 | { 219 | "name": "shares", 220 | "type": "uint256[6]" 221 | } 222 | ], 223 | "payable": false, 224 | "type": "function" 225 | }, 226 | { 227 | "constant": false, 228 | "inputs": [ 229 | { 230 | "name": "c1", 231 | "type": "uint256[2]" 232 | }, 233 | { 234 | "name": "c2", 235 | "type": "uint256[2]" 236 | }, 237 | { 238 | "name": "h", 239 | "type": "uint256" 240 | }, 241 | { 242 | "name": "t", 243 | "type": "uint256[2]" 244 | } 245 | ], 246 | "name": "computeFirstHalfEquality", 247 | "outputs": [ 248 | { 249 | "name": "left", 250 | "type": "uint256[2]" 251 | } 252 | ], 253 | "payable": false, 254 | "type": "function" 255 | }, 256 | { 257 | "constant": false, 258 | "inputs": [ 259 | { 260 | "name": "a", 261 | "type": "uint256" 262 | }, 263 | { 264 | "name": "b", 265 | "type": "uint256" 266 | } 267 | ], 268 | "name": "submod", 269 | "outputs": [ 270 | { 271 | "name": "", 272 | "type": "uint256" 273 | } 274 | ], 275 | "payable": false, 276 | "type": "function" 277 | }, 278 | { 279 | "constant": false, 280 | "inputs": [ 281 | { 282 | "name": "preimage", 283 | "type": "uint256" 284 | }, 285 | { 286 | "name": "index", 287 | "type": "uint256" 288 | } 289 | ], 290 | "name": "hashchain", 291 | "outputs": [ 292 | { 293 | "name": "", 294 | "type": "uint256" 295 | } 296 | ], 297 | "payable": false, 298 | "type": "function" 299 | }, 300 | { 301 | "constant": false, 302 | "inputs": [ 303 | { 304 | "name": "a", 305 | "type": "uint256" 306 | }, 307 | { 308 | "name": "b", 309 | "type": "uint256" 310 | }, 311 | { 312 | "name": "prime", 313 | "type": "uint256" 314 | } 315 | ], 316 | "name": "submod", 317 | "outputs": [ 318 | { 319 | "name": "", 320 | "type": "uint256" 321 | } 322 | ], 323 | "payable": false, 324 | "type": "function" 325 | }, 326 | { 327 | "constant": false, 328 | "inputs": [ 329 | { 330 | "name": "r", 331 | "type": "uint256" 332 | }, 333 | { 334 | "name": "gen", 335 | "type": "uint256[2]" 336 | } 337 | ], 338 | "name": "mul", 339 | "outputs": [ 340 | { 341 | "name": "res", 342 | "type": "uint256[2]" 343 | } 344 | ], 345 | "payable": false, 346 | "type": "function" 347 | }, 348 | { 349 | "constant": false, 350 | "inputs": [ 351 | { 352 | "name": "share1", 353 | "type": "uint256[2]" 354 | }, 355 | { 356 | "name": "share2", 357 | "type": "uint256[2]" 358 | }, 359 | { 360 | "name": "share3", 361 | "type": "uint256[2]" 362 | }, 363 | { 364 | "name": "pos", 365 | "type": "uint256[3]" 366 | } 367 | ], 368 | "name": "joinShares", 369 | "outputs": [ 370 | { 371 | "name": "accum", 372 | "type": "uint256[3]" 373 | } 374 | ], 375 | "payable": false, 376 | "type": "function" 377 | }, 378 | { 379 | "constant": false, 380 | "inputs": [ 381 | { 382 | "name": "w", 383 | "type": "uint256" 384 | }, 385 | { 386 | "name": "a", 387 | "type": "uint256" 388 | }, 389 | { 390 | "name": "gen1", 391 | "type": "uint256[2]" 392 | }, 393 | { 394 | "name": "gen2", 395 | "type": "uint256[2]" 396 | }, 397 | { 398 | "name": "c1", 399 | "type": "uint256[2]" 400 | }, 401 | { 402 | "name": "c2", 403 | "type": "uint256[2]" 404 | } 405 | ], 406 | "name": "createDiscreteLogEquality", 407 | "outputs": [ 408 | { 409 | "name": "a1", 410 | "type": "uint256[2]" 411 | }, 412 | { 413 | "name": "a2", 414 | "type": "uint256[2]" 415 | }, 416 | { 417 | "name": "z", 418 | "type": "uint256" 419 | } 420 | ], 421 | "payable": false, 422 | "type": "function" 423 | }, 424 | { 425 | "constant": false, 426 | "inputs": [ 427 | { 428 | "name": "w", 429 | "type": "uint256" 430 | }, 431 | { 432 | "name": "a", 433 | "type": "uint256" 434 | }, 435 | { 436 | "name": "gen1", 437 | "type": "uint256[2]" 438 | }, 439 | { 440 | "name": "gen2", 441 | "type": "uint256[2]" 442 | }, 443 | { 444 | "name": "e", 445 | "type": "uint256" 446 | } 447 | ], 448 | "name": "createDiscreteLogEqualityGivenE", 449 | "outputs": [ 450 | { 451 | "name": "a1", 452 | "type": "uint256[2]" 453 | }, 454 | { 455 | "name": "a2", 456 | "type": "uint256[2]" 457 | }, 458 | { 459 | "name": "z", 460 | "type": "uint256" 461 | } 462 | ], 463 | "payable": false, 464 | "type": "function" 465 | }, 466 | { 467 | "constant": false, 468 | "inputs": [ 469 | { 470 | "name": "r", 471 | "type": "uint256" 472 | }, 473 | { 474 | "name": "t", 475 | "type": "uint256" 476 | } 477 | ], 478 | "name": "validateCommitments", 479 | "outputs": [ 480 | { 481 | "name": "", 482 | "type": "bool" 483 | } 484 | ], 485 | "payable": false, 486 | "type": "function" 487 | }, 488 | { 489 | "constant": false, 490 | "inputs": [], 491 | "name": "getMsgSender", 492 | "outputs": [ 493 | { 494 | "name": "", 495 | "type": "address" 496 | } 497 | ], 498 | "payable": false, 499 | "type": "function" 500 | }, 501 | { 502 | "constant": false, 503 | "inputs": [ 504 | { 505 | "name": "c", 506 | "type": "uint256[2]" 507 | }, 508 | { 509 | "name": "r", 510 | "type": "uint256" 511 | }, 512 | { 513 | "name": "b", 514 | "type": "uint256" 515 | } 516 | ], 517 | "name": "openCommitment", 518 | "outputs": [ 519 | { 520 | "name": "", 521 | "type": "bool" 522 | } 523 | ], 524 | "payable": false, 525 | "type": "function" 526 | }, 527 | { 528 | "constant": false, 529 | "inputs": [ 530 | { 531 | "name": "id", 532 | "type": "uint256" 533 | }, 534 | { 535 | "name": "commitment", 536 | "type": "uint256[2]" 537 | } 538 | ], 539 | "name": "storeCommitmentTESTING", 540 | "outputs": [], 541 | "payable": false, 542 | "type": "function" 543 | }, 544 | { 545 | "constant": false, 546 | "inputs": [ 547 | { 548 | "name": "x", 549 | "type": "uint256" 550 | }, 551 | { 552 | "name": "v", 553 | "type": "uint256" 554 | }, 555 | { 556 | "name": "xG", 557 | "type": "uint256[2]" 558 | } 559 | ], 560 | "name": "createZKP", 561 | "outputs": [ 562 | { 563 | "name": "res", 564 | "type": "uint256[4]" 565 | } 566 | ], 567 | "payable": false, 568 | "type": "function" 569 | }, 570 | { 571 | "constant": false, 572 | "inputs": [ 573 | { 574 | "name": "b1", 575 | "type": "uint256" 576 | }, 577 | { 578 | "name": "b2", 579 | "type": "uint256" 580 | }, 581 | { 582 | "name": "r1", 583 | "type": "uint256" 584 | }, 585 | { 586 | "name": "r2", 587 | "type": "uint256" 588 | }, 589 | { 590 | "name": "r3", 591 | "type": "uint256" 592 | }, 593 | { 594 | "name": "r4", 595 | "type": "uint256" 596 | }, 597 | { 598 | "name": "c1", 599 | "type": "uint256[2]" 600 | }, 601 | { 602 | "name": "c2", 603 | "type": "uint256[2]" 604 | } 605 | ], 606 | "name": "createInequalityProof", 607 | "outputs": [ 608 | { 609 | "name": "t1", 610 | "type": "uint256[2]" 611 | }, 612 | { 613 | "name": "t2", 614 | "type": "uint256[2]" 615 | }, 616 | { 617 | "name": "n1", 618 | "type": "uint256" 619 | }, 620 | { 621 | "name": "n2", 622 | "type": "uint256" 623 | } 624 | ], 625 | "payable": false, 626 | "type": "function" 627 | }, 628 | { 629 | "constant": false, 630 | "inputs": [ 631 | { 632 | "name": "w", 633 | "type": "uint256" 634 | }, 635 | { 636 | "name": "gen1", 637 | "type": "uint256[2]" 638 | }, 639 | { 640 | "name": "gen2", 641 | "type": "uint256[2]" 642 | } 643 | ], 644 | "name": "createDiscreteLogEqualityWithoutEZ", 645 | "outputs": [ 646 | { 647 | "name": "a1", 648 | "type": "uint256[2]" 649 | }, 650 | { 651 | "name": "a2", 652 | "type": "uint256[2]" 653 | } 654 | ], 655 | "payable": false, 656 | "type": "function" 657 | }, 658 | { 659 | "constant": false, 660 | "inputs": [ 661 | { 662 | "name": "z", 663 | "type": "uint256" 664 | }, 665 | { 666 | "name": "gen1", 667 | "type": "uint256[2]" 668 | }, 669 | { 670 | "name": "gen2", 671 | "type": "uint256[2]" 672 | }, 673 | { 674 | "name": "c1", 675 | "type": "uint256[2]" 676 | }, 677 | { 678 | "name": "c2", 679 | "type": "uint256[2]" 680 | }, 681 | { 682 | "name": "a1", 683 | "type": "uint256[2]" 684 | }, 685 | { 686 | "name": "a2", 687 | "type": "uint256[2]" 688 | } 689 | ], 690 | "name": "verifyDiscreteLogEquality", 691 | "outputs": [ 692 | { 693 | "name": "", 694 | "type": "bool" 695 | } 696 | ], 697 | "payable": false, 698 | "type": "function" 699 | }, 700 | { 701 | "constant": false, 702 | "inputs": [ 703 | { 704 | "name": "r", 705 | "type": "uint256" 706 | }, 707 | { 708 | "name": "b", 709 | "type": "uint256" 710 | } 711 | ], 712 | "name": "createCommitment", 713 | "outputs": [ 714 | { 715 | "name": "", 716 | "type": "uint256[2]" 717 | } 718 | ], 719 | "payable": false, 720 | "type": "function" 721 | }, 722 | { 723 | "constant": false, 724 | "inputs": [ 725 | { 726 | "name": "r", 727 | "type": "uint256" 728 | } 729 | ], 730 | "name": "mulG", 731 | "outputs": [ 732 | { 733 | "name": "res", 734 | "type": "uint256[2]" 735 | } 736 | ], 737 | "payable": false, 738 | "type": "function" 739 | }, 740 | { 741 | "constant": false, 742 | "inputs": [ 743 | { 744 | "name": "params", 745 | "type": "uint256[4]" 746 | }, 747 | { 748 | "name": "xG", 749 | "type": "uint256[2]" 750 | }, 751 | { 752 | "name": "yG", 753 | "type": "uint256[2]" 754 | }, 755 | { 756 | "name": "y", 757 | "type": "uint256[2]" 758 | }, 759 | { 760 | "name": "a1", 761 | "type": "uint256[2]" 762 | }, 763 | { 764 | "name": "b1", 765 | "type": "uint256[2]" 766 | }, 767 | { 768 | "name": "a2", 769 | "type": "uint256[2]" 770 | }, 771 | { 772 | "name": "b2", 773 | "type": "uint256[2]" 774 | } 775 | ], 776 | "name": "verify1outof2ZKP", 777 | "outputs": [ 778 | { 779 | "name": "", 780 | "type": "bool" 781 | } 782 | ], 783 | "payable": false, 784 | "type": "function" 785 | }, 786 | { 787 | "constant": true, 788 | "inputs": [ 789 | { 790 | "name": "", 791 | "type": "uint256" 792 | }, 793 | { 794 | "name": "", 795 | "type": "uint256" 796 | } 797 | ], 798 | "name": "commitments", 799 | "outputs": [ 800 | { 801 | "name": "", 802 | "type": "uint256" 803 | } 804 | ], 805 | "payable": false, 806 | "type": "function" 807 | }, 808 | { 809 | "constant": false, 810 | "inputs": [ 811 | { 812 | "name": "xG", 813 | "type": "uint256[2]" 814 | }, 815 | { 816 | "name": "yG", 817 | "type": "uint256[2]" 818 | }, 819 | { 820 | "name": "w", 821 | "type": "uint256" 822 | }, 823 | { 824 | "name": "r1", 825 | "type": "uint256" 826 | }, 827 | { 828 | "name": "d1", 829 | "type": "uint256" 830 | }, 831 | { 832 | "name": "x", 833 | "type": "uint256" 834 | } 835 | ], 836 | "name": "create1outof2ZKPYesVote", 837 | "outputs": [ 838 | { 839 | "name": "res", 840 | "type": "uint256[10]" 841 | }, 842 | { 843 | "name": "res2", 844 | "type": "uint256[4]" 845 | } 846 | ], 847 | "payable": false, 848 | "type": "function" 849 | }, 850 | { 851 | "constant": false, 852 | "inputs": [ 853 | { 854 | "name": "c1", 855 | "type": "uint256[2]" 856 | }, 857 | { 858 | "name": "c2", 859 | "type": "uint256[2]" 860 | }, 861 | { 862 | "name": "t2", 863 | "type": "uint256[2]" 864 | }, 865 | { 866 | "name": "h", 867 | "type": "uint256" 868 | } 869 | ], 870 | "name": "computeSecondHalfInequality", 871 | "outputs": [ 872 | { 873 | "name": "right", 874 | "type": "uint256[3]" 875 | } 876 | ], 877 | "payable": false, 878 | "type": "function" 879 | }, 880 | { 881 | "constant": false, 882 | "inputs": [ 883 | { 884 | "name": "r", 885 | "type": "uint256" 886 | } 887 | ], 888 | "name": "mulY", 889 | "outputs": [ 890 | { 891 | "name": "res", 892 | "type": "uint256[2]" 893 | } 894 | ], 895 | "payable": false, 896 | "type": "function" 897 | }, 898 | { 899 | "constant": false, 900 | "inputs": [ 901 | { 902 | "name": "c1", 903 | "type": "uint256[2]" 904 | }, 905 | { 906 | "name": "c2", 907 | "type": "uint256[2]" 908 | }, 909 | { 910 | "name": "t1", 911 | "type": "uint256[2]" 912 | }, 913 | { 914 | "name": "t2", 915 | "type": "uint256[2]" 916 | }, 917 | { 918 | "name": "n1", 919 | "type": "uint256" 920 | }, 921 | { 922 | "name": "n2", 923 | "type": "uint256" 924 | } 925 | ], 926 | "name": "verifyInequalityProof", 927 | "outputs": [ 928 | { 929 | "name": "", 930 | "type": "bool" 931 | } 932 | ], 933 | "payable": false, 934 | "type": "function" 935 | }, 936 | { 937 | "constant": false, 938 | "inputs": [ 939 | { 940 | "name": "xG", 941 | "type": "uint256[2]" 942 | }, 943 | { 944 | "name": "r", 945 | "type": "uint256" 946 | }, 947 | { 948 | "name": "vG", 949 | "type": "uint256[3]" 950 | } 951 | ], 952 | "name": "verifyZKP", 953 | "outputs": [ 954 | { 955 | "name": "", 956 | "type": "bool" 957 | } 958 | ], 959 | "payable": false, 960 | "type": "function" 961 | }, 962 | { 963 | "inputs": [], 964 | "payable": false, 965 | "type": "constructor" 966 | } 967 | ], 968 | "unlinked_binary": "0x60606040526000600555341561001157fe5b5b7f79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817986000805b0160005b50557f483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8600060015b0160005b50557fd8bf8b6616bb7d183e2192e1f95bf5a09868dfb1f2e0556d4ab7f572b3c2e0cc600260005b0160005b50557f03fb65bd9acc08d00f5fb91014acc61522aa96c79e3b1aadf3bef0fa7b9c3a09600260015b0160005b50555b5b6156ea80620000d36000396000f300606060405236156101855763ffffffff60e060020a600035041663043c6ddd811461018757806304c09ce9146101d95780630b7f1665146102285780630dfe4e6a1461027757806316f9f521146103b057806327c40b041461048a57806328e442981461053557806333d30313146105ca5780633447e09b1461065c5780633606de6d1461071e57806336a9e47e1461074657806340c91c051461076e5780634a9f61fc146107995780634b31588e14610815578063555ac70f146108f257806368408fd614610a0e578063685588c214610ae85780637a6ce2e114610b125780638a6ab9c714610b3e5780638d151dd314610b9057806391ee81c314610bcf578063a1f70a5d14610c4b578063acde4a2f14610d3b578063b3588eab14610e0a578063b7676b2a14610f05578063bb734c4e14610f5a578063c07bbc8714610fac578063d13e2e60146110e7578063dae176e01461110f578063dba6c34d146111e9578063dcb5ce6714610187578063f5a93beb146112f5578063fb3f0d6f146113ad575bfe5b341561018f57fe5b61019a600435611425565b6040805190819083908083835b8051825260208311156101c757601f1990920191602091820191016101a7565b50505090500191505060405180910390f35b34156101e157fe5b61019a6114aa565b6040805190819083908083835b8051825260208311156101c757601f1990920191602091820191016101a7565b50505090500191505060405180910390f35b341561023057fe5b61019a6114e6565b6040805190819083908083835b8051825260208311156101c757601f1990920191602091820191016101a7565b50505090500191505060405180910390f35b341561027f57fe5b60408051608081810190925261039e916004916084918390819083908290808284375050604080518082018252949695818101959450925060029150839083908082843750506040805180820182529496958181019594509250600291508390839080828437505060408051808201825294969581810195945092506002915083908390808284375050604080518082018252949695818101959450925060029150839083908082843750506040805180820182529496958181019594509250600291508390839080828437505060408051808201825294969581810195945092506002915083908390808284375050604080518082018252949695818101959450925060029150839083908082843750939550611521945050505050565b60408051918252519081900360200190f35b34156103b857fe5b60408051808201825261041b916004916044918390600290839083908082843750506040805180820182529496958181019594509250600291508390839080828437509395505083359360208101359350604081013592506060013590506116f8565b60405180836101408083835b80518252602083111561044757601f199092019160209182019101610427565b5050509190910190508260808083835b80518252602083111561047757601f199092019160209182019101610457565b5050509050019250505060405180910390f35b341561049257fe5b6040805180820182526104ef91600480359260243592604435929160a49160649060029083908390808284375050604080518082018252949695818101959450925060029150839083908082843750939550611a9a945050505050565b6040805190819084908083835b80518252602083111561051c57601f1990920191602091820191016104fc565b5050509050018281526020019250505060405180910390f35b341561053d57fe5b6040805180820182526105b69160048035929091606491906024906002908390839080828437505060408051808201825294969581810195945092506002915083908390808284375050604080518082018252949695818101959450925060029150839083908082843750939550611cc2945050505050565b604080519115158252519081900360200190f35b34156105d257fe5b61061f6004808035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437509496505093359350611eeb92505050565b604051808260c08083835b8051825260208311156101c757601f1990920191602091820191016101a7565b50505090500191505060405180910390f35b341561066457fe5b60408051808201825261019a91600491604491839060029083908390808284375050604080518082018252949695818101959450925060029150839083908082843750506040805180820182529496863596909560608201955093506020019150600290839083908082843750939550611fa5945050505050565b6040805190819083908083835b8051825260208311156101c757601f1990920191602091820191016101a7565b50505090500191505060405180910390f35b341561072657fe5b61039e60043560243561209a565b60408051918252519081900360200190f35b341561074e57fe5b61039e6004356024356120e7565b60408051918252519081900360200190f35b341561077657fe5b61039e60043560243560443561212e565b60408051918252519081900360200190f35b34156107a157fe5b60408051808201825261019a916004803592909160649190602490600290839083908082843750939550612160945050505050565b6040805190819083908083835b8051825260208311156101c757601f1990920191602091820191016101a7565b50505090500191505060405180910390f35b341561081d57fe5b6040805180820182526108b59160049160449183906002908390839080828437505060408051808201825294969581810195945092506002915083908390808284375050604080518082018252949695818101959450925060029150839083908082843750506040805160608181019092529496958181019594509250600391508390839080828437509395506121b8945050505050565b604051808260608083835b8051825260208311156101c757601f1990920191602091820191016101a7565b50505090500191505060405180910390f35b34156108fa57fe5b60408051808201825261099791600480359260243592608491906044906002908390839080828437505060408051808201825294969581810195945092506002915083908390808284375050604080518082018252949695818101959450925060029150839083908082843750506040805180820182529496958181019594509250600291508390839080828437509395506123c1945050505050565b6040805190819085908083835b8051825260208311156109c457601f1990920191602091820191016109a4565b5050509190910190508360408083835b8051825260208311156109f457601f1990920191602091820191016109d4565b505050905001828152602001935050505060405180910390f35b3415610a1657fe5b604080518082018252610997916004803592602435926084919060449060029083908390808284375050604080518082018252949695818101959450925060029150839083908082843750939550509235925061261d915050565b6040805190819085908083835b8051825260208311156109c457601f1990920191602091820191016109a4565b5050509190910190508360408083835b8051825260208311156109f457601f1990920191602091820191016109d4565b505050905001828152602001935050505060405180910390f35b3415610af057fe5b6105b66004356024356126ea565b604080519115158252519081900360200190f35b3415610b1a57fe5b610b22612a26565b60408051600160a060020a039092168252519081900360200190f35b3415610b4657fe5b6040805180820182526105b691600491604491839060029083908390808284375093955050833593602001359250612a2b915050565b604080519115158252519081900360200190f35b3415610b9857fe5b604080518082018252610bcd916004803592909160649190602490600290839083908082843750939550612a8a945050505050565b005b3415610bd757fe5b604080518082018252610c0e9160048035926024359260849190604490600290839083908082843750939550612ab3945050505050565b604051808260808083835b8051825260208311156101c757601f1990920191602091820191016101a7565b50505090500191505060405180910390f35b3415610c5357fe5b604080518082018252610cbd9160048035926024359260443592606435926084359260a43592916101049160c49060029083908390808284375050604080518082018252949695818101959450925060029150839083908082843750939550612c8c945050505050565b6040805190819086908083835b805182526020831115610cea57601f199092019160209182019101610cca565b5050509190910190508460408083835b805182526020831115610d1a57601f199092019160209182019101610cfa565b50505090500183815260200182815260200194505050505060405180910390f35b3415610d4357fe5b604080518082018252610d9a91600480359290916064919060249060029083908390808284375050604080518082018252949695818101959450925060029150839083908082843750939550612f95945050505050565b6040805190819084908083835b805182526020831115610dc757601f199092019160209182019101610da7565b5050509190910190508260408083835b80518252602083111561047757601f199092019160209182019101610457565b5050509050019250505060405180910390f35b3415610e1257fe5b6040805180820182526105b69160048035929091606491906024906002908390839080828437505060408051808201825294969581810195945092506002915083908390808284375050604080518082018252949695818101959450925060029150839083908082843750506040805180820182529496958181019594509250600291508390839080828437505060408051808201825294969581810195945092506002915083908390808284375050604080518082018252949695818101959450925060029150839083908082843750939550613040945050505050565b604080519115158252519081900360200190f35b3415610f0d57fe5b61019a6004356024356132e2565b6040805190819083908083835b8051825260208311156101c757601f1990920191602091820191016101a7565b50505090500191505060405180910390f35b3415610f6257fe5b61019a6004356133e2565b6040805190819083908083835b8051825260208311156101c757601f1990920191602091820191016101a7565b50505090500191505060405180910390f35b3415610fb457fe5b6040805160808181019092526105b6916004916084918390819083908290808284375050604080518082018252949695818101959450925060029150839083908082843750506040805180820182529496958181019594509250600291508390839080828437505060408051808201825294969581810195945092506002915083908390808284375050604080518082018252949695818101959450925060029150839083908082843750506040805180820182529496958181019594509250600291508390839080828437505060408051808201825294969581810195945092506002915083908390808284375050604080518082018252949695818101959450925060029150839083908082843750939550613468945050505050565b604080519115158252519081900360200190f35b34156110ef57fe5b61039e6004356024356139c5565b60408051918252519081900360200190f35b341561111757fe5b60408051808201825261041b916004916044918390600290839083908082843750506040805180820182529496958181019594509250600291508390839080828437509395505083359360208101359350604081013592506060013590506139eb565b60405180836101408083835b80518252602083111561044757601f199092019160209182019101610427565b5050509190910190508260808083835b80518252602083111561047757601f199092019160209182019101610457565b5050509050019250505060405180910390f35b34156111f157fe5b6040805180820182526108b591600491604491839060029083908390808284375050604080518082018252949695818101959450925060029150839083908082843750506040805180820182529496958181019594509250600291508390839080828437509395505092359250613d8a915050565b604051808260608083835b8051825260208311156101c757601f1990920191602091820191016101a7565b50505090500191505060405180910390f35b341561018f57fe5b61019a600435611425565b6040805190819083908083835b8051825260208311156101c757601f1990920191602091820191016101a7565b50505090500191505060405180910390f35b34156112fd57fe5b6040805180820182526105b691600491604491839060029083908390808284375050604080518082018252949695818101959450925060029150839083908082843750506040805180820182529496958181019594509250600291508390839080828437505060408051808201825294969581810195945092506002915083908390808284375093955050833593602001359250613ef3915050565b604080519115158252519081900360200190f35b34156113b557fe5b6040805180820182526105b6916004916044918390600290839083908082843750506040805160608181019092529496863596909560808201955093506020019150600390839083908082843750939550614240945050505050565b604080519115158252519081900360200190f35b61142d615450565b611435615478565b604080518082019182905261146d91859190600290819081845b81548152602001906001019080831161144f575b5050505050614434565b905061147f816401000003d01961493b565b8060005b60200201518260005b60200201528060015b60200201518260015b60200201525b50919050565b6114b2615450565b60408051808201918290529060009060029082845b8154815260200190600101908083116114c7575b505050505090505b90565b6114ee615450565b604080518082019182905290600290819081845b8154815260200190600101908083116114c7575b505050505090505b90565b6000338989898989898989604051808a600160a060020a0316600160a060020a0316606060020a02815260140189600460200280838360008314611580575b80518252602083111561158057601f199092019160209182019101611560565b5050509190910190508860408083835b8051825260208311156115b057601f199092019160209182019101611590565b5050509190910190508760408083835b8051825260208311156115e057601f1990920191602091820191016115c0565b5050509190910190508660408083835b80518252602083111561161057601f1990920191602091820191016115f0565b5050509190910190508560408083835b80518252602083111561164057601f199092019160209182019101611620565b5050509190910190508460408083835b80518252602083111561167057601f199092019160209182019101611650565b5050509190910190508360408083835b8051825260208311156116a057601f199092019160209182019101611680565b5050509190910190508260408083835b8051825260208311156116d057601f1990920191602091820191016116b0565b5050509050019950505050505050505050604051809103902090505b98975050505050505050565b6117006154a0565b6117086154c9565b611710615450565b611718615450565b611720615478565b600061172c878c614434565b915061173e826401000003d01961493b565b8160005b60200201518660005b60200201528160015b60200201518660015b6020020152604080518082019182905261179b918c919060009060029082845b81548152602001906001019080831161144f575b5050505050614434565b91506117ad826401000003d01961493b565b8160005b60200201518660025b60200201528160015b60200201518660035b60200201526117db8a8c614434565b91506117ed826401000003d01961493b565b8160005b60200201518660045b60200201528160015b60200201518660055b6020020152604080518082019182905261184a918b919060009060029082845b81548152602001906001019080831161144f575b5050505050614434565b915061185f8261185a8a8f614434565b614997565b9150611871826401000003d01961493b565b8160005b60200201518660065b60200201528160015b60200201518660075b60200201526000805b0160005b50548460005b6020020152600060015b0160005b50546401000003d019038460015b60200201528560005b60200201518360005b60200201528560015b60200201518360015b60200201526119046118f58985614434565b61185a8a87614434565b614997565b91506119196119138a8d614434565b83614997565b915061192b826401000003d01961493b565b8160005b60200201518660085b60200201528160015b60200201518660095b6020020181815250506002338d886000604051602001526040518084600160a060020a0316600160a060020a0316606060020a028152601401836002602002808383600083146119b5575b8051825260208311156119b557601f199092019160209182019101611995565b505050919091019050826101408083835b8051825260208311156119e657601f1990920191602091820191016119c6565b505050905001935050505060206040518083038160008661646e5a03f11515611a0b57fe5b5050604051519050611a1d818961209a565b8260005b6020020152611a498a60008051602061567f8339815191528460005b60200201518a0961209a565b8260015b60200201528160005b60200201518560005b6020020152878560015b60200201528160015b60200201518560025b6020020152888560035b60200201525b50505050965096945050505050565b611aa2615450565b6000611aac615478565b600060006000611abb88614bec565b1515611ac75760006000fd5b611ad087614bec565b1515611adc5760006000fd5b6040805180820191829052611b14918b9190600290819081845b81548152602001906001019080831161144f575b5050505050614434565b9350611b26846401000003d01961493b565b8360005b60200201518660005b60200201528360015b60200201518660015b602002018181525050600233600060028b8b8b6000604051602001526040518087600160a060020a0316600160a060020a0316606060020a0281526014018660028015611ba7576020028201915b815481526020019060010190808311611b93575b5050604081019086905b815481526020019060010190808311611bb1575b5085905060408083835b805182526020831115611bef57601f199092019160209182019101611bcf565b5050509190910190508360408083835b805182526020831115611c1f57601f199092019160209182019101611bff565b5050509190910190508260408083835b805182526020831115611c4f57601f199092019160209182019101611c2f565b505050905001965050505050505060206040518083038160008661646e5a03f11515611c7757fe5b5050604051519250611c898b8b61209a565b915060008051602061567f833981519152838309905060008051602061567f83398151915289820894505b505050509550959350505050565b60006000611cce615450565b611cd6615478565b611cdf87614bec565b1515611ceb5760006000fd5b611cf486614bec565b1515611d005760006000fd5b611d0985614bec565b1515611d155760006000fd5b600233600060028a8a8a6000604051602001526040518087600160a060020a0316600160a060020a0316606060020a0281526014018660028015611d6e576020028201915b815481526020019060010190808311611d5a575b5050604081019086905b815481526020019060010190808311611d78575b5085905060408083835b805182526020831115611db657601f199092019160209182019101611d96565b5050509190910190508360408083835b805182526020831115611de657601f199092019160209182019101611dc6565b5050509190910190508260408083835b805182526020831115611e1657601f199092019160209182019101611df6565b505050905001965050505050505060206040518083038160008661646e5a03f11515611e3e57fe5b5050604051519250611e5287878588611fa5565b6040805180820191829052919350611e8c918a91600290819081845b81548152602001906001019080831161144f575b5050505050614434565b9050611e9e816401000003d01961493b565b8060005b60200201518260005b6020020151148015611ecc57508060015b60200201518260015b6020020151145b15611eda5760019350611edf565b600093505b5b505050949350505050565b611ef36154f1565b60008051602061567f833981519152600160008080805b878511611f9857886000815181101515611f2057fe5b906020019060200201519350600192505b8851831015611f7657611f45858488614bff565b915085828a85815181101515611f5757fe5b906020019060200201510990508581850893505b600190920191611f31565b8387600019870160068110611f8757fe5b60200201525b600190940193611f0a565b5b50505050505092915050565b611fad615450565b611fb5615478565b611fbd615478565b611fc5615450565b611fcd615478565b8760005b60200201518460005b60200201528760015b60200201516401000003d019038460015b602002015260018460025b602002015261200e848a614c97565b9250612020836401000003d01961493b565b8260005b60200201518260005b60200201528260015b60200201518260015b60200201526120576120518884614434565b87614c97565b9050612069816401000003d01961493b565b8060005b60200201518560005b60200201528060015b60200201518560015b60200201525b50505050949350505050565b600060006000838511156120b0578491506120c4565b60008051602061567f833981519152850191505b60008051602061567f83398151915260008584030890508092505b505092915050565b604080518381529051908190036020019020600090815b8381101561212257604080519283525191829003602001909120905b6001016120fe565b8192505b505092915050565b600060006000848611156121445785915061214a565b83860191505b8360008684030890508092505b50509392505050565b612168615450565b612170615478565b61217a8484614434565b905061218c816401000003d01961493b565b8060005b60200201518260005b60200201528060015b60200201518260015b60200201525b5092915050565b6121c0615478565b60006121ca615519565b600060006000600060006000600060008051602061567f833981519152985060036040518059106121f85750595b90808252806020026020018201604052801561222e57816020015b61221b61552b565b8152602001906001900390816122135790505b5097506020604051908101604052808f81525088600081518110151561225057fe5b906020019060200201819052506020604051908101604052808e81525088600181518110151561227c57fe5b906020019060200201819052506020604051908101604052808d8152508860028151811015156122a857fe5b60209081029091010152600096505b875187101561239f576001955060019450600093505b87518410156123265786841461231a578a87600381106122e957fe5b602002015192508a84600381106122fc57fe5b602002015191508882870995508861231584848c61212e565b860994505b5b6001909301926122cd565b88612331868b614ee9565b870990508615156123655761235e81898981518110151561234e57fe5b6020908102909101015151614434565b9950612393565b6123908a61185a838b8b81518110151561234e57fe5b6020908102909101015151614434565b614997565b99505b5b6001909601956122b7565b6123af8a6401000003d01961493b565b5b505050505050505050949350505050565b6123c9615450565b6123d1615450565b60006123db615478565b6123e3615478565b60006123ef8c8b614434565b92506123fb8c8a614434565b915061240d836401000003d01961493b565b61241d826401000003d01961493b565b8260005b60200201518660005b60200201528260015b60200201518660015b60200201528160005b60200201518560005b60200201528160015b60200201518560015b60200201818152505060023387878d8d8d8d6000604051602001526040518088600160a060020a0316600160a060020a0316606060020a028152601401876002602002808383600083146124cf575b8051825260208311156124cf57601f1990920191602091820191016124af565b5050509190910190508660408083835b8051825260208311156124ff57601f1990920191602091820191016124df565b5050509190910190508560408083835b80518252602083111561252f57601f19909201916020918201910161250f565b5050509190910190508460408083835b80518252602083111561255f57601f19909201916020918201910161253f565b5050509190910190508360408083835b80518252602083111561258f57601f19909201916020918201910161256f565b5050509190910190508260408083835b8051825260208311156125bf57601f19909201916020918201910161259f565b50505090500197505050505050505060206040518083038160008661646e5a03f115156125e857fe5b505060405151905061260b8c60008051602061567f833981519152838e0961209a565b93505b50505096509650969350505050565b612625615450565b61262d615450565b6000612637615478565b61263f615478565b6126498a89614434565b91506126558a88614434565b9050612667826401000003d01961493b565b612677816401000003d01961493b565b8160005b60200201518560005b60200201528160015b60200201518560015b60200201528060005b60200201518460005b60200201528060015b60200201518460015b60200201526126da8a60008051602061567f833981519152888c0961209a565b92505b5050955095509592505050565b60006126f4615478565b6126fc615519565b600060006000600060006000600060018b600554030360405180591061271f5750595b908082528060200260200182016040525b509750600096505b87518710156127b85760008051602061567f83398151915260016002898f600060405160200152604051808381526020018281526020019250505060206040518083038160008661646e5a03f1151561278d57fe5b5050604051510888888151811015156127a257fe5b602090810290910101525b600190960195612738565b600196505b60055487116129e75760019550600194505b6005548511612894578685146128875785600114156128315760008051602061567f833981519152612827612813898860008051602061567f83398151915261212e565b60008051602061567f833981519152614ee9565b6001099550612887565b60008051602061567f83398151915260008051602061567f83398151915261287f6128138a8960008051602061567f83398151915261212e565b60008051602061567f833981519152614ee9565b600109870995505b5b5b6001909401936127cf565b8760008151811015156128a357fe5b906020019060200201519350600194505b87518510156129235760008051602061567f8339815191526128e5888760008051602061567f833981519152614bff565b89600188038151811015156128f657fe5b9060200190602002015109925060008051602061567f83398151915283850893505b6001909401936128b4565b60008051602061567f833981519152848709600019880160009081526004602052604090209092509050600187141561299557604080518082019182905261298e91849190849060029082845b81548152602001906001019080831161144f575b5050505050614434565b98506129db565b60408051808201918290526129d8918b9161185a91869190869060029082845b81548152602001906001019080831161144f575b5050505050614434565b614997565b98505b5b6001909601956127bd565b8860005b6020020151158015612a0357508860015b6020020151155b15612a115760019950612a16565b600099505b5b50505050505050505092915050565b335b90565b6000612a35615450565b612a3f84846132e2565b90508060005b60200201518560005b6020020151148015612a6f57508060015b60200201518560015b6020020151145b15612a7d5760019150612a82565b600091505b509392505050565b6000828152600460205260409020612aa490826002615556565b506005805460010190555b5050565b612abb6154c9565b612ac3615450565b612acb615478565b600080808060008051602061569f83398151915286825b602002015260008051602061565f8339815191528660015b6020020152612b0888614bec565b1515612b145760006000fd5b612b1e8987614434565b9450612b30856401000003d01961493b565b60023360008051602061569f83398151915260008051602061565f8339815191528b896000604051602001526040518086600160a060020a0316600160a060020a0316606060020a02815260140185815260200184815260200183600260200280838360008314612bbc575b805182526020831115612bbc57601f199092019160209182019101612b9c565b5050509190910190508260608083835b805182526020831115612bec57601f199092019160209182019101612bcc565b5050509050019550505050505060206040518083038160008661646e5a03f11515612c1357fe5b505060405151935083925060008051602061567f833981519152838b099150612c3c898361209a565b9050808760005b60200201528460005b60200201518760015b60200201528460015b60200201518760025b60200201528460025b60200201518760035b60200201525b5050505050509392505050565b612c94615450565b612c9c615450565b60006000612ca8615478565b60006000612cb589614bec565b1515612cc15760006000fd5b612cca88614bec565b1515612cd65760006000fd5b6040805180820191829052612d0f918d919060009060029082845b81548152602001906001019080831161144f575b5050505050614434565b9250612d21836401000003d01961493b565b8260005b60200201518760005b60200201528260015b60200201518760015b60200201526040805180820191829052612d7d918c9190600290819081845b81548152602001906001019080831161144f575b5050505050614434565b9250612d8f836401000003d01961493b565b8260005b60200201518660005b60200201528260015b60200201518660015b602002018181525050600233600060028c8c8c8c6000604051602001526040518088600160a060020a0316600160a060020a0316606060020a0281526014018760028015612e11576020028201915b815481526020019060010190808311612dfd575b5050604081019087905b815481526020019060010190808311612e1b575b5086905060408083835b805182526020831115612e5957601f199092019160209182019101612e39565b5050509190910190508460408083835b805182526020831115612e8957601f199092019160209182019101612e69565b5050509190910190508360408083835b805182526020831115612eb957601f199092019160209182019101612e99565b5050509190910190508260408083835b805182526020831115612ee957601f199092019160209182019101612ec9565b50505090500197505050505050505060206040518083038160008661646e5a03f11515612f1257fe5b5050604051519150612f248f8f61209a565b945060008051602061567f833981519152828609905060008051602061567f8339815191528b82089450612f588d8d61209a565b935060008051602061567f833981519152828509905060008051602061567f8339815191528a820893505b50505098509850985098945050505050565b612f9d615450565b612fa5615450565b612fad615478565b612fb5615478565b612fbf8787614434565b9150612fcb8786614434565b9050612fdd826401000003d01961493b565b612fed816401000003d01961493b565b8160005b60200201518460005b60200201528160015b60200201518460015b60200201528060005b60200201518360005b60200201528060015b60200201518360015b60200201525b5050935093915050565b6000600061304c615478565b613054615478565b61305c615478565b613064615478565b60023389898f8f8f8f6000604051602001526040518088600160a060020a0316600160a060020a0316606060020a028152601401876002602002808383600083146130ca575b8051825260208311156130ca57601f1990920191602091820191016130aa565b5050509190910190508660408083835b8051825260208311156130fa57601f1990920191602091820191016130da565b5050509190910190508560408083835b80518252602083111561312a57601f19909201916020918201910161310a565b5050509190910190508460408083835b80518252602083111561315a57601f19909201916020918201910161313a565b5050509190910190508360408083835b80518252602083111561318a57601f19909201916020918201910161316a565b5050509190910190508260408083835b8051825260208311156131ba57601f19909201916020918201910161319a565b50505090500197505050505050505060206040518083038160008661646e5a03f115156131e357fe5b50506040515194506131f58d8d614434565b9350613201858b614434565b925061320d8484614997565b915061321f826401000003d01961493b565b8160005b60200201518860005b602002015114158061324e57508160015b60200201518860015b602002015114155b1561325c57600095506132d2565b6132668d8c614434565b9350613272858a614434565b925061327e8484614997565b9050613290816401000003d01961493b565b8060005b60200201518760005b60200201511415806132bf57508060015b60200201518760015b602002015114155b156132cd57600095506132d2565b600195505b5050505050979650505050505050565b6132ea615450565b6132f2615478565b6132fa615478565b613302615478565b61330a615450565b60408051808201918290526133439188919060009060029082845b81548152602001906001019080831161144f575b5050505050614434565b604080518082019182905291955061337d918991600290819081845b81548152602001906001019080831161144f575b5050505050614434565b92506133898484614997565b915061339b826401000003d01961493b565b8160005b60200201518160005b60200201528160015b60200201518160015b60200201526133c881614bec565b15156133d45760006000fd5b8094505b5050505092915050565b6133ea615450565b6133f2615478565b604080518082019182905261146d9185919060009060029082845b81548152602001906001019080831161144f575b5050505050614434565b905061147f816401000003d01961493b565b8060005b60200201518260005b60200201528060015b60200201518260015b60200201525b50919050565b6000613472615450565b61347a615478565b613482615478565b61348b8b614bec565b158061349d575061349b8a614bec565b155b806134ae57506134ac89614bec565b155b806134bf57506134bd88614bec565b155b806134d057506134ce87614bec565b155b806134e157506134df86614bec565b155b806134f257506134f085614bec565b155b1561350057600093506139b6565b60008051602061567f8339815191528c60015b60200201518d60005b6020020151086002338d8c8c8c8c8c6000604051602001526040518088600160a060020a0316600160a060020a0316606060020a02815260140187600260200280838360008314613588575b80518252602083111561358857601f199092019160209182019101613568565b5050509190910190508660408083835b8051825260208311156135b857601f199092019160209182019101613598565b5050509190910190508560408083835b8051825260208311156135e857601f1990920191602091820191016135c8565b5050509190910190508460408083835b80518252602083111561361857601f1990920191602091820191016135f8565b5050509190910190508360408083835b80518252602083111561364857601f199092019160209182019101613628565b5050509190910190508260408083835b80518252602083111561367857601f199092019160209182019101613658565b50505090500197505050505050505060206040518083038160008661646e5a03f115156136a157fe5b505060405151146136b557600093506139b6565b6136f48c60025b602002015160408051808201918290529060009060029082845b81548152602001906001019080831161144f575b5050505050614434565b91506137118261185a8e60005b60200201518e614434565b614997565b9050613723816401000003d01961493b565b8060005b60200201518860005b602002015114158061375257508060015b60200201518860015b602002015114155b1561376057600093506139b6565b6137728c60025b60200201518b614434565b915061378f8261185a8e60005b60200201518c614434565b614997565b90506137a1816401000003d01961493b565b8060005b60200201518760005b60200201511415806137d057508060015b60200201518760015b602002015114155b156137de57600093506139b6565b6138218c60036136bc565b602002015160408051808201918290529060009060029082845b81548152602001906001019080831161144f575b5050505050614434565b91506138428261185a8e6001613701565b60200201518e614434565b614997565b9050613854816401000003d01961493b565b8060005b60200201518660005b602002015114158061388357508060015b60200201518660015b602002015114155b1561389157600093506139b6565b6000805b0160005b50548360005b6020020152600060015b0160005b50546401000003d019038360015b60200201528860005b60200201518160005b60200201528860015b60200201518160015b602002015260018160025b60200201526138f98184614c97565b915061390b826401000003d01961493b565b8160005b60200201518360005b60200201528160015b60200201518360015b60200201526139418c60015b602002015184614434565b91506139626119138d600361377f565b60200201518c614434565b83614997565b9050613974816401000003d01961493b565b8060005b60200201518560005b60200201511415806139a357508060015b60200201518560015b602002015114155b156139b157600093506139b6565b600193505b50505098975050505050505050565b600460205260008281526040902081600281106139de57fe5b0160005b91509150505481565b6139f36154a0565b6139fb6154c9565b613a03615478565b613a0b615450565b60006000613a19878c614434565b6040805180820191829052919550613a5491869160009060029082845b815481526020019060010190808311613a36575b5050505050614f82565b613a64846401000003d01961493b565b8360005b60200201518660005b60200201528360015b60200201518660015b60200201526040805180820191829052613ac1918b919060009060029082845b81548152602001906001019080831161144f575b5050505050614434565b9350613ad68461185a8a8f614434565b614997565b9350613ae8846401000003d01961493b565b8360005b60200201518660025b60200201528360015b60200201518660035b6020020152613b16898c614434565b93508560005b60200201518360005b60200201528560015b60200201518360015b6020020152613b4f8461185a8a86614434565b614997565b9350613b61846401000003d01961493b565b8360005b60200201518660045b60200201528360015b60200201518660055b60200201526040805180820191829052613bbe918c919060009060029082845b81548152602001906001019080831161144f575b5050505050614434565b9350613bd0846401000003d01961493b565b8360005b60200201518660065b60200201528360015b60200201518660075b6020020152613bfe8a8c614434565b9350613c10846401000003d01961493b565b8360005b60200201518660085b60200201528360015b60200201518660095b6020020181815250506002338d886000604051602001526040518084600160a060020a0316600160a060020a0316606060020a02815260140183600260200280838360008314613c9a575b805182526020831115613c9a57601f199092019160209182019101613c7a565b505050919091019050826101408083835b805182526020831115613ccb57601f199092019160209182019101613cab565b505050905001935050505060206040518083038160008661646e5a03f11515613cf057fe5b5050604051519150819050613d05818961209a565b8360005b6020020152613d358a60008051602061567f833981519152856000611a3d565b60200201518a0961209a565b8360015b6020020152878560005b60200201528260005b60200201518560015b6020020152888560025b60200201528260015b6020020151856003611a85565b60200201525b50505050965096945050505050565b613d92615478565b613d9a615478565b613da2615478565b613daa615450565b613db2615478565b8760005b60200201518460005b60200201528760015b60200201516401000003d019038460015b602002015260018460025b6020020152613df3848a614c97565b9250613e05836401000003d01961493b565b8260005b60200201518260005b60200201528260015b60200201518260015b6020020152613e338683614434565b9050613e3f8188614c97565b945061208e856401000003d01961493b565b5b50505050949350505050565b61142d615450565b611435615478565b604080518082019182905261146d91859190600290819081845b81548152602001906001019080831161144f575b5050505050614434565b905061147f816401000003d01961493b565b806000611483565b602002015182600061148c565b6020020152806001611495565b602002015182600161149e565b60200201525b50919050565b60006000613eff615478565b613f07615478565b613f0f615478565b613f17615478565b613f208c614bec565b1515613f2c5760006000fd5b613f358b614bec565b1515613f415760006000fd5b613f4a8a614bec565b1515613f565760006000fd5b613f5f89614bec565b1515613f6b5760006000fd5b600233600060028f8f8f8f6000604051602001526040518088600160a060020a0316600160a060020a0316606060020a0281526014018760028015613fc5576020028201915b815481526020019060010190808311613fb1575b5050604081019087905b815481526020019060010190808311613fcf575b5086905060408083835b80518252602083111561400d57601f199092019160209182019101613fed565b5050509190910190508460408083835b80518252602083111561403d57601f19909201916020918201910161401d565b5050509190910190508360408083835b80518252602083111561406d57601f19909201916020918201910161404d565b5050509190910190508260408083835b80518252602083111561409d57601f19909201916020918201910161407d565b50505090500197505050505050505060206040518083038160008661646e5a03f115156140c657fe5b50506040515194506140da8c8c8b88613d8a565b6040805180820191829052919550614114918991600290819081845b81548152602001906001019080831161144f575b5050505050614434565b9250614126836401000003d01961493b565b8360005b60200201518360005b60200201511415801561415657508360015b60200201518360015b602002015114155b1561422b57614165848b614c97565b9150614177826401000003d01961493b565b8160005b60200201518460005b60200201528160015b60200201518460015b602002015260408051808201918290526141dd916141d7918b9160009060029082845b81548152602001906001019080831161144f575b5050505050614434565b84614997565b90506141ef816401000003d01961493b565b8360005b60200201518160005b602002015114801561421d57508360015b60200201518160015b6020020151145b1561422b5760019550614231565b5b600095505b50505050509695505050505050565b600061424a615450565b60006000614256615478565b61425e615478565b614266615478565b60008051602061569f8339815191528660005b602002015260008051602061565f8339815191528660015b602002015261429f8a614bec565b15806142b157506142af886151c3565b155b156142bf5760009650612c7f565b60023360008051602061569f83398151915260008051602061565f8339815191528d8c6000604051602001526040518086600160a060020a0316600160a060020a0316606060020a0281526014018581526020018481526020018360026020028083836000831461434b575b80518252602083111561434b57601f19909201916020918201910161432b565b5050509190910190508260608083835b80518252602083111561437b57601f19909201916020918201910161435b565b5050509050019550505050505060206040518083038160008661646e5a03f115156143a257fe5b50506040515194508493506143b78987614434565b92506143c3848b614434565b91506143cf8383614997565b90506143e1816401000003d01961493b565b8760005b60200201518160005b602002015114801561440f57508760015b60200201518160015b6020020151145b1561441d5760019650612c7f565b60009650612c7f565b5b5050505050509392505050565b61443c615478565b60006000600061444a615595565b614452615478565b61445a6155c4565b6401000003d0199550600080808b151561447357612a16565b6000604051985061020089016040525b8c156144bb5760018d16156144aa575060208c06808989015360206010821102818e03019c505b60028d049c50600188019750614483565b506040805160608101909152808c60005b602090810291909101518252018c60015b60209081029190910151825260019101528660005b60200201526145088660005b6020020151615203565b9450614514858c614c97565b8660015b602002015261452f858760015b6020020151614997565b8660025b602002015261454e85876002614525565b6020020151614997565b8660035b602002015261456d85876003614525565b6020020151614997565b8660045b602002015261458c85876004614525565b6020020151614997565b8660055b60200201526145ab85876005614525565b6020020151614997565b8660065b60200201526145ca85876006614525565b6020020151614997565b8660075b60200201528560015b602002015160025b60200201518460005b6020020152888460005b60200201518760025b602002015160025b6020020151098460015b6020020152888460015b60200201518760035b602002015160025b6020020151098460025b6020020152888460025b60200201518760045b602002015160025b6020020151098460035b6020020152888460035b60200201518760055b602002015160025b6020020151098460045b6020020152888460045b60200201518760065b602002015160025b6020020151098460055b6020020152888460055b60200201518760075b602002015160025b6020020151098460065b60200201526146dd8460065b60200201518a614ee9565b8460075b60200201528360075b60200201518460085b6020020152888460085b60200201518560055b60200201510984600f5b6020020152600692505b6002831061479357888460085b602002015187600186016008811061473b57fe5b602002015160025b6020020151098460085b6020020152888460085b60200201518560011986016010811061476c57fe5b60200201510984600885016010811061478157fe5b60200201525b6000199092019161471a565b888460085b60200201518760025b602002015160025b6020020151098460095b6020020152600092505b600783101561482d576148218660018501600881106147d857fe5b60200201518560098601601081106147ec57fe5b60200201518b87600988016010811061480157fe5b602002015188600989016010811061481557fe5b6020020151098c6152b9565b5b6001909201916147bd565b5b6000871115612a165760001987890181015197019660001a91506148518a615304565b60108211156148be576002601f8390035b0490506148b98a604060405190810160405280898560088110151561488357fe5b602002015160005b6020020151815260200189856008811015156148a357fe5b602002015160015b60200201518d039052614f82565b614924565b600082111561492457600260001983015b0490506149248a60406040519081016040528089856008811015156148f057fe5b602002015160005b60200201518152602001898560088110151561491057fe5b602002015160015b60200201519052614f82565b5b5b61482d565b5b50505050505050505092915050565b6000806149508460025b602002015184614ee9565b915082828309905082818560005b6020020151098460005b602002015282808284098560015b6020020151098460015b602002015260018460025b60200201525b50505050565b61499f615478565b60006149a96154c9565b6149b16154c9565b6000808080808a60025b602002015115156149ce57899850614bde565b8960025b602002015115156149e5578a9850614bde565b6401000003d0199750878b60025b60200201518c60025b6020020151098760005b6020020152878760005b60200201518c60025b6020020151098760015b6020020152878a60025b60200201518b60025b6020020151098760025b6020020152878760025b60200201518b60025b6020020151098760035b6020020152604080516080810190915280898960025b60200201518e60005b6020020151098152602001898960035b60200201518e60015b6020020151098152602001898960005b60200201518d60005b6020020151098152602001898960015b60200201518d60015b602002015109905295508560025b60200201518660005b60200201511415614b15578560035b60200201518660015b602002015114614b0557614bde565b614b0e8b615203565b9850614bde565b5b878660005b602002015189038760025b6020020151089450878660015b602002015189038760035b60200201510893508785860992508785840991508782890389868709089050878080858960005b602002015109600209890382089050808960005b6020020152878082810381868a60005b6020020151090885098960015b60200201528780838860015b60200201510989038a60015b6020020151088960015b602002015287808b60025b60200201518d60025b60200201510986098960025b60200201525b505050505050505092915050565b6000614bf7826153b0565b90505b919050565b600080841515614c125760009150612a82565b831515614c225760019150612a82565b821515614c2f5760006000fd5b506001905060ff60020a5b8015612a8257828185161515860a84848509099150826002820485161515860a84848509099150826004820485161515860a84848509099150826008820485161515860a8484850909915060109004614c3a565b5b509392505050565b614c9f615478565b6000614ca9615450565b614cb16154c9565b6000808080808a60025b60200201511515614cfd576040805160608101909152808b60005b602090810291909101518252018b60015b6020020151815260200160018152509850614bde565b8960015b60200201511515614d14578a9850614bde565b6401000003d0199750878b60025b60200201518c60025b6020020151098760005b6020020152878760005b60200201518c60025b6020020151098760015b60200201526040805160808101909152808c60005b602090810291909101518252018c60015b60209081029190910151825201898960005b60200201518d60005b6020020151098152602001898960015b60200201518d60015b602002015109905295508560025b60200201518660005b60200201511415614e19578560035b60200201518660015b602002015114614e0a5760008b815b602002015260008b60015b602002015260008b60025b6020020152614bde565b614e138b615203565b50614bde565b5b878660005b602002015189038760025b6020020151089450878660015b602002015189038760035b60200201510893508785860992508785840991508782890389868709089050878080858960005b602002015109600209890382089050808960005b6020020152878082810381868a60005b6020020151090885098960015b60200201528780838860015b60200201510989038a60015b6020020151088960015b6020020152878b60025b60200201518609896002614bd8565b60200201525b505050505050505092915050565b60008080808080871580614efc57508688145b80614f05575086155b15614f105760006000fd5b86881115614f27578688811515614f2357fe5b0697505b600193508692508791505b8115614f5d578183811515614f4357fe5b949594048581029094039391928383029003919050614f32565b6000851215614f73578460000387039550614f77565b8495505b505050505092915050565b6000614f8c615450565b614f946154c9565b6000808080808960015b60200201511515614fdd578860005b60200201518a60005b60200201528860015b60200201518a60015b602002015260018a60025b60200201526151b7565b8860015b60200201511515614ff1576151b7565b6401000003d0199750878a60025b60200201518b60025b6020020151098760005b6020020152878760005b60200201518b60025b6020020151098760015b60200201526040805160808101909152808b60005b602090810291909101518252018b60015b60209081029190910151825201898960005b60200201518c60005b6020020151098152602001898960015b60200201518c60015b602002015109905295508560025b60200201518660005b602002015114156150f9578560035b60200201518660015b6020020151146150eb5760008a815b602002015260008a60015b602002015260008a6002614fd3565b60200201526151b7565b6150f48a615304565b6151b7565b5b878660005b602002015189038760025b6020020151089450878660015b602002015189038760035b60200201510893508785860992508785840991508782890389868709089050878080858960005b602002015109600209890382089050808a60005b6020020152878082810381868a60005b6020020151090885098a60015b60200201528780838860015b60200201510989038b60015b6020020151088a60015b6020020152878a60025b602002015186098a60025b60200201525b50505050505050505050565b60006151cd615450565b8260005b60200201518160005b60200201528260015b60200201518160015b60200201526151fa816153b0565b91505b50919050565b61520b615478565b6401000003d019600080808080808860025b6020020151151561522d576152ad565b8860005b602002015195508860015b6020020151945086858609935086878588096004099250868787880960030991508687848508880388848509089050808860005b602002015286808086800960080988038889848b0387088509088860015b602002015286808a60025b602002015187096002098860025b60200201525b50505050505050919050565b80828560005b6020020151098460005b60200201528080838509856001614976565b602002015109846001614980565b6020020152600184600261498b565b60200201525b50505050565b6401000003d019600080808080808760025b60200201511515615326576153a6565b8760005b602002015195508760015b6020020151945086858609935086878588096004099250868787880960030991508687848508880388848509089050808860005b602002015286808086800960080988038889848b0387088509088860015b602002015286808960025b602002015187096002098860025b60200201525b5050505050505050565b60006401000003d019818084815b602002015115806153d65750828560005b6020020151145b806153e757508460015b6020020151155b806153f95750828560015b6020020151145b156154075760009350615448565b828560015b60200201518660015b6020020151099150826007818760005b6020020151868960005b60200201518a60005b6020020151090908905080821493505b505050919050565b6040604051908101604052806002905b60008152602001906001900390816154605790505090565b6060604051908101604052806003905b60008152602001906001900390816154605790505090565b61014060405190810160405280600a905b60008152602001906001900390816154605790505090565b6080604051908101604052806004905b60008152602001906001900390816154605790505090565b60c0604051908101604052806006905b60008152602001906001900390816154605790505090565b60408051602081019091526000815290565b60406040519081016040528061553f615450565b905290565b60408051602081019091526000815290565b8260028101928215615584579160200282015b82811115615584578251825591602001919060010190615569565b5b50615591929150615615565b5090565b610300604051908101604052806008905b6155ae615478565b8152602001906001900390816155a65790505090565b610200604051908101604052806010905b60008152602001906001900390816154605790505090565b6040604051908101604052806002905b60008152602001906001900390816154605790505090565b6114e391905b80821115615591576000815560010161561b565b5090565b90565b6060604051908101604052806003905b600081526020019060019003908161546057905050905600483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036414179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798a165627a7a72305820f86e2f6b5891d8dc6373afbf6191f6257efb90de657b12360225696705eec7be0029", 969 | "networks": { 970 | "1": { 971 | "events": {}, 972 | "links": {}, 973 | "address": "0xd0206e356da9267257eecda878ca8b0f85b93332", 974 | "updated_at": 1502021313354 975 | } 976 | }, 977 | "schema_version": "0.0.5", 978 | "updated_at": 1502021313354 979 | } -------------------------------------------------------------------------------- /build/contracts/Migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "Migrations", 3 | "abi": [ 4 | { 5 | "constant": false, 6 | "inputs": [ 7 | { 8 | "name": "new_address", 9 | "type": "address" 10 | } 11 | ], 12 | "name": "upgrade", 13 | "outputs": [], 14 | "payable": false, 15 | "type": "function" 16 | }, 17 | { 18 | "constant": true, 19 | "inputs": [], 20 | "name": "last_completed_migration", 21 | "outputs": [ 22 | { 23 | "name": "", 24 | "type": "uint256" 25 | } 26 | ], 27 | "payable": false, 28 | "type": "function" 29 | }, 30 | { 31 | "constant": true, 32 | "inputs": [], 33 | "name": "owner", 34 | "outputs": [ 35 | { 36 | "name": "", 37 | "type": "address" 38 | } 39 | ], 40 | "payable": false, 41 | "type": "function" 42 | }, 43 | { 44 | "constant": false, 45 | "inputs": [ 46 | { 47 | "name": "completed", 48 | "type": "uint256" 49 | } 50 | ], 51 | "name": "setCompleted", 52 | "outputs": [], 53 | "payable": false, 54 | "type": "function" 55 | }, 56 | { 57 | "inputs": [], 58 | "payable": false, 59 | "type": "constructor" 60 | } 61 | ], 62 | "unlinked_binary": "0x6060604052341561000c57fe5b5b60008054600160a060020a03191633600160a060020a03161790555b5b6101a0806100396000396000f300606060405263ffffffff60e060020a6000350416630900f0108114610042578063445df0ac146100605780638da5cb5b14610082578063fdacd576146100ae575bfe5b341561004a57fe5b61005e600160a060020a03600435166100c3565b005b341561006857fe5b61007061013d565b60408051918252519081900360200190f35b341561008a57fe5b610092610143565b60408051600160a060020a039092168252519081900360200190f35b34156100b657fe5b61005e600435610152565b005b6000805433600160a060020a03908116911614156101375781905080600160a060020a031663fdacd5766001546040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b151561012557fe5b6102c65a03f1151561013357fe5b5050505b5b5b5050565b60015481565b600054600160a060020a031681565b60005433600160a060020a039081169116141561016f5760018190555b5b5b505600a165627a7a723058201567f58849cffb802a81d9df83dabb534c194e73879a0838d71d5d057b6299520029", 63 | "networks": { 64 | "1": { 65 | "events": {}, 66 | "links": {}, 67 | "address": "0xe8d093bc87b9c3580e4d9079b1910c2678080dc4", 68 | "updated_at": 1502021313354 69 | } 70 | }, 71 | "schema_version": "0.0.5", 72 | "updated_at": 1502021313354 73 | } -------------------------------------------------------------------------------- /build/contracts/Secp256k1_noconflict.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "Secp256k1_noconflict", 3 | "abi": [], 4 | "unlinked_binary": "0x60606040523415600b57fe5b5b60338060196000396000f30060606040525bfe00a165627a7a723058204be4e005b11884b7cdb3f13c514cf5719b9104a2a59b1c4d330cbbe1c7f6c8a10029", 5 | "networks": {}, 6 | "schema_version": "0.0.5", 7 | "updated_at": 1502021271203 8 | } -------------------------------------------------------------------------------- /contracts/LocalCrypto.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.10; 2 | 3 | /** 4 | * @title ECCMath_noconflict 5 | * 6 | * Functions for working with integers, curve-points, etc. 7 | * 8 | * @author Andreas Olofsson (androlo1980@gmail.com) 9 | */ 10 | library ECCMath_noconflict { 11 | /// @dev Modular inverse of a (mod p) using euclid. 12 | /// "a" and "p" must be co-prime. 13 | /// @param a The number. 14 | /// @param p The mmodulus. 15 | /// @return x such that ax = 1 (mod p) 16 | function invmod(uint a, uint p) internal constant returns (uint) { 17 | if (a == 0 || a == p || p == 0) 18 | throw; 19 | if (a > p) 20 | a = a % p; 21 | int t1; 22 | int t2 = 1; 23 | uint r1 = p; 24 | uint r2 = a; 25 | uint q; 26 | while (r2 != 0) { 27 | q = r1 / r2; 28 | (t1, t2, r1, r2) = (t2, t1 - int(q) * t2, r2, r1 - q * r2); 29 | } 30 | if (t1 < 0) 31 | return (p - uint(-t1)); 32 | return uint(t1); 33 | } 34 | 35 | /// @dev Modular exponentiation, b^e % m 36 | /// Basically the same as can be found here: 37 | /// https://github.com/ethereum/serpent/blob/develop/examples/ecc/modexp.se 38 | /// @param b The base. 39 | /// @param e The exponent. 40 | /// @param m The modulus. 41 | /// @return x such that x = b**e (mod m) 42 | function expmod(uint b, uint e, uint m) internal constant returns (uint r) { 43 | if (b == 0) 44 | return 0; 45 | if (e == 0) 46 | return 1; 47 | if (m == 0) 48 | throw; 49 | r = 1; 50 | uint bit = 2 ** 255; 51 | bit = bit; 52 | assembly { 53 | loop: 54 | jumpi(end, iszero(bit)) 55 | r := mulmod(mulmod(r, r, m), exp(b, iszero(iszero(and(e, bit)))), m) 56 | r := mulmod(mulmod(r, r, m), exp(b, iszero(iszero(and(e, div(bit, 2))))), m) 57 | r := mulmod(mulmod(r, r, m), exp(b, iszero(iszero(and(e, div(bit, 4))))), m) 58 | r := mulmod(mulmod(r, r, m), exp(b, iszero(iszero(and(e, div(bit, 8))))), m) 59 | bit := div(bit, 16) 60 | jump(loop) 61 | end: 62 | } 63 | } 64 | 65 | /// @dev Converts a point (Px, Py, Pz) expressed in Jacobian coordinates to (Px", Py", 1). 66 | /// Mutates P. 67 | /// @param P The point. 68 | /// @param zInv The modular inverse of "Pz". 69 | /// @param z2Inv The square of zInv 70 | /// @param prime The prime modulus. 71 | /// @return (Px", Py", 1) 72 | function toZ1(uint[3] memory P, uint zInv, uint z2Inv, uint prime) internal constant { 73 | P[0] = mulmod(P[0], z2Inv, prime); 74 | P[1] = mulmod(P[1], mulmod(zInv, z2Inv, prime), prime); 75 | P[2] = 1; 76 | } 77 | 78 | /// @dev See _toZ1(uint[3], uint, uint). 79 | /// Warning: Computes a modular inverse. 80 | /// @param PJ The point. 81 | /// @param prime The prime modulus. 82 | /// @return (Px", Py", 1) 83 | function toZ1(uint[3] PJ, uint prime) internal constant { 84 | uint zInv = invmod(PJ[2], prime); 85 | uint zInv2 = mulmod(zInv, zInv, prime); 86 | PJ[0] = mulmod(PJ[0], zInv2, prime); 87 | PJ[1] = mulmod(PJ[1], mulmod(zInv, zInv2, prime), prime); 88 | PJ[2] = 1; 89 | } 90 | 91 | } 92 | 93 | library Secp256k1_noconflict { 94 | 95 | // TODO separate curve from crypto primitives? 96 | 97 | // Field size 98 | uint constant pp = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; 99 | 100 | // Base point (generator) G 101 | uint constant Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798; 102 | uint constant Gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8; 103 | 104 | // Order of G 105 | uint constant nn = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; 106 | 107 | // Cofactor 108 | // uint constant hh = 1; 109 | 110 | // Maximum value of s 111 | uint constant lowSmax = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0; 112 | 113 | // For later 114 | // uint constant lambda = "0x5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72"; 115 | // uint constant beta = "0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee"; 116 | 117 | /// @dev See Curve.onCurve 118 | function onCurve(uint[2] P) internal constant returns (bool) { 119 | uint p = pp; 120 | if (0 == P[0] || P[0] == p || 0 == P[1] || P[1] == p) 121 | return false; 122 | uint LHS = mulmod(P[1], P[1], p); 123 | uint RHS = addmod(mulmod(mulmod(P[0], P[0], p), P[0], p), 7, p); 124 | return LHS == RHS; 125 | } 126 | 127 | /// @dev See Curve.isPubKey 128 | function isPubKey(uint[2] memory P) internal constant returns (bool isPK) { 129 | isPK = onCurve(P); 130 | } 131 | 132 | /// @dev See Curve.isPubKey 133 | // TODO: We assume we are given affine co-ordinates for now 134 | function isPubKey(uint[3] memory P) internal constant returns (bool isPK) { 135 | uint[2] memory a_P; 136 | a_P[0] = P[0]; 137 | a_P[1] = P[1]; 138 | isPK = onCurve(a_P); 139 | } 140 | 141 | /// @dev See Curve.validateSignature 142 | function validateSignature(bytes32 message, uint[2] rs, uint[2] Q) internal constant returns (bool) { 143 | uint n = nn; 144 | uint p = pp; 145 | if(rs[0] == 0 || rs[0] >= n || rs[1] == 0 || rs[1] > lowSmax) 146 | return false; 147 | if (!isPubKey(Q)) 148 | return false; 149 | 150 | uint sInv = ECCMath_noconflict.invmod(rs[1], n); 151 | uint[3] memory u1G = _mul(mulmod(uint(message), sInv, n), [Gx, Gy]); 152 | uint[3] memory u2Q = _mul(mulmod(rs[0], sInv, n), Q); 153 | uint[3] memory P = _add(u1G, u2Q); 154 | 155 | if (P[2] == 0) 156 | return false; 157 | 158 | uint Px = ECCMath_noconflict.invmod(P[2], p); // need Px/Pz^2 159 | Px = mulmod(P[0], mulmod(Px, Px, p), p); 160 | return Px % n == rs[0]; 161 | } 162 | 163 | /// @dev See Curve.compress 164 | function compress(uint[2] P) internal constant returns (uint8 yBit, uint x) { 165 | x = P[0]; 166 | yBit = P[1] & 1 == 1 ? 1 : 0; 167 | } 168 | 169 | /// @dev See Curve.decompress 170 | function decompress(uint8 yBit, uint x) internal constant returns (uint[2] P) { 171 | uint p = pp; 172 | var y2 = addmod(mulmod(x, mulmod(x, x, p), p), 7, p); 173 | var y_ = ECCMath_noconflict.expmod(y2, (p + 1) / 4, p); 174 | uint cmp = yBit ^ y_ & 1; 175 | P[0] = x; 176 | P[1] = (cmp == 0) ? y_ : p - y_; 177 | } 178 | 179 | // Point addition, P + Q 180 | // inData: Px, Py, Pz, Qx, Qy, Qz 181 | // outData: Rx, Ry, Rz 182 | function _add(uint[3] memory P, uint[3] memory Q) internal constant returns (uint[3] memory R) { 183 | if(P[2] == 0) 184 | return Q; 185 | if(Q[2] == 0) 186 | return P; 187 | uint p = pp; 188 | uint[4] memory zs; // Pz^2, Pz^3, Qz^2, Qz^3 189 | zs[0] = mulmod(P[2], P[2], p); 190 | zs[1] = mulmod(P[2], zs[0], p); 191 | zs[2] = mulmod(Q[2], Q[2], p); 192 | zs[3] = mulmod(Q[2], zs[2], p); 193 | uint[4] memory us = [ 194 | mulmod(P[0], zs[2], p), 195 | mulmod(P[1], zs[3], p), 196 | mulmod(Q[0], zs[0], p), 197 | mulmod(Q[1], zs[1], p) 198 | ]; // Pu, Ps, Qu, Qs 199 | if (us[0] == us[2]) { 200 | if (us[1] != us[3]) 201 | return; 202 | else { 203 | return _double(P); 204 | } 205 | } 206 | uint h = addmod(us[2], p - us[0], p); 207 | uint r = addmod(us[3], p - us[1], p); 208 | uint h2 = mulmod(h, h, p); 209 | uint h3 = mulmod(h2, h, p); 210 | uint Rx = addmod(mulmod(r, r, p), p - h3, p); 211 | Rx = addmod(Rx, p - mulmod(2, mulmod(us[0], h2, p), p), p); 212 | R[0] = Rx; 213 | R[1] = mulmod(r, addmod(mulmod(us[0], h2, p), p - Rx, p), p); 214 | R[1] = addmod(R[1], p - mulmod(us[1], h3, p), p); 215 | R[2] = mulmod(h, mulmod(P[2], Q[2], p), p); 216 | } 217 | 218 | // Point addition, P + Q. P Jacobian, Q affine. 219 | // inData: Px, Py, Pz, Qx, Qy 220 | // outData: Rx, Ry, Rz 221 | function _addMixed(uint[3] memory P, uint[2] memory Q) internal constant returns (uint[3] memory R) { 222 | if(P[2] == 0) 223 | return [Q[0], Q[1], 1]; 224 | if(Q[1] == 0) 225 | return P; 226 | uint p = pp; 227 | uint[2] memory zs; // Pz^2, Pz^3, Qz^2, Qz^3 228 | zs[0] = mulmod(P[2], P[2], p); 229 | zs[1] = mulmod(P[2], zs[0], p); 230 | uint[4] memory us = [ 231 | P[0], 232 | P[1], 233 | mulmod(Q[0], zs[0], p), 234 | mulmod(Q[1], zs[1], p) 235 | ]; // Pu, Ps, Qu, Qs 236 | if (us[0] == us[2]) { 237 | if (us[1] != us[3]) { 238 | P[0] = 0; 239 | P[1] = 0; 240 | P[2] = 0; 241 | return; 242 | } 243 | else { 244 | _double(P); 245 | return; 246 | } 247 | } 248 | uint h = addmod(us[2], p - us[0], p); 249 | uint r = addmod(us[3], p - us[1], p); 250 | uint h2 = mulmod(h, h, p); 251 | uint h3 = mulmod(h2, h, p); 252 | uint Rx = addmod(mulmod(r, r, p), p - h3, p); 253 | Rx = addmod(Rx, p - mulmod(2, mulmod(us[0], h2, p), p), p); 254 | R[0] = Rx; 255 | R[1] = mulmod(r, addmod(mulmod(us[0], h2, p), p - Rx, p), p); 256 | R[1] = addmod(R[1], p - mulmod(us[1], h3, p), p); 257 | R[2] = mulmod(h, P[2], p); 258 | } 259 | 260 | // Same as addMixed but params are different and mutates P. 261 | function _addMixedM(uint[3] memory P, uint[2] memory Q) internal constant { 262 | if(P[1] == 0) { 263 | P[0] = Q[0]; 264 | P[1] = Q[1]; 265 | P[2] = 1; 266 | return; 267 | } 268 | if(Q[1] == 0) 269 | return; 270 | uint p = pp; 271 | uint[2] memory zs; // Pz^2, Pz^3, Qz^2, Qz^3 272 | zs[0] = mulmod(P[2], P[2], p); 273 | zs[1] = mulmod(P[2], zs[0], p); 274 | uint[4] memory us = [ 275 | P[0], 276 | P[1], 277 | mulmod(Q[0], zs[0], p), 278 | mulmod(Q[1], zs[1], p) 279 | ]; // Pu, Ps, Qu, Qs 280 | if (us[0] == us[2]) { 281 | if (us[1] != us[3]) { 282 | P[0] = 0; 283 | P[1] = 0; 284 | P[2] = 0; 285 | return; 286 | } 287 | else { 288 | _doubleM(P); 289 | return; 290 | } 291 | } 292 | uint h = addmod(us[2], p - us[0], p); 293 | uint r = addmod(us[3], p - us[1], p); 294 | uint h2 = mulmod(h, h, p); 295 | uint h3 = mulmod(h2, h, p); 296 | uint Rx = addmod(mulmod(r, r, p), p - h3, p); 297 | Rx = addmod(Rx, p - mulmod(2, mulmod(us[0], h2, p), p), p); 298 | P[0] = Rx; 299 | P[1] = mulmod(r, addmod(mulmod(us[0], h2, p), p - Rx, p), p); 300 | P[1] = addmod(P[1], p - mulmod(us[1], h3, p), p); 301 | P[2] = mulmod(h, P[2], p); 302 | } 303 | 304 | // Point doubling, 2*P 305 | // Params: Px, Py, Pz 306 | // Not concerned about the 1 extra mulmod. 307 | function _double(uint[3] memory P) internal constant returns (uint[3] memory Q) { 308 | uint p = pp; 309 | if (P[2] == 0) 310 | return; 311 | uint Px = P[0]; 312 | uint Py = P[1]; 313 | uint Py2 = mulmod(Py, Py, p); 314 | uint s = mulmod(4, mulmod(Px, Py2, p), p); 315 | uint m = mulmod(3, mulmod(Px, Px, p), p); 316 | var Qx = addmod(mulmod(m, m, p), p - addmod(s, s, p), p); 317 | Q[0] = Qx; 318 | Q[1] = addmod(mulmod(m, addmod(s, p - Qx, p), p), p - mulmod(8, mulmod(Py2, Py2, p), p), p); 319 | Q[2] = mulmod(2, mulmod(Py, P[2], p), p); 320 | } 321 | 322 | // Same as double but mutates P and is internal only. 323 | function _doubleM(uint[3] memory P) internal constant { 324 | uint p = pp; 325 | if (P[2] == 0) 326 | return; 327 | uint Px = P[0]; 328 | uint Py = P[1]; 329 | uint Py2 = mulmod(Py, Py, p); 330 | uint s = mulmod(4, mulmod(Px, Py2, p), p); 331 | uint m = mulmod(3, mulmod(Px, Px, p), p); 332 | var PxTemp = addmod(mulmod(m, m, p), p - addmod(s, s, p), p); 333 | P[0] = PxTemp; 334 | P[1] = addmod(mulmod(m, addmod(s, p - PxTemp, p), p), p - mulmod(8, mulmod(Py2, Py2, p), p), p); 335 | P[2] = mulmod(2, mulmod(Py, P[2], p), p); 336 | } 337 | 338 | // Multiplication dP. P affine, wNAF: w=5 339 | // Params: d, Px, Py 340 | // Output: Jacobian Q 341 | function _mul(uint d, uint[2] memory P) internal constant returns (uint[3] memory Q) { 342 | uint p = pp; 343 | if (d == 0) // TODO 344 | return; 345 | uint dwPtr; // points to array of NAF coefficients. 346 | uint i; 347 | 348 | // wNAF 349 | assembly 350 | { 351 | let dm := 0 352 | dwPtr := mload(0x40) 353 | mstore(0x40, add(dwPtr, 512)) // Should lower this. 354 | loop: 355 | jumpi(loop_end, iszero(d)) 356 | jumpi(even, iszero(and(d, 1))) 357 | dm := mod(d, 32) 358 | mstore8(add(dwPtr, i), dm) // Don"t store as signed - convert when reading. 359 | d := add(sub(d, dm), mul(gt(dm, 16), 32)) 360 | even: 361 | d := div(d, 2) 362 | i := add(i, 1) 363 | jump(loop) 364 | loop_end: 365 | } 366 | 367 | dwPtr = dwPtr; 368 | 369 | // Pre calculation 370 | uint[3][8] memory PREC; // P, 3P, 5P, 7P, 9P, 11P, 13P, 15P 371 | PREC[0] = [P[0], P[1], 1]; 372 | var X = _double(PREC[0]); 373 | PREC[1] = _addMixed(X, P); 374 | PREC[2] = _add(X, PREC[1]); 375 | PREC[3] = _add(X, PREC[2]); 376 | PREC[4] = _add(X, PREC[3]); 377 | PREC[5] = _add(X, PREC[4]); 378 | PREC[6] = _add(X, PREC[5]); 379 | PREC[7] = _add(X, PREC[6]); 380 | 381 | uint[16] memory INV; 382 | INV[0] = PREC[1][2]; // a1 383 | INV[1] = mulmod(PREC[2][2], INV[0], p); // a2 384 | INV[2] = mulmod(PREC[3][2], INV[1], p); // a3 385 | INV[3] = mulmod(PREC[4][2], INV[2], p); // a4 386 | INV[4] = mulmod(PREC[5][2], INV[3], p); // a5 387 | INV[5] = mulmod(PREC[6][2], INV[4], p); // a6 388 | INV[6] = mulmod(PREC[7][2], INV[5], p); // a7 389 | 390 | INV[7] = ECCMath_noconflict.invmod(INV[6], p); // a7inv 391 | INV[8] = INV[7]; // aNinv (a7inv) 392 | 393 | INV[15] = mulmod(INV[5], INV[8], p); // z7inv 394 | for(uint k = 6; k >= 2; k--) { // z6inv to z2inv 395 | INV[8] = mulmod(PREC[k + 1][2], INV[8], p); 396 | INV[8 + k] = mulmod(INV[k - 2], INV[8], p); 397 | } 398 | INV[9] = mulmod(PREC[2][2], INV[8], p); // z1Inv 399 | for(k = 0; k < 7; k++) { 400 | ECCMath_noconflict.toZ1(PREC[k + 1], INV[k + 9], mulmod(INV[k + 9], INV[k + 9], p), p); 401 | } 402 | 403 | // Mult loop 404 | while(i > 0) { 405 | uint dj; 406 | uint pIdx; 407 | i--; 408 | assembly { 409 | dj := byte(0, mload(add(dwPtr, i))) 410 | } 411 | _doubleM(Q); 412 | if (dj > 16) { 413 | pIdx = (31 - dj) / 2; // These are the "negative ones", so invert y. 414 | _addMixedM(Q, [PREC[pIdx][0], p - PREC[pIdx][1]]); 415 | } 416 | else if (dj > 0) { 417 | pIdx = (dj - 1) / 2; 418 | _addMixedM(Q, [PREC[pIdx][0], PREC[pIdx][1]]); 419 | } 420 | } 421 | } 422 | 423 | } 424 | 425 | /* 426 | * @title LocalCrypto 427 | * Allow local calls to create and verify zkp. 428 | * Author: Patrick McCorry 429 | */ 430 | contract LocalCrypto { 431 | 432 | // Modulus for public keys 433 | uint constant pp = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; 434 | 435 | // Base point (generator) G 436 | uint constant Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798; 437 | uint constant Gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8; 438 | 439 | // New point (generator) Y 440 | uint constant Yx = 98038005178408974007512590727651089955354106077095278304532603697039577112780; 441 | uint constant Yy = 1801119347122147381158502909947365828020117721497557484744596940174906898953; 442 | 443 | // Modulus for private keys (sub-group) 444 | uint constant nn = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; 445 | 446 | uint[2] G; 447 | uint[2] Y; 448 | 449 | struct ECPoint { 450 | uint[2] points; 451 | } 452 | 453 | // 2 round anonymous voting protocol 454 | // TODO: Right now due to gas limits there is an upper limit 455 | // on the number of participants that we can have voting... 456 | // I need to split the functions up... so if they cannot 457 | // finish their entire workload in 1 transaction, then 458 | // it does the maximum. This way we can chain transactions 459 | // to complete the job... 460 | function LocalCrypto() { 461 | G[0] = Gx; 462 | G[1] = Gy; 463 | 464 | Y[0] = Yx; 465 | Y[1] = Yy; 466 | } 467 | 468 | // a - b = c (include your own modulus) 469 | function submod(uint a, uint b, uint prime) returns (uint){ 470 | uint a_nn; 471 | 472 | if(a>b) { 473 | a_nn = a; 474 | } else { 475 | a_nn = a+prime; 476 | } 477 | 478 | uint c = addmod(a_nn - b,0,prime); 479 | 480 | return c; 481 | } 482 | 483 | // Create a public key using second genrator 484 | function createPubKeyWithY(uint r) returns (uint[2] key){ 485 | uint[3] memory jacob_key = Secp256k1_noconflict._mul(r,Y); 486 | ECCMath_noconflict.toZ1(jacob_key, pp); 487 | 488 | key[0] = jacob_key[0]; 489 | key[1] = jacob_key[1]; 490 | return key; 491 | } 492 | 493 | // Fuction used by test framework to quickly perform multiplication 494 | function mul(uint r, uint[2] gen) returns (uint[2] res){ 495 | uint[3] memory temp = Secp256k1_noconflict._mul(r, gen); 496 | ECCMath_noconflict.toZ1(temp, pp); 497 | res[0] = temp[0]; 498 | res[1] = temp[1]; 499 | } 500 | 501 | // Fuction used by test framework to quickly perform multiplication 502 | function mulG(uint r) returns (uint[2] res){ 503 | uint[3] memory temp = Secp256k1_noconflict._mul(r, G); 504 | ECCMath_noconflict.toZ1(temp, pp); 505 | res[0] = temp[0]; 506 | res[1] = temp[1]; 507 | } 508 | 509 | function mulY(uint r) returns (uint[2] res){ 510 | uint[3] memory temp = Secp256k1_noconflict._mul(r, Y); 511 | ECCMath_noconflict.toZ1(temp, pp); 512 | res[0] = temp[0]; 513 | res[1] = temp[1]; 514 | } 515 | 516 | function getG() returns (uint[2]){ 517 | return G; 518 | } 519 | 520 | function getY() returns (uint[2]) { 521 | return Y; 522 | } 523 | 524 | // Combine three shares that have the form y^{s_{i}} to recreate secret y^{s}. 525 | function joinShares(uint[2] share1, uint[2] share2, uint[2] share3, uint[3] pos) returns (uint[3] accum){ 526 | uint prime = nn; 527 | ECPoint[] memory points = new ECPoint[](3); 528 | points[0] = ECPoint(share1); 529 | points[1] = ECPoint(share2); 530 | points[2] = ECPoint(share3); 531 | 532 | // Outter loop is a sigma, inner loop is a product 533 | for(uint formula = 0; formula < points.length; formula++) { 534 | 535 | uint numerator = 1; 536 | uint denominator = 1; 537 | 538 | // Product... x_{m} is the share's position (i.e. first/second/third point). 539 | for(uint count=0; count uint[2]) public commitments; 602 | uint n = 0; 603 | 604 | function storeCommitmentTESTING(uint id, uint[2] commitment) { 605 | commitments[id] = commitment; 606 | n = n + 1; 607 | } 608 | 609 | // Check all commitments using code-words. 610 | // r = random number for verification 611 | // n = total number of participants / commitments 612 | // t = threshold for shamir secret 613 | function validateCommitments(uint r, uint t) returns (bool) { 614 | 615 | uint[3] memory res; 616 | 617 | // We need to compute the dual-code 618 | // ** TODO: How do we sample random elements? ** 619 | uint[] memory coef = new uint[](n-t-1); // test polynomial 620 | for(uint i=0; ib) { 806 | a_nn = a; 807 | } else { 808 | a_nn = a+nn; 809 | } 810 | 811 | uint c = addmod(a_nn - b,0,nn); 812 | 813 | return c; 814 | } 815 | 816 | // Parameters xG, r where r = v - xc, and vG. 817 | // Verify that vG = rG + xcG! 818 | function verifyZKP(uint[2] xG, uint r, uint[3] vG) returns (bool){ 819 | uint[2] memory G; 820 | G[0] = Gx; 821 | G[1] = Gy; 822 | 823 | // Check both keys are on the curve. 824 | if(!Secp256k1_noconflict.isPubKey(xG) || !Secp256k1_noconflict.isPubKey(vG)) { 825 | return false; //Must be on the curve! 826 | } 827 | 828 | // Get c = H(g, g^{x}, g^{v}); 829 | bytes32 b_c = sha256(msg.sender, Gx, Gy, xG, vG); 830 | uint c = uint(b_c); 831 | 832 | // Get g^{r}, and g^{xc} 833 | uint[3] memory rG = Secp256k1_noconflict._mul(r, G); 834 | uint[3] memory xcG = Secp256k1_noconflict._mul(c, xG); 835 | 836 | // Add both points together 837 | uint[3] memory rGxcG = Secp256k1_noconflict._add(rG,xcG); 838 | 839 | // Convert to Affine Co-ordinates 840 | ECCMath_noconflict.toZ1(rGxcG, pp); 841 | 842 | // Verify. Do they match? 843 | if(rGxcG[0] == vG[0] && rGxcG[1] == vG[1]) { 844 | return true; 845 | } else { 846 | return false; 847 | } 848 | } 849 | 850 | // random 'w', 'r1', 'd1' 851 | function create1outof2ZKPNoVote(uint[2] xG, uint[2] yG, uint w, uint r2, uint d2, uint x) returns (uint[10] res, uint[4] res2){ 852 | uint[2] memory temp_affine1; 853 | uint[2] memory temp_affine2; 854 | 855 | // y = h^{x} * g 856 | uint[3] memory temp1 = Secp256k1_noconflict._mul(x,yG); 857 | ECCMath_noconflict.toZ1(temp1, pp); 858 | 859 | // Store y_x and y_y 860 | res[0] = temp1[0]; 861 | res[1] = temp1[1]; 862 | 863 | // a1 = g^{w} 864 | temp1 = Secp256k1_noconflict._mul(w,G); 865 | ECCMath_noconflict.toZ1(temp1, pp); 866 | 867 | // Store a1_x and a1_y 868 | res[2] = temp1[0]; 869 | res[3] = temp1[1]; 870 | 871 | // b1 = h^{w} (where h = g^{y}) 872 | temp1 = Secp256k1_noconflict._mul(w, yG); 873 | ECCMath_noconflict.toZ1(temp1, pp); 874 | 875 | res[4] = temp1[0]; 876 | res[5] = temp1[1]; 877 | 878 | // a2 = g^{r2} * x^{d2} 879 | temp1 = Secp256k1_noconflict._mul(r2,G); 880 | temp1 = Secp256k1_noconflict._add(temp1, Secp256k1_noconflict._mul(d2,xG)); 881 | ECCMath_noconflict.toZ1(temp1, pp); 882 | 883 | res[6] = temp1[0]; 884 | res[7] = temp1[1]; 885 | 886 | // Negate the 'y' co-ordinate of G 887 | temp_affine1[0] = G[0]; 888 | temp_affine1[1] = pp - G[1]; 889 | 890 | // We need the public key y in affine co-ordinates 891 | temp_affine2[0] = res[0]; 892 | temp_affine2[1] = res[1]; 893 | 894 | // We should end up with y^{d2} + g^{d2} .... (but we have the negation of g.. so y-g). 895 | temp1 = Secp256k1_noconflict._add(Secp256k1_noconflict._mul(d2,temp_affine2), Secp256k1_noconflict._mul(d2,temp_affine1)); 896 | 897 | // Now... it is h^{r2} + temp2.. 898 | temp1 = Secp256k1_noconflict._add(Secp256k1_noconflict._mul(r2,yG),temp1); 899 | 900 | // Convert to Affine Co-ordinates 901 | ECCMath_noconflict.toZ1(temp1, pp); 902 | 903 | res[8] = temp1[0]; 904 | res[9] = temp1[1]; 905 | 906 | // Get c = H(i, xG, Y, a1, b1, a2, b2); 907 | bytes32 b_c = sha256(msg.sender, xG, res); 908 | 909 | // d1 = c - d2 mod q 910 | temp1[0] = submod(uint(b_c),d2); 911 | 912 | // r1 = w - (x * d1) 913 | temp1[1] = submod(w, mulmod(x,temp1[0],nn)); 914 | 915 | /* We return the following 916 | * res[0] = y_x; 917 | * res[1] = y_y; 918 | * res[2] = a1_x; 919 | * res[3] = a1_y; 920 | * res[4] = b1_x; 921 | * res[5] = b1_y; 922 | * res[6] = a2_x; 923 | * res[7] = a2_y; 924 | * res[8] = b2_x; 925 | * res[9] = b2_y; 926 | * res[10] = d1; 927 | * res[11] = d2; 928 | * res[12] = r1; 929 | * res[13] = r2; 930 | */ 931 | res2[0] = temp1[0]; 932 | res2[1] = d2; 933 | res2[2] = temp1[1]; 934 | res2[3] = r2; 935 | } 936 | 937 | // random 'w', 'r1', 'd1' 938 | // TODO: Make constant 939 | function create1outof2ZKPYesVote(uint[2] xG, uint[2] yG, uint w, uint r1, uint d1, uint x) returns (uint[10] res, uint[4] res2) { 940 | // y = h^{x} * g 941 | uint[3] memory temp1 = Secp256k1_noconflict._mul(x,yG); 942 | Secp256k1_noconflict._addMixedM(temp1,G); 943 | ECCMath_noconflict.toZ1(temp1, pp); 944 | res[0] = temp1[0]; 945 | res[1] = temp1[1]; 946 | 947 | // a1 = g^{r1} * x^{d1} 948 | temp1 = Secp256k1_noconflict._mul(r1,G); 949 | temp1 = Secp256k1_noconflict._add(temp1, Secp256k1_noconflict._mul(d1,xG)); 950 | ECCMath_noconflict.toZ1(temp1, pp); 951 | res[2] = temp1[0]; 952 | res[3] = temp1[1]; 953 | 954 | // b1 = h^{r1} * y^{d1} (temp = affine 'y') 955 | temp1 = Secp256k1_noconflict._mul(r1,yG); 956 | 957 | // Setting temp to 'y' 958 | uint[2] memory temp; 959 | temp[0] = res[0]; 960 | temp[1] = res[1]; 961 | 962 | temp1= Secp256k1_noconflict._add(temp1, Secp256k1_noconflict._mul(d1, temp)); 963 | ECCMath_noconflict.toZ1(temp1, pp); 964 | res[4] = temp1[0]; 965 | res[5] = temp1[1]; 966 | 967 | // a2 = g^{w} 968 | temp1 = Secp256k1_noconflict._mul(w,G); 969 | ECCMath_noconflict.toZ1(temp1, pp); 970 | 971 | res[6] = temp1[0]; 972 | res[7] = temp1[1]; 973 | 974 | // b2 = h^{w} (where h = g^{y}) 975 | temp1 = Secp256k1_noconflict._mul(w, yG); 976 | ECCMath_noconflict.toZ1(temp1, pp); 977 | res[8] = temp1[0]; 978 | res[9] = temp1[1]; 979 | 980 | // Get c = H(id, xG, Y, a1, b1, a2, b2); 981 | // id is H(round, voter_index, voter_address, contract_address)... 982 | bytes32 b_c = sha256(msg.sender, xG, res); 983 | uint c = uint(b_c); 984 | 985 | // d2 = c - d1 mod q 986 | temp[0] = submod(c,d1); 987 | 988 | // r2 = w - (x * d2) 989 | temp[1] = submod(w, mulmod(x,temp[0],nn)); 990 | 991 | /* We return the following 992 | * res[0] = y_x; 993 | * res[1] = y_y; 994 | * res[2] = a1_x; 995 | * res[3] = a1_y; 996 | * res[4] = b1_x; 997 | * res[5] = b1_y; 998 | * res[6] = a2_x; 999 | * res[7] = a2_y; 1000 | * res[8] = b2_x; 1001 | * res[9] = b2_y; 1002 | * res[10] = d1; 1003 | * res[11] = d2; 1004 | * res[12] = r1; 1005 | * res[13] = r2; 1006 | */ 1007 | res2[0] = d1; 1008 | res2[1] = temp[0]; 1009 | res2[2] = r1; 1010 | res2[3] = temp[1]; 1011 | } 1012 | 1013 | // We verify that the ZKP is of 0 or 1. 1014 | function verify1outof2ZKP(uint[4] params, uint[2] xG, uint[2] yG, uint[2] y, uint[2] a1, uint[2] b1, uint[2] a2, uint[2] b2) returns (bool) { 1015 | uint[2] memory temp1; 1016 | uint[3] memory temp2; 1017 | uint[3] memory temp3; 1018 | 1019 | // Make sure we are only dealing with valid public keys! 1020 | if(!Secp256k1_noconflict.isPubKey(xG) || !Secp256k1_noconflict.isPubKey(yG) || !Secp256k1_noconflict.isPubKey(y) || !Secp256k1_noconflict.isPubKey(a1) || 1021 | !Secp256k1_noconflict.isPubKey(b1) || !Secp256k1_noconflict.isPubKey(a2) || !Secp256k1_noconflict.isPubKey(b2)) { 1022 | return false; 1023 | } 1024 | 1025 | // Does c =? d1 + d2 (mod n) 1026 | if(uint(sha256(msg.sender, xG, y, a1, b1, a2, b2)) != addmod(params[0],params[1],nn)) { 1027 | return false; 1028 | } 1029 | 1030 | // a1 =? g^{r1} * x^{d1} 1031 | temp2 = Secp256k1_noconflict._mul(params[2], G); 1032 | temp3 = Secp256k1_noconflict._add(temp2, Secp256k1_noconflict._mul(params[0], xG)); 1033 | ECCMath_noconflict.toZ1(temp3, pp); 1034 | 1035 | if(a1[0] != temp3[0] || a1[1] != temp3[1]) { 1036 | return false; 1037 | } 1038 | 1039 | //b1 =? h^{r1} * y^{d1} (temp = affine 'y') 1040 | temp2 = Secp256k1_noconflict._mul(params[2],yG); 1041 | temp3 = Secp256k1_noconflict._add(temp2, Secp256k1_noconflict._mul(params[0], y)); 1042 | ECCMath_noconflict.toZ1(temp3, pp); 1043 | 1044 | if(b1[0] != temp3[0] || b1[1] != temp3[1]) { 1045 | return false; 1046 | } 1047 | 1048 | //a2 =? g^{r2} * x^{d2} 1049 | temp2 = Secp256k1_noconflict._mul(params[3],G); 1050 | temp3 = Secp256k1_noconflict._add(temp2, Secp256k1_noconflict._mul(params[1], xG)); 1051 | ECCMath_noconflict.toZ1(temp3, pp); 1052 | 1053 | if(a2[0] != temp3[0] || a2[1] != temp3[1]) { 1054 | return false; 1055 | } 1056 | 1057 | // Negate the 'y' co-ordinate of g 1058 | temp1[0] = G[0]; 1059 | temp1[1] = pp - G[1]; 1060 | 1061 | // get 'y' 1062 | temp3[0] = y[0]; 1063 | temp3[1] = y[1]; 1064 | temp3[2] = 1; 1065 | 1066 | // y-g 1067 | temp2 = Secp256k1_noconflict._addMixed(temp3,temp1); 1068 | 1069 | // Return to affine co-ordinates 1070 | ECCMath_noconflict.toZ1(temp2, pp); 1071 | temp1[0] = temp2[0]; 1072 | temp1[1] = temp2[1]; 1073 | 1074 | // (y-g)^{d2} 1075 | temp2 = Secp256k1_noconflict._mul(params[1],temp1); 1076 | 1077 | // Now... it is h^{r2} + temp2.. 1078 | temp3 = Secp256k1_noconflict._add(Secp256k1_noconflict._mul(params[3],yG),temp2); 1079 | 1080 | // Convert to Affine Co-ordinates 1081 | ECCMath_noconflict.toZ1(temp3, pp); 1082 | 1083 | // Should all match up. 1084 | if(b2[0] != temp3[0] || b2[1] != temp3[1]) { 1085 | return false; 1086 | } 1087 | 1088 | return true; 1089 | } 1090 | 1091 | // Expects random factor 'r' and commitment 'b'. Generators are hard-coded into this contract. 1092 | function createCommitment(uint r, uint b) returns (uint[2]){ 1093 | 1094 | uint[3] memory bG = Secp256k1_noconflict._mul(b,G); 1095 | 1096 | uint[3] memory rY = Secp256k1_noconflict._mul(r,Y); 1097 | 1098 | uint[3] memory c = Secp256k1_noconflict._add(bG,rY); 1099 | 1100 | ECCMath_noconflict.toZ1(c, pp); 1101 | 1102 | uint[2] memory c_affine; 1103 | c_affine[0] = c[0]; 1104 | c_affine[1] = c[1]; 1105 | 1106 | // Sanity check that everything worked as expected. 1107 | if(!Secp256k1_noconflict.isPubKey(c_affine)) { 1108 | throw; //Must be on the curve! 1109 | } 1110 | 1111 | return c_affine; 1112 | } 1113 | 1114 | // We need to re-create the commitment and check that it matches c. 1115 | function openCommitment(uint[2] c, uint r, uint b) returns (bool) { 1116 | 1117 | uint[2] memory c_computed = createCommitment(r,b); 1118 | 1119 | // Check that the commitments match... 1120 | if(c[0] == c_computed[0] && c[1] == c_computed[1]) { 1121 | return true; 1122 | } 1123 | 1124 | return false; 1125 | } 1126 | 1127 | // Equality of commitments... 1128 | // 1. Compute t = r3*Y 1129 | // 2. Compute h = H(ID, G, Y, C1, C2, t), where G,Y are generators, C1, C2 are both commitments, and t is random factor. 1130 | // 3. Compute n = h*(r1,r2) + r3. 1131 | // return t,n. 1132 | function createEqualityProof(uint r1, uint r2, uint r3, uint[2] c1, uint[2] c2) returns (uint[2] t, uint n) { 1133 | 1134 | if(!Secp256k1_noconflict.isPubKey(c1)) { 1135 | throw; //Must be on the curve! 1136 | } 1137 | 1138 | if(!Secp256k1_noconflict.isPubKey(c2)) { 1139 | throw; //Must be on the curve! 1140 | } 1141 | 1142 | uint[3] memory r3Y = Secp256k1_noconflict._mul(r3,Y); 1143 | ECCMath_noconflict.toZ1(r3Y, pp); 1144 | 1145 | t[0] = r3Y[0]; 1146 | t[1] = r3Y[1]; 1147 | 1148 | // TODO: add msg.sender 1149 | uint h = uint(sha256(msg.sender, G, Y, c1, c2, t)); 1150 | 1151 | uint subr1r2 = submod(r1, r2); 1152 | uint modrh = mulmod(subr1r2,h,nn); 1153 | n = addmod(modrh,r3,nn); 1154 | } 1155 | 1156 | // We compute h*(c1-c2) + t 1157 | function computeFirstHalfEquality(uint[2] c1, uint[2] c2, uint h, uint[2] t) returns (uint[2] left){ 1158 | 1159 | uint[3] memory negative_c2; 1160 | // Negate the 'y' co-ordinate of C2 1161 | negative_c2[0] = c2[0]; 1162 | negative_c2[1] = pp - c2[1]; 1163 | negative_c2[2] = 1; 1164 | 1165 | // c1 - c2 1166 | uint[3] memory added_commitments_jacob = Secp256k1_noconflict._addMixed(negative_c2,c1); 1167 | 1168 | // convert to affine points 1169 | ECCMath_noconflict.toZ1(added_commitments_jacob,pp); 1170 | uint[2] memory added_commitments; 1171 | added_commitments[0] = added_commitments_jacob[0]; 1172 | added_commitments[1] = added_commitments_jacob[1]; 1173 | 1174 | // h*(c1-c2) + t 1175 | uint[3] memory left_jacob = Secp256k1_noconflict._addMixed(Secp256k1_noconflict._mul(h,added_commitments),t); 1176 | ECCMath_noconflict.toZ1(left_jacob,pp); 1177 | left[0] = left_jacob[0]; 1178 | left[1] = left_jacob[1]; 1179 | 1180 | 1181 | } 1182 | 1183 | // Verify equality proof of two pedersen commitments 1184 | // 1. Compute h = H(ID, G, Y, C1, C2, t), where G,Y are generators, C1, C2 are both commitments, and t is random factor. 1185 | // 2. Does nY == h*(c1-c2) + t 1186 | function verifyEqualityProof(uint n, uint[2] c1, uint[2] c2, uint[2] t) returns (bool) { 1187 | if(!Secp256k1_noconflict.isPubKey(c1)) { throw; } 1188 | if(!Secp256k1_noconflict.isPubKey(c2)) { throw; } 1189 | if(!Secp256k1_noconflict.isPubKey(t)) { throw; } 1190 | 1191 | // Time to start trying to verify it... will be moved to another function 1192 | uint h = uint(sha256(msg.sender, G, Y, c1, c2, t)); 1193 | 1194 | uint[2] memory left = computeFirstHalfEquality(c1,c2,h,t); 1195 | 1196 | // n * Y 1197 | uint[3] memory right = Secp256k1_noconflict._mul(n,Y); 1198 | 1199 | ECCMath_noconflict.toZ1(right, pp); 1200 | 1201 | if(left[0] == right[0] && left[1] == right[1]) { 1202 | return true; 1203 | } else { 1204 | return false; 1205 | } 1206 | } 1207 | 1208 | // Create inequality of commitments... 1209 | // 1. t1 = r3*G, t2 = r4*Y 1210 | // 2. Compute h = H(ID, G, Y, c1, c2, t1, t2), where G,Y generators, c1,c2 commitments, t1,t2 inequality proof 1211 | // 3. n1 = h*(b1-b2) + r3, n2 = h*(r1-r2) + r4. 1212 | // return random factors t1,t2 and proofs n1,n2. 1213 | function createInequalityProof(uint b1, uint b2, uint r1, uint r2, uint r3, uint r4, uint[2] c1, uint[2] c2) returns (uint[2] t1, uint[2] t2, uint n1, uint n2) { 1214 | 1215 | if(!Secp256k1_noconflict.isPubKey(c1)) { throw; } 1216 | if(!Secp256k1_noconflict.isPubKey(c2)) { throw; } 1217 | 1218 | // r3 * G 1219 | uint[3] memory temp = Secp256k1_noconflict._mul(r3,G); 1220 | ECCMath_noconflict.toZ1(temp, pp); 1221 | t1[0] = temp[0]; 1222 | t1[1] = temp[1]; 1223 | 1224 | // r4 * Y 1225 | temp = Secp256k1_noconflict._mul(r4,Y); 1226 | ECCMath_noconflict.toZ1(temp, pp); 1227 | t2[0] = temp[0]; 1228 | t2[1] = temp[1]; 1229 | 1230 | // TODO: add msg.sender 1231 | uint h = uint(sha256(msg.sender, G, Y, c1, c2, t1, t2)); 1232 | 1233 | // h(b1-b2) + r3 1234 | n1 = submod(b1,b2); 1235 | uint helper = mulmod(n1,h,nn); 1236 | n1 = addmod(helper,r3,nn); 1237 | 1238 | // h(r1-r2) + r4 1239 | n2 = submod(r1,r2); 1240 | helper = mulmod(n2,h,nn); 1241 | n2 = addmod(helper,r4,nn); 1242 | 1243 | } 1244 | 1245 | // We are computing h(c1 - c2) + t2 1246 | function computeSecondHalfInequality(uint[2] c1, uint[2] c2, uint[2] t2, uint h) returns (uint[3] right) { 1247 | uint[3] memory negative_c2; 1248 | // Negate the 'y' co-ordinate of C2 1249 | negative_c2[0] = c2[0]; 1250 | negative_c2[1] = pp - c2[1]; 1251 | negative_c2[2] = 1; 1252 | 1253 | // c1 - c2 1254 | uint[3] memory added_commitments_jacob = Secp256k1_noconflict._addMixed(negative_c2,c1); 1255 | 1256 | // convert to affine points 1257 | ECCMath_noconflict.toZ1(added_commitments_jacob,pp); 1258 | uint[2] memory added_commitments; 1259 | added_commitments[0] = added_commitments_jacob[0]; 1260 | added_commitments[1] = added_commitments_jacob[1]; 1261 | 1262 | // h(c1-c2) 1263 | uint[3] memory h_mul_c1c2 = Secp256k1_noconflict._mul(h,added_commitments); 1264 | 1265 | // right hand side h(c1-c2) + t2 1266 | right = Secp256k1_noconflict._addMixed(h_mul_c1c2,t2); 1267 | ECCMath_noconflict.toZ1(right,pp); 1268 | 1269 | } 1270 | 1271 | // Verify inequality of commitments 1272 | // 1. Compute h = H(ID, G, Y, c1, c2, t1, t2), where G,Y generators, c1,c2 commitments, t1,t2 inequality proof 1273 | // 2. Verify n1G + n2Y = h*(c1-c2) + t1 + t2 1274 | // 3. Verify n2Y != h*(c1-c2) + t2 1275 | function verifyInequalityProof(uint[2] c1, uint[2] c2, uint[2] t1, uint[2] t2, uint n1, uint n2) returns (bool) { 1276 | if(!Secp256k1_noconflict.isPubKey(c1)) { throw; } 1277 | if(!Secp256k1_noconflict.isPubKey(c2)) { throw; } 1278 | if(!Secp256k1_noconflict.isPubKey(t1)) { throw; } 1279 | if(!Secp256k1_noconflict.isPubKey(t2)) { throw; } 1280 | 1281 | uint h = uint(sha256(msg.sender, G, Y, c1, c2, t1, t2)); 1282 | 1283 | // h(c1 - c2) + t2 1284 | uint[3] memory right = computeSecondHalfInequality(c1, c2, t2, h); 1285 | 1286 | // n2 * Y 1287 | uint[3] memory n2Y = Secp256k1_noconflict._mul(n2,Y); 1288 | ECCMath_noconflict.toZ1(n2Y,pp); // convert to affine 1289 | 1290 | if(n2Y[0] != right[0] && n2Y[1] != right[1]) { 1291 | 1292 | // h(c1 - c2) + t2 + t1 1293 | uint[3] memory h_c1c2_t2_t1 = Secp256k1_noconflict._addMixed(right, t1); 1294 | ECCMath_noconflict.toZ1(h_c1c2_t2_t1,pp); // convert to affine 1295 | right[0] = h_c1c2_t2_t1[0]; 1296 | right[1] = h_c1c2_t2_t1[1]; 1297 | 1298 | // n1G + n2Y 1299 | uint[3] memory n1Gn2Y = Secp256k1_noconflict._add(Secp256k1_noconflict._mul(n1, G),n2Y); 1300 | ECCMath_noconflict.toZ1(n1Gn2Y,pp); // convert to affine 1301 | 1302 | if(n1Gn2Y[0] == right[0] && n1Gn2Y[1] == right[1]) { 1303 | return true; 1304 | } 1305 | } 1306 | 1307 | return false; 1308 | } 1309 | 1310 | } 1311 | -------------------------------------------------------------------------------- /contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | var LocalCrypto = artifacts.require("./LocalCrypto.sol"); 3 | 4 | module.exports = function(deployer) { 5 | deployer.deploy(Migrations); 6 | deployer.deploy(LocalCrypto); 7 | }; 8 | -------------------------------------------------------------------------------- /migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | var LocalCrypto = artifacts.require("./LocalCrypto.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(LocalCrypto); 5 | }; 6 | -------------------------------------------------------------------------------- /test/TestLocalCrypto.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.10; 2 | 3 | import "truffle/Assert.sol"; 4 | import "truffle/DeployedAddresses.sol"; 5 | import "../contracts/LocalCrypto.sol"; 6 | 7 | contract TestLocalCrypto { 8 | 9 | // Create six shares for a single secret 10 | function testCreateSharesLocalCrypto() returns (bool) { 11 | LocalCrypto crypto = LocalCrypto(DeployedAddresses.LocalCrypto()); 12 | 13 | // Our secret is coef[0] and need to create k-1 random numbers 14 | // Secret + k-1 = k shares that are needed to re-create this polynominal! 15 | uint[] memory coef = new uint[](3); 16 | coef[0] = 129; 17 | coef[1] = 166; 18 | coef[2] = 94; 19 | 20 | // Secret is 1234 21 | // Two random coefficients 22 | // We need 3 23 | uint[6] memory shares = crypto.createShares(coef, 6); 24 | 25 | // Receiver must be given (i+1, share). 26 | // The secret s isn't included below - but that is the very first index of the equation! 27 | Assert.equal(shares[0], 389, "First share"); 28 | Assert.equal(shares[1], 837, "Second share"); 29 | Assert.equal(shares[2], 1473, "Third share"); 30 | Assert.equal(shares[3], 2297, "Fourth share"); 31 | Assert.equal(shares[4], 3309, "Fifth share"); 32 | Assert.equal(shares[5], 4509, "Sixth share"); 33 | Assert.equal(shares[0],0,"Should fail"); 34 | } 35 | 36 | // Test re-combining shamir's secrets 37 | // based on the public keys 38 | function testJoinSharesLocalCrypto() { 39 | LocalCrypto crypto = LocalCrypto(DeployedAddresses.LocalCrypto()); 40 | uint[2] memory key = crypto.createPubKeyWithY(129); 41 | 42 | uint[3] memory pos; 43 | pos[0] = 2; 44 | pos[1] = 4; 45 | pos[2] = 5; 46 | uint[3] memory key2 = crypto.joinShares(crypto.createPubKeyWithY(837), crypto.createPubKeyWithY(2297), crypto.createPubKeyWithY(3309), pos); 47 | 48 | Assert.equal(key[0], key2[0], "X-cordinates of key should match!"); 49 | Assert.equal(key[0],0,"Should fail"); 50 | } 51 | 52 | function testCommitmentValidation() { 53 | LocalCrypto crypto = LocalCrypto(DeployedAddresses.LocalCrypto()); 54 | crypto.storeCommitmentTESTING(0, crypto.createPubKeyWithY(389)); 55 | crypto.storeCommitmentTESTING(1, crypto.createPubKeyWithY(837)); 56 | crypto.storeCommitmentTESTING(2, crypto.createPubKeyWithY(1473)); 57 | crypto.storeCommitmentTESTING(3, crypto.createPubKeyWithY(2297)); 58 | crypto.storeCommitmentTESTING(4, crypto.createPubKeyWithY(3309)); 59 | crypto.storeCommitmentTESTING(5, crypto.createPubKeyWithY(4509)); 60 | Assert.equal(crypto.validateCommitments(123213,3), true, "Validation of commitments failed."); 61 | uint t = 123; 62 | Assert.equal(t,1,"Should fail"); 63 | } 64 | 65 | function testCommitmentValidationFailBadShares() { 66 | LocalCrypto crypto = LocalCrypto(DeployedAddresses.LocalCrypto()); 67 | crypto.storeCommitmentTESTING(0, crypto.createPubKeyWithY(732183)); 68 | crypto.storeCommitmentTESTING(1, crypto.createPubKeyWithY(1231273)); 69 | crypto.storeCommitmentTESTING(2, crypto.createPubKeyWithY(14473)); 70 | crypto.storeCommitmentTESTING(3, crypto.createPubKeyWithY(22197)); 71 | crypto.storeCommitmentTESTING(4, crypto.createPubKeyWithY(33309)); 72 | crypto.storeCommitmentTESTING(5, crypto.createPubKeyWithY(45209)); 73 | Assert.equal(crypto.validateCommitments(123213,3), false, "Validation of commitments failed."); 74 | uint t = 123; 75 | Assert.equal(t,1,"Should fail"); 76 | } 77 | 78 | // TODO: This throws. Blows up. lol 79 | /*function testCommitmentValidationFailBadThreshold() { 80 | LocalCrypto crypto = LocalCrypto(DeployedAddresses.LocalCrypto()); 81 | crypto.storeCommitmentTESTING(0, crypto.createPubKeyWithY(732183)); 82 | crypto.storeCommitmentTESTING(1, crypto.createPubKeyWithY(1231273)); 83 | crypto.storeCommitmentTESTING(2, crypto.createPubKeyWithY(14473)); 84 | crypto.storeCommitmentTESTING(3, crypto.createPubKeyWithY(22197)); 85 | crypto.storeCommitmentTESTING(4, crypto.createPubKeyWithY(33309)); 86 | crypto.storeCommitmentTESTING(5, crypto.createPubKeyWithY(45209)); 87 | Assert.equal(crypto.validateCommitments(123213,2), false, "Validation of commitments failed."); 88 | uint t = 123; 89 | Assert.equal(t,1,"Should fail"); 90 | }*/ 91 | 92 | 93 | // Test creating two discrete logs g^{d} and y^{d}, and proving their equality! 94 | function testDiscreteLogEquality() { 95 | LocalCrypto crypto = LocalCrypto(DeployedAddresses.LocalCrypto()); 96 | uint d = 123; 97 | uint w = 1230123102; 98 | 99 | // Create g^{d} and y^{d} 100 | uint[2] memory dG = crypto.mulG(d); 101 | uint[2] memory dY = crypto.mulY(d); 102 | 103 | uint[2] memory a1; 104 | uint[2] memory a2; 105 | uint z; 106 | 107 | // Create our discrete log equality proof 108 | (a1,a2,z) = crypto.createDiscreteLogEquality(w, d, crypto.getG(), crypto.getY(), dG, dY); 109 | 110 | // Verify our discrete log equality proof 111 | bool res = crypto.verifyDiscreteLogEquality(z, crypto.getG(), crypto.getY(), dG, dY, a1, a2); 112 | 113 | // Did it work?! 114 | Assert.equal(res,true, "Discrete Log Equality"); 115 | Assert.equal(d,0,"Should fail"); 116 | 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /test/TestLocalCrypto2.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.10; 2 | 3 | import "truffle/Assert.sol"; 4 | import "truffle/DeployedAddresses.sol"; 5 | import "../contracts/LocalCrypto.sol"; 6 | 7 | // Contract to test access from non-owner accounts. 8 | contract SecondAccount { 9 | LocalCrypto con; 10 | 11 | uint[2] xG; 12 | uint[2] yG; 13 | uint x; 14 | 15 | // Second Person 16 | function SecondAccount(LocalCrypto _con, uint[2] _xG, uint[2] _yG, uint _x) { 17 | con = _con; 18 | 19 | xG = _xG; 20 | yG = _yG; 21 | x = _x; 22 | } 23 | 24 | // Submit voting key to Ethereum 25 | function singleZKP(uint v) returns (bool result, uint[4] res) { 26 | res = con.createZKP(x,v,xG); 27 | 28 | uint[3] memory vG = [res[1], res[2], res[3]]; 29 | 30 | result = con.verifyZKP(xG, res[0], vG); 31 | } 32 | 33 | // Create a YES vote ZKP (in real life this is done via a call.... not a transaction) 34 | function yes(uint w, uint r, uint d) returns (bool) { 35 | uint[10] memory res; 36 | uint[4] memory params; 37 | (res, params) = con.create1outof2ZKPYesVote(xG, yG, w, r, d, x); 38 | 39 | uint[2] memory y = [res[0], res[1]]; 40 | uint[2] memory a1 = [res[2], res[3]]; 41 | uint[2] memory b1 = [res[4], res[5]]; 42 | uint[2] memory a2 = [res[6], res[7]]; 43 | uint[2] memory b2 = [res[8], res[9]]; 44 | 45 | return con.verify1outof2ZKP(params, xG, yG, y, a1, b1, a2, b2); 46 | } 47 | 48 | // Create a NO vote ZKP (in real life this is done via a call.... not a transaction) 49 | function no(uint w, uint r, uint d) returns (bool) { 50 | uint[10] memory res; 51 | uint[4] memory params; 52 | 53 | (res, params) = con.create1outof2ZKPNoVote(xG, yG, w, r, d, x); 54 | 55 | uint[2] memory y = [res[0], res[1]]; 56 | uint[2] memory a1 = [res[2], res[3]]; 57 | uint[2] memory b1 = [res[4], res[5]]; 58 | uint[2] memory a2 = [res[6], res[7]]; 59 | uint[2] memory b2 = [res[8], res[9]]; 60 | 61 | return con.verify1outof2ZKP(params, xG, yG, y, a1, b1, a2, b2); 62 | } 63 | 64 | // Submit voting key to Ethereum 65 | function inequalityProof() returns (bool) { 66 | // Accepts as input random factor 'r', and our commitment 'b'. 67 | uint r1 = 100792359988221257522464744073694181557998811287873941943642234039632667801743; 68 | uint r2 = 73684597056470802520640839675442817373247702535850643999083350831860051477001; 69 | uint b1 = 23; 70 | uint b2 = 24; 71 | 72 | // Create two commitments to the same value (b) 73 | uint[2] memory c1 = con.createCommitment(r1,b1); 74 | 75 | if(!con.openCommitment(c1,r1,b1)) { 76 | return false; 77 | } 78 | 79 | uint[2] memory c2 = con.createCommitment(r2,b2); 80 | 81 | if(!con.openCommitment(c2,r2,b2)) { 82 | return false; 83 | } 84 | 85 | // Create an equality proof 86 | // 1. Prover computes a random nonce 87 | uint r3 = 106554628258140934843991940734271727557510876833354296893443127816727132563340; 88 | uint r4 = 50011181273477635355105934748199911221235256089199741271573814847024879061829; 89 | uint[2] memory t1; 90 | uint[2] memory t2; 91 | uint n1; 92 | uint n2; 93 | 94 | (t1,t2,n1,n2) = con.createInequalityProof(b1, b2, r1, r2, r3, r4, c1, c2); 95 | 96 | if(!con.verifyInequalityProof(c1,c2,t1,t2,n1,n2)) { 97 | return false; 98 | } 99 | 100 | return true; 101 | } 102 | 103 | function equalityProof() returns (bool) { 104 | // Accepts as input random factor 'r', and our commitment 'b'. 105 | uint r1 = 100792359988221257522464744073694181557998811287873941943642234039631667801743; 106 | uint r2 = 73684597056470802520640839675442817373247702535850643999083350831860052477001; 107 | uint b = 23; 108 | 109 | // Create two commitments to the same value (b) 110 | uint[2] memory c1 = con.createCommitment(r1,b); 111 | 112 | if(!con.openCommitment(c1,r1,b)) { 113 | return false; 114 | } 115 | 116 | uint[2] memory c2 = con.createCommitment(r2,b); 117 | 118 | if(!con.openCommitment(c2,r2,b)) { 119 | return false; 120 | } 121 | 122 | // Create an equality proof 123 | // 1. Prover computes a random nonce 124 | uint r3 = 106554628258140934843991940734271727557510876833354296893443127816727132563840; 125 | uint[2] memory t; 126 | uint n; 127 | 128 | (t,n) = con.createEqualityProof(r1, r2, r3, c1, c2); 129 | 130 | // Verify equality proof 131 | if(!con.verifyEqualityProof(n, c1,c2,t)) { 132 | return false; 133 | } 134 | 135 | return true; 136 | } 137 | } 138 | 139 | contract TestLocalCrypto2 { 140 | 141 | LocalCrypto con; 142 | SecondAccount A; 143 | SecondAccount B; 144 | SecondAccount C; 145 | 146 | // The function called "setUp" with no arguments is 147 | // called on a fresh instance of this contract before 148 | // each test. TODO: Document when to put setup logic in 149 | // setUp vs subclass constructor when writing Test subclasses 150 | function testFirst() { 151 | con = LocalCrypto(DeployedAddresses.LocalCrypto()); 152 | 153 | uint x = 100792359988221257522464744073694181557998811287873941943642234039631667801743; 154 | uint[2] memory xG = [50011181273477635355105934748199911221235256089199741271573814847024879061899, 71802419974013591686591529237219896883303932349628173412957707346469215125624]; 155 | uint[2] memory yG = [98038005178408974007512590727651089955354106077095278304532603697039577112780,1801119347122147381158502909947365828020117721497557484744596940174906898953]; 156 | A = new SecondAccount(con, xG, yG, x); 157 | 158 | x = 73684597056470802520640839675442817373247702535850643999083350831860052477001; 159 | xG = [98038005178408974007512590727651089955354106077095278304532603697039577112780,1801119347122147381158502909947365828020117721497557484744596940174906898953]; 160 | yG = [50011181273477635355105934748199911221235256089199741271573814847024879061899, 71802419974013591686591529237219896883303932349628173412957707346469215125624]; 161 | B = new SecondAccount(con, xG, yG, x); 162 | 163 | x = 106554628258140934843991940734271727557510876833354296893443127816727132563840; 164 | xG = [33836939586123110014913515630722089627445238026599436014853176202391948851936,112012169245950924685217915153942207169026199800060889564176846526381877678915]; 165 | yG = [50011181273477635355105934748199911221235256089199741271573814847024879061899, 71802419974013591686591529237219896883303932349628173412957707346469215125624]; 166 | C = new SecondAccount(con, xG, yG, x); 167 | uint t = 123; 168 | Assert.equal(t, 1, "Should Fail"); 169 | } 170 | 171 | // Test Equality Proof 172 | function testEqualityCommitmentProofs() { 173 | uint t = 123; 174 | Assert.equal(A.equalityProof(), true, "Equality Proof did not pass!"); 175 | Assert.equal(t, 1, "Should Fail"); 176 | } 177 | 178 | // Test Inequality Proof 179 | function testInequalityCommitmentProofs() { 180 | uint t = 123; 181 | Assert.equal(A.inequalityProof(), true, "Inequality Proof did not pass!"); 182 | Assert.equal(t, 1, "Should Fail"); 183 | } 184 | 185 | // All voters submit their voting key 186 | function verifySingleZKP() returns (bool[3]){ 187 | 188 | bool[3] memory res; 189 | uint[4] memory nums; 190 | 191 | uint v = 114941333558360567695678851060848045245826375581561159846926673173053566932687; 192 | (res[0],nums) = A.singleZKP(v); 193 | 194 | v = 28201629513124344311667277080113205903076096953435080012961531044913135153251; 195 | (res[1],nums) = B.singleZKP(v); 196 | 197 | v = 43299936944025232330163985825794231821139305521742829361426928502076888495802; 198 | (res[2],nums) = C.singleZKP(v); 199 | 200 | return res; 201 | } 202 | 203 | // Each user submits their vote. 204 | function verifyOrZKP() returns (bool[3]) { 205 | bool[3] memory res; 206 | 207 | // Secrets of ZKP 208 | uint w = 25291153222690468941875333155056279849838848426097128907648274067789060660273; 209 | uint r = 68245514418532339184005707392894217247971162351489303687284716936396921389966; 210 | uint d = 69359315012171413053095778073649855770462866229159476171746022558873132690484; 211 | 212 | // A will vote 'yes' 213 | res[0] = A.no(w, r, d); 214 | /* 215 | w = 19931063034338608040397431389036375166444930113540469342178236240587103276978; 216 | r = 87107851681277429609192387607437427289427886314855879969256798426721441034774; 217 | d = 72164131658574279179250456277220223585855304300653523095781426974019205356799; 218 | 219 | res[1] = B.yes(w, r, d); 220 | 221 | w = 115286148593094397817919321895481582202334666397686766739301438664537464210065; 222 | r = 815396253592732808824014303738871690433014125945487317500773529831657827334; 223 | d = 23176707862498098379332945567991301108469279788561094237174439014024723886337; 224 | 225 | res[2] = C.no(w, r, d);*/ 226 | 227 | return res; 228 | } 229 | 230 | function testSingleZKP() { 231 | bool[3] memory res = verifySingleZKP(); 232 | uint t = 123; 233 | Assert.equal(res[0],true,"single zkp were false, not true! 0"); 234 | Assert.equal(res[1],true,"single zkp were false, not true! 1"); 235 | Assert.equal(res[2],true,"single zkp were false, not true! 2"); 236 | Assert.equal(t, 1, "Should Fail"); 237 | } 238 | 239 | function testOrZKP() { 240 | bool[3] memory res = verifyOrZKP(); 241 | uint t = 1203; 242 | Assert.equal(res[0],true,"OR zkp were false, not true! 0"); 243 | /*Assert.equal(res[1],true,"OR zkp were false, not true! 1"); 244 | Assert.equal(res[2],true,"OR zkp were false, not true! 2");*/ 245 | Assert.equal(t, 1, "Should Fail"); 246 | } 247 | 248 | // Not all voters have cast their vote.. should throw 249 | function testCannotSubmitFakeZKP() { 250 | 251 | uint x = 110792359988221257522464744073694181557998811287873941943642234039631667801743; 252 | uint[2] memory xG = [50011181273477635355105934748199911221235256089199741271573814847024879061899, 71802419974013591686591529237219896883303932349628173412957707346469215125624]; 253 | uint[2] memory yG = [98038005178408974007512590727651089955354106077095278304532603697039577112780,1801119347122147381158502909947365828020117721497557484744596940174906898953]; 254 | 255 | SecondAccount D = new SecondAccount(con, xG, yG, x); 256 | uint v = 114941333558360567695678851060848045245826375581561159846926673173053566932687; 257 | bool res; 258 | uint[4] memory nums; 259 | 260 | (res,nums) = D.singleZKP(v); 261 | 262 | Assert.equal(res, false, "Fake ZKP submitted"); 263 | Assert.equal(v, 1, "Should Fail"); 264 | } 265 | 266 | // Not all voters have cast their vote.. should throw 267 | function testCannotFakeVote() { 268 | uint x = 110792359988221257522464744073694181557998811287873941943642234039631667801743; 269 | uint[2] memory xG = [50011181273477635355105934748199911221235256089199741271573814847024879061899, 71802419974013591686591529237219896883303932349628173412957707346469215125624]; 270 | uint[2] memory yG = [98038005178408974007512590727651089955354106077095278304532603697039577112780,1801119347122147381158502909947365828020117721497557484744596940174906898953]; 271 | 272 | SecondAccount D = new SecondAccount(con, xG, yG, x); 273 | uint w = 25291153222690468941875333155056279849838848426097128907648274067789060660273; 274 | uint r = 68245514418532339184005707392894217247971162351489303687284716936396921389966; 275 | uint d = 79359315012171413053095778073649855770462866229159476171746022558873132690484; 276 | 277 | bool res = D.no(w,r,d); 278 | 279 | // Wrong private key used... 280 | Assert.equal(res, false, "Wrong private key should have been used"); 281 | Assert.equal(w, 1, "Should Fail"); 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8545, 6 | network_id: "*", // Match any network id 7 | gas: 7000000 8 | } 9 | } 10 | }; 11 | --------------------------------------------------------------------------------