diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..34d7b61 --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,17 @@ +name: Rust + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Update submodules + run: git submodule update --init + - name: Build contract + run: make all-via-docker + - name: Run tests + run: cargo test diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2845246 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +target/ +build/ +!build/.gitkeep +.vscode +cmake-build-debug diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..06fde71 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "deps/ckb-c-std-lib"] + path = deps/ckb-c-std-lib + url = https://github.com/nervosnetwork/ckb-c-stdlib +[submodule "deps/secp256k1"] + path = deps/secp256k1 + url = https://github.com/nervosnetwork/secp256k1 diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..e7c8b4d --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2778 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "autocfg" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ed203b9ba68b242c62b3fb7480f589dd49829be1edb3fe8fc8b4ffda2dcb8d" +dependencies = [ + "addr2line", + "cfg-if 1.0.0", + "libc", + "miniz_oxide 0.4.4", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" +dependencies = [ + "byteorder", +] + +[[package]] +name = "bit-vec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "blake2b-rs" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e35e362830ef90ecea16f09b21b75d22d33a8562a679c74ab4f4fa49b4fcb87" +dependencies = [ + "cc", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "either", + "iovec", + "serde", +] + +[[package]] +name = "cc" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "serde", + "time", + "wasm-bindgen", + "winapi 0.3.9", +] + +[[package]] +name = "ckb-chain-spec" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "ckb-crypto", + "ckb-dao-utils", + "ckb-error", + "ckb-hash", + "ckb-jsonrpc-types", + "ckb-pow", + "ckb-rational", + "ckb-resource", + "ckb-types", + "failure", + "serde", + "serde_derive", + "toml", +] + +[[package]] +name = "ckb-crypto" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "ckb-fixed-hash", + "failure", + "faster-hex 0.4.1", + "lazy_static", + "rand 0.6.5", + "secp256k1", +] + +[[package]] +name = "ckb-dao-utils" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "byteorder", + "ckb-error", + "ckb-types", + "enum-display-derive", + "failure", +] + +[[package]] +name = "ckb-error" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "ckb-occupied-capacity", + "enum-display-derive", + "failure", +] + +[[package]] +name = "ckb-fixed-hash" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "ckb-fixed-hash-core", + "ckb-fixed-hash-hack", + "proc-macro-hack", +] + +[[package]] +name = "ckb-fixed-hash-core" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "failure", + "faster-hex 0.4.1", + "serde", +] + +[[package]] +name = "ckb-fixed-hash-hack" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "ckb-fixed-hash-core", + "proc-macro-hack", + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", +] + +[[package]] +name = "ckb-hash" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "blake2b-rs", +] + +[[package]] +name = "ckb-jsonrpc-types" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "ckb-types", + "faster-hex 0.4.1", + "jsonrpc-core", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "ckb-logger" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "ansi_term", + "backtrace", + "chrono", + "crossbeam-channel", + "env_logger", + "lazy_static", + "log", + "parking_lot 0.7.1", + "regex", + "sentry", + "serde", + "serde_derive", +] + +[[package]] +name = "ckb-occupied-capacity" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "ckb-occupied-capacity-core", + "ckb-occupied-capacity-macros", + "proc-macro-hack", +] + +[[package]] +name = "ckb-occupied-capacity-core" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "ckb-occupied-capacity-macros" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "ckb-occupied-capacity-core", + "proc-macro-hack", + "quote 0.6.13", + "syn 0.15.44", +] + +[[package]] +name = "ckb-pow" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "byteorder", + "ckb-types", + "eaglesong", + "serde", + "serde_derive", +] + +[[package]] +name = "ckb-production-scripts" +version = "0.5.1" +dependencies = [ + "blake2b-rs", + "byteorder", + "ckb-crypto", + "ckb-dao-utils", + "ckb-error", + "ckb-hash", + "ckb-script", + "ckb-types", + "faster-hex 0.3.1", + "includedir", + "includedir_codegen", + "lazy_static", + "phf", + "rand 0.6.5", + "ripemd160", + "secp256k1", + "sha2", +] + +[[package]] +name = "ckb-rational" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "numext-fixed-uint", +] + +[[package]] +name = "ckb-resource" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "ckb-system-scripts", + "ckb-types", + "includedir", + "includedir_codegen", + "phf", + "serde", + "serde_derive", + "tempfile", + "walkdir", +] + +[[package]] +name = "ckb-script" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "byteorder", + "ckb-chain-spec", + "ckb-error", + "ckb-hash", + "ckb-logger", + "ckb-script-data-loader", + "ckb-types", + "ckb-vm", + "failure", + "faster-hex 0.4.1", + "serde", + "serde_derive", +] + +[[package]] +name = "ckb-script-data-loader" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "ckb-types", +] + +[[package]] +name = "ckb-system-scripts" +version = "0.4.0-alpha.10+witness-args" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387db7de0020cbc3c20801cdba8ed1ae19acc9fd89ffb0b02c34862c71cda2db" +dependencies = [ + "blake2b-rs", + "faster-hex 0.3.1", + "includedir", + "includedir_codegen", + "phf", +] + +[[package]] +name = "ckb-types" +version = "0.24.0-pre" +source = "git+https://github.com/nervosnetwork/ckb.git?rev=d75e4c5#d75e4c56ffa40e17fd2fe477da3f98c5578edcd1" +dependencies = [ + "bit-vec", + "bytes", + "ckb-error", + "ckb-fixed-hash", + "ckb-hash", + "ckb-occupied-capacity", + "ckb-rational", + "crossbeam-channel", + "failure", + "merkle-cbt", + "molecule", + "numext-fixed-uint", +] + +[[package]] +name = "ckb-vm" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "684aca846d958bc5c2196b10839b69ec573cc693b14dc701986adda123ffbef0" +dependencies = [ + "byteorder", + "bytes", + "cc", + "ckb-vm-definitions", + "derive_more", + "goblin", + "libc", + "memmap", +] + +[[package]] +name = "ckb-vm-definitions" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b4a65696efd8974a3c785619f2bfc4c40f2cf318ac184c30aa72d0f539a4a4f" + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "cookie" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" +dependencies = [ + "time", + "url 1.7.2", +] + +[[package]] +name = "cookie_store" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" +dependencies = [ + "cookie", + "failure", + "idna 0.1.5", + "log", + "publicsuffix", + "serde", + "serde_json", + "time", + "try_from", + "url 1.7.2", +] + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "crossbeam-channel" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" +dependencies = [ + "crossbeam-utils 0.6.6", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20ff29ded3204c5106278a81a38f4b482636ed4fa1e6cfbeef193291beb29ed" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils 0.7.2", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +dependencies = [ + "autocfg 1.1.0", + "cfg-if 0.1.10", + "crossbeam-utils 0.7.2", + "lazy_static", + "maybe-uninit", + "memoffset", + "scopeguard 1.1.0", +] + +[[package]] +name = "crossbeam-queue" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" +dependencies = [ + "cfg-if 0.1.10", + "crossbeam-utils 0.7.2", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-utils" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" +dependencies = [ + "cfg-if 0.1.10", + "lazy_static", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +dependencies = [ + "autocfg 1.1.0", + "cfg-if 0.1.10", + "lazy_static", +] + +[[package]] +name = "debugid" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "088c9627adec1e494ff9dea77377f1e69893023d631254a0ec68b16ee20be3e9" +dependencies = [ + "lazy_static", + "regex", + "serde", + "uuid", +] + +[[package]] +name = "derive_more" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a141330240c921ec6d074a3e188a7c7ef95668bb95e7d44fa0e5778ec2a7afe" +dependencies = [ + "lazy_static", + "proc-macro2 0.4.30", + "quote 0.6.13", + "regex", + "rustc_version", + "syn 0.15.44", +] + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "dtoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" + +[[package]] +name = "eaglesong" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d978bd5d343e8ab9b5c0fc8d93ff9c602fdc96616ffff9c05ac7a155419b824" + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "enum-display-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f16ef37b2a9b242295d61a154ee91ae884afff6b8b933b486b12481cc58310ca" +dependencies = [ + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.108", +] + +[[package]] +name = "env_logger" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +dependencies = [ + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.108", + "synstructure", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "faster-hex" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5b8cccaafb5aae8c282692e5590f341925edea6c696e8715ff0d973320b2646" + +[[package]] +name = "faster-hex" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348138dd23e03bb0018caef99647fb1a5befec5ff4b501991de88f09854d4c28" + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "flate2" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +dependencies = [ + "crc32fast", + "miniz_oxide 0.6.2", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding 2.2.0", +] + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + +[[package]] +name = "futures" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" + +[[package]] +name = "futures-cpupool" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +dependencies = [ + "futures", + "num_cpus", +] + +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "gimli" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" + +[[package]] +name = "goblin" +version = "0.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3fa261d919c1ae9d1e4533c4a2f99e10938603c4208d56c05bec7a872b661b0" +dependencies = [ + "log", + "plain", + "scroll", +] + +[[package]] +name = "h2" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" +dependencies = [ + "byteorder", + "bytes", + "fnv", + "futures", + "http", + "indexmap", + "log", + "slab", + "string", + "tokio-io", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "heapsize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hostname" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" +dependencies = [ + "libc", + "winutil", +] + +[[package]] +name = "http" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" +dependencies = [ + "bytes", + "fnv", + "itoa 0.4.8", +] + +[[package]] +name = "http-body" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" +dependencies = [ + "bytes", + "futures", + "http", + "tokio-buf", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "hyper" +version = "0.12.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c843caf6296fc1f93444735205af9ed4e109a539005abb2564ae1d6fad34c52" +dependencies = [ + "bytes", + "futures", + "futures-cpupool", + "h2", + "http", + "http-body", + "httparse", + "iovec", + "itoa 0.4.8", + "log", + "net2", + "rustc_version", + "time", + "tokio", + "tokio-buf", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" +dependencies = [ + "bytes", + "futures", + "hyper", + "native-tls", + "tokio-io", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd911b35d940d2bd0bea0f9100068e5b97b51a1cbe13d13382f132e0365257a0" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "js-sys", + "wasm-bindgen", + "winapi 0.3.9", +] + +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "im" +version = "12.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de38d1511a0ce7677538acb1e31b5df605147c458e061b2cdb89858afb1cd182" +dependencies = [ + "rustc_version", + "sized-chunks", + "typenum", +] + +[[package]] +name = "includedir" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97402f770a519ebea51b27131c3b6558cfd2375aff21294bad806bad91bf0b6" +dependencies = [ + "flate2", + "phf", +] + +[[package]] +name = "includedir_codegen" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7d542be113fd84855692fb536c16cc4c09527724d1dca8953047d71cccadef" +dependencies = [ + "flate2", + "phf_codegen", + "walkdir", +] + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg 1.1.0", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonrpc-core" +version = "10.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc15eef5f8b6bef5ac5f7440a957ff95d036e2f98706947741bfc93d1976db4c" +dependencies = [ + "futures", + "log", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "lock_api" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +dependencies = [ + "owning_ref", + "scopeguard 0.3.3", +] + +[[package]] +name = "lock_api" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +dependencies = [ + "scopeguard 1.1.0", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memmap" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" +dependencies = [ + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "memoffset" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "merkle-cbt" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c95c71a8dc57c7ad9b7623cf05711bb4e3daef44f1931c91e7d49c60de693ca" +dependencies = [ + "cfg-if 0.1.10", +] + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg 1.1.0", +] + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + +[[package]] +name = "molecule" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba0619bb93e13e12d7e04ab7a1e57f2331f37fa7412f64cf8ef49d1603e0a82a" +dependencies = [ + "bytes", + "faster-hex 0.4.1", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "net2" +version = "0.2.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530c0c97408837c631" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg 1.1.0", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + +[[package]] +name = "numext-constructor" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "621fe0f044729f810c6815cdd77e8f5e0cd803ce4f6a38380ebfc1322af98661" +dependencies = [ + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.108", +] + +[[package]] +name = "numext-fixed-uint" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c68c76f96d589d1009a666c5072f37f3114d682696505f2cf445f27766c7d70" +dependencies = [ + "numext-fixed-uint-core", + "numext-fixed-uint-hack", +] + +[[package]] +name = "numext-fixed-uint-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aab1d6457b97b49482f22a92f0f58a2f39bdd7f3b2f977eae67e8bc206aa980" +dependencies = [ + "heapsize", + "numext-constructor", + "rand 0.7.3", + "serde", + "thiserror", +] + +[[package]] +name = "numext-fixed-uint-hack" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0200f8d55c36ec1b6a8cf810115be85d4814f045e0097dfd50033ba25adb4c9e" +dependencies = [ + "numext-fixed-uint-core", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.108", +] + +[[package]] +name = "object" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "openssl" +version = "0.10.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" +dependencies = [ + "bitflags", + "cfg-if 1.0.0", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.108", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" +dependencies = [ + "autocfg 1.1.0", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "owning_ref" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "parking_lot" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +dependencies = [ + "lock_api 0.1.5", + "parking_lot_core 0.4.0", +] + +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +dependencies = [ + "lock_api 0.3.4", + "parking_lot_core 0.6.3", + "rustc_version", +] + +[[package]] +name = "parking_lot_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +dependencies = [ + "libc", + "rand 0.6.5", + "rustc_version", + "smallvec", + "winapi 0.3.9", +] + +[[package]] +name = "parking_lot_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66b810a62be75176a80873726630147a5ca780cd33921e0b5709033e66b0a" +dependencies = [ + "cfg-if 0.1.10", + "cloudabi", + "libc", + "redox_syscall 0.1.57", + "rustc_version", + "smallvec", + "winapi 0.3.9", +] + +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "phf" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" +dependencies = [ + "phf_shared", + "rand 0.6.5", +] + +[[package]] +name = "phf_shared" +version = "0.7.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "publicsuffix" +version = "1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b4ce31ff0a27d93c8de1849cf58162283752f065a90d508f1105fa6c9a213f" +dependencies = [ + "idna 0.2.3", + "url 2.3.1", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2 1.0.51", +] + +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +dependencies = [ + "autocfg 0.1.8", + "libc", + "rand_chacha 0.1.1", + "rand_core 0.4.2", + "rand_hc 0.1.0", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi 0.3.9", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc 0.2.0", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.3.1", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +dependencies = [ + "libc", + "rand_core 0.4.2", + "winapi 0.3.9", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi 0.3.9", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "reqwest" +version = "0.9.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" +dependencies = [ + "base64", + "bytes", + "cookie", + "cookie_store", + "encoding_rs", + "flate2", + "futures", + "http", + "hyper", + "hyper-tls", + "log", + "mime", + "mime_guess", + "native-tls", + "serde", + "serde_json", + "serde_urlencoded", + "time", + "tokio", + "tokio-executor", + "tokio-io", + "tokio-threadpool", + "tokio-timer", + "url 1.7.2", + "uuid", + "winreg", +] + +[[package]] +name = "ripemd160" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad5112e0dbbb87577bfbc56c42450235e3012ce336e29c5befd7807bd626da4a" +dependencies = [ + "block-buffer", + "digest", + "opaque-debug", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "scroll" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f84d114ef17fd144153d608fba7c446b0145d038985e7a8cc5d08bb0ce20383" +dependencies = [ + "rustc_version", + "scroll_derive", +] + +[[package]] +name = "scroll_derive" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1aa96c45e7f5a91cb7fabe7b279f02fea7126239fc40b732316e8b6a2d0fcb" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", +] + +[[package]] +name = "secp256k1" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d311229f403d64002e9eed9964dfa5a0a0c1ac443344f7546bf48e916c6053a" +dependencies = [ + "cc", + "rand 0.6.5", +] + +[[package]] +name = "security-framework" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "sentry" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "509c5fbb9e875fafcd9c4612c0e49d476083b848bf87380cfe1126ebc745c140" +dependencies = [ + "backtrace", + "env_logger", + "failure", + "hostname", + "httpdate", + "im", + "lazy_static", + "libc", + "log", + "rand 0.6.5", + "regex", + "reqwest", + "rustc_version", + "sentry-types", + "uname", + "url 1.7.2", +] + +[[package]] +name = "sentry-types" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b23e3d9c8c6e4a1523f24df6753c4088bfe16c44a73c8881c1d23c70f28ae280" +dependencies = [ + "chrono", + "debugid", + "failure", + "serde", + "serde_json", + "url 1.7.2", + "url_serde", + "uuid", +] + +[[package]] +name = "serde" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +dependencies = [ + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.108", +] + +[[package]] +name = "serde_json" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +dependencies = [ + "itoa 1.0.5", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" +dependencies = [ + "dtoa", + "itoa 0.4.8", + "serde", + "url 1.7.2", +] + +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer", + "digest", + "fake-simd", + "opaque-debug", +] + +[[package]] +name = "siphasher" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" + +[[package]] +name = "sized-chunks" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d3e7f23bad2d6694e0f46f5e470ec27eb07b8f3e8b309a4b0dc17501928b9f2" +dependencies = [ + "typenum", +] + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "smallvec" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" +dependencies = [ + "maybe-uninit", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "string" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" +dependencies = [ + "bytes", +] + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] + +[[package]] +name = "syn" +version = "1.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56e159d99e6c2b93995d171050271edb50ecc5288fbc7cc17de8fdce4e58c14" +dependencies = [ + "proc-macro2 1.0.51", + "quote 1.0.23", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.108", + "unicode-xid 0.2.4", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if 1.0.0", + "fastrand", + "libc", + "redox_syscall 0.2.16", + "remove_dir_all", + "winapi 0.3.9", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +dependencies = [ + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.108", +] + +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi 0.3.9", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" +dependencies = [ + "bytes", + "futures", + "mio", + "num_cpus", + "tokio-current-thread", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer", +] + +[[package]] +name = "tokio-buf" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" +dependencies = [ + "bytes", + "either", + "futures", +] + +[[package]] +name = "tokio-current-thread" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" +dependencies = [ + "futures", + "tokio-executor", +] + +[[package]] +name = "tokio-executor" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" +dependencies = [ + "crossbeam-utils 0.7.2", + "futures", +] + +[[package]] +name = "tokio-io" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" +dependencies = [ + "bytes", + "futures", + "log", +] + +[[package]] +name = "tokio-reactor" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" +dependencies = [ + "crossbeam-utils 0.7.2", + "futures", + "lazy_static", + "log", + "mio", + "num_cpus", + "parking_lot 0.9.0", + "slab", + "tokio-executor", + "tokio-io", + "tokio-sync", +] + +[[package]] +name = "tokio-sync" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" +dependencies = [ + "fnv", + "futures", +] + +[[package]] +name = "tokio-tcp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" +dependencies = [ + "bytes", + "futures", + "iovec", + "mio", + "tokio-io", + "tokio-reactor", +] + +[[package]] +name = "tokio-threadpool" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" +dependencies = [ + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils 0.7.2", + "futures", + "lazy_static", + "log", + "num_cpus", + "slab", + "tokio-executor", +] + +[[package]] +name = "tokio-timer" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" +dependencies = [ + "crossbeam-utils 0.7.2", + "futures", + "slab", + "tokio-executor", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "try_from" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" +dependencies = [ + "cfg-if 0.1.10", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "uname" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b72f89f0ca32e4db1c04e2a72f5345d59796d4866a1ee0609084569f73683dc8" +dependencies = [ + "libc", +] + +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "url" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +dependencies = [ + "idna 0.1.5", + "matches", + "percent-encoding 1.0.1", +] + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna 0.3.0", + "percent-encoding 2.2.0", +] + +[[package]] +name = "url_serde" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" +dependencies = [ + "serde", + "url 1.7.2", +] + +[[package]] +name = "uuid" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" +dependencies = [ + "rand 0.6.5", + "serde", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi 0.3.9", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" +dependencies = [ + "futures", + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.108", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote 1.0.23", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2 1.0.51", + "quote 1.0.23", + "syn 1.0.108", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + +[[package]] +name = "winreg" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "winutil" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..68e52cd --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "ckb-production-scripts" +version = "0.5.1" +authors = ["Nervos Core Dev "] +edition = "2018" +build = "build.rs" +license = "MIT" +description = "CKB Production Scripts" +repository = "https://github.com/nervosnetwork/ckb-production-scripts" +include = ["src/**/*", "Cargo.toml", "build.rs", "specs/cells/*"] + +[dependencies] +includedir = "0.5.0" +phf = "0.7.21" + +[build-dependencies] +includedir_codegen = "0.5.0" +blake2b-rs = "0.1.5" +faster-hex = "0.3" + +[dev-dependencies] +byteorder = "1.3.1" +ckb-types = { git = "https://github.com/nervosnetwork/ckb.git", rev = "d75e4c5" } +ckb-script = { git = "https://github.com/nervosnetwork/ckb.git", rev = "d75e4c5" } +ckb-crypto = { git = "https://github.com/nervosnetwork/ckb.git", rev = "d75e4c5" } +ckb-dao-utils = { git = "https://github.com/nervosnetwork/ckb.git", rev = "d75e4c5" } +ckb-hash = { git = "https://github.com/nervosnetwork/ckb.git", rev = "d75e4c5" } +ckb-error = { git = "https://github.com/nervosnetwork/ckb.git", rev = "d75e4c5" } +rand = "0.6.5" +lazy_static = "1.3.0" +ripemd160 = "0.8.0" +sha2 = "0.8.0" +secp256k1 = { version = "0.15.1" } +faster-hex = "0.3" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9ecd514 --- /dev/null +++ b/Makefile @@ -0,0 +1,90 @@ +TARGET := riscv64-unknown-linux-gnu +CC := $(TARGET)-gcc +LD := $(TARGET)-gcc +OBJCOPY := $(TARGET)-objcopy +CFLAGS := -fPIC -O3 -fno-builtin-printf -fno-builtin-memcmp -nostdinc -nostdlib -nostartfiles -fvisibility=hidden -fdata-sections -ffunction-sections -I deps/secp256k1/src -I deps/secp256k1 -I deps/ckb-c-std-lib -I deps/ckb-c-std-lib/libc -I deps/ckb-c-std-lib/molecule -I c -I build -Wall -Werror -Wno-nonnull -Wno-nonnull-compare -Wno-unused-function -g +LDFLAGS := -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections +SECP256K1_SRC := deps/secp256k1/src/ecmult_static_pre_context.h + +PROTOCOL_HEADER := c/blockchain.h +PROTOCOL_SCHEMA := c/blockchain.mol +PROTOCOL_VERSION := d75e4c56ffa40e17fd2fe477da3f98c5578edcd1 +PROTOCOL_URL := https://raw.githubusercontent.com/nervosnetwork/ckb/${PROTOCOL_VERSION}/util/types/schemas/blockchain.mol +MOLC := moleculec +MOLC_VERSION := 0.7.0 + +# docker pull nervos/ckb-riscv-gnu-toolchain:gnu-bionic-20191012 +BUILDER_DOCKER := nervos/ckb-riscv-gnu-toolchain@sha256:aae8a3f79705f67d505d1f1d5ddc694a4fd537ed1c7e9622420a470d59ba2ec3 +CLANG_FORMAT_DOCKER := kason223/clang-format@sha256:3cce35b0400a7d420ec8504558a02bdfc12fd2d10e40206f140c4545059cd95d + +all: build/anyone_can_pay build/always_success +all-via-docker: ${PROTOCOL_HEADER} + docker run --rm -v `pwd`:/code ${BUILDER_DOCKER} bash -c "cd /code && make" + +build/anyone_can_pay: c/anyone_can_pay.c ${PROTOCOL_HEADER} c/secp256k1_lock.h build/secp256k1_data_info.h $(SECP256K1_SRC) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + $(OBJCOPY) --only-keep-debug $@ $@.debug + $(OBJCOPY) --strip-debug --strip-all $@ + +build/always_success: c/always_success.c + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + $(OBJCOPY) --only-keep-debug $@ $@.debug + $(OBJCOPY) --strip-debug --strip-all $@ + +build/secp256k1_data_info.h: build/dump_secp256k1_data + $< + +build/dump_secp256k1_data: c/dump_secp256k1_data.c $(SECP256K1_SRC) + mkdir -p build + gcc -I deps/secp256k1/src -I deps/secp256k1 -o $@ $< + +$(SECP256K1_SRC): + cd deps/secp256k1 && \ + ./autogen.sh && \ + CC=$(CC) LD=$(LD) ./configure --with-bignum=no --enable-ecmult-static-precomputation --enable-endomorphism --enable-module-recovery --host=$(TARGET) && \ + make src/ecmult_static_pre_context.h src/ecmult_static_context.h + +${PROTOCOL_SCHEMA}: + curl -L -o $@ ${PROTOCOL_URL} + +ALL_C_SOURCE := $(wildcard c/*.c) + +fmt: + docker run --rm -v `pwd`:/code ${CLANG_FORMAT_DOCKER} bash -c "cd code && clang-format -i -style=Google $(ALL_C_SOURCE)" + git diff --exit-code $(ALL_C_SOURCE) + +publish: + git diff --exit-code Cargo.toml + sed -i.bak 's/.*git =/# &/' Cargo.toml + cargo publish --allow-dirty + git checkout Cargo.toml Cargo.lock + rm -f Cargo.toml.bak + +package: + git diff --exit-code Cargo.toml + sed -i.bak 's/.*git =/# &/' Cargo.toml + cargo package --allow-dirty + git checkout Cargo.toml Cargo.lock + rm -f Cargo.toml.bak + +package-clean: + git checkout Cargo.toml Cargo.lock + rm -rf Cargo.toml.bak target/package/ + +clean: + rm -rf build/anyone_can_pay + rm -rf build/secp256k1_data_info.h build/dump_secp256k1_data + rm -rf build/secp256k1_data + rm -rf build/*.debug + cd deps/secp256k1 && [ -f "Makefile" ] && make clean + cargo clean + +install-tools: + if [ ! -x "$$(command -v "${MOLC}")" ] \ + || [ "$$(${MOLC} --version | awk '{ print $$2 }' | tr -d ' ')" != "${MOLC_VERSION}" ]; then \ + cargo install --force --version "${MOLC_VERSION}" "${MOLC}"; \ + fi + +dist: clean all + +.PHONY: all all-via-docker dist clean package-clean package publish diff --git a/README.md b/README.md new file mode 100644 index 0000000..aa8d113 --- /dev/null +++ b/README.md @@ -0,0 +1,94 @@ +# ckb-anyone-can-pay + +CKB anyone-can-pay lock. + +[RFC Draft](https://talk.nervos.org/t/rfc-anyone-can-pay-lock/4438) + +## Build + +``` sh +make all-via-docker && cargo test +``` + +## Quick start + +### Create + +1, create a cell to receive UDT and CKB: + +``` +Cell { + lock: { + code_hash: + args: + } + data: + type: +} +``` + +2, create a cell to receive only CKB: + +``` +Cell { + lock: { + code_hash: + args: + } + data: + type: +} +``` + +3, we can add minimum amount transfer condition: + +``` +Cell { + lock: { + code_hash: + args: | | + } + data: + type: +} +``` + +`minimum CKB` and `minimum UDT` are two optional args, each occupied a byte, and represent `10 ^ x` minimal amount. The default value is `0` which means anyone can transfer any amount to the cell. A transfer must satisfy the `minimum CKB` **or** `minimum UDT`. + +If the owner only wants to receive `UDT`, the owner can set `minimum CKB` to `255`. + +### Send UDT and CKB + +To transfer coins to an anyone-can-pay lock cell, the sender must build an output cell that has the same `lock_hash` and `type_hash` to the input anyone-can-pay lock cell; if the input anyone-can-pay cell has no `data`, the output cell must also be empty. + +``` +# inputs +Cell { + lock: { + code_hash: + args: | + } + data: + type: + capacity: 100 +} +... + +# outputs +Cell { + lock: { + code_hash: + args: | + } + data: + type: + capacity: 200 +} +... +``` + +### Signature + +The owner can provide a secp256k1 signature to unlock the cell, the signature method is the same as the [P2PH](https://github.com/nervosnetwork/ckb-system-scripts/wiki/How-to-sign-transaction#p2ph). + +Unlock a cell with a signature has no restrictions, which helps owner to manage the cell as he wants. diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..a94b665 --- /dev/null +++ b/build.rs @@ -0,0 +1,86 @@ +pub use blake2b_rs::{Blake2b, Blake2bBuilder}; +use includedir_codegen::Compression; + +use std::{ + env, + fs::File, + io::{BufWriter, Read, Write}, + path::Path, +}; + +const PATH_PREFIX: &str = "build/"; +const BUF_SIZE: usize = 8 * 1024; +const CKB_HASH_PERSONALIZATION: &[u8] = b"ckb-default-hash"; + +const BINARIES: &[(&str, &str)] = &[ + ( + "secp256k1_data", + "9799bee251b975b82c45a02154ce28cec89c5853ecc14d12b7b8cccfc19e0af4", + ), + ( + "anyone_can_pay", + "cd69ba816f7471e59110058aa37387c362ed9a240cd178f7bb1ecee386cb31e6", + ), +]; + +fn main() { + let mut bundled = includedir_codegen::start("BUNDLED_CELL"); + + let out_path = Path::new(&env::var("OUT_DIR").unwrap()).join("code_hashes.rs"); + let mut out_file = BufWriter::new(File::create(&out_path).expect("create code_hashes.rs")); + + let mut errors = Vec::new(); + + for (name, expected_hash) in BINARIES { + let path = format!("{}{}", PATH_PREFIX, name); + + let mut buf = [0u8; BUF_SIZE]; + bundled + .add_file(&path, Compression::Gzip) + .expect("add files to resource bundle"); + + // build hash + let mut blake2b = new_blake2b(); + let mut fd = File::open(&path).expect("open file"); + loop { + let read_bytes = fd.read(&mut buf).expect("read file"); + if read_bytes > 0 { + blake2b.update(&buf[..read_bytes]); + } else { + break; + } + } + + let mut hash = [0u8; 32]; + blake2b.finalize(&mut hash); + + let actual_hash = faster_hex::hex_string(&hash).unwrap(); + if expected_hash != &actual_hash { + errors.push((name, expected_hash, actual_hash)); + continue; + } + + write!( + &mut out_file, + "pub const {}: [u8; 32] = {:?};\n", + format!("CODE_HASH_{}", name.to_uppercase()), + hash + ) + .expect("write to code_hashes.rs"); + } + + if !errors.is_empty() { + for (name, expected, actual) in errors.into_iter() { + eprintln!("{}: expect {}, actual {}", name, expected, actual); + } + panic!("not all hashes are right"); + } + + bundled.build("bundled.rs").expect("build resource bundle"); +} + +pub fn new_blake2b() -> Blake2b { + Blake2bBuilder::new(32) + .personal(CKB_HASH_PERSONALIZATION) + .build() +} diff --git a/c/always_success.c b/c/always_success.c new file mode 100644 index 0000000..1bf5922 --- /dev/null +++ b/c/always_success.c @@ -0,0 +1,4 @@ +/* for testing purpose */ + +#include "ckb_syscalls.h" +int main() { return 0; } diff --git a/c/anyone_can_pay.c b/c/anyone_can_pay.c new file mode 100644 index 0000000..889c069 --- /dev/null +++ b/c/anyone_can_pay.c @@ -0,0 +1,328 @@ +/* UDT anyone-can-pay lock script + * For simplify, we call a cell with anyone-can-pay lock a wallet cell. + * + * Wallet cell can be unlocked without a signature, if: + * + * 1. There is 1 output wallet cell that has the same type hash with the + * unlocked wallet cell. + * 2. The UDT or CKB(if type script is none) in the output wallet is more than + * the unlocked wallet. + * 3. if the type script is none, the cell data is empty. + * + * otherwise, the script perform secp256k1_blake160_sighash_all verification. + */ + +#include "blake2b.h" +#include "blockchain.h" +#include "ckb_syscalls.h" +#include "defs.h" +#include "overflow_add.h" +#include "quick_pow10.h" +#include "secp256k1_helper.h" +#include "secp256k1_lock.h" + +#define BLAKE2B_BLOCK_SIZE 32 +#define SCRIPT_SIZE 32768 +#define CKB_LEN 8 +#define UDT_LEN 16 +#define MAX_WITNESS_SIZE 32768 +#define MAX_TYPE_HASH 256 + +/* anyone can pay errors */ +#define ERROR_OVERFLOW -41 +#define ERROR_OUTPUT_AMOUNT_NOT_ENOUGH -42 +#define ERROR_TOO_MUCH_TYPE_HASH_INPUTS -43 +#define ERROR_NO_PAIR -44 +#define ERROR_DUPLICATED_INPUTS -45 +#define ERROR_DUPLICATED_OUTPUTS -46 + +typedef struct { + int is_ckb_only; + unsigned char type_hash[BLAKE2B_BLOCK_SIZE]; + uint64_t ckb_amount; + uint128_t udt_amount; + uint32_t output_cnt; +} InputWallet; + +int load_type_hash_and_amount(uint64_t cell_index, uint64_t cell_source, + uint8_t type_hash[BLAKE2B_BLOCK_SIZE], + uint64_t *ckb_amount, uint128_t *udt_amount, + int *is_ckb_only) { + uint64_t len = BLAKE2B_BLOCK_SIZE; + int ret = ckb_checked_load_cell_by_field( + type_hash, &len, 0, cell_index, cell_source, CKB_CELL_FIELD_TYPE_HASH); + if (ret == CKB_INDEX_OUT_OF_BOUND) { + return ret; + } + + if (ret == CKB_SUCCESS) { + if (len != BLAKE2B_BLOCK_SIZE) { + return ERROR_ENCODING; + } + } else if (ret != CKB_ITEM_MISSING) { + return ERROR_SYSCALL; + } + + *is_ckb_only = ret == CKB_ITEM_MISSING; + + /* load amount */ + len = CKB_LEN; + ret = + ckb_checked_load_cell_by_field((uint8_t *)ckb_amount, &len, 0, cell_index, + cell_source, CKB_CELL_FIELD_CAPACITY); + if (ret != CKB_SUCCESS) { + *ckb_amount = 0; + return ERROR_SYSCALL; + } + if (len != CKB_LEN) { + return ERROR_ENCODING; + } + len = UDT_LEN; + ret = ckb_load_cell_data((uint8_t *)udt_amount, &len, 0, cell_index, + cell_source); + if (ret != CKB_SUCCESS) { + *udt_amount = 0; + if (ret != CKB_ITEM_MISSING) { + return ERROR_SYSCALL; + } + + return CKB_SUCCESS; + } + + /* check data length */ + if (*is_ckb_only) { + /* ckb only wallet should has no data */ + if (len != 0) { + return ERROR_ENCODING; + } + } else { + if (len < UDT_LEN) { + return ERROR_ENCODING; + } + } + + return CKB_SUCCESS; +} + +int check_payment_unlock(uint64_t min_ckb_amount, uint128_t min_udt_amount) { + unsigned char lock_hash[BLAKE2B_BLOCK_SIZE] = {0}; + InputWallet input_wallets[MAX_TYPE_HASH] = {0}; + uint64_t len = BLAKE2B_BLOCK_SIZE; + /* load wallet lock hash */ + int ret = ckb_load_script_hash(lock_hash, &len, 0); + if (ret != CKB_SUCCESS) { + return ERROR_SYSCALL; + } + if (len > BLAKE2B_BLOCK_SIZE) { + return ERROR_SCRIPT_TOO_LONG; + } + + /* iterate inputs and find input wallet cell */ + int i = 0; + len = BLAKE2B_BLOCK_SIZE; + while (1) { + if (i >= MAX_TYPE_HASH) { + return ERROR_TOO_MUCH_TYPE_HASH_INPUTS; + } + + ret = load_type_hash_and_amount( + i, CKB_SOURCE_GROUP_INPUT, input_wallets[i].type_hash, + &input_wallets[i].ckb_amount, &input_wallets[i].udt_amount, + &input_wallets[i].is_ckb_only); + if (ret == CKB_INDEX_OUT_OF_BOUND) { + break; + } else if (ret != CKB_SUCCESS) { + return ret; + } + + i++; + } + + int input_wallets_cnt = i; + + /* iterate outputs wallet cell */ + i = 0; + while (1) { + uint8_t output_lock_hash[BLAKE2B_BLOCK_SIZE] = {0}; + uint8_t output_type_hash[BLAKE2B_BLOCK_SIZE] = {0}; + uint64_t len = BLAKE2B_BLOCK_SIZE; + /* check lock hash */ + ret = ckb_checked_load_cell_by_field(output_lock_hash, &len, 0, i, + CKB_SOURCE_OUTPUT, + CKB_CELL_FIELD_LOCK_HASH); + if (ret == CKB_INDEX_OUT_OF_BOUND) { + break; + } + if (ret != CKB_SUCCESS) { + return ret; + } + if (len != BLAKE2B_BLOCK_SIZE) { + return ERROR_ENCODING; + } + int has_same_lock = + memcmp(output_lock_hash, lock_hash, BLAKE2B_BLOCK_SIZE) == 0; + + /* skip non ACP lock cells*/ + if (!has_same_lock) { + i++; + continue; + } + + /* load output cell */ + int is_ckb_only = 0; + uint64_t ckb_amount = 0; + uint128_t udt_amount = 0; + ret = load_type_hash_and_amount(i, CKB_SOURCE_OUTPUT, output_type_hash, + &ckb_amount, &udt_amount, &is_ckb_only); + if (ret == CKB_INDEX_OUT_OF_BOUND) { + break; + } else if (ret != CKB_SUCCESS) { + return ret; + } + + /* find input wallet which has same type hash */ + int found_inputs = 0; + for (int j = 0; j < input_wallets_cnt; j++) { + int has_same_type = 0; + /* check type hash */ + if (is_ckb_only) { + has_same_type = input_wallets[j].is_ckb_only; + } else { + has_same_type = memcmp(output_type_hash, input_wallets[j].type_hash, + BLAKE2B_BLOCK_SIZE) == 0; + } + if (!has_same_type) { + continue; + } + /* compare amount */ + uint64_t min_output_ckb_amount = 0; + uint128_t min_output_udt_amount = 0; + int overflow = 0; + overflow = uint64_overflow_add( + &min_output_ckb_amount, input_wallets[j].ckb_amount, min_ckb_amount); + int meet_ckb_cond = !overflow && ckb_amount >= min_output_ckb_amount; + overflow = uint128_overflow_add( + &min_output_udt_amount, input_wallets[j].udt_amount, min_udt_amount); + int meet_udt_cond = !overflow && udt_amount >= min_output_udt_amount; + + /* fail if can't meet both conditions */ + if (!(meet_ckb_cond || meet_udt_cond)) { + return ERROR_OUTPUT_AMOUNT_NOT_ENOUGH; + } + /* output coins must meet condition, or remain the old amount */ + if ((!meet_ckb_cond && ckb_amount != input_wallets[j].ckb_amount) || + (!meet_udt_cond && udt_amount != input_wallets[j].udt_amount)) { + + return ERROR_OUTPUT_AMOUNT_NOT_ENOUGH; + } + + /* increase counter */ + found_inputs++; + input_wallets[j].output_cnt += 1; + if (found_inputs > 1) { + return ERROR_DUPLICATED_INPUTS; + } + if (input_wallets[j].output_cnt > 1) { + return ERROR_DUPLICATED_OUTPUTS; + } + } + + /* one output should pair with one input */ + if (found_inputs == 0) { + return ERROR_NO_PAIR; + } else if (found_inputs > 1) { + return ERROR_DUPLICATED_INPUTS; + } + + i++; + } + + /* check inputs wallet, one input should pair with one output */ + for (int j = 0; j < input_wallets_cnt; j++) { + if (input_wallets[j].output_cnt == 0) { + return ERROR_NO_PAIR; + } else if (input_wallets[j].output_cnt > 1) { + return ERROR_DUPLICATED_OUTPUTS; + } + } + + return CKB_SUCCESS; +} + +int read_args(unsigned char *pubkey_hash, uint64_t *min_ckb_amount, + uint128_t *min_udt_amount) { + int ret; + uint64_t len = 0; + + /* Load args */ + unsigned char script[SCRIPT_SIZE]; + len = SCRIPT_SIZE; + ret = ckb_load_script(script, &len, 0); + if (ret != CKB_SUCCESS) { + return ERROR_SYSCALL; + } + if (len > SCRIPT_SIZE) { + return ERROR_SCRIPT_TOO_LONG; + } + mol_seg_t script_seg; + script_seg.ptr = (uint8_t *)script; + script_seg.size = len; + + if (MolReader_Script_verify(&script_seg, false) != MOL_OK) { + return ERROR_ENCODING; + } + + mol_seg_t args_seg = MolReader_Script_get_args(&script_seg); + mol_seg_t args_bytes_seg = MolReader_Bytes_raw_bytes(&args_seg); + if (args_bytes_seg.size < BLAKE160_SIZE || + args_bytes_seg.size > BLAKE160_SIZE + 2) { + return ERROR_ARGUMENTS_LEN; + } + memcpy(pubkey_hash, args_bytes_seg.ptr, BLAKE160_SIZE); + *min_ckb_amount = 0; + *min_udt_amount = 0; + if (args_bytes_seg.size > BLAKE160_SIZE) { + int x = args_bytes_seg.ptr[BLAKE160_SIZE]; + int is_overflow = quick_pow10(x, min_ckb_amount); + if (is_overflow) { + *min_ckb_amount = MAX_UINT64; + } + } + if (args_bytes_seg.size > BLAKE160_SIZE + 1) { + int x = args_bytes_seg.ptr[BLAKE160_SIZE + 1]; + int is_overflow = uint128_quick_pow10(x, min_udt_amount); + if (is_overflow) { + *min_udt_amount = MAX_UINT128; + } + } + return CKB_SUCCESS; +} + +int main() { + int ret; + /* read script args */ + unsigned char pubkey_hash[BLAKE160_SIZE] = {0}; + uint64_t min_ckb_amount = 0; + uint128_t min_udt_amount = 0; + ret = read_args(pubkey_hash, &min_ckb_amount, &min_udt_amount); + if (ret != CKB_SUCCESS) { + return ret; + } + + /* try load signature */ + unsigned char first_witness[MAX_WITNESS_SIZE]; + uint64_t first_witness_len = 0; + ret = load_secp256k1_first_witness_and_check_signature(first_witness, + &first_witness_len); + int has_sig = ret == CKB_SUCCESS; + + /* ACP verification */ + if (has_sig) { + /* unlock via signature */ + return verify_secp256k1_blake160_sighash_all_with_witness( + pubkey_hash, first_witness, first_witness_len); + } else { + /* unlock via payment */ + return check_payment_unlock(min_ckb_amount, min_udt_amount); + } +} diff --git a/c/blake2b.h b/c/blake2b.h new file mode 100644 index 0000000..a0f5810 --- /dev/null +++ b/c/blake2b.h @@ -0,0 +1,542 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Copyright 2012, Samuel Neves . You may use this under the + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at + your option. The terms of these licenses can be found at: + + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ + +// blake2.h +#ifndef BLAKE2_H +#define BLAKE2_H + +#include +#include + +#if defined(_MSC_VER) +#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop)) +#else +#define BLAKE2_PACKED(x) x __attribute__((packed)) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + + enum blake2b_constant + { + BLAKE2B_BLOCKBYTES = 128, + BLAKE2B_OUTBYTES = 64, + BLAKE2B_KEYBYTES = 64, + BLAKE2B_SALTBYTES = 16, + BLAKE2B_PERSONALBYTES = 16 + }; + + typedef struct blake2b_state__ + { + uint64_t h[8]; + uint64_t t[2]; + uint64_t f[2]; + uint8_t buf[BLAKE2B_BLOCKBYTES]; + size_t buflen; + size_t outlen; + uint8_t last_node; + } blake2b_state; + + BLAKE2_PACKED(struct blake2b_param__ + { + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint32_t leaf_length; /* 8 */ + uint32_t node_offset; /* 12 */ + uint32_t xof_length; /* 16 */ + uint8_t node_depth; /* 17 */ + uint8_t inner_length; /* 18 */ + uint8_t reserved[14]; /* 32 */ + uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ + uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ + }); + + typedef struct blake2b_param__ blake2b_param; + + /* Padded structs result in a compile-time error */ + enum { + BLAKE2_DUMMY_2 = 1/(sizeof(blake2b_param) == BLAKE2B_OUTBYTES) + }; + + /* Streaming API */ + int blake2b_init( blake2b_state *S, size_t outlen ); + int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen ); + int blake2b_init_param( blake2b_state *S, const blake2b_param *P ); + int blake2b_update( blake2b_state *S, const void *in, size_t inlen ); + int blake2b_final( blake2b_state *S, void *out, size_t outlen ); + + /* Simple API */ + int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + + /* This is simply an alias for blake2b */ + int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + +#if defined(__cplusplus) +} +#endif + +#endif + +//blake2-impl.h +#ifndef BLAKE2_IMPL_H +#define BLAKE2_IMPL_H + +#include +#include + +#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) + #if defined(_MSC_VER) + #define BLAKE2_INLINE __inline + #elif defined(__GNUC__) + #define BLAKE2_INLINE __inline__ + #else + #define BLAKE2_INLINE + #endif +#else + #define BLAKE2_INLINE inline +#endif + +static BLAKE2_INLINE uint64_t load64( const void *src ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + uint64_t w; + memcpy(&w, src, sizeof w); + return w; +#else + const uint8_t *p = ( const uint8_t * )src; + return (( uint64_t )( p[0] ) << 0) | + (( uint64_t )( p[1] ) << 8) | + (( uint64_t )( p[2] ) << 16) | + (( uint64_t )( p[3] ) << 24) | + (( uint64_t )( p[4] ) << 32) | + (( uint64_t )( p[5] ) << 40) | + (( uint64_t )( p[6] ) << 48) | + (( uint64_t )( p[7] ) << 56) ; +#endif +} + +static BLAKE2_INLINE void store32( void *dst, uint32_t w ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + memcpy(dst, &w, sizeof w); +#else + uint8_t *p = ( uint8_t * )dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); +#endif +} + +static BLAKE2_INLINE void store64( void *dst, uint64_t w ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + memcpy(dst, &w, sizeof w); +#else + uint8_t *p = ( uint8_t * )dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); + p[4] = (uint8_t)(w >> 32); + p[5] = (uint8_t)(w >> 40); + p[6] = (uint8_t)(w >> 48); + p[7] = (uint8_t)(w >> 56); +#endif +} + +static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c ) +{ + return ( w >> c ) | ( w << ( 64 - c ) ); +} + +/* prevents compiler optimizing out memset() */ +static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) +{ + static void *(*const volatile memset_v)(void *, int, size_t) = &memset; + memset_v(v, 0, n); +} + +#endif + +// blake2b-ref.c +#include +#include +#include + +static const uint64_t blake2b_IV[8] = +{ + 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL +}; + +static const uint8_t blake2b_sigma[12][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } +}; + + +static void blake2b_set_lastnode( blake2b_state *S ) +{ + S->f[1] = (uint64_t)-1; +} + +/* Some helper functions, not necessarily useful */ +static int blake2b_is_lastblock( const blake2b_state *S ) +{ + return S->f[0] != 0; +} + +static void blake2b_set_lastblock( blake2b_state *S ) +{ + if( S->last_node ) blake2b_set_lastnode( S ); + + S->f[0] = (uint64_t)-1; +} + +static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc ) +{ + S->t[0] += inc; + S->t[1] += ( S->t[0] < inc ); +} + +static void blake2b_init0( blake2b_state *S ) +{ + size_t i; + memset( S, 0, sizeof( blake2b_state ) ); + + for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i]; +} + +/* init xors IV with input parameter block */ +int blake2b_init_param( blake2b_state *S, const blake2b_param *P ) +{ + const uint8_t *p = ( const uint8_t * )( P ); + size_t i; + + blake2b_init0( S ); + + /* IV XOR ParamBlock */ + for( i = 0; i < 8; ++i ) + S->h[i] ^= load64( p + sizeof( S->h[i] ) * i ); + + S->outlen = P->digest_length; + return 0; +} + + +const char *DEFAULT_PERSONAL = "ckb-default-hash"; +int blake2b_init( blake2b_state *S, size_t outlen ) +{ + blake2b_param P[1]; + + if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; + + P->digest_length = (uint8_t)outlen; + P->key_length = 0; + P->fanout = 1; + P->depth = 1; + store32( &P->leaf_length, 0 ); + store32( &P->node_offset, 0 ); + store32( &P->xof_length, 0 ); + P->node_depth = 0; + P->inner_length = 0; + memset( P->reserved, 0, sizeof( P->reserved ) ); + memset( P->salt, 0, sizeof( P->salt ) ); + memset( P->personal, 0, sizeof( P->personal ) ); + for (int i = 0; i < BLAKE2B_PERSONALBYTES; ++i) { + (P->personal)[i] = DEFAULT_PERSONAL[i]; + } + return blake2b_init_param( S, P ); +} + + +int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen ) +{ + blake2b_param P[1]; + + if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; + + if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; + + P->digest_length = (uint8_t)outlen; + P->key_length = (uint8_t)keylen; + P->fanout = 1; + P->depth = 1; + store32( &P->leaf_length, 0 ); + store32( &P->node_offset, 0 ); + store32( &P->xof_length, 0 ); + P->node_depth = 0; + P->inner_length = 0; + memset( P->reserved, 0, sizeof( P->reserved ) ); + memset( P->salt, 0, sizeof( P->salt ) ); + memset( P->personal, 0, sizeof( P->personal ) ); + + if( blake2b_init_param( S, P ) < 0 ) return -1; + + { + uint8_t block[BLAKE2B_BLOCKBYTES]; + memset( block, 0, BLAKE2B_BLOCKBYTES ); + memcpy( block, key, keylen ); + blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); + secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */ + } + return 0; +} + +#define G(r,i,a,b,c,d) \ + do { \ + a = a + b + m[blake2b_sigma[r][2*i+0]]; \ + d = rotr64(d ^ a, 32); \ + c = c + d; \ + b = rotr64(b ^ c, 24); \ + a = a + b + m[blake2b_sigma[r][2*i+1]]; \ + d = rotr64(d ^ a, 16); \ + c = c + d; \ + b = rotr64(b ^ c, 63); \ + } while(0) + +#define ROUND(r) \ + do { \ + G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ + G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ + G(r,2,v[ 2],v[ 6],v[10],v[14]); \ + G(r,3,v[ 3],v[ 7],v[11],v[15]); \ + G(r,4,v[ 0],v[ 5],v[10],v[15]); \ + G(r,5,v[ 1],v[ 6],v[11],v[12]); \ + G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ + G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ + } while(0) + +static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] ) +{ + uint64_t m[16]; + uint64_t v[16]; + size_t i; + + for( i = 0; i < 16; ++i ) { + m[i] = load64( block + i * sizeof( m[i] ) ); + } + + for( i = 0; i < 8; ++i ) { + v[i] = S->h[i]; + } + + v[ 8] = blake2b_IV[0]; + v[ 9] = blake2b_IV[1]; + v[10] = blake2b_IV[2]; + v[11] = blake2b_IV[3]; + v[12] = blake2b_IV[4] ^ S->t[0]; + v[13] = blake2b_IV[5] ^ S->t[1]; + v[14] = blake2b_IV[6] ^ S->f[0]; + v[15] = blake2b_IV[7] ^ S->f[1]; + + ROUND( 0 ); + ROUND( 1 ); + ROUND( 2 ); + ROUND( 3 ); + ROUND( 4 ); + ROUND( 5 ); + ROUND( 6 ); + ROUND( 7 ); + ROUND( 8 ); + ROUND( 9 ); + ROUND( 10 ); + ROUND( 11 ); + + for( i = 0; i < 8; ++i ) { + S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; + } +} + +#undef G +#undef ROUND + +int blake2b_update( blake2b_state *S, const void *pin, size_t inlen ) +{ + const unsigned char * in = (const unsigned char *)pin; + if( inlen > 0 ) + { + size_t left = S->buflen; + size_t fill = BLAKE2B_BLOCKBYTES - left; + if( inlen > fill ) + { + S->buflen = 0; + memcpy( S->buf + left, in, fill ); /* Fill buffer */ + blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); + blake2b_compress( S, S->buf ); /* Compress */ + in += fill; inlen -= fill; + while(inlen > BLAKE2B_BLOCKBYTES) { + blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); + blake2b_compress( S, in ); + in += BLAKE2B_BLOCKBYTES; + inlen -= BLAKE2B_BLOCKBYTES; + } + } + memcpy( S->buf + S->buflen, in, inlen ); + S->buflen += inlen; + } + return 0; +} + +int blake2b_final( blake2b_state *S, void *out, size_t outlen ) +{ + uint8_t buffer[BLAKE2B_OUTBYTES] = {0}; + size_t i; + + if( out == NULL || outlen < S->outlen ) + return -1; + + if( blake2b_is_lastblock( S ) ) + return -1; + + blake2b_increment_counter( S, S->buflen ); + blake2b_set_lastblock( S ); + memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */ + blake2b_compress( S, S->buf ); + + for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ + store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); + + memcpy( out, buffer, S->outlen ); + secure_zero_memory(buffer, sizeof(buffer)); + return 0; +} + +/* inlen, at least, should be uint64_t. Others can be size_t. */ +int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) +{ + blake2b_state S[1]; + + /* Verify parameters */ + if ( NULL == in && inlen > 0 ) return -1; + + if ( NULL == out ) return -1; + + if( NULL == key && keylen > 0 ) return -1; + + if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1; + + if( keylen > BLAKE2B_KEYBYTES ) return -1; + + if( keylen > 0 ) + { + if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1; + } + else + { + if( blake2b_init( S, outlen ) < 0 ) return -1; + } + + blake2b_update( S, ( const uint8_t * )in, inlen ); + blake2b_final( S, out, outlen ); + return 0; +} + +int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) { + return blake2b(out, outlen, in, inlen, key, keylen); +} + +#if defined(SUPERCOP) +int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen ) +{ + return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 ); +} +#endif + +#if defined(BLAKE2B_SELFTEST) +#include +#include "blake2-kat.h" +int main( void ) +{ + uint8_t key[BLAKE2B_KEYBYTES]; + uint8_t buf[BLAKE2_KAT_LENGTH]; + size_t i, step; + + for( i = 0; i < BLAKE2B_KEYBYTES; ++i ) + key[i] = ( uint8_t )i; + + for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) + buf[i] = ( uint8_t )i; + + /* Test simple API */ + for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) + { + uint8_t hash[BLAKE2B_OUTBYTES]; + blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES ); + + if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) ) + { + goto fail; + } + } + + /* Test streaming API */ + for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) { + for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) { + uint8_t hash[BLAKE2B_OUTBYTES]; + blake2b_state S; + uint8_t * p = buf; + size_t mlen = i; + int err = 0; + + if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) { + goto fail; + } + + while (mlen >= step) { + if ( (err = blake2b_update(&S, p, step)) < 0 ) { + goto fail; + } + mlen -= step; + p += step; + } + if ( (err = blake2b_update(&S, p, mlen)) < 0) { + goto fail; + } + if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) { + goto fail; + } + + if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) { + goto fail; + } + } + } + + puts( "ok" ); + return 0; +fail: + puts("error"); + return -1; +} +#endif + diff --git a/c/blockchain.h b/c/blockchain.h new file mode 100644 index 0000000..a9f9d33 --- /dev/null +++ b/c/blockchain.h @@ -0,0 +1,1864 @@ +// Generated by Molecule 0.4.1 + +#include "molecule_reader.h" +#include "molecule_builder.h" + +#ifndef BLOCKCHAIN_H +#define BLOCKCHAIN_H + +#ifdef __cplusplus +#define _CPP_BEGIN extern "C" { +#define _CPP_END } +_CPP_BEGIN +#endif /* __cplusplus */ + +/* + * Reader APIs + */ + +#define MolReader_Uint32_verify(s, c) mol_verify_fixed_size(s, 4) +#define MolReader_Uint32_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_Uint32_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_Uint32_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_Uint32_get_nth3(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_Uint64_verify(s, c) mol_verify_fixed_size(s, 8) +#define MolReader_Uint64_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_Uint64_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_Uint64_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_Uint64_get_nth3(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_Uint64_get_nth4(s) mol_slice_by_offset(s, 4, 1) +#define MolReader_Uint64_get_nth5(s) mol_slice_by_offset(s, 5, 1) +#define MolReader_Uint64_get_nth6(s) mol_slice_by_offset(s, 6, 1) +#define MolReader_Uint64_get_nth7(s) mol_slice_by_offset(s, 7, 1) +#define MolReader_Uint128_verify(s, c) mol_verify_fixed_size(s, 16) +#define MolReader_Uint128_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_Uint128_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_Uint128_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_Uint128_get_nth3(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_Uint128_get_nth4(s) mol_slice_by_offset(s, 4, 1) +#define MolReader_Uint128_get_nth5(s) mol_slice_by_offset(s, 5, 1) +#define MolReader_Uint128_get_nth6(s) mol_slice_by_offset(s, 6, 1) +#define MolReader_Uint128_get_nth7(s) mol_slice_by_offset(s, 7, 1) +#define MolReader_Uint128_get_nth8(s) mol_slice_by_offset(s, 8, 1) +#define MolReader_Uint128_get_nth9(s) mol_slice_by_offset(s, 9, 1) +#define MolReader_Uint128_get_nth10(s) mol_slice_by_offset(s, 10, 1) +#define MolReader_Uint128_get_nth11(s) mol_slice_by_offset(s, 11, 1) +#define MolReader_Uint128_get_nth12(s) mol_slice_by_offset(s, 12, 1) +#define MolReader_Uint128_get_nth13(s) mol_slice_by_offset(s, 13, 1) +#define MolReader_Uint128_get_nth14(s) mol_slice_by_offset(s, 14, 1) +#define MolReader_Uint128_get_nth15(s) mol_slice_by_offset(s, 15, 1) +#define MolReader_Byte32_verify(s, c) mol_verify_fixed_size(s, 32) +#define MolReader_Byte32_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_Byte32_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_Byte32_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_Byte32_get_nth3(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_Byte32_get_nth4(s) mol_slice_by_offset(s, 4, 1) +#define MolReader_Byte32_get_nth5(s) mol_slice_by_offset(s, 5, 1) +#define MolReader_Byte32_get_nth6(s) mol_slice_by_offset(s, 6, 1) +#define MolReader_Byte32_get_nth7(s) mol_slice_by_offset(s, 7, 1) +#define MolReader_Byte32_get_nth8(s) mol_slice_by_offset(s, 8, 1) +#define MolReader_Byte32_get_nth9(s) mol_slice_by_offset(s, 9, 1) +#define MolReader_Byte32_get_nth10(s) mol_slice_by_offset(s, 10, 1) +#define MolReader_Byte32_get_nth11(s) mol_slice_by_offset(s, 11, 1) +#define MolReader_Byte32_get_nth12(s) mol_slice_by_offset(s, 12, 1) +#define MolReader_Byte32_get_nth13(s) mol_slice_by_offset(s, 13, 1) +#define MolReader_Byte32_get_nth14(s) mol_slice_by_offset(s, 14, 1) +#define MolReader_Byte32_get_nth15(s) mol_slice_by_offset(s, 15, 1) +#define MolReader_Byte32_get_nth16(s) mol_slice_by_offset(s, 16, 1) +#define MolReader_Byte32_get_nth17(s) mol_slice_by_offset(s, 17, 1) +#define MolReader_Byte32_get_nth18(s) mol_slice_by_offset(s, 18, 1) +#define MolReader_Byte32_get_nth19(s) mol_slice_by_offset(s, 19, 1) +#define MolReader_Byte32_get_nth20(s) mol_slice_by_offset(s, 20, 1) +#define MolReader_Byte32_get_nth21(s) mol_slice_by_offset(s, 21, 1) +#define MolReader_Byte32_get_nth22(s) mol_slice_by_offset(s, 22, 1) +#define MolReader_Byte32_get_nth23(s) mol_slice_by_offset(s, 23, 1) +#define MolReader_Byte32_get_nth24(s) mol_slice_by_offset(s, 24, 1) +#define MolReader_Byte32_get_nth25(s) mol_slice_by_offset(s, 25, 1) +#define MolReader_Byte32_get_nth26(s) mol_slice_by_offset(s, 26, 1) +#define MolReader_Byte32_get_nth27(s) mol_slice_by_offset(s, 27, 1) +#define MolReader_Byte32_get_nth28(s) mol_slice_by_offset(s, 28, 1) +#define MolReader_Byte32_get_nth29(s) mol_slice_by_offset(s, 29, 1) +#define MolReader_Byte32_get_nth30(s) mol_slice_by_offset(s, 30, 1) +#define MolReader_Byte32_get_nth31(s) mol_slice_by_offset(s, 31, 1) +#define MolReader_Uint256_verify(s, c) mol_verify_fixed_size(s, 32) +#define MolReader_Uint256_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_Uint256_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_Uint256_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_Uint256_get_nth3(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_Uint256_get_nth4(s) mol_slice_by_offset(s, 4, 1) +#define MolReader_Uint256_get_nth5(s) mol_slice_by_offset(s, 5, 1) +#define MolReader_Uint256_get_nth6(s) mol_slice_by_offset(s, 6, 1) +#define MolReader_Uint256_get_nth7(s) mol_slice_by_offset(s, 7, 1) +#define MolReader_Uint256_get_nth8(s) mol_slice_by_offset(s, 8, 1) +#define MolReader_Uint256_get_nth9(s) mol_slice_by_offset(s, 9, 1) +#define MolReader_Uint256_get_nth10(s) mol_slice_by_offset(s, 10, 1) +#define MolReader_Uint256_get_nth11(s) mol_slice_by_offset(s, 11, 1) +#define MolReader_Uint256_get_nth12(s) mol_slice_by_offset(s, 12, 1) +#define MolReader_Uint256_get_nth13(s) mol_slice_by_offset(s, 13, 1) +#define MolReader_Uint256_get_nth14(s) mol_slice_by_offset(s, 14, 1) +#define MolReader_Uint256_get_nth15(s) mol_slice_by_offset(s, 15, 1) +#define MolReader_Uint256_get_nth16(s) mol_slice_by_offset(s, 16, 1) +#define MolReader_Uint256_get_nth17(s) mol_slice_by_offset(s, 17, 1) +#define MolReader_Uint256_get_nth18(s) mol_slice_by_offset(s, 18, 1) +#define MolReader_Uint256_get_nth19(s) mol_slice_by_offset(s, 19, 1) +#define MolReader_Uint256_get_nth20(s) mol_slice_by_offset(s, 20, 1) +#define MolReader_Uint256_get_nth21(s) mol_slice_by_offset(s, 21, 1) +#define MolReader_Uint256_get_nth22(s) mol_slice_by_offset(s, 22, 1) +#define MolReader_Uint256_get_nth23(s) mol_slice_by_offset(s, 23, 1) +#define MolReader_Uint256_get_nth24(s) mol_slice_by_offset(s, 24, 1) +#define MolReader_Uint256_get_nth25(s) mol_slice_by_offset(s, 25, 1) +#define MolReader_Uint256_get_nth26(s) mol_slice_by_offset(s, 26, 1) +#define MolReader_Uint256_get_nth27(s) mol_slice_by_offset(s, 27, 1) +#define MolReader_Uint256_get_nth28(s) mol_slice_by_offset(s, 28, 1) +#define MolReader_Uint256_get_nth29(s) mol_slice_by_offset(s, 29, 1) +#define MolReader_Uint256_get_nth30(s) mol_slice_by_offset(s, 30, 1) +#define MolReader_Uint256_get_nth31(s) mol_slice_by_offset(s, 31, 1) +#define MolReader_Bytes_verify(s, c) mol_fixvec_verify(s, 1) +#define MolReader_Bytes_length(s) mol_fixvec_length(s) +#define MolReader_Bytes_get(s, i) mol_fixvec_slice_by_index(s, 1, i) +#define MolReader_Bytes_raw_bytes(s) mol_fixvec_slice_raw_bytes(s) +mol_errno MolReader_BytesOpt_verify (const mol_seg_t*, bool); +#define MolReader_BytesOpt_is_none(s) mol_option_is_none(s) +mol_errno MolReader_BytesVec_verify (const mol_seg_t*, bool); +#define MolReader_BytesVec_length(s) mol_dynvec_length(s) +#define MolReader_BytesVec_get(s, i) mol_dynvec_slice_by_index(s, i) +#define MolReader_Byte32Vec_verify(s, c) mol_fixvec_verify(s, 32) +#define MolReader_Byte32Vec_length(s) mol_fixvec_length(s) +#define MolReader_Byte32Vec_get(s, i) mol_fixvec_slice_by_index(s, 32, i) +mol_errno MolReader_ScriptOpt_verify (const mol_seg_t*, bool); +#define MolReader_ScriptOpt_is_none(s) mol_option_is_none(s) +#define MolReader_ProposalShortId_verify(s, c) mol_verify_fixed_size(s, 10) +#define MolReader_ProposalShortId_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_ProposalShortId_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_ProposalShortId_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_ProposalShortId_get_nth3(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_ProposalShortId_get_nth4(s) mol_slice_by_offset(s, 4, 1) +#define MolReader_ProposalShortId_get_nth5(s) mol_slice_by_offset(s, 5, 1) +#define MolReader_ProposalShortId_get_nth6(s) mol_slice_by_offset(s, 6, 1) +#define MolReader_ProposalShortId_get_nth7(s) mol_slice_by_offset(s, 7, 1) +#define MolReader_ProposalShortId_get_nth8(s) mol_slice_by_offset(s, 8, 1) +#define MolReader_ProposalShortId_get_nth9(s) mol_slice_by_offset(s, 9, 1) +mol_errno MolReader_UncleBlockVec_verify (const mol_seg_t*, bool); +#define MolReader_UncleBlockVec_length(s) mol_dynvec_length(s) +#define MolReader_UncleBlockVec_get(s, i) mol_dynvec_slice_by_index(s, i) +mol_errno MolReader_TransactionVec_verify (const mol_seg_t*, bool); +#define MolReader_TransactionVec_length(s) mol_dynvec_length(s) +#define MolReader_TransactionVec_get(s, i) mol_dynvec_slice_by_index(s, i) +#define MolReader_ProposalShortIdVec_verify(s, c) mol_fixvec_verify(s, 10) +#define MolReader_ProposalShortIdVec_length(s) mol_fixvec_length(s) +#define MolReader_ProposalShortIdVec_get(s, i) mol_fixvec_slice_by_index(s, 10, i) +#define MolReader_CellDepVec_verify(s, c) mol_fixvec_verify(s, 37) +#define MolReader_CellDepVec_length(s) mol_fixvec_length(s) +#define MolReader_CellDepVec_get(s, i) mol_fixvec_slice_by_index(s, 37, i) +#define MolReader_CellInputVec_verify(s, c) mol_fixvec_verify(s, 44) +#define MolReader_CellInputVec_length(s) mol_fixvec_length(s) +#define MolReader_CellInputVec_get(s, i) mol_fixvec_slice_by_index(s, 44, i) +mol_errno MolReader_CellOutputVec_verify (const mol_seg_t*, bool); +#define MolReader_CellOutputVec_length(s) mol_dynvec_length(s) +#define MolReader_CellOutputVec_get(s, i) mol_dynvec_slice_by_index(s, i) +mol_errno MolReader_Script_verify (const mol_seg_t*, bool); +#define MolReader_Script_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Script_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_Script_get_code_hash(s) mol_table_slice_by_index(s, 0) +#define MolReader_Script_get_hash_type(s) mol_table_slice_by_index(s, 1) +#define MolReader_Script_get_args(s) mol_table_slice_by_index(s, 2) +#define MolReader_OutPoint_verify(s, c) mol_verify_fixed_size(s, 36) +#define MolReader_OutPoint_get_tx_hash(s) mol_slice_by_offset(s, 0, 32) +#define MolReader_OutPoint_get_index(s) mol_slice_by_offset(s, 32, 4) +#define MolReader_CellInput_verify(s, c) mol_verify_fixed_size(s, 44) +#define MolReader_CellInput_get_since(s) mol_slice_by_offset(s, 0, 8) +#define MolReader_CellInput_get_previous_output(s) mol_slice_by_offset(s, 8, 36) +mol_errno MolReader_CellOutput_verify (const mol_seg_t*, bool); +#define MolReader_CellOutput_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_CellOutput_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_CellOutput_get_capacity(s) mol_table_slice_by_index(s, 0) +#define MolReader_CellOutput_get_lock(s) mol_table_slice_by_index(s, 1) +#define MolReader_CellOutput_get_type_(s) mol_table_slice_by_index(s, 2) +#define MolReader_CellDep_verify(s, c) mol_verify_fixed_size(s, 37) +#define MolReader_CellDep_get_out_point(s) mol_slice_by_offset(s, 0, 36) +#define MolReader_CellDep_get_dep_type(s) mol_slice_by_offset(s, 36, 1) +mol_errno MolReader_RawTransaction_verify (const mol_seg_t*, bool); +#define MolReader_RawTransaction_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_RawTransaction_has_extra_fields(s) mol_table_has_extra_fields(s, 6) +#define MolReader_RawTransaction_get_version(s) mol_table_slice_by_index(s, 0) +#define MolReader_RawTransaction_get_cell_deps(s) mol_table_slice_by_index(s, 1) +#define MolReader_RawTransaction_get_header_deps(s) mol_table_slice_by_index(s, 2) +#define MolReader_RawTransaction_get_inputs(s) mol_table_slice_by_index(s, 3) +#define MolReader_RawTransaction_get_outputs(s) mol_table_slice_by_index(s, 4) +#define MolReader_RawTransaction_get_outputs_data(s) mol_table_slice_by_index(s, 5) +mol_errno MolReader_Transaction_verify (const mol_seg_t*, bool); +#define MolReader_Transaction_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Transaction_has_extra_fields(s) mol_table_has_extra_fields(s, 2) +#define MolReader_Transaction_get_raw(s) mol_table_slice_by_index(s, 0) +#define MolReader_Transaction_get_witnesses(s) mol_table_slice_by_index(s, 1) +#define MolReader_RawHeader_verify(s, c) mol_verify_fixed_size(s, 192) +#define MolReader_RawHeader_get_version(s) mol_slice_by_offset(s, 0, 4) +#define MolReader_RawHeader_get_compact_target(s) mol_slice_by_offset(s, 4, 4) +#define MolReader_RawHeader_get_timestamp(s) mol_slice_by_offset(s, 8, 8) +#define MolReader_RawHeader_get_number(s) mol_slice_by_offset(s, 16, 8) +#define MolReader_RawHeader_get_epoch(s) mol_slice_by_offset(s, 24, 8) +#define MolReader_RawHeader_get_parent_hash(s) mol_slice_by_offset(s, 32, 32) +#define MolReader_RawHeader_get_transactions_root(s) mol_slice_by_offset(s, 64, 32) +#define MolReader_RawHeader_get_proposals_hash(s) mol_slice_by_offset(s, 96, 32) +#define MolReader_RawHeader_get_uncles_hash(s) mol_slice_by_offset(s, 128, 32) +#define MolReader_RawHeader_get_dao(s) mol_slice_by_offset(s, 160, 32) +#define MolReader_Header_verify(s, c) mol_verify_fixed_size(s, 208) +#define MolReader_Header_get_raw(s) mol_slice_by_offset(s, 0, 192) +#define MolReader_Header_get_nonce(s) mol_slice_by_offset(s, 192, 16) +mol_errno MolReader_UncleBlock_verify (const mol_seg_t*, bool); +#define MolReader_UncleBlock_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_UncleBlock_has_extra_fields(s) mol_table_has_extra_fields(s, 2) +#define MolReader_UncleBlock_get_header(s) mol_table_slice_by_index(s, 0) +#define MolReader_UncleBlock_get_proposals(s) mol_table_slice_by_index(s, 1) +mol_errno MolReader_Block_verify (const mol_seg_t*, bool); +#define MolReader_Block_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_Block_has_extra_fields(s) mol_table_has_extra_fields(s, 4) +#define MolReader_Block_get_header(s) mol_table_slice_by_index(s, 0) +#define MolReader_Block_get_uncles(s) mol_table_slice_by_index(s, 1) +#define MolReader_Block_get_transactions(s) mol_table_slice_by_index(s, 2) +#define MolReader_Block_get_proposals(s) mol_table_slice_by_index(s, 3) +mol_errno MolReader_CellbaseWitness_verify (const mol_seg_t*, bool); +#define MolReader_CellbaseWitness_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_CellbaseWitness_has_extra_fields(s) mol_table_has_extra_fields(s, 2) +#define MolReader_CellbaseWitness_get_lock(s) mol_table_slice_by_index(s, 0) +#define MolReader_CellbaseWitness_get_message(s) mol_table_slice_by_index(s, 1) +mol_errno MolReader_WitnessArgs_verify (const mol_seg_t*, bool); +#define MolReader_WitnessArgs_actual_field_count(s) mol_table_actual_field_count(s) +#define MolReader_WitnessArgs_has_extra_fields(s) mol_table_has_extra_fields(s, 3) +#define MolReader_WitnessArgs_get_lock(s) mol_table_slice_by_index(s, 0) +#define MolReader_WitnessArgs_get_input_type(s) mol_table_slice_by_index(s, 1) +#define MolReader_WitnessArgs_get_output_type(s) mol_table_slice_by_index(s, 2) + +/* + * Builder APIs + */ + +#define MolBuilder_Uint32_init(b) mol_builder_initialize_fixed_size(b, 4) +#define MolBuilder_Uint32_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_Uint32_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_Uint32_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_Uint32_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_Uint32_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_Uint32_clear(b) mol_builder_discard(b) +#define MolBuilder_Uint64_init(b) mol_builder_initialize_fixed_size(b, 8) +#define MolBuilder_Uint64_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_Uint64_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_Uint64_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_Uint64_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_Uint64_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) +#define MolBuilder_Uint64_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) +#define MolBuilder_Uint64_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) +#define MolBuilder_Uint64_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) +#define MolBuilder_Uint64_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_Uint64_clear(b) mol_builder_discard(b) +#define MolBuilder_Uint128_init(b) mol_builder_initialize_fixed_size(b, 16) +#define MolBuilder_Uint128_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_Uint128_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_Uint128_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_Uint128_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_Uint128_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) +#define MolBuilder_Uint128_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) +#define MolBuilder_Uint128_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) +#define MolBuilder_Uint128_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) +#define MolBuilder_Uint128_set_nth8(b, p) mol_builder_set_byte_by_offset(b, 8, p) +#define MolBuilder_Uint128_set_nth9(b, p) mol_builder_set_byte_by_offset(b, 9, p) +#define MolBuilder_Uint128_set_nth10(b, p) mol_builder_set_byte_by_offset(b, 10, p) +#define MolBuilder_Uint128_set_nth11(b, p) mol_builder_set_byte_by_offset(b, 11, p) +#define MolBuilder_Uint128_set_nth12(b, p) mol_builder_set_byte_by_offset(b, 12, p) +#define MolBuilder_Uint128_set_nth13(b, p) mol_builder_set_byte_by_offset(b, 13, p) +#define MolBuilder_Uint128_set_nth14(b, p) mol_builder_set_byte_by_offset(b, 14, p) +#define MolBuilder_Uint128_set_nth15(b, p) mol_builder_set_byte_by_offset(b, 15, p) +#define MolBuilder_Uint128_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_Uint128_clear(b) mol_builder_discard(b) +#define MolBuilder_Byte32_init(b) mol_builder_initialize_fixed_size(b, 32) +#define MolBuilder_Byte32_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_Byte32_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_Byte32_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_Byte32_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_Byte32_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) +#define MolBuilder_Byte32_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) +#define MolBuilder_Byte32_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) +#define MolBuilder_Byte32_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) +#define MolBuilder_Byte32_set_nth8(b, p) mol_builder_set_byte_by_offset(b, 8, p) +#define MolBuilder_Byte32_set_nth9(b, p) mol_builder_set_byte_by_offset(b, 9, p) +#define MolBuilder_Byte32_set_nth10(b, p) mol_builder_set_byte_by_offset(b, 10, p) +#define MolBuilder_Byte32_set_nth11(b, p) mol_builder_set_byte_by_offset(b, 11, p) +#define MolBuilder_Byte32_set_nth12(b, p) mol_builder_set_byte_by_offset(b, 12, p) +#define MolBuilder_Byte32_set_nth13(b, p) mol_builder_set_byte_by_offset(b, 13, p) +#define MolBuilder_Byte32_set_nth14(b, p) mol_builder_set_byte_by_offset(b, 14, p) +#define MolBuilder_Byte32_set_nth15(b, p) mol_builder_set_byte_by_offset(b, 15, p) +#define MolBuilder_Byte32_set_nth16(b, p) mol_builder_set_byte_by_offset(b, 16, p) +#define MolBuilder_Byte32_set_nth17(b, p) mol_builder_set_byte_by_offset(b, 17, p) +#define MolBuilder_Byte32_set_nth18(b, p) mol_builder_set_byte_by_offset(b, 18, p) +#define MolBuilder_Byte32_set_nth19(b, p) mol_builder_set_byte_by_offset(b, 19, p) +#define MolBuilder_Byte32_set_nth20(b, p) mol_builder_set_byte_by_offset(b, 20, p) +#define MolBuilder_Byte32_set_nth21(b, p) mol_builder_set_byte_by_offset(b, 21, p) +#define MolBuilder_Byte32_set_nth22(b, p) mol_builder_set_byte_by_offset(b, 22, p) +#define MolBuilder_Byte32_set_nth23(b, p) mol_builder_set_byte_by_offset(b, 23, p) +#define MolBuilder_Byte32_set_nth24(b, p) mol_builder_set_byte_by_offset(b, 24, p) +#define MolBuilder_Byte32_set_nth25(b, p) mol_builder_set_byte_by_offset(b, 25, p) +#define MolBuilder_Byte32_set_nth26(b, p) mol_builder_set_byte_by_offset(b, 26, p) +#define MolBuilder_Byte32_set_nth27(b, p) mol_builder_set_byte_by_offset(b, 27, p) +#define MolBuilder_Byte32_set_nth28(b, p) mol_builder_set_byte_by_offset(b, 28, p) +#define MolBuilder_Byte32_set_nth29(b, p) mol_builder_set_byte_by_offset(b, 29, p) +#define MolBuilder_Byte32_set_nth30(b, p) mol_builder_set_byte_by_offset(b, 30, p) +#define MolBuilder_Byte32_set_nth31(b, p) mol_builder_set_byte_by_offset(b, 31, p) +#define MolBuilder_Byte32_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_Byte32_clear(b) mol_builder_discard(b) +#define MolBuilder_Uint256_init(b) mol_builder_initialize_fixed_size(b, 32) +#define MolBuilder_Uint256_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_Uint256_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_Uint256_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_Uint256_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_Uint256_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) +#define MolBuilder_Uint256_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) +#define MolBuilder_Uint256_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) +#define MolBuilder_Uint256_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) +#define MolBuilder_Uint256_set_nth8(b, p) mol_builder_set_byte_by_offset(b, 8, p) +#define MolBuilder_Uint256_set_nth9(b, p) mol_builder_set_byte_by_offset(b, 9, p) +#define MolBuilder_Uint256_set_nth10(b, p) mol_builder_set_byte_by_offset(b, 10, p) +#define MolBuilder_Uint256_set_nth11(b, p) mol_builder_set_byte_by_offset(b, 11, p) +#define MolBuilder_Uint256_set_nth12(b, p) mol_builder_set_byte_by_offset(b, 12, p) +#define MolBuilder_Uint256_set_nth13(b, p) mol_builder_set_byte_by_offset(b, 13, p) +#define MolBuilder_Uint256_set_nth14(b, p) mol_builder_set_byte_by_offset(b, 14, p) +#define MolBuilder_Uint256_set_nth15(b, p) mol_builder_set_byte_by_offset(b, 15, p) +#define MolBuilder_Uint256_set_nth16(b, p) mol_builder_set_byte_by_offset(b, 16, p) +#define MolBuilder_Uint256_set_nth17(b, p) mol_builder_set_byte_by_offset(b, 17, p) +#define MolBuilder_Uint256_set_nth18(b, p) mol_builder_set_byte_by_offset(b, 18, p) +#define MolBuilder_Uint256_set_nth19(b, p) mol_builder_set_byte_by_offset(b, 19, p) +#define MolBuilder_Uint256_set_nth20(b, p) mol_builder_set_byte_by_offset(b, 20, p) +#define MolBuilder_Uint256_set_nth21(b, p) mol_builder_set_byte_by_offset(b, 21, p) +#define MolBuilder_Uint256_set_nth22(b, p) mol_builder_set_byte_by_offset(b, 22, p) +#define MolBuilder_Uint256_set_nth23(b, p) mol_builder_set_byte_by_offset(b, 23, p) +#define MolBuilder_Uint256_set_nth24(b, p) mol_builder_set_byte_by_offset(b, 24, p) +#define MolBuilder_Uint256_set_nth25(b, p) mol_builder_set_byte_by_offset(b, 25, p) +#define MolBuilder_Uint256_set_nth26(b, p) mol_builder_set_byte_by_offset(b, 26, p) +#define MolBuilder_Uint256_set_nth27(b, p) mol_builder_set_byte_by_offset(b, 27, p) +#define MolBuilder_Uint256_set_nth28(b, p) mol_builder_set_byte_by_offset(b, 28, p) +#define MolBuilder_Uint256_set_nth29(b, p) mol_builder_set_byte_by_offset(b, 29, p) +#define MolBuilder_Uint256_set_nth30(b, p) mol_builder_set_byte_by_offset(b, 30, p) +#define MolBuilder_Uint256_set_nth31(b, p) mol_builder_set_byte_by_offset(b, 31, p) +#define MolBuilder_Uint256_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_Uint256_clear(b) mol_builder_discard(b) +#define MolBuilder_Bytes_init(b) mol_fixvec_builder_initialize(b, 16) +#define MolBuilder_Bytes_push(b, p) mol_fixvec_builder_push_byte(b, p) +#define MolBuilder_Bytes_build(b) mol_fixvec_builder_finalize(b) +#define MolBuilder_Bytes_clear(b) mol_builder_discard(b) +#define MolBuilder_BytesOpt_init(b) mol_builder_initialize_fixed_size(b, 0) +#define MolBuilder_BytesOpt_set(b, p, l) mol_option_builder_set(b, p, l) +#define MolBuilder_BytesOpt_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_BytesOpt_clear(b) mol_builder_discard(b) +#define MolBuilder_BytesVec_init(b) mol_builder_initialize_with_capacity(b, 64, 64) +#define MolBuilder_BytesVec_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_BytesVec_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_BytesVec_clear(b) mol_builder_discard(b) +#define MolBuilder_Byte32Vec_init(b) mol_fixvec_builder_initialize(b, 512) +#define MolBuilder_Byte32Vec_push(b, p) mol_fixvec_builder_push(b, p, 32) +#define MolBuilder_Byte32Vec_build(b) mol_fixvec_builder_finalize(b) +#define MolBuilder_Byte32Vec_clear(b) mol_builder_discard(b) +#define MolBuilder_ScriptOpt_init(b) mol_builder_initialize_fixed_size(b, 0) +#define MolBuilder_ScriptOpt_set(b, p, l) mol_option_builder_set(b, p, l) +#define MolBuilder_ScriptOpt_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_ScriptOpt_clear(b) mol_builder_discard(b) +#define MolBuilder_ProposalShortId_init(b) mol_builder_initialize_fixed_size(b, 10) +#define MolBuilder_ProposalShortId_set_nth0(b, p) mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_ProposalShortId_set_nth1(b, p) mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_ProposalShortId_set_nth2(b, p) mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_ProposalShortId_set_nth3(b, p) mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_ProposalShortId_set_nth4(b, p) mol_builder_set_byte_by_offset(b, 4, p) +#define MolBuilder_ProposalShortId_set_nth5(b, p) mol_builder_set_byte_by_offset(b, 5, p) +#define MolBuilder_ProposalShortId_set_nth6(b, p) mol_builder_set_byte_by_offset(b, 6, p) +#define MolBuilder_ProposalShortId_set_nth7(b, p) mol_builder_set_byte_by_offset(b, 7, p) +#define MolBuilder_ProposalShortId_set_nth8(b, p) mol_builder_set_byte_by_offset(b, 8, p) +#define MolBuilder_ProposalShortId_set_nth9(b, p) mol_builder_set_byte_by_offset(b, 9, p) +#define MolBuilder_ProposalShortId_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_ProposalShortId_clear(b) mol_builder_discard(b) +#define MolBuilder_UncleBlockVec_init(b) mol_builder_initialize_with_capacity(b, 4096, 64) +#define MolBuilder_UncleBlockVec_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_UncleBlockVec_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_UncleBlockVec_clear(b) mol_builder_discard(b) +#define MolBuilder_TransactionVec_init(b) mol_builder_initialize_with_capacity(b, 2048, 64) +#define MolBuilder_TransactionVec_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_TransactionVec_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_TransactionVec_clear(b) mol_builder_discard(b) +#define MolBuilder_ProposalShortIdVec_init(b) mol_fixvec_builder_initialize(b, 256) +#define MolBuilder_ProposalShortIdVec_push(b, p) mol_fixvec_builder_push(b, p, 10) +#define MolBuilder_ProposalShortIdVec_build(b) mol_fixvec_builder_finalize(b) +#define MolBuilder_ProposalShortIdVec_clear(b) mol_builder_discard(b) +#define MolBuilder_CellDepVec_init(b) mol_fixvec_builder_initialize(b, 1024) +#define MolBuilder_CellDepVec_push(b, p) mol_fixvec_builder_push(b, p, 37) +#define MolBuilder_CellDepVec_build(b) mol_fixvec_builder_finalize(b) +#define MolBuilder_CellDepVec_clear(b) mol_builder_discard(b) +#define MolBuilder_CellInputVec_init(b) mol_fixvec_builder_initialize(b, 1024) +#define MolBuilder_CellInputVec_push(b, p) mol_fixvec_builder_push(b, p, 44) +#define MolBuilder_CellInputVec_build(b) mol_fixvec_builder_finalize(b) +#define MolBuilder_CellInputVec_clear(b) mol_builder_discard(b) +#define MolBuilder_CellOutputVec_init(b) mol_builder_initialize_with_capacity(b, 2048, 64) +#define MolBuilder_CellOutputVec_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_CellOutputVec_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_CellOutputVec_clear(b) mol_builder_discard(b) +#define MolBuilder_Script_init(b) mol_table_builder_initialize(b, 256, 3) +#define MolBuilder_Script_set_code_hash(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Script_set_hash_type(b, p) mol_table_builder_add_byte(b, 1, p) +#define MolBuilder_Script_set_args(b, p, l) mol_table_builder_add(b, 2, p, l) +mol_seg_res_t MolBuilder_Script_build (mol_builder_t); +#define MolBuilder_Script_clear(b) mol_builder_discard(b) +#define MolBuilder_OutPoint_init(b) mol_builder_initialize_fixed_size(b, 36) +#define MolBuilder_OutPoint_set_tx_hash(b, p) mol_builder_set_by_offset(b, 0, p, 32) +#define MolBuilder_OutPoint_set_index(b, p) mol_builder_set_by_offset(b, 32, p, 4) +#define MolBuilder_OutPoint_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_OutPoint_clear(b) mol_builder_discard(b) +#define MolBuilder_CellInput_init(b) mol_builder_initialize_fixed_size(b, 44) +#define MolBuilder_CellInput_set_since(b, p) mol_builder_set_by_offset(b, 0, p, 8) +#define MolBuilder_CellInput_set_previous_output(b, p) mol_builder_set_by_offset(b, 8, p, 36) +#define MolBuilder_CellInput_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_CellInput_clear(b) mol_builder_discard(b) +#define MolBuilder_CellOutput_init(b) mol_table_builder_initialize(b, 512, 3) +#define MolBuilder_CellOutput_set_capacity(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_CellOutput_set_lock(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_CellOutput_set_type_(b, p, l) mol_table_builder_add(b, 2, p, l) +mol_seg_res_t MolBuilder_CellOutput_build (mol_builder_t); +#define MolBuilder_CellOutput_clear(b) mol_builder_discard(b) +#define MolBuilder_CellDep_init(b) mol_builder_initialize_fixed_size(b, 37) +#define MolBuilder_CellDep_set_out_point(b, p) mol_builder_set_by_offset(b, 0, p, 36) +#define MolBuilder_CellDep_set_dep_type(b, p) mol_builder_set_byte_by_offset(b, 36, p) +#define MolBuilder_CellDep_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_CellDep_clear(b) mol_builder_discard(b) +#define MolBuilder_RawTransaction_init(b) mol_table_builder_initialize(b, 256, 6) +#define MolBuilder_RawTransaction_set_version(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_RawTransaction_set_cell_deps(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_RawTransaction_set_header_deps(b, p, l) mol_table_builder_add(b, 2, p, l) +#define MolBuilder_RawTransaction_set_inputs(b, p, l) mol_table_builder_add(b, 3, p, l) +#define MolBuilder_RawTransaction_set_outputs(b, p, l) mol_table_builder_add(b, 4, p, l) +#define MolBuilder_RawTransaction_set_outputs_data(b, p, l) mol_table_builder_add(b, 5, p, l) +mol_seg_res_t MolBuilder_RawTransaction_build (mol_builder_t); +#define MolBuilder_RawTransaction_clear(b) mol_builder_discard(b) +#define MolBuilder_Transaction_init(b) mol_table_builder_initialize(b, 512, 2) +#define MolBuilder_Transaction_set_raw(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Transaction_set_witnesses(b, p, l) mol_table_builder_add(b, 1, p, l) +mol_seg_res_t MolBuilder_Transaction_build (mol_builder_t); +#define MolBuilder_Transaction_clear(b) mol_builder_discard(b) +#define MolBuilder_RawHeader_init(b) mol_builder_initialize_fixed_size(b, 192) +#define MolBuilder_RawHeader_set_version(b, p) mol_builder_set_by_offset(b, 0, p, 4) +#define MolBuilder_RawHeader_set_compact_target(b, p) mol_builder_set_by_offset(b, 4, p, 4) +#define MolBuilder_RawHeader_set_timestamp(b, p) mol_builder_set_by_offset(b, 8, p, 8) +#define MolBuilder_RawHeader_set_number(b, p) mol_builder_set_by_offset(b, 16, p, 8) +#define MolBuilder_RawHeader_set_epoch(b, p) mol_builder_set_by_offset(b, 24, p, 8) +#define MolBuilder_RawHeader_set_parent_hash(b, p) mol_builder_set_by_offset(b, 32, p, 32) +#define MolBuilder_RawHeader_set_transactions_root(b, p) mol_builder_set_by_offset(b, 64, p, 32) +#define MolBuilder_RawHeader_set_proposals_hash(b, p) mol_builder_set_by_offset(b, 96, p, 32) +#define MolBuilder_RawHeader_set_uncles_hash(b, p) mol_builder_set_by_offset(b, 128, p, 32) +#define MolBuilder_RawHeader_set_dao(b, p) mol_builder_set_by_offset(b, 160, p, 32) +#define MolBuilder_RawHeader_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_RawHeader_clear(b) mol_builder_discard(b) +#define MolBuilder_Header_init(b) mol_builder_initialize_fixed_size(b, 208) +#define MolBuilder_Header_set_raw(b, p) mol_builder_set_by_offset(b, 0, p, 192) +#define MolBuilder_Header_set_nonce(b, p) mol_builder_set_by_offset(b, 192, p, 16) +#define MolBuilder_Header_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_Header_clear(b) mol_builder_discard(b) +#define MolBuilder_UncleBlock_init(b) mol_table_builder_initialize(b, 1024, 2) +#define MolBuilder_UncleBlock_set_header(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_UncleBlock_set_proposals(b, p, l) mol_table_builder_add(b, 1, p, l) +mol_seg_res_t MolBuilder_UncleBlock_build (mol_builder_t); +#define MolBuilder_UncleBlock_clear(b) mol_builder_discard(b) +#define MolBuilder_Block_init(b) mol_table_builder_initialize(b, 1024, 4) +#define MolBuilder_Block_set_header(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_Block_set_uncles(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_Block_set_transactions(b, p, l) mol_table_builder_add(b, 2, p, l) +#define MolBuilder_Block_set_proposals(b, p, l) mol_table_builder_add(b, 3, p, l) +mol_seg_res_t MolBuilder_Block_build (mol_builder_t); +#define MolBuilder_Block_clear(b) mol_builder_discard(b) +#define MolBuilder_CellbaseWitness_init(b) mol_table_builder_initialize(b, 512, 2) +#define MolBuilder_CellbaseWitness_set_lock(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_CellbaseWitness_set_message(b, p, l) mol_table_builder_add(b, 1, p, l) +mol_seg_res_t MolBuilder_CellbaseWitness_build (mol_builder_t); +#define MolBuilder_CellbaseWitness_clear(b) mol_builder_discard(b) +#define MolBuilder_WitnessArgs_init(b) mol_table_builder_initialize(b, 64, 3) +#define MolBuilder_WitnessArgs_set_lock(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_WitnessArgs_set_input_type(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_WitnessArgs_set_output_type(b, p, l) mol_table_builder_add(b, 2, p, l) +mol_seg_res_t MolBuilder_WitnessArgs_build (mol_builder_t); +#define MolBuilder_WitnessArgs_clear(b) mol_builder_discard(b) + +/* + * Default Value + */ + +#define ____ 0x00 + +const uint8_t MolDefault_Uint32[4] = {____, ____, ____, ____}; +const uint8_t MolDefault_Uint64[8] = { + ____, ____, ____, ____, ____, ____, ____, ____, +}; +const uint8_t MolDefault_Uint128[16] = { + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, +}; +const uint8_t MolDefault_Byte32[32] = { + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, +}; +const uint8_t MolDefault_Uint256[32] = { + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, +}; +const uint8_t MolDefault_Bytes[4] = {____, ____, ____, ____}; +const uint8_t MolDefault_BytesOpt[0] = {}; +const uint8_t MolDefault_BytesVec[4] = {0x04, ____, ____, ____}; +const uint8_t MolDefault_Byte32Vec[4] = {____, ____, ____, ____}; +const uint8_t MolDefault_ScriptOpt[0] = {}; +const uint8_t MolDefault_ProposalShortId[10] = { + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +}; +const uint8_t MolDefault_UncleBlockVec[4] = {0x04, ____, ____, ____}; +const uint8_t MolDefault_TransactionVec[4] = {0x04, ____, ____, ____}; +const uint8_t MolDefault_ProposalShortIdVec[4] = {____, ____, ____, ____}; +const uint8_t MolDefault_CellDepVec[4] = {____, ____, ____, ____}; +const uint8_t MolDefault_CellInputVec[4] = {____, ____, ____, ____}; +const uint8_t MolDefault_CellOutputVec[4] = {0x04, ____, ____, ____}; +const uint8_t MolDefault_Script[53] = { + 0x35, ____, ____, ____, 0x10, ____, ____, ____, 0x30, ____, ____, ____, + 0x31, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, +}; +const uint8_t MolDefault_OutPoint[36] = { + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +}; +const uint8_t MolDefault_CellInput[44] = { + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, +}; +const uint8_t MolDefault_CellOutput[77] = { + 0x4d, ____, ____, ____, 0x10, ____, ____, ____, 0x18, ____, ____, ____, + 0x4d, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + 0x35, ____, ____, ____, 0x10, ____, ____, ____, 0x30, ____, ____, ____, + 0x31, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, +}; +const uint8_t MolDefault_CellDep[37] = { + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, +}; +const uint8_t MolDefault_RawTransaction[52] = { + 0x34, ____, ____, ____, 0x1c, ____, ____, ____, 0x20, ____, ____, ____, + 0x24, ____, ____, ____, 0x28, ____, ____, ____, 0x2c, ____, ____, ____, + 0x30, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, 0x04, ____, ____, ____, + 0x04, ____, ____, ____, +}; +const uint8_t MolDefault_Transaction[68] = { + 0x44, ____, ____, ____, 0x0c, ____, ____, ____, 0x40, ____, ____, ____, + 0x34, ____, ____, ____, 0x1c, ____, ____, ____, 0x20, ____, ____, ____, + 0x24, ____, ____, ____, 0x28, ____, ____, ____, 0x2c, ____, ____, ____, + 0x30, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, 0x04, ____, ____, ____, + 0x04, ____, ____, ____, 0x04, ____, ____, ____, +}; +const uint8_t MolDefault_RawHeader[192] = { + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, +}; +const uint8_t MolDefault_Header[208] = { + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, +}; +const uint8_t MolDefault_UncleBlock[224] = { + 0xe0, ____, ____, ____, 0x0c, ____, ____, ____, 0xdc, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, +}; +const uint8_t MolDefault_Block[240] = { + 0xf0, ____, ____, ____, 0x14, ____, ____, ____, 0xe4, ____, ____, ____, + 0xe8, ____, ____, ____, 0xec, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + 0x04, ____, ____, ____, 0x04, ____, ____, ____, ____, ____, ____, ____, +}; +const uint8_t MolDefault_CellbaseWitness[69] = { + 0x45, ____, ____, ____, 0x0c, ____, ____, ____, 0x41, ____, ____, ____, + 0x35, ____, ____, ____, 0x10, ____, ____, ____, 0x30, ____, ____, ____, + 0x31, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, +}; +const uint8_t MolDefault_WitnessArgs[16] = { + 0x10, ____, ____, ____, 0x10, ____, ____, ____, 0x10, ____, ____, ____, + 0x10, ____, ____, ____, +}; + +#undef ____ + +/* + * Reader Functions + */ + +mol_errno MolReader_BytesOpt_verify (const mol_seg_t *input, bool compatible) { + if (input->size != 0) { + return MolReader_Bytes_verify(input, compatible); + } else { + return MOL_OK; + } +} +mol_errno MolReader_BytesVec_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size == MOL_NUM_T_SIZE) { + return MOL_OK; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t item_count = offset / 4 - 1; + if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { + return MOL_ERR_HEADER; + } + mol_num_t end; + for (mol_num_t i=1; i end) { + return MOL_ERR_OFFSET; + } + mol_seg_t inner; + inner.ptr = input->ptr + offset; + inner.size = end - offset; + mol_errno errno = MolReader_Bytes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + offset = end; + } + if (offset > total_size) { + return MOL_ERR_OFFSET; + } + mol_seg_t inner; + inner.ptr = input->ptr + offset; + inner.size = total_size - offset; + return MolReader_Bytes_verify(&inner, compatible); +} +mol_errno MolReader_ScriptOpt_verify (const mol_seg_t *input, bool compatible) { + if (input->size != 0) { + return MolReader_Script_verify(input, compatible); + } else { + return MOL_OK; + } +} +mol_errno MolReader_UncleBlockVec_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size == MOL_NUM_T_SIZE) { + return MOL_OK; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t item_count = offset / 4 - 1; + if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { + return MOL_ERR_HEADER; + } + mol_num_t end; + for (mol_num_t i=1; i end) { + return MOL_ERR_OFFSET; + } + mol_seg_t inner; + inner.ptr = input->ptr + offset; + inner.size = end - offset; + mol_errno errno = MolReader_UncleBlock_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + offset = end; + } + if (offset > total_size) { + return MOL_ERR_OFFSET; + } + mol_seg_t inner; + inner.ptr = input->ptr + offset; + inner.size = total_size - offset; + return MolReader_UncleBlock_verify(&inner, compatible); +} +mol_errno MolReader_TransactionVec_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size == MOL_NUM_T_SIZE) { + return MOL_OK; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t item_count = offset / 4 - 1; + if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { + return MOL_ERR_HEADER; + } + mol_num_t end; + for (mol_num_t i=1; i end) { + return MOL_ERR_OFFSET; + } + mol_seg_t inner; + inner.ptr = input->ptr + offset; + inner.size = end - offset; + mol_errno errno = MolReader_Transaction_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + offset = end; + } + if (offset > total_size) { + return MOL_ERR_OFFSET; + } + mol_seg_t inner; + inner.ptr = input->ptr + offset; + inner.size = total_size - offset; + return MolReader_Transaction_verify(&inner, compatible); +} +mol_errno MolReader_CellOutputVec_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size == MOL_NUM_T_SIZE) { + return MOL_OK; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t item_count = offset / 4 - 1; + if (input->size < MOL_NUM_T_SIZE*(item_count+1)) { + return MOL_ERR_HEADER; + } + mol_num_t end; + for (mol_num_t i=1; i end) { + return MOL_ERR_OFFSET; + } + mol_seg_t inner; + inner.ptr = input->ptr + offset; + inner.size = end - offset; + mol_errno errno = MolReader_CellOutput_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + offset = end; + } + if (offset > total_size) { + return MOL_ERR_OFFSET; + } + mol_seg_t inner; + inner.ptr = input->ptr + offset; + inner.size = total_size - offset; + return MolReader_CellOutput_verify(&inner, compatible); +} +mol_errno MolReader_Script_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t field_count = offset / 4 - 1; + if (field_count < 3) { + return MOL_ERR_FIELD_COUNT; + } else if (!compatible && field_count > 3) { + return MOL_ERR_FIELD_COUNT; + } + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + return MOL_ERR_HEADER; + } + mol_num_t offsets[field_count+1]; + offsets[0] = offset; + for (mol_num_t i=1; i offsets[i]) { + return MOL_ERR_OFFSET; + } + } + if (offsets[field_count-1] > total_size) { + return MOL_ERR_OFFSET; + } + offsets[field_count] = total_size; + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_Byte32_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + if (offsets[2] - offsets[1] != 1) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_Bytes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + return MOL_OK; +} +mol_errno MolReader_CellOutput_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t field_count = offset / 4 - 1; + if (field_count < 3) { + return MOL_ERR_FIELD_COUNT; + } else if (!compatible && field_count > 3) { + return MOL_ERR_FIELD_COUNT; + } + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + return MOL_ERR_HEADER; + } + mol_num_t offsets[field_count+1]; + offsets[0] = offset; + for (mol_num_t i=1; i offsets[i]) { + return MOL_ERR_OFFSET; + } + } + if (offsets[field_count-1] > total_size) { + return MOL_ERR_OFFSET; + } + offsets[field_count] = total_size; + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_Uint64_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_Script_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_ScriptOpt_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + return MOL_OK; +} +mol_errno MolReader_RawTransaction_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t field_count = offset / 4 - 1; + if (field_count < 6) { + return MOL_ERR_FIELD_COUNT; + } else if (!compatible && field_count > 6) { + return MOL_ERR_FIELD_COUNT; + } + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + return MOL_ERR_HEADER; + } + mol_num_t offsets[field_count+1]; + offsets[0] = offset; + for (mol_num_t i=1; i offsets[i]) { + return MOL_ERR_OFFSET; + } + } + if (offsets[field_count-1] > total_size) { + return MOL_ERR_OFFSET; + } + offsets[field_count] = total_size; + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_Uint32_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_CellDepVec_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_Byte32Vec_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[3]; + inner.size = offsets[4] - offsets[3]; + errno = MolReader_CellInputVec_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[4]; + inner.size = offsets[5] - offsets[4]; + errno = MolReader_CellOutputVec_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[5]; + inner.size = offsets[6] - offsets[5]; + errno = MolReader_BytesVec_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + return MOL_OK; +} +mol_errno MolReader_Transaction_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t field_count = offset / 4 - 1; + if (field_count < 2) { + return MOL_ERR_FIELD_COUNT; + } else if (!compatible && field_count > 2) { + return MOL_ERR_FIELD_COUNT; + } + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + return MOL_ERR_HEADER; + } + mol_num_t offsets[field_count+1]; + offsets[0] = offset; + for (mol_num_t i=1; i offsets[i]) { + return MOL_ERR_OFFSET; + } + } + if (offsets[field_count-1] > total_size) { + return MOL_ERR_OFFSET; + } + offsets[field_count] = total_size; + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_RawTransaction_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_BytesVec_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + return MOL_OK; +} +mol_errno MolReader_UncleBlock_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t field_count = offset / 4 - 1; + if (field_count < 2) { + return MOL_ERR_FIELD_COUNT; + } else if (!compatible && field_count > 2) { + return MOL_ERR_FIELD_COUNT; + } + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + return MOL_ERR_HEADER; + } + mol_num_t offsets[field_count+1]; + offsets[0] = offset; + for (mol_num_t i=1; i offsets[i]) { + return MOL_ERR_OFFSET; + } + } + if (offsets[field_count-1] > total_size) { + return MOL_ERR_OFFSET; + } + offsets[field_count] = total_size; + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_Header_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_ProposalShortIdVec_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + return MOL_OK; +} +mol_errno MolReader_Block_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t field_count = offset / 4 - 1; + if (field_count < 4) { + return MOL_ERR_FIELD_COUNT; + } else if (!compatible && field_count > 4) { + return MOL_ERR_FIELD_COUNT; + } + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + return MOL_ERR_HEADER; + } + mol_num_t offsets[field_count+1]; + offsets[0] = offset; + for (mol_num_t i=1; i offsets[i]) { + return MOL_ERR_OFFSET; + } + } + if (offsets[field_count-1] > total_size) { + return MOL_ERR_OFFSET; + } + offsets[field_count] = total_size; + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_Header_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_UncleBlockVec_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_TransactionVec_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[3]; + inner.size = offsets[4] - offsets[3]; + errno = MolReader_ProposalShortIdVec_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + return MOL_OK; +} +mol_errno MolReader_CellbaseWitness_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t field_count = offset / 4 - 1; + if (field_count < 2) { + return MOL_ERR_FIELD_COUNT; + } else if (!compatible && field_count > 2) { + return MOL_ERR_FIELD_COUNT; + } + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + return MOL_ERR_HEADER; + } + mol_num_t offsets[field_count+1]; + offsets[0] = offset; + for (mol_num_t i=1; i offsets[i]) { + return MOL_ERR_OFFSET; + } + } + if (offsets[field_count-1] > total_size) { + return MOL_ERR_OFFSET; + } + offsets[field_count] = total_size; + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_Script_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_Bytes_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + return MOL_OK; +} +mol_errno MolReader_WitnessArgs_verify (const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE*2) { + return MOL_ERR_OFFSET; + } + mol_num_t field_count = offset / 4 - 1; + if (field_count < 3) { + return MOL_ERR_FIELD_COUNT; + } else if (!compatible && field_count > 3) { + return MOL_ERR_FIELD_COUNT; + } + if (input->size < MOL_NUM_T_SIZE*(field_count+1)){ + return MOL_ERR_HEADER; + } + mol_num_t offsets[field_count+1]; + offsets[0] = offset; + for (mol_num_t i=1; i offsets[i]) { + return MOL_ERR_OFFSET; + } + } + if (offsets[field_count-1] > total_size) { + return MOL_ERR_OFFSET; + } + offsets[field_count] = total_size; + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + errno = MolReader_BytesOpt_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + errno = MolReader_BytesOpt_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + errno = MolReader_BytesOpt_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + return MOL_OK; +} + +/* + * Builder Functions + */ + +mol_seg_res_t MolBuilder_Script_build (mol_builder_t builder) { + mol_seg_res_t res; + res.errno = MOL_OK; + mol_num_t offset = 16; + mol_num_t len; + res.seg.size = offset; + len = builder.number_ptr[1]; + res.seg.size += len == 0 ? 32 : len; + len = builder.number_ptr[3]; + res.seg.size += len == 0 ? 1 : len; + len = builder.number_ptr[5]; + res.seg.size += len == 0 ? 4 : len; + res.seg.ptr = (uint8_t*)malloc(res.seg.size); + uint8_t *dst = res.seg.ptr; + mol_pack_number(dst, &res.seg.size); + dst += MOL_NUM_T_SIZE; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[1]; + offset += len == 0 ? 32 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[3]; + offset += len == 0 ? 1 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[5]; + offset += len == 0 ? 4 : len; + uint8_t *src = builder.data_ptr; + len = builder.number_ptr[1]; + if (len == 0) { + len = 32; + memcpy(dst, &MolDefault_Byte32, len); + } else { + mol_num_t of = builder.number_ptr[0]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[3]; + if (len == 0) { + len = 1; + *dst = 0; + } else { + mol_num_t of = builder.number_ptr[2]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[5]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_Bytes, len); + } else { + mol_num_t of = builder.number_ptr[4]; + memcpy(dst, src+of, len); + } + dst += len; + mol_builder_discard(builder); + return res; +} +mol_seg_res_t MolBuilder_CellOutput_build (mol_builder_t builder) { + mol_seg_res_t res; + res.errno = MOL_OK; + mol_num_t offset = 16; + mol_num_t len; + res.seg.size = offset; + len = builder.number_ptr[1]; + res.seg.size += len == 0 ? 8 : len; + len = builder.number_ptr[3]; + res.seg.size += len == 0 ? 53 : len; + len = builder.number_ptr[5]; + res.seg.size += len == 0 ? 0 : len; + res.seg.ptr = (uint8_t*)malloc(res.seg.size); + uint8_t *dst = res.seg.ptr; + mol_pack_number(dst, &res.seg.size); + dst += MOL_NUM_T_SIZE; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[1]; + offset += len == 0 ? 8 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[3]; + offset += len == 0 ? 53 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[5]; + offset += len == 0 ? 0 : len; + uint8_t *src = builder.data_ptr; + len = builder.number_ptr[1]; + if (len == 0) { + len = 8; + memcpy(dst, &MolDefault_Uint64, len); + } else { + mol_num_t of = builder.number_ptr[0]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[3]; + if (len == 0) { + len = 53; + memcpy(dst, &MolDefault_Script, len); + } else { + mol_num_t of = builder.number_ptr[2]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[5]; + if (len == 0) { + len = 0; + memcpy(dst, &MolDefault_ScriptOpt, len); + } else { + mol_num_t of = builder.number_ptr[4]; + memcpy(dst, src+of, len); + } + dst += len; + mol_builder_discard(builder); + return res; +} +mol_seg_res_t MolBuilder_RawTransaction_build (mol_builder_t builder) { + mol_seg_res_t res; + res.errno = MOL_OK; + mol_num_t offset = 28; + mol_num_t len; + res.seg.size = offset; + len = builder.number_ptr[1]; + res.seg.size += len == 0 ? 4 : len; + len = builder.number_ptr[3]; + res.seg.size += len == 0 ? 4 : len; + len = builder.number_ptr[5]; + res.seg.size += len == 0 ? 4 : len; + len = builder.number_ptr[7]; + res.seg.size += len == 0 ? 4 : len; + len = builder.number_ptr[9]; + res.seg.size += len == 0 ? 4 : len; + len = builder.number_ptr[11]; + res.seg.size += len == 0 ? 4 : len; + res.seg.ptr = (uint8_t*)malloc(res.seg.size); + uint8_t *dst = res.seg.ptr; + mol_pack_number(dst, &res.seg.size); + dst += MOL_NUM_T_SIZE; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[1]; + offset += len == 0 ? 4 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[3]; + offset += len == 0 ? 4 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[5]; + offset += len == 0 ? 4 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[7]; + offset += len == 0 ? 4 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[9]; + offset += len == 0 ? 4 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[11]; + offset += len == 0 ? 4 : len; + uint8_t *src = builder.data_ptr; + len = builder.number_ptr[1]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_Uint32, len); + } else { + mol_num_t of = builder.number_ptr[0]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[3]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_CellDepVec, len); + } else { + mol_num_t of = builder.number_ptr[2]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[5]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_Byte32Vec, len); + } else { + mol_num_t of = builder.number_ptr[4]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[7]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_CellInputVec, len); + } else { + mol_num_t of = builder.number_ptr[6]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[9]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_CellOutputVec, len); + } else { + mol_num_t of = builder.number_ptr[8]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[11]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_BytesVec, len); + } else { + mol_num_t of = builder.number_ptr[10]; + memcpy(dst, src+of, len); + } + dst += len; + mol_builder_discard(builder); + return res; +} +mol_seg_res_t MolBuilder_Transaction_build (mol_builder_t builder) { + mol_seg_res_t res; + res.errno = MOL_OK; + mol_num_t offset = 12; + mol_num_t len; + res.seg.size = offset; + len = builder.number_ptr[1]; + res.seg.size += len == 0 ? 52 : len; + len = builder.number_ptr[3]; + res.seg.size += len == 0 ? 4 : len; + res.seg.ptr = (uint8_t*)malloc(res.seg.size); + uint8_t *dst = res.seg.ptr; + mol_pack_number(dst, &res.seg.size); + dst += MOL_NUM_T_SIZE; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[1]; + offset += len == 0 ? 52 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[3]; + offset += len == 0 ? 4 : len; + uint8_t *src = builder.data_ptr; + len = builder.number_ptr[1]; + if (len == 0) { + len = 52; + memcpy(dst, &MolDefault_RawTransaction, len); + } else { + mol_num_t of = builder.number_ptr[0]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[3]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_BytesVec, len); + } else { + mol_num_t of = builder.number_ptr[2]; + memcpy(dst, src+of, len); + } + dst += len; + mol_builder_discard(builder); + return res; +} +mol_seg_res_t MolBuilder_UncleBlock_build (mol_builder_t builder) { + mol_seg_res_t res; + res.errno = MOL_OK; + mol_num_t offset = 12; + mol_num_t len; + res.seg.size = offset; + len = builder.number_ptr[1]; + res.seg.size += len == 0 ? 208 : len; + len = builder.number_ptr[3]; + res.seg.size += len == 0 ? 4 : len; + res.seg.ptr = (uint8_t*)malloc(res.seg.size); + uint8_t *dst = res.seg.ptr; + mol_pack_number(dst, &res.seg.size); + dst += MOL_NUM_T_SIZE; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[1]; + offset += len == 0 ? 208 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[3]; + offset += len == 0 ? 4 : len; + uint8_t *src = builder.data_ptr; + len = builder.number_ptr[1]; + if (len == 0) { + len = 208; + memcpy(dst, &MolDefault_Header, len); + } else { + mol_num_t of = builder.number_ptr[0]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[3]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_ProposalShortIdVec, len); + } else { + mol_num_t of = builder.number_ptr[2]; + memcpy(dst, src+of, len); + } + dst += len; + mol_builder_discard(builder); + return res; +} +mol_seg_res_t MolBuilder_Block_build (mol_builder_t builder) { + mol_seg_res_t res; + res.errno = MOL_OK; + mol_num_t offset = 20; + mol_num_t len; + res.seg.size = offset; + len = builder.number_ptr[1]; + res.seg.size += len == 0 ? 208 : len; + len = builder.number_ptr[3]; + res.seg.size += len == 0 ? 4 : len; + len = builder.number_ptr[5]; + res.seg.size += len == 0 ? 4 : len; + len = builder.number_ptr[7]; + res.seg.size += len == 0 ? 4 : len; + res.seg.ptr = (uint8_t*)malloc(res.seg.size); + uint8_t *dst = res.seg.ptr; + mol_pack_number(dst, &res.seg.size); + dst += MOL_NUM_T_SIZE; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[1]; + offset += len == 0 ? 208 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[3]; + offset += len == 0 ? 4 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[5]; + offset += len == 0 ? 4 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[7]; + offset += len == 0 ? 4 : len; + uint8_t *src = builder.data_ptr; + len = builder.number_ptr[1]; + if (len == 0) { + len = 208; + memcpy(dst, &MolDefault_Header, len); + } else { + mol_num_t of = builder.number_ptr[0]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[3]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_UncleBlockVec, len); + } else { + mol_num_t of = builder.number_ptr[2]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[5]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_TransactionVec, len); + } else { + mol_num_t of = builder.number_ptr[4]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[7]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_ProposalShortIdVec, len); + } else { + mol_num_t of = builder.number_ptr[6]; + memcpy(dst, src+of, len); + } + dst += len; + mol_builder_discard(builder); + return res; +} +mol_seg_res_t MolBuilder_CellbaseWitness_build (mol_builder_t builder) { + mol_seg_res_t res; + res.errno = MOL_OK; + mol_num_t offset = 12; + mol_num_t len; + res.seg.size = offset; + len = builder.number_ptr[1]; + res.seg.size += len == 0 ? 53 : len; + len = builder.number_ptr[3]; + res.seg.size += len == 0 ? 4 : len; + res.seg.ptr = (uint8_t*)malloc(res.seg.size); + uint8_t *dst = res.seg.ptr; + mol_pack_number(dst, &res.seg.size); + dst += MOL_NUM_T_SIZE; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[1]; + offset += len == 0 ? 53 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[3]; + offset += len == 0 ? 4 : len; + uint8_t *src = builder.data_ptr; + len = builder.number_ptr[1]; + if (len == 0) { + len = 53; + memcpy(dst, &MolDefault_Script, len); + } else { + mol_num_t of = builder.number_ptr[0]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[3]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_Bytes, len); + } else { + mol_num_t of = builder.number_ptr[2]; + memcpy(dst, src+of, len); + } + dst += len; + mol_builder_discard(builder); + return res; +} +mol_seg_res_t MolBuilder_WitnessArgs_build (mol_builder_t builder) { + mol_seg_res_t res; + res.errno = MOL_OK; + mol_num_t offset = 16; + mol_num_t len; + res.seg.size = offset; + len = builder.number_ptr[1]; + res.seg.size += len == 0 ? 0 : len; + len = builder.number_ptr[3]; + res.seg.size += len == 0 ? 0 : len; + len = builder.number_ptr[5]; + res.seg.size += len == 0 ? 0 : len; + res.seg.ptr = (uint8_t*)malloc(res.seg.size); + uint8_t *dst = res.seg.ptr; + mol_pack_number(dst, &res.seg.size); + dst += MOL_NUM_T_SIZE; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[1]; + offset += len == 0 ? 0 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[3]; + offset += len == 0 ? 0 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[5]; + offset += len == 0 ? 0 : len; + uint8_t *src = builder.data_ptr; + len = builder.number_ptr[1]; + if (len == 0) { + len = 0; + memcpy(dst, &MolDefault_BytesOpt, len); + } else { + mol_num_t of = builder.number_ptr[0]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[3]; + if (len == 0) { + len = 0; + memcpy(dst, &MolDefault_BytesOpt, len); + } else { + mol_num_t of = builder.number_ptr[2]; + memcpy(dst, src+of, len); + } + dst += len; + len = builder.number_ptr[5]; + if (len == 0) { + len = 0; + memcpy(dst, &MolDefault_BytesOpt, len); + } else { + mol_num_t of = builder.number_ptr[4]; + memcpy(dst, src+of, len); + } + dst += len; + mol_builder_discard(builder); + return res; +} +#ifdef __cplusplus +_CPP_END +#undef _CPP_BEGIN +#undef _CPP_END +#endif /* __cplusplus */ + +#endif /* BLOCKCHAIN_H */ diff --git a/c/blockchain.mol b/c/blockchain.mol new file mode 100644 index 0000000..ef7fec8 --- /dev/null +++ b/c/blockchain.mol @@ -0,0 +1,108 @@ +/* Basic Types */ + +array Uint32 [byte; 4]; +array Uint64 [byte; 8]; +array Uint128 [byte; 16]; +array Byte32 [byte; 32]; +array Uint256 [byte; 32]; + +vector Bytes ; +option BytesOpt (Bytes); + +vector BytesVec ; +vector Byte32Vec ; + +/* Types for Chain */ + +option ScriptOpt (Script); + +array ProposalShortId [byte; 10]; + +vector UncleBlockVec ; +vector TransactionVec ; +vector ProposalShortIdVec ; +vector CellDepVec ; +vector CellInputVec ; +vector CellOutputVec ; + +table Script { + code_hash: Byte32, + hash_type: byte, + args: Bytes, +} + +struct OutPoint { + tx_hash: Byte32, + index: Uint32, +} + +struct CellInput { + since: Uint64, + previous_output: OutPoint, +} + +table CellOutput { + capacity: Uint64, + lock: Script, + type_: ScriptOpt, +} + +struct CellDep { + out_point: OutPoint, + dep_type: byte, +} + +table RawTransaction { + version: Uint32, + cell_deps: CellDepVec, + header_deps: Byte32Vec, + inputs: CellInputVec, + outputs: CellOutputVec, + outputs_data: BytesVec, +} + +table Transaction { + raw: RawTransaction, + witnesses: BytesVec, +} + +struct RawHeader { + version: Uint32, + compact_target: Uint32, + timestamp: Uint64, + number: Uint64, + epoch: Uint64, + parent_hash: Byte32, + transactions_root: Byte32, + proposals_hash: Byte32, + uncles_hash: Byte32, + dao: Byte32, +} + +struct Header { + raw: RawHeader, + nonce: Uint128, +} + +table UncleBlock { + header: Header, + proposals: ProposalShortIdVec, +} + +table Block { + header: Header, + uncles: UncleBlockVec, + transactions: TransactionVec, + proposals: ProposalShortIdVec, +} + +table CellbaseWitness { + lock: Script, + message: Bytes, +} + +table WitnessArgs { + lock: BytesOpt, // Lock args + input_type: BytesOpt, // Type args for input + output_type: BytesOpt, // Type args for output +} diff --git a/c/defs.h b/c/defs.h new file mode 100644 index 0000000..3f24b19 --- /dev/null +++ b/c/defs.h @@ -0,0 +1,4 @@ +#define MAX_UINT64 0xffffffffffffffffUL +#define MAX_UINT128 (((uint128_t)MAX_UINT64 << 64) + MAX_UINT64) + +typedef unsigned __int128 uint128_t; diff --git a/c/dump_secp256k1_data.c b/c/dump_secp256k1_data.c new file mode 100644 index 0000000..83f6065 --- /dev/null +++ b/c/dump_secp256k1_data.c @@ -0,0 +1,57 @@ +#include +#include "blake2b.h" + +/* + * We are including secp256k1 implementation directly so gcc can strip + * unused functions. For some unknown reasons, if we link in libsecp256k1.a + * directly, the final binary will include all functions rather than those used. + */ +#define HAVE_CONFIG_H 1 +#include + +#define ERROR_IO -1 + +int main(int argc, char* argv[]) { + size_t pre_size = sizeof(secp256k1_ecmult_static_pre_context); + size_t pre128_size = sizeof(secp256k1_ecmult_static_pre128_context); + + FILE* fp_data = fopen("build/secp256k1_data", "wb"); + if (!fp_data) { + return ERROR_IO; + } + fwrite(secp256k1_ecmult_static_pre_context, pre_size, 1, fp_data); + fwrite(secp256k1_ecmult_static_pre128_context, pre128_size, 1, fp_data); + fclose(fp_data); + + FILE* fp = fopen("build/secp256k1_data_info.h", "w"); + if (!fp) { + return ERROR_IO; + } + + fprintf(fp, "#ifndef CKB_SECP256K1_DATA_INFO_H_\n"); + fprintf(fp, "#define CKB_SECP256K1_DATA_INFO_H_\n"); + fprintf(fp, "#define CKB_SECP256K1_DATA_SIZE %ld\n", pre_size + pre128_size); + fprintf(fp, "#define CKB_SECP256K1_DATA_PRE_SIZE %ld\n", pre_size); + fprintf(fp, "#define CKB_SECP256K1_DATA_PRE128_SIZE %ld\n", pre128_size); + + blake2b_state blake2b_ctx; + uint8_t hash[32]; + blake2b_init(&blake2b_ctx, 32); + blake2b_update(&blake2b_ctx, secp256k1_ecmult_static_pre_context, pre_size); + blake2b_update(&blake2b_ctx, secp256k1_ecmult_static_pre128_context, + pre128_size); + blake2b_final(&blake2b_ctx, hash, 32); + + fprintf(fp, "static uint8_t ckb_secp256k1_data_hash[32] = {\n "); + for (int i = 0; i < 32; i++) { + fprintf(fp, "%u", hash[i]); + if (i != 31) { + fprintf(fp, ", "); + } + } + fprintf(fp, "\n};\n"); + fprintf(fp, "#endif\n"); + fclose(fp); + + return 0; +} diff --git a/c/overflow_add.h b/c/overflow_add.h new file mode 100644 index 0000000..48f7e14 --- /dev/null +++ b/c/overflow_add.h @@ -0,0 +1,19 @@ +#include "defs.h" + +int uint64_overflow_add(uint64_t *result, uint64_t a, uint64_t b) { + if (MAX_UINT64 - a < b) { + /* overflow */ + return 1; + } + *result = a + b; + return 0; +} + +int uint128_overflow_add(uint128_t *result, uint128_t a, uint128_t b) { + if (MAX_UINT128 - a < b) { + /* overflow */ + return 1; + } + *result = a + b; + return 0; +} diff --git a/c/quick_pow10.h b/c/quick_pow10.h new file mode 100644 index 0000000..752d2e4 --- /dev/null +++ b/c/quick_pow10.h @@ -0,0 +1,66 @@ +#include "defs.h" + +#define MAX_POW_N 19 +#define UINT128_MAX_POW_N 38 + +int quick_pow10(int n, uint64_t *result) { + static uint64_t pow10[MAX_POW_N + 1] = { + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000, + 100000000000, + 1000000000000, + 10000000000000, + 100000000000000, + 1000000000000000, + 10000000000000000, + 100000000000000000, + 1000000000000000000, + 10000000000000000000U, + }; + + if (n > MAX_POW_N) { + return 1; + } + + *result = pow10[n]; + return 0; +} + +int uint128_quick_pow10(int n, uint128_t *result) { + if (n > UINT128_MAX_POW_N) { + return 1; + } + + int ret; + uint64_t mid_result; + if (n <= MAX_POW_N) { + ret = quick_pow10(n, &mid_result); + if (ret) { + return ret; + } + *result = mid_result; + } else { + /* a^(x+y) -> a^x * a^y */ + ret = quick_pow10(n - MAX_POW_N, &mid_result); + if (ret) { + return ret; + } + *result = mid_result; + ret = quick_pow10(MAX_POW_N, &mid_result); + if (ret) { + return ret; + } + *result *= mid_result; + } + + return 0; +} diff --git a/c/secp256k1_helper.h b/c/secp256k1_helper.h new file mode 100644 index 0000000..0f858ce --- /dev/null +++ b/c/secp256k1_helper.h @@ -0,0 +1,88 @@ +#ifndef CKB_SECP256K1_HELPER_H_ +#define CKB_SECP256K1_HELPER_H_ + +#include "ckb_syscalls.h" +#include "secp256k1_data_info.h" + +#define CKB_SECP256K1_HELPER_ERROR_LOADING_DATA -101 +#define CKB_SECP256K1_HELPER_ERROR_ILLEGAL_CALLBACK -102 +#define CKB_SECP256K1_HELPER_ERROR_ERROR_CALLBACK -103 + +/* + * We are including secp256k1 implementation directly so gcc can strip + * unused functions. For some unknown reasons, if we link in libsecp256k1.a + * directly, the final binary will include all functions rather than those used. + */ +#define HAVE_CONFIG_H 1 +#define USE_EXTERNAL_DEFAULT_CALLBACKS +#include + +void secp256k1_default_illegal_callback_fn(const char* str, void* data) { + (void)str; + (void)data; + ckb_exit(CKB_SECP256K1_HELPER_ERROR_ILLEGAL_CALLBACK); +} + +void secp256k1_default_error_callback_fn(const char* str, void* data) { + (void)str; + (void)data; + ckb_exit(CKB_SECP256K1_HELPER_ERROR_ERROR_CALLBACK); +} + +/* + * data should at least be CKB_SECP256K1_DATA_SIZE big + * so as to hold all loaded data. + */ +int ckb_secp256k1_custom_verify_only_initialize(secp256k1_context* context, + void* data) { + size_t index = 0; + int running = 1; + while (running && index < SIZE_MAX) { + uint64_t len = 32; + uint8_t hash[32]; + + int ret = ckb_load_cell_by_field(hash, &len, 0, index, CKB_SOURCE_CELL_DEP, + CKB_CELL_FIELD_DATA_HASH); + switch (ret) { + case CKB_ITEM_MISSING: + break; + case CKB_SUCCESS: + if (memcmp(ckb_secp256k1_data_hash, hash, 32) == 0) { + /* Found a match, load data here */ + len = CKB_SECP256K1_DATA_SIZE; + ret = ckb_load_cell_data(data, &len, 0, index, CKB_SOURCE_CELL_DEP); + if (ret != CKB_SUCCESS || len != CKB_SECP256K1_DATA_SIZE) { + return CKB_SECP256K1_HELPER_ERROR_LOADING_DATA; + } + running = 0; + } + break; + default: + return CKB_SECP256K1_HELPER_ERROR_LOADING_DATA; + } + if (running) { + index++; + } + } + if (index == SIZE_MAX) { + return CKB_SECP256K1_HELPER_ERROR_LOADING_DATA; + } + + context->illegal_callback = default_illegal_callback; + context->error_callback = default_error_callback; + + secp256k1_ecmult_context_init(&context->ecmult_ctx); + secp256k1_ecmult_gen_context_init(&context->ecmult_gen_ctx); + + /* Recasting data to (uint8_t*) for pointer math */ + uint8_t* p = data; + secp256k1_ge_storage(*pre_g)[] = (secp256k1_ge_storage(*)[])p; + secp256k1_ge_storage(*pre_g_128)[] = + (secp256k1_ge_storage(*)[])(&p[CKB_SECP256K1_DATA_PRE_SIZE]); + context->ecmult_ctx.pre_g = pre_g; + context->ecmult_ctx.pre_g_128 = pre_g_128; + + return 0; +} + +#endif diff --git a/c/secp256k1_lock.h b/c/secp256k1_lock.h new file mode 100644 index 0000000..83f6caf --- /dev/null +++ b/c/secp256k1_lock.h @@ -0,0 +1,224 @@ +#ifndef CKB_LOCK_UTILS_H_ +#define CKB_LOCK_UTILS_H_ + +#define BLAKE2B_BLOCK_SIZE 32 +#define BLAKE160_SIZE 20 +#define PUBKEY_SIZE 33 +#define TEMP_SIZE 32768 +#define RECID_INDEX 64 +/* 32 KB */ +#define MAX_WITNESS_SIZE 32768 +#define SCRIPT_SIZE 32768 +#define SIGNATURE_SIZE 65 + +/* secp256k1 unlock errors */ +#define ERROR_ARGUMENTS_LEN -1 +#define ERROR_ENCODING -2 +#define ERROR_SYSCALL -3 +#define ERROR_SECP_RECOVER_PUBKEY -11 +#define ERROR_SECP_VERIFICATION -12 +#define ERROR_SECP_PARSE_PUBKEY -13 +#define ERROR_SECP_PARSE_SIGNATURE -14 +#define ERROR_SECP_SERIALIZE_PUBKEY -15 +#define ERROR_SCRIPT_TOO_LONG -21 +#define ERROR_WITNESS_SIZE -22 +#define ERROR_INCORRECT_SINCE_FLAGS -23 +#define ERROR_INCORRECT_SINCE_VALUE -24 +#define ERROR_PUBKEY_BLAKE160_HASH -31 + +#if (MAX_WITNESS_SIZE > TEMP_SIZE) || (SCRIPT_SIZE > TEMP_SIZE) +#error "Temp buffer is not big enough!" +#endif + +/* Extract lock from WitnessArgs */ +int extract_witness_lock(uint8_t *witness, uint64_t len, + mol_seg_t *lock_bytes_seg) { + mol_seg_t witness_seg; + witness_seg.ptr = witness; + witness_seg.size = len; + + if (MolReader_WitnessArgs_verify(&witness_seg, false) != MOL_OK) { + return ERROR_ENCODING; + } + mol_seg_t lock_seg = MolReader_WitnessArgs_get_lock(&witness_seg); + + if (MolReader_BytesOpt_is_none(&lock_seg)) { + return ERROR_ENCODING; + } + *lock_bytes_seg = MolReader_Bytes_raw_bytes(&lock_seg); + return CKB_SUCCESS; +} + +/* + * Load secp256k1 first witness and check the signature + * + * This function return CKB_SUCCESS if the witness is a valid WitnessArgs + * and the length of WitnessArgs#lock field is exactly the SIGNATURE_SIZE + * + * Arguments: + * * witness bytes, a buffer to receive the first witness bytes of the input + * cell group + * * witness len, a pointer to receive the first witness length + * + * Witness: + * WitnessArgs with a signature in lock field used to present ownership. + */ +int load_secp256k1_first_witness_and_check_signature( + unsigned char witness_bytes[MAX_WITNESS_SIZE], uint64_t *witness_len) { + int ret; + /* Load witness of first input */ + *witness_len = MAX_WITNESS_SIZE; + ret = ckb_load_witness(witness_bytes, witness_len, 0, 0, + CKB_SOURCE_GROUP_INPUT); + if (ret != CKB_SUCCESS) { + return ERROR_SYSCALL; + } + + if (*witness_len > MAX_WITNESS_SIZE) { + return ERROR_WITNESS_SIZE; + } + + /* load signature */ + mol_seg_t witness_lock_seg; + ret = extract_witness_lock(witness_bytes, *witness_len, &witness_lock_seg); + if (ret != 0) { + return ERROR_ENCODING; + } + + if (witness_lock_seg.size != SIGNATURE_SIZE) { + return ERROR_ARGUMENTS_LEN; + } + return CKB_SUCCESS; +} + +/* + * Arguments: + * * pubkey blake160 hash, blake2b hash of pubkey first 20 bytes, used to + * shield the real pubkey. + * * first witness bytes, the first witness bytes of the input cell group + * * first witness len, length of first witness bytes + */ +int verify_secp256k1_blake160_sighash_all_with_witness( + unsigned char pubkey_hash[BLAKE160_SIZE], + unsigned char first_witness_bytes[MAX_WITNESS_SIZE], + uint64_t first_witness_len) { + int ret; + unsigned char temp[MAX_WITNESS_SIZE]; + unsigned char lock_bytes[SIGNATURE_SIZE]; + + /* copy first witness to temp, we keep the first_witness_bytes untouched in + * this function */ + uint64_t len = first_witness_len; + memcpy(temp, first_witness_bytes, len); + + /* load signature */ + mol_seg_t lock_bytes_seg; + ret = extract_witness_lock(temp, first_witness_len, &lock_bytes_seg); + if (ret != 0) { + return ERROR_ENCODING; + } + + if (lock_bytes_seg.size != SIGNATURE_SIZE) { + return ERROR_ARGUMENTS_LEN; + } + memcpy(lock_bytes, lock_bytes_seg.ptr, lock_bytes_seg.size); + + /* Load tx hash */ + unsigned char tx_hash[BLAKE2B_BLOCK_SIZE]; + len = BLAKE2B_BLOCK_SIZE; + ret = ckb_load_tx_hash(tx_hash, &len, 0); + if (ret != CKB_SUCCESS) { + return ret; + } + if (len != BLAKE2B_BLOCK_SIZE) { + return ERROR_SYSCALL; + } + + /* Prepare sign message */ + unsigned char message[BLAKE2B_BLOCK_SIZE]; + blake2b_state blake2b_ctx; + blake2b_init(&blake2b_ctx, BLAKE2B_BLOCK_SIZE); + blake2b_update(&blake2b_ctx, tx_hash, BLAKE2B_BLOCK_SIZE); + + /* Clear lock field to zero, then digest the first witness */ + memset((void *)lock_bytes_seg.ptr, 0, lock_bytes_seg.size); + blake2b_update(&blake2b_ctx, (char *)&first_witness_len, sizeof(uint64_t)); + blake2b_update(&blake2b_ctx, temp, first_witness_len); + + /* Digest same group witnesses */ + size_t i = 1; + while (1) { + len = MAX_WITNESS_SIZE; + ret = ckb_load_witness(temp, &len, 0, i, CKB_SOURCE_GROUP_INPUT); + if (ret == CKB_INDEX_OUT_OF_BOUND) { + break; + } + if (ret != CKB_SUCCESS) { + return ERROR_SYSCALL; + } + if (len > MAX_WITNESS_SIZE) { + return ERROR_WITNESS_SIZE; + } + blake2b_update(&blake2b_ctx, (char *)&len, sizeof(uint64_t)); + blake2b_update(&blake2b_ctx, temp, len); + i += 1; + } + /* Digest witnesses that not covered by inputs */ + i = ckb_calculate_inputs_len(); + while (1) { + len = MAX_WITNESS_SIZE; + ret = ckb_load_witness(temp, &len, 0, i, CKB_SOURCE_INPUT); + if (ret == CKB_INDEX_OUT_OF_BOUND) { + break; + } + if (ret != CKB_SUCCESS) { + return ERROR_SYSCALL; + } + if (len > MAX_WITNESS_SIZE) { + return ERROR_WITNESS_SIZE; + } + blake2b_update(&blake2b_ctx, (char *)&len, sizeof(uint64_t)); + blake2b_update(&blake2b_ctx, temp, len); + i += 1; + } + blake2b_final(&blake2b_ctx, message, BLAKE2B_BLOCK_SIZE); + + /* Load signature */ + secp256k1_context context; + uint8_t secp_data[CKB_SECP256K1_DATA_SIZE]; + ret = ckb_secp256k1_custom_verify_only_initialize(&context, secp_data); + if (ret != 0) { + return ret; + } + + secp256k1_ecdsa_recoverable_signature signature; + if (secp256k1_ecdsa_recoverable_signature_parse_compact( + &context, &signature, lock_bytes, lock_bytes[RECID_INDEX]) == 0) { + return ERROR_SECP_PARSE_SIGNATURE; + } + + /* Recover pubkey */ + secp256k1_pubkey pubkey; + if (secp256k1_ecdsa_recover(&context, &pubkey, &signature, message) != 1) { + return ERROR_SECP_RECOVER_PUBKEY; + } + + /* Check pubkey hash */ + size_t pubkey_size = PUBKEY_SIZE; + if (secp256k1_ec_pubkey_serialize(&context, temp, &pubkey_size, &pubkey, + SECP256K1_EC_COMPRESSED) != 1) { + return ERROR_SECP_SERIALIZE_PUBKEY; + } + + blake2b_init(&blake2b_ctx, BLAKE2B_BLOCK_SIZE); + blake2b_update(&blake2b_ctx, temp, pubkey_size); + blake2b_final(&blake2b_ctx, temp, BLAKE2B_BLOCK_SIZE); + + if (memcmp(pubkey_hash, temp, BLAKE160_SIZE) != 0) { + return ERROR_PUBKEY_BLAKE160_HASH; + } + + return 0; +} + +#endif /* CKB_LOCK_UTILS_H_ */ diff --git a/deps/ckb-c-std-lib b/deps/ckb-c-std-lib new file mode 160000 index 0000000..c056b00 --- /dev/null +++ b/deps/ckb-c-std-lib @@ -0,0 +1 @@ +Subproject commit c056b00fedebff527900586848e2d8fdb53ed317 diff --git a/deps/secp256k1 b/deps/secp256k1 new file mode 160000 index 0000000..3ffde18 --- /dev/null +++ b/deps/secp256k1 @@ -0,0 +1 @@ +Subproject commit 3ffde18a060aaf4df5b81e7d88355f1e99874650 diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 0000000..4934985 --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +1.69.0 diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..d5b0154 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,12 @@ +//! pub use const BUNDLED_CELL: Files +//! pub use const CODE_HASH_DAO: [u8; 32] +//! pub use const CODE_HASH_SECP256K1_BLAKE160_SIGHASH_ALL: [u8; 32] +//! pub use const CODE_HASH_SECP256K1_RIPEMD160_SHA256_SIGHASH_ALL: [u8; 32] + +#![allow(clippy::unreadable_literal)] + +include!(concat!(env!("OUT_DIR"), "/bundled.rs")); +include!(concat!(env!("OUT_DIR"), "/code_hashes.rs")); + +#[cfg(test)] +mod tests; diff --git a/src/tests/anyone_can_pay.rs b/src/tests/anyone_can_pay.rs new file mode 100644 index 0000000..060c7a6 --- /dev/null +++ b/src/tests/anyone_can_pay.rs @@ -0,0 +1,534 @@ +use super::{ + blake160, build_resolved_tx, gen_tx, gen_tx_with_grouped_args, DummyDataLoader, ALWAYS_SUCCESS, + ANYONE_CAN_PAY, ERROR_DUPLICATED_INPUTS, ERROR_DUPLICATED_OUTPUTS, ERROR_ENCODING, + ERROR_NO_PAIR, ERROR_OUTPUT_AMOUNT_NOT_ENOUGH, MAX_CYCLES, +}; +use ckb_crypto::secp::Generator; +use ckb_error::assert_error_eq; +use ckb_script::{ScriptError, TransactionScriptsVerifier}; +use ckb_types::{ + bytes::Bytes, + core::ScriptHashType, + packed::{CellOutput, Script}, + prelude::*, +}; +use rand::thread_rng; + +fn build_anyone_can_pay_script(args: Bytes) -> Script { + let sighash_all_cell_data_hash = CellOutput::calc_data_hash(&ANYONE_CAN_PAY); + Script::new_builder() + .args(args.pack()) + .code_hash(sighash_all_cell_data_hash.clone()) + .hash_type(ScriptHashType::Data.into()) + .build() +} + +fn build_udt_script() -> Script { + let data_hash = CellOutput::calc_data_hash(&ALWAYS_SUCCESS); + Script::new_builder() + .code_hash(data_hash.clone()) + .hash_type(ScriptHashType::Data.into()) + .build() +} + +#[test] +fn test_unlock_by_anyone() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + + let script = build_anyone_can_pay_script(pubkey_hash.to_owned()); + let tx = gen_tx(&mut data_loader, pubkey_hash); + let output = tx.outputs().get(0).unwrap(); + let tx = tx + .as_advanced_builder() + .set_witnesses(Vec::new()) + .set_outputs(vec![output + .as_builder() + .lock(script) + .capacity(44u64.pack()) + .build()]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verifier = TransactionScriptsVerifier::new(&resolved_tx, &data_loader); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass"); +} + +#[test] +fn test_put_output_data() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + + let script = build_anyone_can_pay_script(pubkey_hash.to_owned()); + let tx = gen_tx(&mut data_loader, pubkey_hash); + let output = tx.outputs().get(0).unwrap(); + let tx = tx + .as_advanced_builder() + .set_witnesses(Vec::new()) + .set_outputs(vec![output + .as_builder() + .lock(script) + .capacity(44u64.pack()) + .build()]) + .set_outputs_data(vec![Bytes::from(vec![42u8]).pack()]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verifier = TransactionScriptsVerifier::new(&resolved_tx, &data_loader); + let verify_result = verifier.verify(MAX_CYCLES); + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_ENCODING), + ); +} + +#[test] +fn test_wrong_output_args() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + + let script = build_anyone_can_pay_script(pubkey_hash.to_owned()); + let tx = gen_tx(&mut data_loader, pubkey_hash.to_owned()); + let output = tx.outputs().get(0).unwrap(); + let tx = tx + .as_advanced_builder() + .set_witnesses(Vec::new()) + .set_outputs(vec![output + .as_builder() + .lock({ + let mut args = pubkey_hash.to_vec(); + // a valid args + args.push(0); + script.as_builder().args(Bytes::from(args).pack()).build() + }) + .capacity(44u64.pack()) + .build()]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verifier = TransactionScriptsVerifier::new(&resolved_tx, &data_loader); + let verify_result = verifier.verify(MAX_CYCLES); + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_NO_PAIR), + ); +} + +#[test] +fn test_split_cell() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + + let script = build_anyone_can_pay_script(pubkey_hash.to_owned()); + let tx = gen_tx(&mut data_loader, pubkey_hash.to_owned()); + let output = tx.outputs().get(0).unwrap(); + let tx = tx + .as_advanced_builder() + .set_witnesses(Vec::new()) + .set_outputs(vec![ + output + .clone() + .as_builder() + .lock(script.clone()) + .capacity(44u64.pack()) + .build(), + output + .as_builder() + .lock(script) + .capacity(44u64.pack()) + .build(), + ]) + .set_outputs_data(vec![ + Bytes::from(Vec::new()).pack(), + Bytes::from(Vec::new()).pack(), + ]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verifier = TransactionScriptsVerifier::new(&resolved_tx, &data_loader); + let verify_result = verifier.verify(MAX_CYCLES); + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_DUPLICATED_OUTPUTS), + ); +} + +#[test] +fn test_merge_cell() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + + let script = build_anyone_can_pay_script(pubkey_hash.to_owned()); + let mut rng = thread_rng(); + let tx = gen_tx_with_grouped_args(&mut data_loader, vec![(pubkey_hash, 2)], &mut rng); + let output = tx.outputs().get(0).unwrap(); + let tx = tx + .as_advanced_builder() + .set_witnesses(Vec::new()) + .set_outputs(vec![output + .clone() + .as_builder() + .lock(script.clone()) + .capacity(88u64.pack()) + .build()]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verifier = TransactionScriptsVerifier::new(&resolved_tx, &data_loader); + let verify_result = verifier.verify(MAX_CYCLES); + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_DUPLICATED_INPUTS), + ); +} + +#[test] +fn test_insufficient_pay() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + + let script = build_anyone_can_pay_script(pubkey_hash.to_owned()); + let tx = gen_tx(&mut data_loader, pubkey_hash); + let output = tx.outputs().get(0).unwrap(); + let tx = tx + .as_advanced_builder() + .set_witnesses(Vec::new()) + .set_outputs(vec![output + .clone() + .as_builder() + .lock(script.clone()) + .capacity(41u64.pack()) + .build()]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verifier = TransactionScriptsVerifier::new(&resolved_tx, &data_loader); + let verify_result = verifier.verify(MAX_CYCLES); + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_OUTPUT_AMOUNT_NOT_ENOUGH), + ); +} + +#[test] +fn test_payment_not_meet_requirement() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + let mut args = pubkey_hash.to_vec(); + args.push(1); + let args = Bytes::from(args); + let script = build_anyone_can_pay_script(args.clone()); + let tx = gen_tx(&mut data_loader, args); + let output = tx.outputs().get(0).unwrap(); + let tx = tx + .as_advanced_builder() + .set_witnesses(Vec::new()) + .set_outputs(vec![output + .clone() + .as_builder() + .lock(script.clone()) + .capacity(44u64.pack()) + .build()]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verifier = TransactionScriptsVerifier::new(&resolved_tx, &data_loader); + let verify_result = verifier.verify(MAX_CYCLES); + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_OUTPUT_AMOUNT_NOT_ENOUGH), + ); +} + +#[test] +fn test_no_pair() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + + let another_script = build_anyone_can_pay_script(vec![42].into()); + let tx = gen_tx(&mut data_loader, pubkey_hash.to_owned()); + let output = tx.outputs().get(0).unwrap(); + let tx = tx + .as_advanced_builder() + .set_witnesses(Vec::new()) + .set_outputs(vec![output + .clone() + .as_builder() + .lock(another_script.clone()) + .capacity(44u64.pack()) + .build()]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verifier = TransactionScriptsVerifier::new(&resolved_tx, &data_loader); + let verify_result = verifier.verify(MAX_CYCLES); + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_NO_PAIR), + ); +} + +#[test] +fn test_overflow() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + let mut args = pubkey_hash.to_vec(); + args.push(255); + let args = Bytes::from(args); + + let script = build_anyone_can_pay_script(args.to_owned()); + let tx = gen_tx(&mut data_loader, args); + let output = tx.outputs().get(0).unwrap(); + let tx = tx + .as_advanced_builder() + .set_witnesses(Vec::new()) + .set_outputs(vec![output + .as_builder() + .lock(script) + .capacity(44u64.pack()) + .build()]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verifier = TransactionScriptsVerifier::new(&resolved_tx, &data_loader); + let verify_result = verifier.verify(MAX_CYCLES); + + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_OUTPUT_AMOUNT_NOT_ENOUGH), + ); +} + +#[test] +fn test_only_pay_ckb() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + let mut args = pubkey_hash.to_vec(); + args.push(0); + // do not accept UDT transfer + args.push(255); + let args = Bytes::from(args); + + let script = build_anyone_can_pay_script(args.to_owned()); + let tx = gen_tx(&mut data_loader, args); + let input = tx.inputs().get(0).unwrap(); + let (prev_output, _) = data_loader.cells.remove(&input.previous_output()).unwrap(); + let prev_output = prev_output + .as_builder() + .type_(Some(build_udt_script()).pack()) + .build(); + let prev_data = 44u128.to_le_bytes().to_vec().into(); + data_loader + .cells + .insert(input.previous_output(), (prev_output, prev_data)); + let output = tx.outputs().get(0).unwrap(); + let tx = tx + .as_advanced_builder() + .set_witnesses(Vec::new()) + .set_outputs(vec![output + .as_builder() + .lock(script) + .capacity(44u64.pack()) + .type_(Some(build_udt_script()).pack()) + .build()]) + .set_outputs_data(vec![Bytes::from(44u128.to_le_bytes().to_vec()).pack()]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verifier = TransactionScriptsVerifier::new(&resolved_tx, &data_loader); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.unwrap(); +} + +#[test] +fn test_only_pay_udt() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let mut args = { + let pubkey_hash = blake160(&pubkey.serialize()); + pubkey_hash.to_vec() + }; + args.push(255); + let args = Bytes::from(args); + + let script = build_anyone_can_pay_script(args.to_owned()); + let tx = gen_tx(&mut data_loader, args); + let input = tx.inputs().get(0).unwrap(); + let (prev_output, _) = data_loader.cells.remove(&input.previous_output()).unwrap(); + let input_capacity = prev_output.capacity(); + let prev_output = prev_output + .as_builder() + .type_(Some(build_udt_script()).pack()) + .build(); + let prev_data = 44u128.to_le_bytes().to_vec().into(); + data_loader + .cells + .insert(input.previous_output(), (prev_output, prev_data)); + let output = tx.outputs().get(0).unwrap(); + let tx = tx + .as_advanced_builder() + .set_witnesses(Vec::new()) + .set_outputs(vec![output + .as_builder() + .lock(script) + .capacity(input_capacity) + .type_(Some(build_udt_script()).pack()) + .build()]) + .set_outputs_data(vec![Bytes::from(44u128.to_le_bytes().to_vec()).pack()]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verifier = TransactionScriptsVerifier::new(&resolved_tx, &data_loader); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass"); +} + +#[test] +fn test_udt_unlock_by_anyone() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + + let script = build_anyone_can_pay_script(pubkey_hash.to_owned()); + let tx = gen_tx(&mut data_loader, pubkey_hash); + let input = tx.inputs().get(0).unwrap(); + let (prev_output, _) = data_loader.cells.remove(&input.previous_output()).unwrap(); + let prev_output = prev_output + .as_builder() + .type_(Some(build_udt_script()).pack()) + .build(); + let prev_data = 44u128.to_le_bytes().to_vec().into(); + data_loader + .cells + .insert(input.previous_output(), (prev_output, prev_data)); + let output = tx.outputs().get(0).unwrap(); + let tx = tx + .as_advanced_builder() + .set_witnesses(Vec::new()) + .set_outputs(vec![output + .as_builder() + .lock(script) + .capacity(44u64.pack()) + .type_(Some(build_udt_script()).pack()) + .build()]) + .set_outputs_data(vec![Bytes::from(44u128.to_le_bytes().to_vec()).pack()]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verifier = TransactionScriptsVerifier::new(&resolved_tx, &data_loader); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass"); +} + +#[test] +fn test_udt_overflow() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + let mut args = pubkey_hash.to_vec(); + args.push(1); + args.push(255); + let args = Bytes::from(args); + + let script = build_anyone_can_pay_script(args.to_owned()); + let tx = gen_tx(&mut data_loader, args); + let input = tx.inputs().get(0).unwrap(); + let (prev_output, _) = data_loader.cells.remove(&input.previous_output()).unwrap(); + let prev_output = prev_output + .as_builder() + .type_(Some(build_udt_script()).pack()) + .build(); + let prev_data = 44u128.to_le_bytes().to_vec().into(); + data_loader + .cells + .insert(input.previous_output(), (prev_output, prev_data)); + let output = tx.outputs().get(0).unwrap(); + let tx = tx + .as_advanced_builder() + .set_witnesses(Vec::new()) + .set_outputs(vec![output + .as_builder() + .lock(script) + .capacity(44u64.pack()) + .type_(Some(build_udt_script()).pack()) + .build()]) + .set_outputs_data(vec![Bytes::from(44u128.to_le_bytes().to_vec()).pack()]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verifier = TransactionScriptsVerifier::new(&resolved_tx, &data_loader); + let verify_result = verifier.verify(MAX_CYCLES); + + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_OUTPUT_AMOUNT_NOT_ENOUGH), + ); +} + +#[test] +fn test_extended_udt() { + // we assume the first 16 bytes data represent token amount + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + + let script = build_anyone_can_pay_script(pubkey_hash.to_owned()); + let tx = gen_tx(&mut data_loader, pubkey_hash); + let input = tx.inputs().get(0).unwrap(); + let (prev_output, _) = data_loader.cells.remove(&input.previous_output()).unwrap(); + let prev_output = prev_output + .as_builder() + .type_(Some(build_udt_script()).pack()) + .build(); + let mut prev_data = 44u128.to_le_bytes().to_vec(); + // push junk data + prev_data.push(42); + data_loader + .cells + .insert(input.previous_output(), (prev_output, prev_data.into())); + let output = tx.outputs().get(0).unwrap(); + let mut output_udt = 44u128.to_le_bytes().to_vec(); + // push junk data + output_udt.push(42); + let tx = tx + .as_advanced_builder() + .set_witnesses(Vec::new()) + .set_outputs(vec![output + .as_builder() + .lock(script) + .capacity(44u64.pack()) + .type_(Some(build_udt_script()).pack()) + .build()]) + .set_outputs_data(vec![Bytes::from(output_udt).pack()]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verifier = TransactionScriptsVerifier::new(&resolved_tx, &data_loader); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass"); +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs new file mode 100644 index 0000000..5839073 --- /dev/null +++ b/src/tests/mod.rs @@ -0,0 +1,334 @@ +mod anyone_can_pay; +mod secp256k1_compatibility; + +use ckb_crypto::secp::Privkey; +use ckb_script::DataLoader; +use ckb_types::{ + bytes::Bytes, + core::{ + cell::{CellMeta, CellMetaBuilder, ResolvedTransaction}, + BlockExt, Capacity, DepType, EpochExt, HeaderView, ScriptHashType, TransactionBuilder, + TransactionView, + }, + packed::{ + self, Byte32, CellDep, CellInput, CellOutput, OutPoint, Script, WitnessArgs, + WitnessArgsBuilder, + }, + prelude::*, + H256, +}; +use lazy_static::lazy_static; +use rand::{thread_rng, Rng}; +use std::collections::HashMap; + +pub const MAX_CYCLES: u64 = std::u64::MAX; +pub const SIGNATURE_SIZE: usize = 65; + +// errors +pub const ERROR_ENCODING: i8 = -2; +pub const ERROR_PUBKEY_BLAKE160_HASH: i8 = -31; +pub const ERROR_OUTPUT_AMOUNT_NOT_ENOUGH: i8 = -42; +pub const ERROR_NO_PAIR: i8 = -44; +pub const ERROR_DUPLICATED_INPUTS: i8 = -45; +pub const ERROR_DUPLICATED_OUTPUTS: i8 = -46; + +lazy_static! { + pub static ref ANYONE_CAN_PAY: Bytes = + Bytes::from(&include_bytes!("../../build/anyone_can_pay")[..]); + pub static ref SECP256K1_DATA_BIN: Bytes = + Bytes::from(&include_bytes!("../../build/secp256k1_data")[..]); + pub static ref ALWAYS_SUCCESS: Bytes = + Bytes::from(&include_bytes!("../../build/always_success")[..]); +} + +#[derive(Default)] +pub struct DummyDataLoader { + pub cells: HashMap, + pub headers: HashMap, + pub epoches: HashMap, +} + +impl DummyDataLoader { + fn new() -> Self { + Self::default() + } +} + +impl DataLoader for DummyDataLoader { + // load Cell Data + fn load_cell_data(&self, cell: &CellMeta) -> Option<(Bytes, Byte32)> { + cell.mem_cell_data.clone().or_else(|| { + self.cells + .get(&cell.out_point) + .map(|(_, data)| (data.clone(), CellOutput::calc_data_hash(&data))) + }) + } + // load BlockExt + fn get_block_ext(&self, _hash: &Byte32) -> Option { + unreachable!() + } + + // load header + fn get_header(&self, block_hash: &Byte32) -> Option { + self.headers.get(block_hash).cloned() + } + + // load EpochExt + fn get_block_epoch(&self, block_hash: &Byte32) -> Option { + self.epoches.get(block_hash).cloned() + } +} + +pub fn blake160(message: &[u8]) -> Bytes { + Bytes::from(&ckb_hash::blake2b_256(message)[..20]) +} + +pub fn sign_tx(tx: TransactionView, key: &Privkey) -> TransactionView { + let witnesses_len = tx.witnesses().len(); + sign_tx_by_input_group(tx, key, 0, witnesses_len) +} + +pub fn sign_tx_by_input_group( + tx: TransactionView, + key: &Privkey, + begin_index: usize, + len: usize, +) -> TransactionView { + let tx_hash = tx.hash(); + let mut signed_witnesses: Vec = tx + .inputs() + .into_iter() + .enumerate() + .map(|(i, _)| { + if i == begin_index { + let mut blake2b = ckb_hash::new_blake2b(); + let mut message = [0u8; 32]; + blake2b.update(&tx_hash.raw_data()); + // digest the first witness + let witness = WitnessArgs::new_unchecked(tx.witnesses().get(i).unwrap().unpack()); + let zero_lock: Bytes = { + let mut buf = Vec::new(); + buf.resize(SIGNATURE_SIZE, 0); + buf.into() + }; + let witness_for_digest = + witness.clone().as_builder().lock(zero_lock.pack()).build(); + let witness_len = witness_for_digest.as_bytes().len() as u64; + blake2b.update(&witness_len.to_le_bytes()); + blake2b.update(&witness_for_digest.as_bytes()); + ((i + 1)..(i + len)).for_each(|n| { + let witness = tx.witnesses().get(n).unwrap(); + let witness_len = witness.raw_data().len() as u64; + blake2b.update(&witness_len.to_le_bytes()); + blake2b.update(&witness.raw_data()); + }); + blake2b.finalize(&mut message); + let message = H256::from(message); + let sig = key.sign_recoverable(&message).expect("sign"); + witness + .as_builder() + .lock(sig.serialize().pack()) + .build() + .as_bytes() + .pack() + } else { + tx.witnesses().get(i).unwrap_or_default() + } + }) + .collect(); + for i in signed_witnesses.len()..tx.witnesses().len() { + signed_witnesses.push(tx.witnesses().get(i).unwrap()); + } + // calculate message + tx.as_advanced_builder() + .set_witnesses(signed_witnesses) + .build() +} + +pub fn gen_tx(dummy: &mut DummyDataLoader, lock_args: Bytes) -> TransactionView { + let mut rng = thread_rng(); + gen_tx_with_grouped_args(dummy, vec![(lock_args, 1)], &mut rng) +} + +pub fn gen_tx_with_grouped_args( + dummy: &mut DummyDataLoader, + grouped_args: Vec<(Bytes, usize)>, + rng: &mut R, +) -> TransactionView { + // setup sighash_all dep + let sighash_all_out_point = { + let contract_tx_hash = { + let mut buf = [0u8; 32]; + rng.fill(&mut buf); + buf.pack() + }; + OutPoint::new(contract_tx_hash.clone(), 0) + }; + // dep contract code + let sighash_all_cell = CellOutput::new_builder() + .capacity( + Capacity::bytes(ANYONE_CAN_PAY.len()) + .expect("script capacity") + .pack(), + ) + .build(); + let sighash_all_cell_data_hash = CellOutput::calc_data_hash(&ANYONE_CAN_PAY); + dummy.cells.insert( + sighash_all_out_point.clone(), + (sighash_all_cell, ANYONE_CAN_PAY.clone()), + ); + // always success + let always_success_out_point = { + let contract_tx_hash = { + let mut buf = [0u8; 32]; + rng.fill(&mut buf); + buf.pack() + }; + OutPoint::new(contract_tx_hash.clone(), 0) + }; + let always_success_cell = CellOutput::new_builder() + .capacity( + Capacity::bytes(ALWAYS_SUCCESS.len()) + .expect("script capacity") + .pack(), + ) + .build(); + dummy.cells.insert( + always_success_out_point.clone(), + (always_success_cell, ALWAYS_SUCCESS.clone()), + ); + // setup secp256k1_data dep + let secp256k1_data_out_point = { + let tx_hash = { + let mut buf = [0u8; 32]; + rng.fill(&mut buf); + buf.pack() + }; + OutPoint::new(tx_hash, 0) + }; + let secp256k1_data_cell = CellOutput::new_builder() + .capacity( + Capacity::bytes(SECP256K1_DATA_BIN.len()) + .expect("data capacity") + .pack(), + ) + .build(); + dummy.cells.insert( + secp256k1_data_out_point.clone(), + (secp256k1_data_cell, SECP256K1_DATA_BIN.clone()), + ); + // setup default tx builder + let dummy_capacity = Capacity::shannons(42); + let mut tx_builder = TransactionBuilder::default() + .cell_dep( + CellDep::new_builder() + .out_point(sighash_all_out_point) + .dep_type(DepType::Code.into()) + .build(), + ) + .cell_dep( + CellDep::new_builder() + .out_point(always_success_out_point) + .dep_type(DepType::Code.into()) + .build(), + ) + .cell_dep( + CellDep::new_builder() + .out_point(secp256k1_data_out_point) + .dep_type(DepType::Code.into()) + .build(), + ) + .output( + CellOutput::new_builder() + .capacity(dummy_capacity.pack()) + .build(), + ) + .output_data(Bytes::new().pack()); + + for (args, inputs_size) in grouped_args { + // setup dummy input unlock script + for _ in 0..inputs_size { + let previous_tx_hash = { + let mut buf = [0u8; 32]; + rng.fill(&mut buf); + buf.pack() + }; + let previous_out_point = OutPoint::new(previous_tx_hash, 0); + let script = Script::new_builder() + .args(args.pack()) + .code_hash(sighash_all_cell_data_hash.clone()) + .hash_type(ScriptHashType::Data.into()) + .build(); + let previous_output_cell = CellOutput::new_builder() + .capacity(dummy_capacity.pack()) + .lock(script) + .build(); + dummy.cells.insert( + previous_out_point.clone(), + (previous_output_cell.clone(), Bytes::new()), + ); + let mut random_extra_witness = [0u8; 32]; + rng.fill(&mut random_extra_witness); + let witness_args = WitnessArgsBuilder::default() + .extra(Bytes::from(random_extra_witness.to_vec()).pack()) + .build(); + tx_builder = tx_builder + .input(CellInput::new(previous_out_point, 0)) + .witness(witness_args.as_bytes().pack()); + } + } + + tx_builder.build() +} + +pub fn sign_tx_hash(tx: TransactionView, key: &Privkey, tx_hash: &[u8]) -> TransactionView { + // calculate message + let mut blake2b = ckb_hash::new_blake2b(); + let mut message = [0u8; 32]; + blake2b.update(tx_hash); + blake2b.finalize(&mut message); + let message = H256::from(message); + let sig = key.sign_recoverable(&message).expect("sign"); + let witness_args = WitnessArgsBuilder::default() + .lock(Bytes::from(sig.serialize()).pack()) + .build(); + tx.as_advanced_builder() + .set_witnesses(vec![witness_args.as_bytes().pack()]) + .build() +} + +pub fn build_resolved_tx( + data_loader: &DummyDataLoader, + tx: &TransactionView, +) -> ResolvedTransaction { + let resolved_cell_deps = tx + .cell_deps() + .into_iter() + .map(|dep| { + let deps_out_point = dep.clone(); + let (dep_output, dep_data) = + data_loader.cells.get(&deps_out_point.out_point()).unwrap(); + CellMetaBuilder::from_cell_output(dep_output.to_owned(), dep_data.to_owned()) + .out_point(deps_out_point.out_point().clone()) + .build() + }) + .collect(); + + let mut resolved_inputs = Vec::new(); + for i in 0..tx.inputs().len() { + let previous_out_point = tx.inputs().get(i).unwrap().previous_output(); + let (input_output, input_data) = data_loader.cells.get(&previous_out_point).unwrap(); + resolved_inputs.push( + CellMetaBuilder::from_cell_output(input_output.to_owned(), input_data.to_owned()) + .out_point(previous_out_point) + .build(), + ); + } + + ResolvedTransaction { + transaction: tx.clone(), + resolved_cell_deps, + resolved_inputs, + resolved_dep_groups: vec![], + } +} diff --git a/src/tests/secp256k1_compatibility.rs b/src/tests/secp256k1_compatibility.rs new file mode 100644 index 0000000..1227351 --- /dev/null +++ b/src/tests/secp256k1_compatibility.rs @@ -0,0 +1,439 @@ +use super::{ + blake160, build_resolved_tx, gen_tx, gen_tx_with_grouped_args, sign_tx, sign_tx_by_input_group, + sign_tx_hash, DummyDataLoader, ERROR_NO_PAIR, ERROR_PUBKEY_BLAKE160_HASH, MAX_CYCLES, +}; +use ckb_crypto::secp::Generator; +use ckb_error::assert_error_eq; +use ckb_script::{ScriptError, TransactionScriptsVerifier}; +use ckb_types::{bytes::Bytes, packed::WitnessArgs, prelude::*, H256}; +use rand::{thread_rng, Rng, SeedableRng}; + +#[test] +fn test_sighash_all_unlock() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + let tx = gen_tx(&mut data_loader, pubkey_hash); + let tx = sign_tx(tx, &privkey); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verify_result = + TransactionScriptsVerifier::new(&resolved_tx, &data_loader).verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_sighash_all_unlock_with_args() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let lock_args = { + let mut args = blake160(&pubkey.serialize()).to_vec(); + args.push(42); + args.push(255); + Bytes::from(args) + }; + let mut rng = thread_rng(); + let tx = gen_tx_with_grouped_args(&mut data_loader, vec![(lock_args, 1)], &mut rng); + let tx = sign_tx(tx, &privkey); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verify_result = + TransactionScriptsVerifier::new(&resolved_tx, &data_loader).verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_sighash_all_with_extra_witness_unlock() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + let tx = gen_tx(&mut data_loader, pubkey_hash); + let extract_witness = vec![1, 2, 3, 4]; + let tx = tx + .as_advanced_builder() + .set_witnesses(vec![WitnessArgs::new_builder() + .extra(Bytes::from(extract_witness).pack()) + .build() + .as_bytes() + .pack()]) + .build(); + { + let tx = sign_tx(tx.clone(), &privkey); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verify_result = + TransactionScriptsVerifier::new(&resolved_tx, &data_loader).verify(MAX_CYCLES); + verify_result.expect("pass verification"); + } + { + let tx = sign_tx(tx, &privkey); + let wrong_witness = tx + .witnesses() + .get(0) + .map(|w| { + WitnessArgs::new_unchecked(w.unpack()) + .as_builder() + .extra(Bytes::from(vec![0]).pack()) + .build() + }) + .unwrap(); + let tx = tx + .as_advanced_builder() + .set_witnesses(vec![wrong_witness.as_bytes().pack()]) + .build(); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verify_result = + TransactionScriptsVerifier::new(&resolved_tx, &data_loader).verify(MAX_CYCLES); + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_PUBKEY_BLAKE160_HASH), + ); + } +} + +#[test] +fn test_sighash_all_with_grouped_inputs_unlock() { + let mut rng = thread_rng(); + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + let tx = gen_tx_with_grouped_args(&mut data_loader, vec![(pubkey_hash, 2)], &mut rng); + { + let tx = sign_tx(tx.clone(), &privkey); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verify_result = + TransactionScriptsVerifier::new(&resolved_tx, &data_loader).verify(MAX_CYCLES); + verify_result.expect("pass verification"); + } + { + let tx = sign_tx(tx.clone(), &privkey); + let wrong_witness = tx + .witnesses() + .get(1) + .map(|w| { + WitnessArgs::new_unchecked(w.unpack()) + .as_builder() + .extra(Bytes::from(vec![0]).pack()) + .build() + }) + .unwrap(); + let tx = tx + .as_advanced_builder() + .set_witnesses(vec![ + tx.witnesses().get(0).unwrap(), + wrong_witness.as_bytes().pack(), + ]) + .build(); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verify_result = + TransactionScriptsVerifier::new(&resolved_tx, &data_loader).verify(MAX_CYCLES); + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_PUBKEY_BLAKE160_HASH), + ); + } +} + +#[test] +fn test_sighash_all_with_2_different_inputs_unlock() { + let mut rng = thread_rng(); + let mut data_loader = DummyDataLoader::new(); + // key1 + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + // key2 + let privkey2 = Generator::random_privkey(); + let pubkey2 = privkey2.pubkey().expect("pubkey"); + let pubkey_hash2 = blake160(&pubkey2.serialize()); + + // sign with 2 keys + let tx = gen_tx_with_grouped_args( + &mut data_loader, + vec![(pubkey_hash, 2), (pubkey_hash2, 2)], + &mut rng, + ); + let tx = sign_tx_by_input_group(tx, &privkey, 0, 2); + let tx = sign_tx_by_input_group(tx, &privkey2, 2, 2); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verify_result = + TransactionScriptsVerifier::new(&resolved_tx, &data_loader).verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_signing_with_wrong_key() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let wrong_privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + let tx = gen_tx(&mut data_loader, pubkey_hash); + let tx = sign_tx(tx, &wrong_privkey); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verify_result = + TransactionScriptsVerifier::new(&resolved_tx, &data_loader).verify(MAX_CYCLES); + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_PUBKEY_BLAKE160_HASH), + ); +} + +#[test] +fn test_signing_wrong_tx_hash() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + let tx = gen_tx(&mut data_loader, pubkey_hash); + let tx = { + let mut rand_tx_hash = [0u8; 32]; + let mut rng = thread_rng(); + rng.fill(&mut rand_tx_hash); + sign_tx_hash(tx, &privkey, &rand_tx_hash[..]) + }; + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verify_result = + TransactionScriptsVerifier::new(&resolved_tx, &data_loader).verify(MAX_CYCLES); + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_PUBKEY_BLAKE160_HASH), + ); +} + +#[test] +fn test_super_long_witness() { + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + let tx = gen_tx(&mut data_loader, pubkey_hash); + let tx_hash = tx.hash(); + + let mut buffer: Vec = vec![]; + buffer.resize(40000, 1); + let super_long_message = Bytes::from(&buffer[..]); + + let mut blake2b = ckb_hash::new_blake2b(); + let mut message = [0u8; 32]; + blake2b.update(&tx_hash.raw_data()); + blake2b.update(&super_long_message[..]); + blake2b.finalize(&mut message); + let message = H256::from(message); + let sig = privkey.sign_recoverable(&message).expect("sign"); + let witness = WitnessArgs::new_builder() + .lock(Bytes::from(sig.serialize()).pack()) + .extra(super_long_message.pack()) + .build(); + let tx = tx + .as_advanced_builder() + .set_witnesses(vec![witness.as_bytes().pack()]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verify_result = + TransactionScriptsVerifier::new(&resolved_tx, &data_loader).verify(MAX_CYCLES); + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_NO_PAIR), + ); +} + +#[test] +fn test_sighash_all_2_in_2_out_cycles() { + const CONSUME_CYCLES: u64 = 3377980; + + let mut data_loader = DummyDataLoader::new(); + let mut generator = Generator::non_crypto_safe_prng(42); + let mut rng = rand::rngs::SmallRng::seed_from_u64(42); + + // key1 + let privkey = generator.gen_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + // key2 + let privkey2 = generator.gen_privkey(); + let pubkey2 = privkey2.pubkey().expect("pubkey"); + let pubkey_hash2 = blake160(&pubkey2.serialize()); + + // sign with 2 keys + let tx = gen_tx_with_grouped_args( + &mut data_loader, + vec![(pubkey_hash, 1), (pubkey_hash2, 1)], + &mut rng, + ); + let tx = sign_tx_by_input_group(tx, &privkey, 0, 1); + let tx = sign_tx_by_input_group(tx, &privkey2, 1, 1); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verify_result = + TransactionScriptsVerifier::new(&resolved_tx, &data_loader).verify(MAX_CYCLES); + let cycles = verify_result.expect("pass verification"); + assert_eq!(CONSUME_CYCLES, cycles) +} + +#[test] +fn test_sighash_all_witness_append_junk_data() { + let mut rng = thread_rng(); + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + + // sign with 2 keys + let tx = gen_tx_with_grouped_args(&mut data_loader, vec![(pubkey_hash, 2)], &mut rng); + let tx = sign_tx_by_input_group(tx, &privkey, 0, 2); + let mut witnesses: Vec<_> = Unpack::>::unpack(&tx.witnesses()); + // append junk data to first witness + let mut witness = Vec::new(); + witness.resize(witnesses[0].len(), 0); + witness.copy_from_slice(&witnesses[0]); + witness.push(0); + witnesses[0] = witness.into(); + + let tx = tx + .as_advanced_builder() + .set_witnesses(witnesses.into_iter().map(|w| w.pack()).collect()) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verify_result = + TransactionScriptsVerifier::new(&resolved_tx, &data_loader).verify(MAX_CYCLES); + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_NO_PAIR), + ); +} + +#[test] +fn test_sighash_all_witness_args_ambiguity() { + // This test case build tx with WitnessArgs(lock, data, "") + // and try unlock with WitnessArgs(lock, "", data) + // + // this case will fail if contract use a naive function to digest witness. + + let mut rng = thread_rng(); + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + + let tx = gen_tx_with_grouped_args(&mut data_loader, vec![(pubkey_hash, 2)], &mut rng); + let tx = sign_tx_by_input_group(tx, &privkey, 0, 2); + let witnesses: Vec<_> = Unpack::>::unpack(&tx.witnesses()); + // move extra data to type_ + let witnesses: Vec<_> = witnesses + .into_iter() + .map(|witness| { + let witness = WitnessArgs::new_unchecked(witness); + let data = witness.extra().clone(); + witness + .as_builder() + .extra(Bytes::new().pack()) + .type_(data) + .build() + }) + .collect(); + + let tx = tx + .as_advanced_builder() + .set_witnesses(witnesses.into_iter().map(|w| w.as_bytes().pack()).collect()) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verify_result = + TransactionScriptsVerifier::new(&resolved_tx, &data_loader).verify(MAX_CYCLES); + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_PUBKEY_BLAKE160_HASH), + ); +} + +#[test] +fn test_sighash_all_witnesses_ambiguity() { + // This test case sign tx with [witness1, "", witness2] + // and try unlock with [witness1, witness2, ""] + // + // this case will fail if contract use a naive function to digest witness. + + let mut rng = thread_rng(); + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + + let tx = gen_tx_with_grouped_args(&mut data_loader, vec![(pubkey_hash, 3)], &mut rng); + let witness = Unpack::>::unpack(&tx.witnesses()).remove(0); + let tx = tx + .as_advanced_builder() + .set_witnesses(vec![ + witness.pack(), + Bytes::new().pack(), + Bytes::from(vec![42]).pack(), + ]) + .build(); + let tx = sign_tx_by_input_group(tx, &privkey, 0, 3); + + // exchange witness position + let witness = Unpack::>::unpack(&tx.witnesses()).remove(0); + let tx = tx + .as_advanced_builder() + .set_witnesses(vec![ + witness.pack(), + Bytes::from(vec![42]).pack(), + Bytes::new().pack(), + ]) + .build(); + + assert_eq!(tx.witnesses().len(), tx.inputs().len()); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verify_result = + TransactionScriptsVerifier::new(&resolved_tx, &data_loader).verify(MAX_CYCLES); + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_PUBKEY_BLAKE160_HASH), + ); +} + +#[test] +fn test_sighash_all_cover_extra_witnesses() { + let mut rng = thread_rng(); + let mut data_loader = DummyDataLoader::new(); + let privkey = Generator::random_privkey(); + let pubkey = privkey.pubkey().expect("pubkey"); + let pubkey_hash = blake160(&pubkey.serialize()); + + let tx = gen_tx_with_grouped_args(&mut data_loader, vec![(pubkey_hash, 2)], &mut rng); + let witness = Unpack::>::unpack(&tx.witnesses()).remove(0); + let tx = tx + .as_advanced_builder() + .set_witnesses(vec![ + witness.pack(), + Bytes::from(vec![42]).pack(), + Bytes::new().pack(), + ]) + .build(); + let tx = sign_tx_by_input_group(tx, &privkey, 0, 3); + assert!(tx.witnesses().len() > tx.inputs().len()); + + // change last witness + let mut witnesses = Unpack::>::unpack(&tx.witnesses()); + let tx = tx + .as_advanced_builder() + .set_witnesses(vec![ + witnesses.remove(0).pack(), + witnesses.remove(1).pack(), + Bytes::from(vec![0]).pack(), + ]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + let verify_result = + TransactionScriptsVerifier::new(&resolved_tx, &data_loader).verify(60000000); + assert_error_eq!( + verify_result.unwrap_err(), + ScriptError::ValidationFailure(ERROR_PUBKEY_BLAKE160_HASH), + ); +}