From 70c2ae3610fa91557af2ee3f3f45f3e9d35b0724 Mon Sep 17 00:00:00 2001 From: RetricSu Date: Thu, 21 Nov 2024 23:21:10 +0800 Subject: [PATCH 1/5] feat(example): add simple spawn script --- examples/spawn-script/.gitignore | 3 + examples/spawn-script/Cargo.lock | 1907 +++++++++++++++++ examples/spawn-script/Cargo.toml | 17 + examples/spawn-script/Makefile | 142 ++ examples/spawn-script/README.md | 7 + .../spawn-script/contracts/callee/.gitignore | 2 + .../spawn-script/contracts/callee/Cargo.toml | 10 + .../spawn-script/contracts/callee/Makefile | 80 + .../spawn-script/contracts/callee/README.md | 7 + .../contracts/callee/src/error.rs | 35 + .../spawn-script/contracts/callee/src/lib.rs | 7 + .../spawn-script/contracts/callee/src/main.rs | 35 + .../spawn-script/contracts/caller/.gitignore | 2 + .../spawn-script/contracts/caller/Cargo.toml | 10 + .../spawn-script/contracts/caller/Makefile | 80 + .../spawn-script/contracts/caller/README.md | 7 + .../contracts/caller/src/error.rs | 35 + .../spawn-script/contracts/caller/src/lib.rs | 7 + .../spawn-script/contracts/caller/src/main.rs | 62 + examples/spawn-script/scripts/find_clang | 32 + .../scripts/reproducible_build_docker | 66 + examples/spawn-script/tests/Cargo.toml | 11 + examples/spawn-script/tests/src/lib.rs | 112 + examples/spawn-script/tests/src/tests.rs | 75 + 24 files changed, 2751 insertions(+) create mode 100644 examples/spawn-script/.gitignore create mode 100644 examples/spawn-script/Cargo.lock create mode 100644 examples/spawn-script/Cargo.toml create mode 100644 examples/spawn-script/Makefile create mode 100644 examples/spawn-script/README.md create mode 100644 examples/spawn-script/contracts/callee/.gitignore create mode 100644 examples/spawn-script/contracts/callee/Cargo.toml create mode 100644 examples/spawn-script/contracts/callee/Makefile create mode 100644 examples/spawn-script/contracts/callee/README.md create mode 100644 examples/spawn-script/contracts/callee/src/error.rs create mode 100644 examples/spawn-script/contracts/callee/src/lib.rs create mode 100644 examples/spawn-script/contracts/callee/src/main.rs create mode 100644 examples/spawn-script/contracts/caller/.gitignore create mode 100644 examples/spawn-script/contracts/caller/Cargo.toml create mode 100644 examples/spawn-script/contracts/caller/Makefile create mode 100644 examples/spawn-script/contracts/caller/README.md create mode 100644 examples/spawn-script/contracts/caller/src/error.rs create mode 100644 examples/spawn-script/contracts/caller/src/lib.rs create mode 100644 examples/spawn-script/contracts/caller/src/main.rs create mode 100755 examples/spawn-script/scripts/find_clang create mode 100755 examples/spawn-script/scripts/reproducible_build_docker create mode 100644 examples/spawn-script/tests/Cargo.toml create mode 100644 examples/spawn-script/tests/src/lib.rs create mode 100644 examples/spawn-script/tests/src/tests.rs diff --git a/examples/spawn-script/.gitignore b/examples/spawn-script/.gitignore new file mode 100644 index 000000000..0ff4f2fa8 --- /dev/null +++ b/examples/spawn-script/.gitignore @@ -0,0 +1,3 @@ +/build +/target +/tests/failed_txs diff --git a/examples/spawn-script/Cargo.lock b/examples/spawn-script/Cargo.lock new file mode 100644 index 000000000..ecf309781 --- /dev/null +++ b/examples/spawn-script/Cargo.lock @@ -0,0 +1,1907 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.15", + "once_cell", + "version_check", +] + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "blake2b-ref" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "294d17c72e0ba59fad763caa112368d0672083779cdebbb97164f4bb4c1e339a" + +[[package]] +name = "blake2b-rs" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89a8565807f21b913288968e391819e7f9b2f0f46c7b89549c051cccf3a2771" +dependencies = [ + "cc", + "cty", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "buddy-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee741d62dcaf41ca303576ef890989ccb01d5dd77f8ce1a6d6c7846ab5d09efb" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +dependencies = [ + "serde", +] + +[[package]] +name = "cacache" +version = "12.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142316461ed3a3dfcba10417317472da5bfd0461e4d276bf7c07b330766d9490" +dependencies = [ + "digest", + "either", + "futures", + "hex", + "libc", + "memmap2", + "miette", + "reflink-copy", + "serde", + "serde_derive", + "serde_json", + "sha1", + "sha2", + "ssri", + "tempfile", + "thiserror", + "tokio", + "tokio-stream", + "walkdir", +] + +[[package]] +name = "callee" +version = "0.1.0" +dependencies = [ + "ckb-std", +] + +[[package]] +name = "caller" +version = "0.1.0" +dependencies = [ + "ckb-std", +] + +[[package]] +name = "cc" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "907d8581360765417f8f2e0e7d602733bbed60156b4465b7617243689ef9b83d" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ckb-always-success-script" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b3b72a38c9920a29990df12002c4d069a147c8782f0c211f8a01b2df8f42bfd" + +[[package]] +name = "ckb-chain-spec" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084b4b3c2d0d5ca51e47812130615535cad47772005af3535f3d4e6a63e947ae" +dependencies = [ + "cacache", + "ckb-constant", + "ckb-crypto", + "ckb-dao-utils", + "ckb-error", + "ckb-hash", + "ckb-jsonrpc-types", + "ckb-logger", + "ckb-pow", + "ckb-rational", + "ckb-resource", + "ckb-traits", + "ckb-types", + "serde", + "toml", +] + +[[package]] +name = "ckb-channel" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4c7f5530737f8a02329075581b29ab7003a72d6ee747d1b2ea9d2239faea7a" +dependencies = [ + "crossbeam-channel", +] + +[[package]] +name = "ckb-constant" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e1424bf7490c14cdbd13697629ece8c1ba0ed02ff1c8a5b14a8713431ec6ff8" + +[[package]] +name = "ckb-crypto" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee335e672a67e4d951a65d5a3b03072f038dc1487e559133953912bcbe41d4d9" +dependencies = [ + "ckb-fixed-hash", + "faster-hex", + "lazy_static", + "rand 0.8.5", + "secp256k1", + "thiserror", +] + +[[package]] +name = "ckb-dao" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956a82fae564f5d207118f8a152f7c8daf1db4119ac4d3a18dfe5695bcd9b0e4" +dependencies = [ + "byteorder", + "ckb-chain-spec", + "ckb-dao-utils", + "ckb-traits", + "ckb-types", +] + +[[package]] +name = "ckb-dao-utils" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "766da195cb9a17f5a625de6924058ef1f12241317835cc83a09368018074366a" +dependencies = [ + "byteorder", + "ckb-error", + "ckb-types", +] + +[[package]] +name = "ckb-error" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109adb3c26e697861e3f57c1ca8cf2f2a399c46e64c97be2b05f751535ac1b75" +dependencies = [ + "anyhow", + "ckb-occupied-capacity", + "derive_more", + "thiserror", +] + +[[package]] +name = "ckb-fixed-hash" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71ea8f4896f945ecdb473cc8b747a47a9f282393a37a681bcbe0cdde94894bfc" +dependencies = [ + "ckb-fixed-hash-core", + "ckb-fixed-hash-macros", +] + +[[package]] +name = "ckb-fixed-hash-core" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1c265cd6b0ec00b8dc671b9344906a2428f9b756e4e789660c71f535252fe2d" +dependencies = [ + "ckb_schemars", + "faster-hex", + "serde", + "thiserror", +] + +[[package]] +name = "ckb-fixed-hash-macros" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976b10df5474be0ff33b22a84b44875e065679fc41155350c11e420124910ca1" +dependencies = [ + "ckb-fixed-hash-core", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ckb-gen-types" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc221d4b9d6d39215b1d62be855861b8b0c8d668ca29874903b0bf5d0b4d9fa" +dependencies = [ + "cfg-if", + "ckb-error", + "ckb-fixed-hash", + "ckb-hash", + "ckb-occupied-capacity", + "molecule", + "numext-fixed-uint", +] + +[[package]] +name = "ckb-hash" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99ba7c72f86f239b3e0154f51d6cd5d0d83bbaa8775fdc7b6bcac459ae24b6fd" +dependencies = [ + "blake2b-ref", + "blake2b-rs", +] + +[[package]] +name = "ckb-jsonrpc-types" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3983584cc6e269125c3bf502fa6d84a4f6e47d5b4c1e3a4070db86382ed4ba15" +dependencies = [ + "ckb-types", + "ckb_schemars", + "faster-hex", + "serde", + "serde_json", +] + +[[package]] +name = "ckb-logger" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b19523bb7b582ccd98615a48c687e41ce1511e72d903520ea36100ef5c5ba9a3" +dependencies = [ + "log", +] + +[[package]] +name = "ckb-merkle-mountain-range" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ccb671c5921be8a84686e6212ca184cb1d7c51cadcdbfcbd1cc3f042f5dfb8" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ckb-mock-tx-types" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bce36d06097bca7df141a89ba970566bbf4075945c6dd95a0771e8830c2c1a8" +dependencies = [ + "ckb-jsonrpc-types", + "ckb-traits", + "ckb-types", + "serde", +] + +[[package]] +name = "ckb-occupied-capacity" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6b706bce252b627543ce3bac5240f4d2f1e5d73daca9e451c88db44c2ea94bb" +dependencies = [ + "ckb-occupied-capacity-core", + "ckb-occupied-capacity-macros", +] + +[[package]] +name = "ckb-occupied-capacity-core" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "510608e5c7c2f3bf025c6ae80ed7782a1cd12897e15dc930167c8dbd3165ece6" +dependencies = [ + "serde", +] + +[[package]] +name = "ckb-occupied-capacity-macros" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b79a3fd71708b5068fb377497d6be6dbca53725f1a13d174335105c4bd39ffd5" +dependencies = [ + "ckb-occupied-capacity-core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ckb-pow" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40266a0bbf46eb4d92fc7137c93b22b8518d7a5a8991d6b52931b1fc43cb9863" +dependencies = [ + "byteorder", + "ckb-hash", + "ckb-types", + "eaglesong", + "log", + "serde", +] + +[[package]] +name = "ckb-rational" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91835c60dba878e54da2dfcfad62369638b88f910d9e8c7eb31f9c357a331ff7" +dependencies = [ + "numext-fixed-uint", + "serde", +] + +[[package]] +name = "ckb-resource" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ec19c5f0d6e96a0347492acdf992f6db7838f70b1c3ae4d32e9d3558f0557f0" +dependencies = [ + "ckb-system-scripts", + "ckb-types", + "includedir", + "includedir_codegen", + "phf", + "serde", + "walkdir", +] + +[[package]] +name = "ckb-script" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c247ea3580c240a7eb82516258c8523c7c22219b6681016be83284ebb15cd22" +dependencies = [ + "byteorder", + "ckb-chain-spec", + "ckb-error", + "ckb-hash", + "ckb-logger", + "ckb-traits", + "ckb-types", + "ckb-vm", + "faster-hex", + "serde", + "tokio", +] + +[[package]] +name = "ckb-std" +version = "0.16.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a673595baadfa1712ff03a36e1519f28015cf9944282410863d5e256336f5b9" +dependencies = [ + "buddy-alloc", + "cc", + "ckb-gen-types", + "ckb-x64-simulator", + "gcd", +] + +[[package]] +name = "ckb-system-scripts" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa5c59063142de7a68cfad4449c6b3863563856219a2925dfb8c5f019ec2aa47" +dependencies = [ + "blake2b-rs", + "faster-hex", + "includedir", + "includedir_codegen", + "phf", +] + +[[package]] +name = "ckb-systemtime" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0acbeae9e64b10d26ea477dc982caf643d4143f086cb5cf69f2d0f94e4fa2e4" + +[[package]] +name = "ckb-testtool" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04def89b489205dfcf3cb03468f427e23990987fcdd5aa274515a775846c8c5" +dependencies = [ + "ckb-always-success-script", + "ckb-chain-spec", + "ckb-crypto", + "ckb-error", + "ckb-hash", + "ckb-jsonrpc-types", + "ckb-mock-tx-types", + "ckb-resource", + "ckb-script", + "ckb-traits", + "ckb-types", + "ckb-verification", + "faster-hex", + "lazy_static", + "libloading", + "rand 0.8.5", + "serde_json", +] + +[[package]] +name = "ckb-traits" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab91cb32bd5655b5b4c6574d6f07dd919d93759dc9e07f9ee6a2a9823848c4dc" +dependencies = [ + "ckb-types", +] + +[[package]] +name = "ckb-types" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f02dc76ea18e9838ec996c0f1f8a822d65176d2c9f052b3855c1d0a2d0a4d885" +dependencies = [ + "bit-vec", + "bytes", + "ckb-channel", + "ckb-constant", + "ckb-error", + "ckb-fixed-hash", + "ckb-gen-types", + "ckb-hash", + "ckb-merkle-mountain-range", + "ckb-occupied-capacity", + "ckb-rational", + "derive_more", + "golomb-coded-set", + "merkle-cbt", + "molecule", + "numext-fixed-uint", + "once_cell", + "paste", +] + +[[package]] +name = "ckb-verification" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45211151ba0f3d949739f7e4b0bb3368064f6388022c977c2fb316373ccf5f3" +dependencies = [ + "ckb-chain-spec", + "ckb-dao", + "ckb-dao-utils", + "ckb-error", + "ckb-pow", + "ckb-script", + "ckb-systemtime", + "ckb-traits", + "ckb-types", + "ckb-verification-traits", + "derive_more", + "lru", + "tokio", +] + +[[package]] +name = "ckb-verification-traits" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "468d29a43ebacfdecb5cd5a7b9f90a9dc6fb610380a4251208e567fdcce88c0d" +dependencies = [ + "bitflags 1.3.2", + "ckb-error", +] + +[[package]] +name = "ckb-vm" +version = "0.24.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddff96029d3298cb630e95f29d4b9a93384e938a0b75758684aa8794b53bdd1a" +dependencies = [ + "byteorder", + "bytes", + "cc", + "ckb-vm-definitions", + "derive_more", + "goblin 0.2.3", + "goblin 0.4.0", + "rand 0.7.3", + "scroll", + "serde", +] + +[[package]] +name = "ckb-vm-definitions" +version = "0.24.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c280bf1d589d23ab0358f58601c2187fc6be86a131644583ef72ea96a0a13ddd" +dependencies = [ + "paste", +] + +[[package]] +name = "ckb-x64-simulator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4734273cff42f99205f5d3b6d6673786339443ca169ed5ff85bfc69730d910" +dependencies = [ + "cc", + "ckb-mock-tx-types", + "ckb-types", + "faster-hex", + "lazy_static", + "libc", + "libloading", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "ckb_schemars" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f21f99fca82a4eb8708e406e99246987b087ecc1e1babeece1a0b1d5238b1750" +dependencies = [ + "ckb_schemars_derive", + "dyn-clone", + "serde", + "serde_json", +] + +[[package]] +name = "ckb_schemars_derive" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c813b4fadbdd9f33b1cf02a1ddfa9537d955c8d2fbe150d1fc1684dbf78e73" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "cpufeatures" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cty" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.70", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "eaglesong" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d978bd5d343e8ab9b5c0fc8d93ff9c602fdc96616ffff9c05ac7a155419b824" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "faster-hex" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e2ce894d53b295cf97b05685aa077950ff3e8541af83217fc720a6437169f8" + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "flate2" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "gcd" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "goblin" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d20fd25aa456527ce4f544271ae4fea65d2eda4a6561ea56f39fb3ee4f7e3884" +dependencies = [ + "log", + "plain", + "scroll", +] + +[[package]] +name = "goblin" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "532a09cd3df2c6bbfc795fb0434bff8f22255d1d07328180e918a2e6ce122d4d" +dependencies = [ + "log", + "plain", + "scroll", +] + +[[package]] +name = "golomb-coded-set" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f314a99fb5b7f0f9d0a8388539578f83f3aca6a65f588b8dbeefb731e2f98" +dependencies = [ + "siphasher", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "heapsize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" +dependencies = [ + "winapi", +] + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "includedir" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afd126bd778c00c43a9dc76d1609a0894bf4222088088b2217ccc0ce9e816db7" +dependencies = [ + "flate2", + "phf", +] + +[[package]] +name = "includedir_codegen" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ac1500c9780957c9808c4ec3b94002f35aab01483833f5a8bce7dfb243e3148" +dependencies = [ + "flate2", + "phf_codegen", + "walkdir", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "lru" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "merkle-cbt" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "171d2f700835121c3b04ccf0880882987a050fd5c7ae88148abf537d33dd3a56" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "miette" +version = "5.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e" +dependencies = [ + "miette-derive", + "once_cell", + "thiserror", + "unicode-width", +] + +[[package]] +name = "miette-derive" +version = "5.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + +[[package]] +name = "molecule" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6efe1c7efcd0bdf4ca590e104bcb13087d9968956ae4ae98e92fb8c1da0f3730" +dependencies = [ + "bytes", + "cfg-if", + "faster-hex", +] + +[[package]] +name = "numext-constructor" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "621fe0f044729f810c6815cdd77e8f5e0cd803ce4f6a38380ebfc1322af98661" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[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", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "object" +version = "0.36.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +dependencies = [ + "phf_shared", + "rand 0.7.3", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[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-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[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_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] + +[[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_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "reflink-copy" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc31414597d1cd7fdd2422798b7652a6329dda0fe0219e6335a13d5bcaa9aeb6" +dependencies = [ + "cfg-if", + "rustix", + "windows", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[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 = "scroll" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda28d4b4830b807a8b43f7b0e6b5df875311b3e7621d84577188c175b6ec1ec" +dependencies = [ + "scroll_derive", +] + +[[package]] +name = "scroll_derive" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaaae8f38bb311444cfb7f1979af0bc9240d95795f75f9ceddf6a59b79ceffa0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "secp256k1" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +dependencies = [ + "cc", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "serde_json" +version = "1.0.120" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha-1" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "ssri" +version = "9.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7a2b3c2bc9693bcb40870c4e9b5bf0d79f9cb46273321bf855ec513e919082" +dependencies = [ + "base64", + "digest", + "hex", + "miette", + "serde", + "sha-1", + "sha2", + "thiserror", + "xxhash-rust", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0209b68b3613b093e0ec905354eccaedcfe83b8cb37cbdeae64026c3064c16" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "tests" +version = "0.1.0" +dependencies = [ + "ckb-testtool", + "serde_json", +] + +[[package]] +name = "thiserror" +version = "1.0.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "tokio" +version = "1.39.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "signal-hook-registry", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + +[[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.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[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.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[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-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.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys 0.52.0", +] + +[[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" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.70", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "xxhash-rust" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" diff --git a/examples/spawn-script/Cargo.toml b/examples/spawn-script/Cargo.toml new file mode 100644 index 000000000..e7f80e6a5 --- /dev/null +++ b/examples/spawn-script/Cargo.toml @@ -0,0 +1,17 @@ +[workspace] +resolver = "2" + +members = [ + # Please don't remove the following line, we use it to automatically + # detect insertion point for newly generated crates. + # @@INSERTION_POINT@@ + "contracts/callee", + "contracts/caller", + "tests", +] + +[profile.release] +overflow-checks = true +strip = false +codegen-units = 1 +debug = true diff --git a/examples/spawn-script/Makefile b/examples/spawn-script/Makefile new file mode 100644 index 000000000..ebb24a667 --- /dev/null +++ b/examples/spawn-script/Makefile @@ -0,0 +1,142 @@ +# We cannot use $(shell pwd), which will return unix path format on Windows, +# making it hard to use. +cur_dir = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + +TOP := $(cur_dir) +# RUSTFLAGS that are likely to be tweaked by developers. For example, +# while we enable debug logs by default here, some might want to strip them +# for minimal code size / consumed cycles. +CUSTOM_RUSTFLAGS := -C debug-assertions +# Additional cargo args to append here. For example, one can use +# make test CARGO_ARGS="-- --nocapture" so as to inspect data emitted to +# stdout in unit tests +CARGO_ARGS := +MODE := release +# Tweak this to change the clang version to use for building C code. By default +# we use a bash script with somes heuristics to find clang in current system. +CLANG := $(shell $(TOP)/scripts/find_clang) +# When this is set, a single contract will be built instead of all contracts +CONTRACT := +# By default, we would clean build/{release,debug} folder first, in case old +# contracts are mixed together with new ones, if for some reason you want to +# revert this behavior, you can change this to anything other than true +CLEAN_BUILD_DIR_FIRST := true +BUILD_DIR := build/$(MODE) + +ifeq (release,$(MODE)) + MODE_ARGS := --release +endif + +# Pass setups to child make processes +export CUSTOM_RUSTFLAGS +export TOP +export CARGO_ARGS +export MODE +export CLANG +export BUILD_DIR + +default: build test + +build: + @if [ "x$(CLEAN_BUILD_DIR_FIRST)" = "xtrue" ]; then \ + echo "Cleaning $(BUILD_DIR) directory..."; \ + rm -rf $(BUILD_DIR); \ + fi + mkdir -p $(BUILD_DIR) + @set -eu; \ + if [ "x$(CONTRACT)" = "x" ]; then \ + for contract in $(wildcard contracts/*); do \ + $(MAKE) -e -C $$contract build; \ + done; \ + for crate in $(wildcard crates/*); do \ + cargo build -p $$(basename $$crate) $(MODE_ARGS) $(CARGO_ARGS); \ + done; \ + for sim in $(wildcard native-simulators/*); do \ + cargo build -p $$(basename $$sim) $(CARGO_ARGS); \ + done; \ + else \ + $(MAKE) -e -C contracts/$(CONTRACT) build; \ + cargo build -p $(CONTRACT)-sim; \ + fi; + +# Run a single make task for a specific contract. For example: +# +# make run CONTRACT=stack-reorder TASK=adjust_stack_size STACK_SIZE=0x200000 +TASK := +run: + $(MAKE) -e -C contracts/$(CONTRACT) $(TASK) + +# test, check, clippy and fmt here are provided for completeness, +# there is nothing wrong invoking cargo directly instead of make. +test: + cargo test $(CARGO_ARGS) + +check: + cargo check $(CARGO_ARGS) + +clippy: + cargo clippy $(CARGO_ARGS) + +fmt: + cargo fmt $(CARGO_ARGS) + +# Arbitrary cargo command is supported here. For example: +# +# make cargo CARGO_CMD=expand CARGO_ARGS="--ugly" +# +# Invokes: +# cargo expand --ugly +CARGO_CMD := +cargo: + cargo $(CARGO_CMD) $(CARGO_ARGS) + +clean: + rm -rf build + cargo clean + +TEMPLATE_TYPE := --git +TEMPLATE_REPO := https://github.com/cryptape/ckb-script-templates +CRATE := +TEMPLATE := contract +DESTINATION := contracts +generate: + @set -eu; \ + if [ "x$(CRATE)" = "x" ]; then \ + cargo generate $(TEMPLATE_TYPE) $(TEMPLATE_REPO) $(TEMPLATE) \ + --destination $(DESTINATION); \ + GENERATED_DIR=$$(ls -dt $(DESTINATION)/* | head -n 1); \ + if [ -f "$$GENERATED_DIR/.cargo-generate/tests.rs" ]; then \ + cat $$GENERATED_DIR/.cargo-generate/tests.rs >> tests/src/tests.rs; \ + rm -rf $$GENERATED_DIR/.cargo-generate/; \ + fi; \ + sed "s,@@INSERTION_POINT@@,@@INSERTION_POINT@@\n \"$$GENERATED_DIR\"\,," Cargo.toml > Cargo.toml.new; \ + mv Cargo.toml.new Cargo.toml; \ + else \ + cargo generate $(TEMPLATE_TYPE) $(TEMPLATE_REPO) $(TEMPLATE) \ + --destination $(DESTINATION) \ + --name $(CRATE); \ + if [ -f "$(DESTINATION)/$(CRATE)/.cargo-generate/tests.rs" ]; then \ + cat $(DESTINATION)/$(CRATE)/.cargo-generate/tests.rs >> tests/src/tests.rs; \ + rm -rf $(DESTINATION)/$(CRATE)/.cargo-generate/; \ + fi; \ + sed '/@@INSERTION_POINT@@/s/$$/\n "$(DESTINATION)\/$(CRATE)",/' Cargo.toml > Cargo.toml.new; \ + mv Cargo.toml.new Cargo.toml; \ + fi; + +generate-native-simulator: + @set -eu; \ + cargo generate $(TEMPLATE_TYPE) $(TEMPLATE_REPO) native-simulator \ + -n $(CRATE)-sim \ + --destination native-simulators; \ + sed '/@@INSERTION_POINT@@/s/$$/\n "native-simulators\/$(CRATE)-sim",/' Cargo.toml > Cargo.toml.new; \ + mv Cargo.toml.new Cargo.toml; + +prepare: + rustup target add riscv64imac-unknown-none-elf + +# Generate checksum info for reproducible build +CHECKSUM_FILE := build/checksums-$(MODE).txt +checksum: build + shasum -a 256 build/$(MODE)/* > $(CHECKSUM_FILE) + +.PHONY: build test check clippy fmt cargo clean prepare checksum diff --git a/examples/spawn-script/README.md b/examples/spawn-script/README.md new file mode 100644 index 000000000..5a2fceea1 --- /dev/null +++ b/examples/spawn-script/README.md @@ -0,0 +1,7 @@ +# spawn-script + +TODO: Write this readme + +*This project was bootstrapped with [ckb-script-templates].* + +[ckb-script-templates]: https://github.com/cryptape/ckb-script-templates diff --git a/examples/spawn-script/contracts/callee/.gitignore b/examples/spawn-script/contracts/callee/.gitignore new file mode 100644 index 000000000..c3dca1b96 --- /dev/null +++ b/examples/spawn-script/contracts/callee/.gitignore @@ -0,0 +1,2 @@ +/build +/target diff --git a/examples/spawn-script/contracts/callee/Cargo.toml b/examples/spawn-script/contracts/callee/Cargo.toml new file mode 100644 index 000000000..51f8fc8be --- /dev/null +++ b/examples/spawn-script/contracts/callee/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "callee" +version = "0.1.0" +edition = "2021" + +[dependencies] +ckb-std = "0.16.3" + +[features] +native-simulator = ["ckb-std/native-simulator"] diff --git a/examples/spawn-script/contracts/callee/Makefile b/examples/spawn-script/contracts/callee/Makefile new file mode 100644 index 000000000..7e88d6e9f --- /dev/null +++ b/examples/spawn-script/contracts/callee/Makefile @@ -0,0 +1,80 @@ +# We cannot use $(shell pwd), which will return unix path format on Windows, +# making it hard to use. +cur_dir = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + +TOP := $(cur_dir) +# RUSTFLAGS that are likely to be tweaked by developers. For example, +# while we enable debug logs by default here, some might want to strip them +# for minimal code size / consumed cycles. +CUSTOM_RUSTFLAGS := -C debug-assertions +# RUSTFLAGS that are less likely to be tweaked by developers. Most likely +# one would want to keep the default values here. +FULL_RUSTFLAGS := -C target-feature=+zba,+zbb,+zbc,+zbs,-a $(CUSTOM_RUSTFLAGS) +# Additional cargo args to append here. For example, one can use +# make test CARGO_ARGS="-- --nocapture" so as to inspect data emitted to +# stdout in unit tests +CARGO_ARGS := +MODE := release +# Tweak this to change the clang version to use for building C code. By default +# we use a bash script with somes heuristics to find clang in current system. +CLANG := $(shell $(TOP)/scripts/find_clang) +AR := $(subst clang,llvm-ar,$(CLANG)) +OBJCOPY := $(subst clang,llvm-objcopy,$(CLANG)) +# When this is set to some value, the generated binaries will be copied over +BUILD_DIR := +# Generated binaries to copy. By convention, a Rust crate's directory name will +# likely match the crate name, which is also the name of the final binary. +# However if this is not the case, you can tweak this variable. As the name hints, +# more than one binary is supported here. +BINARIES := $(notdir $(shell pwd)) + +ifeq (release,$(MODE)) + MODE_ARGS := --release +endif + +default: build test + +build: + RUSTFLAGS="$(FULL_RUSTFLAGS)" TARGET_CC="$(CLANG)" TARGET_AR="$(AR)" \ + cargo build --target=riscv64imac-unknown-none-elf $(MODE_ARGS) $(CARGO_ARGS) + @set -eu; \ + if [ "x$(BUILD_DIR)" != "x" ]; then \ + for binary in $(BINARIES); do \ + echo "Copying binary $$binary to build directory"; \ + cp $(TOP)/target/riscv64imac-unknown-none-elf/$(MODE)/$$binary $(TOP)/$(BUILD_DIR); \ + cp $(TOP)/$(BUILD_DIR)/$$binary $(TOP)/$(BUILD_DIR)/$$binary.debug; \ + $(OBJCOPY) --strip-debug --strip-all $(TOP)/$(BUILD_DIR)/$$binary; \ + done \ + fi + +# test, check, clippy and fmt here are provided for completeness, +# there is nothing wrong invoking cargo directly instead of make. +test: + cargo test $(CARGO_ARGS) + +check: + cargo check $(CARGO_ARGS) + +clippy: + cargo clippy $(CARGO_ARGS) + +fmt: + cargo fmt $(CARGO_ARGS) + +# Arbitrary cargo command is supported here. For example: +# +# make cargo CARGO_CMD=expand CARGO_ARGS="--ugly" +# +# Invokes: +# cargo expand --ugly +CARGO_CMD := +cargo: + cargo $(CARGO_CMD) $(CARGO_ARGS) + +clean: + cargo clean + +prepare: + rustup target add riscv64imac-unknown-none-elf + +.PHONY: build test check clippy fmt cargo clean prepare diff --git a/examples/spawn-script/contracts/callee/README.md b/examples/spawn-script/contracts/callee/README.md new file mode 100644 index 000000000..7a6c9f217 --- /dev/null +++ b/examples/spawn-script/contracts/callee/README.md @@ -0,0 +1,7 @@ +# callee + +TODO: Write this readme + +*This contract was bootstrapped with [ckb-script-templates].* + +[ckb-script-templates]: https://github.com/cryptape/ckb-script-templates diff --git a/examples/spawn-script/contracts/callee/src/error.rs b/examples/spawn-script/contracts/callee/src/error.rs new file mode 100644 index 000000000..1a0a03500 --- /dev/null +++ b/examples/spawn-script/contracts/callee/src/error.rs @@ -0,0 +1,35 @@ +use ckb_std::error::SysError; + +#[cfg(test)] +extern crate alloc; + +#[repr(i8)] +pub enum Error { + IndexOutOfBound = 1, + ItemMissing, + LengthNotEnough, + Encoding, + WaitFailure, + InvalidFD, + OtherEndClose, + MaxVmSpawned, + MaxFdCreated, + // Add customized errors here... +} + +impl From for Error { + fn from(err: SysError) -> Self { + match err { + SysError::IndexOutOfBound => Self::IndexOutOfBound, + SysError::ItemMissing => Self::ItemMissing, + SysError::LengthNotEnough(_) => Self::LengthNotEnough, + SysError::Encoding => Self::Encoding, + SysError::WaitFailure => Self::WaitFailure, + SysError::InvalidFd => Self::InvalidFD, + SysError::OtherEndClosed => Self::OtherEndClose, + SysError::MaxVmsSpawned => Self::MaxVmSpawned, + SysError::MaxFdsCreated => Self::MaxFdCreated, + SysError::Unknown(err_code) => panic!("unexpected sys error {}", err_code), + } + } +} diff --git a/examples/spawn-script/contracts/callee/src/lib.rs b/examples/spawn-script/contracts/callee/src/lib.rs new file mode 100644 index 000000000..7b58725d6 --- /dev/null +++ b/examples/spawn-script/contracts/callee/src/lib.rs @@ -0,0 +1,7 @@ +#![cfg_attr(not(feature = "native-simulator"), no_std)] +#![allow(special_module_name)] +#![allow(unused_attributes)] +#[cfg(feature = "native-simulator")] +mod main; +#[cfg(feature = "native-simulator")] +pub use main::program_entry; diff --git a/examples/spawn-script/contracts/callee/src/main.rs b/examples/spawn-script/contracts/callee/src/main.rs new file mode 100644 index 000000000..e0d97a96a --- /dev/null +++ b/examples/spawn-script/contracts/callee/src/main.rs @@ -0,0 +1,35 @@ +#![cfg_attr(not(any(feature = "native-simulator", test)), no_std)] +#![cfg_attr(not(test), no_main)] + +#[cfg(any(feature = "native-simulator", test))] +extern crate alloc; + +#[cfg(not(any(feature = "native-simulator", test)))] +ckb_std::entry!(program_entry); +#[cfg(not(any(feature = "native-simulator", test)))] +ckb_std::default_alloc!(); + +mod error; +use alloc::vec; + +pub fn program_entry() -> i8 { + ckb_std::debug!("Enter callee contract!"); + + match callee() { + Ok(_) => 0, + Err(err) => err as i8, + } +} + +pub fn callee() -> Result<(), error::Error> { + let argv = ckb_std::env::argv(); + let mut std_fds: [u64; 2] = [0; 2]; + ckb_std::syscalls::inherited_fds(&mut std_fds); + let mut out = vec![]; + for arg in argv { + out.extend_from_slice(arg.to_bytes()); + } + let len = ckb_std::syscalls::write(std_fds[1], &out)?; + assert_eq!(len, 10); + Ok(()) +} diff --git a/examples/spawn-script/contracts/caller/.gitignore b/examples/spawn-script/contracts/caller/.gitignore new file mode 100644 index 000000000..c3dca1b96 --- /dev/null +++ b/examples/spawn-script/contracts/caller/.gitignore @@ -0,0 +1,2 @@ +/build +/target diff --git a/examples/spawn-script/contracts/caller/Cargo.toml b/examples/spawn-script/contracts/caller/Cargo.toml new file mode 100644 index 000000000..6725ee6fc --- /dev/null +++ b/examples/spawn-script/contracts/caller/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "caller" +version = "0.1.0" +edition = "2021" + +[dependencies] +ckb-std = "0.16.3" + +[features] +native-simulator = ["ckb-std/native-simulator"] diff --git a/examples/spawn-script/contracts/caller/Makefile b/examples/spawn-script/contracts/caller/Makefile new file mode 100644 index 000000000..7e88d6e9f --- /dev/null +++ b/examples/spawn-script/contracts/caller/Makefile @@ -0,0 +1,80 @@ +# We cannot use $(shell pwd), which will return unix path format on Windows, +# making it hard to use. +cur_dir = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + +TOP := $(cur_dir) +# RUSTFLAGS that are likely to be tweaked by developers. For example, +# while we enable debug logs by default here, some might want to strip them +# for minimal code size / consumed cycles. +CUSTOM_RUSTFLAGS := -C debug-assertions +# RUSTFLAGS that are less likely to be tweaked by developers. Most likely +# one would want to keep the default values here. +FULL_RUSTFLAGS := -C target-feature=+zba,+zbb,+zbc,+zbs,-a $(CUSTOM_RUSTFLAGS) +# Additional cargo args to append here. For example, one can use +# make test CARGO_ARGS="-- --nocapture" so as to inspect data emitted to +# stdout in unit tests +CARGO_ARGS := +MODE := release +# Tweak this to change the clang version to use for building C code. By default +# we use a bash script with somes heuristics to find clang in current system. +CLANG := $(shell $(TOP)/scripts/find_clang) +AR := $(subst clang,llvm-ar,$(CLANG)) +OBJCOPY := $(subst clang,llvm-objcopy,$(CLANG)) +# When this is set to some value, the generated binaries will be copied over +BUILD_DIR := +# Generated binaries to copy. By convention, a Rust crate's directory name will +# likely match the crate name, which is also the name of the final binary. +# However if this is not the case, you can tweak this variable. As the name hints, +# more than one binary is supported here. +BINARIES := $(notdir $(shell pwd)) + +ifeq (release,$(MODE)) + MODE_ARGS := --release +endif + +default: build test + +build: + RUSTFLAGS="$(FULL_RUSTFLAGS)" TARGET_CC="$(CLANG)" TARGET_AR="$(AR)" \ + cargo build --target=riscv64imac-unknown-none-elf $(MODE_ARGS) $(CARGO_ARGS) + @set -eu; \ + if [ "x$(BUILD_DIR)" != "x" ]; then \ + for binary in $(BINARIES); do \ + echo "Copying binary $$binary to build directory"; \ + cp $(TOP)/target/riscv64imac-unknown-none-elf/$(MODE)/$$binary $(TOP)/$(BUILD_DIR); \ + cp $(TOP)/$(BUILD_DIR)/$$binary $(TOP)/$(BUILD_DIR)/$$binary.debug; \ + $(OBJCOPY) --strip-debug --strip-all $(TOP)/$(BUILD_DIR)/$$binary; \ + done \ + fi + +# test, check, clippy and fmt here are provided for completeness, +# there is nothing wrong invoking cargo directly instead of make. +test: + cargo test $(CARGO_ARGS) + +check: + cargo check $(CARGO_ARGS) + +clippy: + cargo clippy $(CARGO_ARGS) + +fmt: + cargo fmt $(CARGO_ARGS) + +# Arbitrary cargo command is supported here. For example: +# +# make cargo CARGO_CMD=expand CARGO_ARGS="--ugly" +# +# Invokes: +# cargo expand --ugly +CARGO_CMD := +cargo: + cargo $(CARGO_CMD) $(CARGO_ARGS) + +clean: + cargo clean + +prepare: + rustup target add riscv64imac-unknown-none-elf + +.PHONY: build test check clippy fmt cargo clean prepare diff --git a/examples/spawn-script/contracts/caller/README.md b/examples/spawn-script/contracts/caller/README.md new file mode 100644 index 000000000..59c5a74e7 --- /dev/null +++ b/examples/spawn-script/contracts/caller/README.md @@ -0,0 +1,7 @@ +# caller + +TODO: Write this readme + +*This contract was bootstrapped with [ckb-script-templates].* + +[ckb-script-templates]: https://github.com/cryptape/ckb-script-templates diff --git a/examples/spawn-script/contracts/caller/src/error.rs b/examples/spawn-script/contracts/caller/src/error.rs new file mode 100644 index 000000000..1a0a03500 --- /dev/null +++ b/examples/spawn-script/contracts/caller/src/error.rs @@ -0,0 +1,35 @@ +use ckb_std::error::SysError; + +#[cfg(test)] +extern crate alloc; + +#[repr(i8)] +pub enum Error { + IndexOutOfBound = 1, + ItemMissing, + LengthNotEnough, + Encoding, + WaitFailure, + InvalidFD, + OtherEndClose, + MaxVmSpawned, + MaxFdCreated, + // Add customized errors here... +} + +impl From for Error { + fn from(err: SysError) -> Self { + match err { + SysError::IndexOutOfBound => Self::IndexOutOfBound, + SysError::ItemMissing => Self::ItemMissing, + SysError::LengthNotEnough(_) => Self::LengthNotEnough, + SysError::Encoding => Self::Encoding, + SysError::WaitFailure => Self::WaitFailure, + SysError::InvalidFd => Self::InvalidFD, + SysError::OtherEndClosed => Self::OtherEndClose, + SysError::MaxVmsSpawned => Self::MaxVmSpawned, + SysError::MaxFdsCreated => Self::MaxFdCreated, + SysError::Unknown(err_code) => panic!("unexpected sys error {}", err_code), + } + } +} diff --git a/examples/spawn-script/contracts/caller/src/lib.rs b/examples/spawn-script/contracts/caller/src/lib.rs new file mode 100644 index 000000000..7b58725d6 --- /dev/null +++ b/examples/spawn-script/contracts/caller/src/lib.rs @@ -0,0 +1,7 @@ +#![cfg_attr(not(feature = "native-simulator"), no_std)] +#![allow(special_module_name)] +#![allow(unused_attributes)] +#[cfg(feature = "native-simulator")] +mod main; +#[cfg(feature = "native-simulator")] +pub use main::program_entry; diff --git a/examples/spawn-script/contracts/caller/src/main.rs b/examples/spawn-script/contracts/caller/src/main.rs new file mode 100644 index 000000000..e3d3b2b70 --- /dev/null +++ b/examples/spawn-script/contracts/caller/src/main.rs @@ -0,0 +1,62 @@ +#![cfg_attr(not(any(feature = "native-simulator", test)), no_std)] +#![cfg_attr(not(test), no_main)] + +#[cfg(any(feature = "native-simulator", test))] +extern crate alloc; + +#[cfg(not(any(feature = "native-simulator", test)))] +ckb_std::entry!(program_entry); +#[cfg(not(any(feature = "native-simulator", test)))] +ckb_std::default_alloc!(); + +mod error; +use ckb_std::syscalls::SpawnArgs; +use core::ffi::CStr; + +pub fn program_entry() -> i8 { + ckb_std::debug!("Enter caller contract!"); + + match caller() { + Ok(_) => 0, + Err(err) => err as i8, + } +} + +fn caller() -> Result<(), error::Error> { + let (r1, w1) = ckb_std::syscalls::pipe()?; + let (r2, w2) = ckb_std::syscalls::pipe()?; + let std_fds: [u64; 2] = [r1, w2]; + let son_fds: [u64; 3] = [r2, w1, 0]; // must ends with 0 + + let mut pid: u64 = 0; + let place = 0; // 0 means read from cell data + let bounds = 0; // 0 means read to end + let argc: u64 = 2; + let argv = [ + CStr::from_bytes_with_nul(b"hello\0").unwrap().as_ptr(), + CStr::from_bytes_with_nul(b"world\0").unwrap().as_ptr(), + ]; + let mut spgs: SpawnArgs = SpawnArgs { + argc, + argv: argv.as_ptr(), + process_id: &mut pid as *mut u64, + inherited_fds: son_fds.as_ptr(), + }; + ckb_std::syscalls::spawn( + 0, + ckb_std::ckb_constants::Source::CellDep, + place, + bounds, + &mut spgs, + )?; + + let mut buf = [0; 256]; + let len = ckb_std::syscalls::read(std_fds[0], &mut buf)?; + assert_eq!(len, 10); + buf[len] = 0; + assert_eq!( + CStr::from_bytes_until_nul(&buf).unwrap().to_str().unwrap(), + "helloworld" + ); + Ok(()) +} diff --git a/examples/spawn-script/scripts/find_clang b/examples/spawn-script/scripts/find_clang new file mode 100755 index 000000000..f1ffeed4c --- /dev/null +++ b/examples/spawn-script/scripts/find_clang @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +# +# An utility script used to find a binary of clang 16+ + +if [[ -n "${CLANG}" ]]; then + echo "${CLANG}" + exit 0 +fi + +CANDIDATES=("clang" "clang-16" "clang-17" "clang-18") + +BREW_PREFIX=$(brew --prefix 2> /dev/null) +if [[ -n "${BREW_PREFIX}" ]]; then + CANDIDATES+=( + "${BREW_PREFIX}/opt/llvm/bin/clang" + "${BREW_PREFIX}/opt/llvm@16/bin/clang" + "${BREW_PREFIX}/opt/llvm@17/bin/clang" + "${BREW_PREFIX}/opt/llvm@18/bin/clang" + ) +fi + +for candidate in ${CANDIDATES[@]}; do + OUTPUT=$($candidate -dumpversion 2> /dev/null | cut -d'.' -f 1) + + if [[ $((OUTPUT)) -ge 16 ]]; then + echo "$candidate" + exit 0 + fi +done + +>&2 echo "Cannot find clang of version 16+!" +exit 1 diff --git a/examples/spawn-script/scripts/reproducible_build_docker b/examples/spawn-script/scripts/reproducible_build_docker new file mode 100755 index 000000000..fdf35ad84 --- /dev/null +++ b/examples/spawn-script/scripts/reproducible_build_docker @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# +# An utility script helping with reproducible script builds via docker. +# Note that this utility serves only as one example, docker is not +# necessarily THE way to do reproducible build, nor is it the best way +# to do reproducible build. +set -ex + +DOCKER="${DOCKER:-docker}" +# docker pull docker.io/cryptape/llvm-n-rust:20240630 +DOCKER_IMAGE="${DOCKER_IMAGE:-docker.io/cryptape/llvm-n-rust@sha256:bafaf76d4f342a69b8691c08e77a330b7740631f3d1d9c9bee4ead521b29ee55}" +CHECKSUM_FILE_PATH="${CHECKSUM_FILE_PATH:-checksums.txt}" + +# We are parsing command line arguments based on tips from: +# https://stackoverflow.com/a/14203146 + +while [[ $# -gt 0 ]]; do + case $1 in + -p|--proxy) + PROXY="$2" + shift # past argument + shift # past value + ;; + -u|--update) + UPDATE="yes" + shift # past argument + ;; + --no-clean) + NOCLEAN="yes" + shift # past argument + ;; + -*|--*) + echo "Unknown option $1" + exit 1 + ;; + *) + echo "Unknown argument $1" + exit 1 + ;; + esac +done + +if [[ -n "${PROXY}" ]]; then + DOCKER_RUN_ARGS="-e ALL_PROXY=${PROXY} -e HTTPS_PROXY=${PROXY} -e HTTP_PROXY=${PROXY} ${DOCKER_RUN_ARGS}" +fi + +TASKS="" +if [[ "${NOCLEAN}" != "yes" ]]; then + TASKS+=" clean " +fi + +if [[ "${UPDATE}" = "yes" ]]; then + TASKS+=" checksum CHECKSUM_FILE=${CHECKSUM_FILE_PATH} " +else + TASKS+=" build " +fi + +$DOCKER run --rm $DOCKER_RUN_ARGS -v `pwd`:/code $DOCKER_IMAGE make $TASKS +# Reset file ownerships for all files docker might touch +$DOCKER run --rm $DOCKER_RUN_ARGS -e UID=`id -u` -e GID=`id -g` -v `pwd`:/code $DOCKER_IMAGE bash -c 'chown -R -f $UID:$GID checksums.txt build target' + +if [[ "${UPDATE}" = "yes" ]]; then + echo "${CHECKSUM_FILE_PATH} file is updated with latest binary hashes!" +else + shasum -a 256 -c ${CHECKSUM_FILE_PATH} +fi diff --git a/examples/spawn-script/tests/Cargo.toml b/examples/spawn-script/tests/Cargo.toml new file mode 100644 index 000000000..c749f2d5b --- /dev/null +++ b/examples/spawn-script/tests/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "tests" +version = "0.1.0" +edition = "2021" + +[features] +native-simulator = [ "ckb-testtool/native-simulator" ] + +[dependencies] +ckb-testtool = "0.14.0" +serde_json = "1.0" diff --git a/examples/spawn-script/tests/src/lib.rs b/examples/spawn-script/tests/src/lib.rs new file mode 100644 index 000000000..53fb2abe6 --- /dev/null +++ b/examples/spawn-script/tests/src/lib.rs @@ -0,0 +1,112 @@ +use ckb_testtool::{ + ckb_error::Error, + ckb_types::{ + bytes::Bytes, + core::{Cycle, TransactionView}, + }, + context::Context, +}; +use std::env; +use std::fs; +use std::path::PathBuf; +use std::str::FromStr; + +#[cfg(test)] +mod tests; + +// The exact same Loader code from capsule's template, except that +// now we use MODE as the environment variable +const TEST_ENV_VAR: &str = "MODE"; + +pub enum TestEnv { + Debug, + Release, +} + +impl FromStr for TestEnv { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "debug" => Ok(TestEnv::Debug), + "release" => Ok(TestEnv::Release), + _ => Err("no match"), + } + } +} + +pub struct Loader(PathBuf); + +impl Default for Loader { + fn default() -> Self { + let test_env = match env::var(TEST_ENV_VAR) { + Ok(val) => val.parse().expect("test env"), + Err(_) => TestEnv::Release, + }; + Self::with_test_env(test_env) + } +} + +impl Loader { + fn with_test_env(env: TestEnv) -> Self { + let load_prefix = match env { + TestEnv::Debug => "debug", + TestEnv::Release => "release", + }; + let mut base_path = match env::var("TOP") { + Ok(val) => { + let mut base_path: PathBuf = val.into(); + base_path.push("build"); + base_path + } + Err(_) => { + let mut base_path = PathBuf::new(); + // cargo may use a different cwd when running tests, for example: + // when running debug in vscode, it will use workspace root as cwd by default, + // when running test by `cargo test`, it will use tests directory as cwd, + // so we need a fallback path + base_path.push("build"); + if !base_path.exists() { + base_path.pop(); + base_path.push(".."); + base_path.push("build"); + } + base_path + } + }; + + base_path.push(load_prefix); + Loader(base_path) + } + + pub fn load_binary(&self, name: &str) -> Bytes { + let mut path = self.0.clone(); + path.push(name); + let result = fs::read(&path); + if result.is_err() { + panic!("Binary {:?} is missing!", path); + } + result.unwrap().into() + } +} + +// This helper method runs Context::verify_tx, but in case error happens, +// it also dumps current transaction to failed_txs folder. +pub fn verify_and_dump_failed_tx( + context: &Context, + tx: &TransactionView, + max_cycles: u64, +) -> Result { + let result = context.verify_tx(tx, max_cycles); + if result.is_err() { + let mut path = env::current_dir().expect("current dir"); + path.push("failed_txs"); + std::fs::create_dir_all(&path).expect("create failed_txs dir"); + let mock_tx = context.dump_tx(tx).expect("dump failed tx"); + let json = serde_json::to_string_pretty(&mock_tx).expect("json"); + path.push(format!("0x{:x}.json", tx.hash())); + println!("Failed tx written to {:?}", path); + std::fs::write(path, json).expect("write"); + } + result +} diff --git a/examples/spawn-script/tests/src/tests.rs b/examples/spawn-script/tests/src/tests.rs new file mode 100644 index 000000000..0587bcaad --- /dev/null +++ b/examples/spawn-script/tests/src/tests.rs @@ -0,0 +1,75 @@ +use crate::Loader; +use ckb_testtool::ckb_types::{ + bytes::Bytes, + core::TransactionBuilder, + packed::*, + prelude::*, +}; +use ckb_testtool::context::Context; + +// Include your tests here +// See https://github.com/xxuejie/ckb-native-build-sample/blob/main/tests/src/tests.rs for more examples + +// generated unit test for contract caller +#[test] +fn test_spawn() { + // deploy contract + let mut context = Context::default(); + let caller_contract_bin: Bytes = Loader::default().load_binary("caller"); + let caller_out_point = context.deploy_cell(caller_contract_bin); + let callee_contract_bin: Bytes = Loader::default().load_binary("callee"); + let callee_out_point = context.deploy_cell(callee_contract_bin); + + // prepare scripts + let lock_script = context + .build_script(&caller_out_point, Bytes::from(vec![42])) + .expect("script"); + + // prepare cells + let input_out_point = context.create_cell( + CellOutput::new_builder() + .capacity(1000u64.pack()) + .lock(lock_script.clone()) + .build(), + Bytes::new(), + ); + let input = CellInput::new_builder() + .previous_output(input_out_point) + .build(); + let outputs = vec![ + CellOutput::new_builder() + .capacity(500u64.pack()) + .lock(lock_script.clone()) + .build(), + CellOutput::new_builder() + .capacity(500u64.pack()) + .lock(lock_script) + .build(), + ]; + + let outputs_data = vec![Bytes::new(); 2]; + + // prepare cell deps + let callee_dep = CellDep::new_builder() + .out_point(callee_out_point) + .build(); + let caller_dep = CellDep::new_builder() + .out_point(caller_out_point) + .build(); + let cell_deps: Vec = vec![callee_dep, caller_dep]; + + // build transaction + let tx = TransactionBuilder::default() + .input(input) + .outputs(outputs) + .outputs_data(outputs_data.pack()) + .cell_deps(cell_deps) + .build(); + let tx = context.complete_tx(tx); + + // run + let cycles = context + .verify_tx(&tx, 10_000_000) + .expect("pass verification"); + println!("consume cycles: {}", cycles); +} From 0518a6d1b794acda6b2e1134b018899dff7a341c Mon Sep 17 00:00:00 2001 From: RetricSu Date: Sat, 23 Nov 2024 14:24:32 +0800 Subject: [PATCH 2/5] feat(script): add simple spawn tutorial --- .../spawn-script/contracts/callee/src/main.rs | 6 +- .../spawn-script/contracts/caller/src/main.rs | 8 +- website/docs/script/spawn-script.mdx | 587 ++++++++++++++++++ website/sidebars.js | 1 + 4 files changed, 595 insertions(+), 7 deletions(-) create mode 100644 website/docs/script/spawn-script.mdx diff --git a/examples/spawn-script/contracts/callee/src/main.rs b/examples/spawn-script/contracts/callee/src/main.rs index e0d97a96a..11a8869e9 100644 --- a/examples/spawn-script/contracts/callee/src/main.rs +++ b/examples/spawn-script/contracts/callee/src/main.rs @@ -23,13 +23,13 @@ pub fn program_entry() -> i8 { pub fn callee() -> Result<(), error::Error> { let argv = ckb_std::env::argv(); - let mut std_fds: [u64; 2] = [0; 2]; - ckb_std::syscalls::inherited_fds(&mut std_fds); + let mut to_parent_fds: [u64; 2] = [0; 2]; + ckb_std::syscalls::inherited_fds(&mut to_parent_fds); let mut out = vec![]; for arg in argv { out.extend_from_slice(arg.to_bytes()); } - let len = ckb_std::syscalls::write(std_fds[1], &out)?; + let len = ckb_std::syscalls::write(to_parent_fds[1], &out)?; assert_eq!(len, 10); Ok(()) } diff --git a/examples/spawn-script/contracts/caller/src/main.rs b/examples/spawn-script/contracts/caller/src/main.rs index e3d3b2b70..66aa0c8dd 100644 --- a/examples/spawn-script/contracts/caller/src/main.rs +++ b/examples/spawn-script/contracts/caller/src/main.rs @@ -25,8 +25,8 @@ pub fn program_entry() -> i8 { fn caller() -> Result<(), error::Error> { let (r1, w1) = ckb_std::syscalls::pipe()?; let (r2, w2) = ckb_std::syscalls::pipe()?; - let std_fds: [u64; 2] = [r1, w2]; - let son_fds: [u64; 3] = [r2, w1, 0]; // must ends with 0 + let to_parent_fds: [u64; 2] = [r1, w2]; + let to_child_fds: [u64; 3] = [r2, w1, 0]; // must ends with 0 let mut pid: u64 = 0; let place = 0; // 0 means read from cell data @@ -40,7 +40,7 @@ fn caller() -> Result<(), error::Error> { argc, argv: argv.as_ptr(), process_id: &mut pid as *mut u64, - inherited_fds: son_fds.as_ptr(), + inherited_fds: to_child_fds.as_ptr(), }; ckb_std::syscalls::spawn( 0, @@ -51,7 +51,7 @@ fn caller() -> Result<(), error::Error> { )?; let mut buf = [0; 256]; - let len = ckb_std::syscalls::read(std_fds[0], &mut buf)?; + let len = ckb_std::syscalls::read(to_parent_fds[0], &mut buf)?; assert_eq!(len, 10); buf[len] = 0; assert_eq!( diff --git a/website/docs/script/spawn-script.mdx b/website/docs/script/spawn-script.mdx new file mode 100644 index 000000000..d06fda17b --- /dev/null +++ b/website/docs/script/spawn-script.mdx @@ -0,0 +1,587 @@ +--- +id: spawn-script +title: "Tutorial: Spawn Script" +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; +import TutorialHeader from "@components/TutorialHeader"; +import Tooltip from "@components/Tooltip"; +import ScriptTools from "./_ScriptTools.mdx"; + +# Tutorial: Spawn Script + + + +The design of the syscall spawn function draws inspiration from Unix and Linux, hence they share the same terminologies: process, pipe, and file descriptor. +The spawn mechanism is used in ckb-vm to create new processes, which can then execute a different program or command independently of the parent process. + +In the context of ckb-vm, a process represents the active execution of a RISC-V binary. +This binary can be located within a cell. Additionally, a RISC-V binary can also be found within the witness during a syscall spawn. +A pipe is established by associating two file descriptors, each linked to one of its ends. +These file descriptors can't be duplicated and are exclusively owned by the process. +Furthermore, the file descriptors can only be either read from or written to; they can't be both read from and written to simultaneously. + +In this tutorial, you will learn how to write a full Rust example using Spawn syscall to call a Script from a Script on CKB. +The full code of this tutorial can be found at [Github](https://github.com/nervosnetwork/docs.nervos.org/tree/develop/examples/spawn-script). + +## Initialize a Script Project + +```mdx-code-block + + +``` + +```bash +offckb create --script spawn-script +``` + +```mdx-code-block + + +``` + +```bash +⚠️ Favorite `gh:cryptape/ckb-script-templates` not found in config, using it as a git repository: https://github.com/cryptape/ckb-script-templates.git +🀷 Project Name: spawn-script +πŸ”§ Destination: /tmp/spawn-script ... +πŸ”§ project-name: spawn-script ... +πŸ”§ Generating template ... +πŸ”§ Moving generated files into: `/tmp/spawn-script`... +πŸ”§ Initializing a fresh Git repository +✨ Done! New project created /tmp/spawn-script +``` + +```mdx-code-block + + +``` + +## Create two New Scripts + +Let’s create a new Script called `caller` inside the project. + +```mdx-code-block + + +``` + +```bash +cd caller-script +make generate +``` + +```mdx-code-block + + +``` + +```bash +🀷 Project Name: caller +πŸ”§ Destination: /tmp/spawn-script/contracts/caller ... +πŸ”§ project-name: caller ... +πŸ”§ Generating template ... +πŸ”§ Moving generated files into: `/tmp/caller-script/contracts/caller`... +πŸ”§ Initializing a fresh Git repository +✨ Done! New project created /tmp/caller-script/contracts/caller +``` + +```mdx-code-block + + +``` + +And create another new Script called `callee` inside the project. + +```mdx-code-block + + +``` + +```bash +make generate +``` + +```mdx-code-block + + +``` + +```bash +🀷 Project Name: callee +πŸ”§ Destination: /tmp/spawn-script/contracts/callee ... +πŸ”§ project-name: callee ... +πŸ”§ Generating template ... +πŸ”§ Moving generated files into: `/tmp/spawn-script/contracts/callee`... +πŸ”§ Initializing a fresh Git repository +✨ Done! New project created /tmp/spawn-script/contracts/callee +``` + +```mdx-code-block + + +``` + +Our project is successfully setup now. + +## Implementing Caller + +First, add a error handler module called `Error` in `error.rs`: + +```rust name="spawn-script/contracts/caller/src/error.rs" +use ckb_std::error::SysError; + +#[cfg(test)] +extern crate alloc; + +#[repr(i8)] +pub enum Error { + IndexOutOfBound = 1, + ItemMissing, + LengthNotEnough, + Encoding, + WaitFailure, + InvalidFD, + OtherEndClose, + MaxVmSpawned, + MaxFdCreated, + // Add customized errors here... +} + +impl From for Error { + fn from(err: SysError) -> Self { + match err { + SysError::IndexOutOfBound => Self::IndexOutOfBound, + SysError::ItemMissing => Self::ItemMissing, + SysError::LengthNotEnough(_) => Self::LengthNotEnough, + SysError::Encoding => Self::Encoding, + SysError::WaitFailure => Self::WaitFailure, + SysError::InvalidFd => Self::InvalidFD, + SysError::OtherEndClosed => Self::OtherEndClose, + SysError::MaxVmsSpawned => Self::MaxVmSpawned, + SysError::MaxFdsCreated => Self::MaxFdCreated, + SysError::Unknown(err_code) => panic!("unexpected sys error {}", err_code), + } + } +} +``` + +Let's include the error module and necessary libs in the `main.rs` file: + +```rust name="spawn-script/contracts/caller/src/main.rs" +mod error; +use ckb_std::syscalls::SpawnArgs; +use core::ffi::CStr; +``` + +Next, we will wrap the logic in a `caller` function and using this function in the `program_entry`: + +```rust name="spawn-script/contracts/caller/src/main.rs" +pub fn program_entry() -> i8 { + ckb_std::debug!("Enter caller contract!"); + + match caller() { + Ok(_) => 0, + Err(err) => err as i8, + } +} + +fn caller() -> Result<(), error::Error> {} +``` + +Now, let's implement the function of `caller`, which involved creating pipes and use spawn syscall to call another Script in a standalone process. + +The pipe is used as a one-direction data flow that carries data from one Script to another Script. +We will pass two string as arguments to the callee Script and hopes it returns the concat result of those two string. +We also assume that the callee Script is located at the first cell from the cellDeps of the transaction. + +```rust name="spawn-script/contracts/caller/src/main.rs" +fn caller() -> Result<(), error::Error> { + let (r1, w1) = ckb_std::syscalls::pipe()?; + let (r2, w2) = ckb_std::syscalls::pipe()?; + let to_parent_fds: [u64; 2] = [r1, w2]; + let to_child_fds: [u64; 3] = [r2, w1, 0]; // must ends with 0 + + let mut pid: u64 = 0; + let place = 0; // 0 means read from cell data + let bounds = 0; // 0 means read to end + let argc: u64 = 2; + let argv = [ + CStr::from_bytes_with_nul(b"hello\0").unwrap().as_ptr(), + CStr::from_bytes_with_nul(b"world\0").unwrap().as_ptr(), + ]; + let mut spgs: SpawnArgs = SpawnArgs { + argc, + argv: argv.as_ptr(), + process_id: &mut pid as *mut u64, + inherited_fds: to_child_fds.as_ptr(), + }; + ckb_std::syscalls::spawn( + 0, + ckb_std::ckb_constants::Source::CellDep, + place, + bounds, + &mut spgs, + )?; + + let mut buf = [0; 256]; + let len = ckb_std::syscalls::read(to_parent_fds[0], &mut buf)?; + assert_eq!(len, 10); + buf[len] = 0; + assert_eq!( + CStr::from_bytes_until_nul(&buf).unwrap().to_str().unwrap(), + "helloworld" + ); + Ok(()) +} +``` + +One thing to be noted here is that each pipe we creating can only be either read from or written to. We create two pipes, one is for child process writing, parent process reading, one is the opposite. + +```rust +let (r1, w1) = ckb_std::syscalls::pipe()?; +let (r2, w2) = ckb_std::syscalls::pipe()?; +let to_parent_fds: [u64; 2] = [r1, w2]; +let to_child_fds: [u64; 3] = [r2, w1, 0]; // must ends with 0 + + +// ... + +let len = ckb_std::syscalls::read(to_parent_fds[0], &mut buf)?; +``` + +## Implementing Callee + +We need to create the same thing here, a `error.rs` file and a `callee` function in the `main.rs`: + +```rust name="spawn-script/contracts/callee/src/error.rs" +use ckb_std::error::SysError; + +#[cfg(test)] +extern crate alloc; + +#[repr(i8)] +pub enum Error { + IndexOutOfBound = 1, + ItemMissing, + LengthNotEnough, + Encoding, + WaitFailure, + InvalidFD, + OtherEndClose, + MaxVmSpawned, + MaxFdCreated, + // Add customized errors here... +} + +impl From for Error { + fn from(err: SysError) -> Self { + match err { + SysError::IndexOutOfBound => Self::IndexOutOfBound, + SysError::ItemMissing => Self::ItemMissing, + SysError::LengthNotEnough(_) => Self::LengthNotEnough, + SysError::Encoding => Self::Encoding, + SysError::WaitFailure => Self::WaitFailure, + SysError::InvalidFd => Self::InvalidFD, + SysError::OtherEndClosed => Self::OtherEndClose, + SysError::MaxVmsSpawned => Self::MaxVmSpawned, + SysError::MaxFdsCreated => Self::MaxFdCreated, + SysError::Unknown(err_code) => panic!("unexpected sys error {}", err_code), + } + } +} +``` + +```rust name="spawn-script/contracts/callee/src/error.rs" +mod error; +use alloc::vec; + +pub fn program_entry() -> i8 { + ckb_std::debug!("Enter callee contract!"); + + match callee() { + Ok(_) => 0, + Err(err) => err as i8, + } +} + +pub fn callee() -> Result<(), error::Error> { + let argv = ckb_std::env::argv(); + let mut to_parent_fds: [u64; 2] = [0; 2]; + ckb_std::syscalls::inherited_fds(&mut to_parent_fds); + let mut out = vec![]; + for arg in argv { + out.extend_from_slice(arg.to_bytes()); + } + let len = ckb_std::syscalls::write(to_parent_fds[1], &out)?; + assert_eq!(len, 10); + Ok(()) +} +``` + +The `callee` function logic is simpler. +It received the arguments using `ckb_std::env::argv()` and inherited the pipe using `inherited_fds`. + +Then it use `write` syscall to write the concat result to the pipe: + +```rust +let len = ckb_std::syscalls::write(to_parent_fds[1], &out)?; +``` + +## Writing Unit Tests + +The Unit Test files are located in the `spawn-script/tests/src/tests.rs`. +We only need one test for our Scripts, which will use `caller` as input lock Script and verify the Script in the transaction. The `callee` Script Cell will be pushed into cellDeps of the transaction too. + +```rust name="spawn-script/tests/src/tests.rs" +use crate::Loader; +use ckb_testtool::ckb_types::{ + bytes::Bytes, + core::TransactionBuilder, + packed::*, + prelude::*, +}; +use ckb_testtool::context::Context; + +// Include your tests here +// See https://github.com/xxuejie/ckb-native-build-sample/blob/main/tests/src/tests.rs for more examples + +// generated unit test for contract caller +#[test] +fn test_spawn() { + // deploy contract + let mut context = Context::default(); + let caller_contract_bin: Bytes = Loader::default().load_binary("caller"); + let caller_out_point = context.deploy_cell(caller_contract_bin); + let callee_contract_bin: Bytes = Loader::default().load_binary("callee"); + let callee_out_point = context.deploy_cell(callee_contract_bin); + + // prepare scripts + let lock_script = context + .build_script(&caller_out_point, Bytes::from(vec![42])) + .expect("script"); + + // prepare cells + let input_out_point = context.create_cell( + CellOutput::new_builder() + .capacity(1000u64.pack()) + .lock(lock_script.clone()) + .build(), + Bytes::new(), + ); + let input = CellInput::new_builder() + .previous_output(input_out_point) + .build(); + let outputs = vec![ + CellOutput::new_builder() + .capacity(500u64.pack()) + .lock(lock_script.clone()) + .build(), + CellOutput::new_builder() + .capacity(500u64.pack()) + .lock(lock_script) + .build(), + ]; + + let outputs_data = vec![Bytes::new(); 2]; + + // prepare cell deps + let callee_dep = CellDep::new_builder() + .out_point(callee_out_point) + .build(); + let caller_dep = CellDep::new_builder() + .out_point(caller_out_point) + .build(); + let cell_deps: Vec = vec![callee_dep, caller_dep]; + + // build transaction + let tx = TransactionBuilder::default() + .input(input) + .outputs(outputs) + .outputs_data(outputs_data.pack()) + .cell_deps(cell_deps) + .build(); + let tx = context.complete_tx(tx); + + // run + let cycles = context + .verify_tx(&tx, 10_000_000) + .expect("pass verification"); + println!("consume cycles: {}", cycles); +} +``` + +First, build the Scripts: + +```sh +make build +``` + +Running Tests: + +```sh +make test +``` + +## Testing on Devnet + +After testing our Scripts, we feel more confident to test it on a more real environment. + +We will use `offckb` to start a devnet and deploy the Scripts. Then we will test the Script by sending transaction to the devnet using `offckb` REPL. + +1. Start the devnet + +```sh +offckb node +``` + +2. Deploy the Scripts + +Open a new terminal and `cd` into the root of the `spawn-script` project then run: + +```mdx-code-block + + +``` + +```sh +offckb deploy --target build/release/caller +``` + +```mdx-code-block + + +``` + +```sh +contract caller deployed, tx hash: 0x74bed00091f062e46225662fc90e460a4cc975478117eaa8570d454bf8dc58e9 +wait for tx confirmed on-chain... +tx committed. +caller deployment.toml file /Users/retric/Library/Application Support/offckb-nodejs/devnet/contracts/caller/deployment.toml generated successfully. +caller migration json file /Users/retric/Library/Application Support/offckb-nodejs/devnet/contracts/caller/migrations/2024-11-23-133222.json generated successfully. +done. +``` + +```mdx-code-block + + +``` + +```mdx-code-block + + +``` + +```sh +offckb deploy --target build/release/callee +``` + +```mdx-code-block + + +``` + +```sh +contract callee deployed, tx hash: 0xdb91398beafb3c41b3e6f4c4a078a08aa1f4245b0d964b9d51913e8514f20b72 +wait for tx confirmed on-chain... +tx committed. +callee deployment.toml file /Users/retric/Library/Application Support/offckb-nodejs/devnet/contracts/callee/deployment.toml generated successfully. +callee migration json file /Users/retric/Library/Application Support/offckb-nodejs/devnet/contracts/callee/migrations/2024-11-23-133257.json generated successfully. +done. +``` + +```mdx-code-block + + +``` + +3. Send a test Transaction + +Open a new terminal and start a offckb REPL: + +```mdx-code-block + + +``` + +```sh +offckb repl -r +``` + +```mdx-code-block + + +``` + +```sh +Welcome to OffCKB REPL! +[[ Default Network: devnet, enableProxyRPC: true, CCC SDK: 0.0.16-alpha.3 ]] +Type 'help()' to learn how to use. +OffCKB > +``` + +```mdx-code-block + + +``` + +Next, we construct a transaction right in the offckb REPL: + +```sh +OffCKB > let amountInCKB = ccc.fixedPointFrom(63); +OffCKB > let caller = myScripts['caller']; +OffCKB > let lockScript = new ccc.Script(caller.codeHash, caller.hashType, "0x00"); +OffCKB > let tx = ccc.Transaction.from({ +... outputs: [ +... { +... capacity: ccc.fixedPointFrom(amountInCKB), +... lock: lockScript, +... }, +... ], +... cellDeps: [ +... ...myScripts["callee"].cellDeps.map(c => c.cellDep), +... ...myScripts['caller'].cellDeps.map(c => c.cellDep), +... ]} +... ); +OffCKB > let signer = new ccc.SignerCkbPrivateKey(client, accounts[0].privkey); +OffCKB > await tx.completeInputsByCapacity(signer); +1 +OffCKB > await tx.completeFeeBy(signer, 1000); +[ 0, true ] +OffCKB > await signer.sendTransaction(tx) +'0x252305141e6b7db81f7da94b098493a36b756fe9d5d4436c9d7c966882bc0b38' +``` + +We can re-run the tx with `offckb debug` for our Scripts: + +```sh +offckb debug --tx-hash 0x252305141e6b7db81f7da94b098493a36b756fe9d5d4436c9d7c966882bc0b38 +Dump transaction successfully + +****************************** +****** Input[0].Lock ****** + +Run result: 0 +All cycles: 1646754(1.6M) +``` + +## Note: the deployed Scripts are using `cargo build ---release` mode so all the log are removed from the Script binary to reduce size. + +## Congratulations! + +By following this tutorial so far, you have mastered how to write simple Spawn Scripts that brings passing data between them. +Here's a quick recap: + +- Use `offckb` and `ckb-script-templates` to init a Script project +- Use `ckb_std` to leverage CKB syscalls to create pipes and calling spawn Script. +- Write unit tests to make sure the Spawn Scripts work as expected. +- Use `offckb` REPL to send a testing transaction that verify the Spawn Scripts. + +## Additional Resources + +- Full source code of this tutorial: + [spawn-script](https://github.com/nervosnetwork/docs.nervos.org/tree/develop/examples/spawn-script) +- CKB syscalls specs: [RFC-0009](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0009-vm-syscalls/0009-vm-syscalls.md) +- Script templates: [ckb-script-templates](https://github.com/cryptape/ckb-script-templates) +- CKB transaction structure: [RFC-0022-transaction-structure](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0022-transaction-structure/0022-transaction-structure.md) +- CKB data structure basics: [RFC-0019-data-structure](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0019-data-structures/0019-data-structures.md) diff --git a/website/sidebars.js b/website/sidebars.js index 99599865a..1718679e6 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -53,6 +53,7 @@ export default { "script/vm-cycle-limits", "script/minimal-script", "script/sudt-script", + "script/spawn-script", "script/type-id", "script/js-script", "script/debug-script", From 49bdaa352e0201c971a9a687919800f806f53ce1 Mon Sep 17 00:00:00 2001 From: RetricSu Date: Mon, 25 Nov 2024 18:57:55 +0800 Subject: [PATCH 3/5] Apply suggestions from code review Co-authored-by: Sss_is_me <107824088+linnnsss@users.noreply.github.com> --- website/docs/script/spawn-script.mdx | 67 +++++++++++++++------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/website/docs/script/spawn-script.mdx b/website/docs/script/spawn-script.mdx index d06fda17b..660fbc358 100644 --- a/website/docs/script/spawn-script.mdx +++ b/website/docs/script/spawn-script.mdx @@ -14,15 +14,15 @@ import ScriptTools from "./_ScriptTools.mdx"; The design of the syscall spawn function draws inspiration from Unix and Linux, hence they share the same terminologies: process, pipe, and file descriptor. -The spawn mechanism is used in ckb-vm to create new processes, which can then execute a different program or command independently of the parent process. +The spawn mechanism is used in CKB-VM to create new processes, which can then execute a different program or command independently of the parent process. -In the context of ckb-vm, a process represents the active execution of a RISC-V binary. -This binary can be located within a cell. Additionally, a RISC-V binary can also be found within the witness during a syscall spawn. +In the context of CKB-VM, a process represents the active execution of a RISC-V binary, which can be located within a Cell. +Additionally, a RISC-V binary can also be found within the witness during a Spawn syscall. A pipe is established by associating two file descriptors, each linked to one of its ends. These file descriptors can't be duplicated and are exclusively owned by the process. Furthermore, the file descriptors can only be either read from or written to; they can't be both read from and written to simultaneously. -In this tutorial, you will learn how to write a full Rust example using Spawn syscall to call a Script from a Script on CKB. +In this tutorial, you will learn how to write a complete Rust example using Spawn syscall to call a Script from another on CKB. The full code of this tutorial can be found at [Github](https://github.com/nervosnetwork/docs.nervos.org/tree/develop/examples/spawn-script). ## Initialize a Script Project @@ -57,7 +57,7 @@ offckb create --script spawn-script ``` -## Create two New Scripts +## Create Two New Scripts Let’s create a new Script called `caller` inside the project. @@ -124,9 +124,9 @@ make generate Our project is successfully setup now. -## Implementing Caller +## Implement Caller -First, add a error handler module called `Error` in `error.rs`: +First, add an error handler module called `Error` in `error.rs`: ```rust name="spawn-script/contracts/caller/src/error.rs" use ckb_std::error::SysError; @@ -174,7 +174,7 @@ use ckb_std::syscalls::SpawnArgs; use core::ffi::CStr; ``` -Next, we will wrap the logic in a `caller` function and using this function in the `program_entry`: +Next, we will wrap the logic in a `caller` function and use it in the `program_entry`: ```rust name="spawn-script/contracts/caller/src/main.rs" pub fn program_entry() -> i8 { @@ -189,11 +189,11 @@ pub fn program_entry() -> i8 { fn caller() -> Result<(), error::Error> {} ``` -Now, let's implement the function of `caller`, which involved creating pipes and use spawn syscall to call another Script in a standalone process. +Now, let's implement the `caller` function, which creates pipes and uses Spawn syscall to call another Script in a standalone process. The pipe is used as a one-direction data flow that carries data from one Script to another Script. -We will pass two string as arguments to the callee Script and hopes it returns the concat result of those two string. -We also assume that the callee Script is located at the first cell from the cellDeps of the transaction. +We will pass two strings as arguments to the callee Script, expecting it to return their concatenated result. +We also assume that the callee Script is located in the first Cell of the transaction's Cell Deps. ```rust name="spawn-script/contracts/caller/src/main.rs" fn caller() -> Result<(), error::Error> { @@ -236,7 +236,7 @@ fn caller() -> Result<(), error::Error> { } ``` -One thing to be noted here is that each pipe we creating can only be either read from or written to. We create two pipes, one is for child process writing, parent process reading, one is the opposite. +Note that each pipe can only be used for either reading or writing. To facilitate communication, we create two pipes: one for the child process to write and the parent process to read; the other does the reverse. ```rust let (r1, w1) = ckb_std::syscalls::pipe()?; @@ -250,9 +250,9 @@ let to_child_fds: [u64; 3] = [r2, w1, 0]; // must ends with 0 let len = ckb_std::syscalls::read(to_parent_fds[0], &mut buf)?; ``` -## Implementing Callee +## Implement Callee -We need to create the same thing here, a `error.rs` file and a `callee` function in the `main.rs`: +We need to create the same components here: an `error.rs` file and a `callee` function in the `main.rs`: ```rust name="spawn-script/contracts/callee/src/error.rs" use ckb_std::error::SysError; @@ -319,19 +319,19 @@ pub fn callee() -> Result<(), error::Error> { } ``` -The `callee` function logic is simpler. -It received the arguments using `ckb_std::env::argv()` and inherited the pipe using `inherited_fds`. +The `callee` function has a simpler logic. +It receives arguments using `ckb_std::env::argv()` and inherits the pipe using `inherited_fds`. -Then it use `write` syscall to write the concat result to the pipe: +Then it uses the `write` syscall to write the concatenated result to the pipe: ```rust let len = ckb_std::syscalls::write(to_parent_fds[1], &out)?; ``` -## Writing Unit Tests +## Write Unit Tests The Unit Test files are located in the `spawn-script/tests/src/tests.rs`. -We only need one test for our Scripts, which will use `caller` as input lock Script and verify the Script in the transaction. The `callee` Script Cell will be pushed into cellDeps of the transaction too. +We'll create one test for our Scripts that uses `caller` as the input Lock Script and verifies it in the transaction. The `callee` Script Cell will also be pushed into the Cell Deps of the transaction. ```rust name="spawn-script/tests/src/tests.rs" use crate::Loader; @@ -417,17 +417,17 @@ First, build the Scripts: make build ``` -Running Tests: +Then, run the tests: ```sh make test ``` -## Testing on Devnet +## Test on Devnet -After testing our Scripts, we feel more confident to test it on a more real environment. +After testing our Scripts, we can be more confident to test them in a more realistic environment. -We will use `offckb` to start a devnet and deploy the Scripts. Then we will test the Script by sending transaction to the devnet using `offckb` REPL. +We will use `offckb` to start a devnet and deploy the Scripts, then test the Scripts by sending a transaction to the devnet using `offckb` REPL. 1. Start the devnet @@ -437,7 +437,7 @@ offckb node 2. Deploy the Scripts -Open a new terminal and `cd` into the root of the `spawn-script` project then run: +Open a new terminal, navigate to the root of the `spawn-script` project, then run: ```mdx-code-block @@ -495,9 +495,9 @@ done. ``` -3. Send a test Transaction +3. Send a Test Transaction -Open a new terminal and start a offckb REPL: +Open a new terminal and start an offckb REPL: ```mdx-code-block @@ -525,7 +525,7 @@ OffCKB > ``` -Next, we construct a transaction right in the offckb REPL: +Next, we'll construct a transaction in the offckb REPL: ```sh OffCKB > let amountInCKB = ccc.fixedPointFrom(63); @@ -552,7 +552,7 @@ OffCKB > await signer.sendTransaction(tx) '0x252305141e6b7db81f7da94b098493a36b756fe9d5d4436c9d7c966882bc0b38' ``` -We can re-run the tx with `offckb debug` for our Scripts: +We can re-run the transaction with `offckb debug` to test our Scripts: ```sh offckb debug --tx-hash 0x252305141e6b7db81f7da94b098493a36b756fe9d5d4436c9d7c966882bc0b38 @@ -565,17 +565,20 @@ Run result: 0 All cycles: 1646754(1.6M) ``` -## Note: the deployed Scripts are using `cargo build ---release` mode so all the log are removed from the Script binary to reduce size. +##Note +:::note +The deployed Scripts use `cargo build --release` mode that removes all the logs from the Script binary to reduce the size. +::: ## Congratulations! -By following this tutorial so far, you have mastered how to write simple Spawn Scripts that brings passing data between them. +By following this tutorial so far, you have mastered how to write simple Spawn Scripts that pass data between them. Here's a quick recap: - Use `offckb` and `ckb-script-templates` to init a Script project -- Use `ckb_std` to leverage CKB syscalls to create pipes and calling spawn Script. +- Use `ckb_std` to leverage CKB syscalls to create pipes and call Spawn Script. - Write unit tests to make sure the Spawn Scripts work as expected. -- Use `offckb` REPL to send a testing transaction that verify the Spawn Scripts. +- Use `offckb` REPL to send a testing transaction that verifies Spawn Scripts. ## Additional Resources From c94e2d615eef0c0e8b900dc656f6dc92ba25c030 Mon Sep 17 00:00:00 2001 From: RetricSu Date: Fri, 29 Nov 2024 11:49:38 +0800 Subject: [PATCH 4/5] Update website/docs/script/spawn-script.mdx Co-authored-by: yfeng2824 <140578792+yfeng2824@users.noreply.github.com> --- website/docs/script/spawn-script.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/script/spawn-script.mdx b/website/docs/script/spawn-script.mdx index 660fbc358..c03ab88f6 100644 --- a/website/docs/script/spawn-script.mdx +++ b/website/docs/script/spawn-script.mdx @@ -427,9 +427,9 @@ make test After testing our Scripts, we can be more confident to test them in a more realistic environment. -We will use `offckb` to start a devnet and deploy the Scripts, then test the Scripts by sending a transaction to the devnet using `offckb` REPL. +We will use `offckb` to start a Devnet and deploy the Scripts, then test the Scripts by sending a transaction to the Devnet using `offckb` REPL. -1. Start the devnet +1. Start the Devnet ```sh offckb node From 8f5d5dd0570b384e7994f4b4e8ce8c97c3dae3b6 Mon Sep 17 00:00:00 2001 From: RetricSu Date: Fri, 29 Nov 2024 14:28:43 +0800 Subject: [PATCH 5/5] Update website/docs/script/spawn-script.mdx --- website/docs/script/spawn-script.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/website/docs/script/spawn-script.mdx b/website/docs/script/spawn-script.mdx index c03ab88f6..89113a0c9 100644 --- a/website/docs/script/spawn-script.mdx +++ b/website/docs/script/spawn-script.mdx @@ -565,7 +565,6 @@ Run result: 0 All cycles: 1646754(1.6M) ``` -##Note :::note The deployed Scripts use `cargo build --release` mode that removes all the logs from the Script binary to reduce the size. :::