diff --git a/.github/workflows/rust-with-clang.yml b/.github/workflows/rust-with-clang.yml new file mode 100644 index 0000000..765b69d --- /dev/null +++ b/.github/workflows/rust-with-clang.yml @@ -0,0 +1,17 @@ +name: Rust + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Install llvm 16 + run: sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14 && wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && sudo ./llvm.sh 16 + - name: Update submodules + run: git submodule update --init + - name: Run sphincs+ rust tests + run: ./tests/sphincsplus_rust/run_rust_with_clang.sh diff --git a/Makefile.clang b/Makefile.clang new file mode 100644 index 0000000..ebda77a --- /dev/null +++ b/Makefile.clang @@ -0,0 +1,87 @@ +CC := clang-16 +LD := ld.lld-16 +OBJCOPY := llvm-objcopy-16 +AR := llvm-ar-16 +RANLIB := llvm-ranlib-16 + +PARAMS = sphincs-shake-128f +THASH = simple + +CFLAGS := --target=riscv64 -march=rv64imc_zba_zbb_zbc_zbs \ + -g -O3 -fPIC \ + -Wall -Werror -Wno-nonnull -Wno-unused-function \ + -Wno-error=unused-but-set-variable \ + -Wno-error=unused-command-line-argument \ + -Wno-error=bitwise-instead-of-logical \ + -fno-builtin-printf -fno-builtin-memcmp \ + -nostdinc -nostdlib -fvisibility=hidden \ + -fdata-sections -ffunction-sections \ + -DCKB_VM -DCKB_DECLARATION_ONLY + +LDFLAGS := -static -Wl,--gc-sections + +CFLAGS := $(CFLAGS) -I c -I deps/ckb-c-stdlib/libc -I deps/ckb-c-stdlib -I deps/ckb-c-stdlib/molecule +CFLAGS := $(CFLAGS) -I deps/sphincsplus/ref -DPARAMS=$(PARAMS) + +SPHINCS_PLUS_DIR = deps/sphincsplus/ref/ + +SOURCES = \ + $(SPHINCS_PLUS_DIR)address.c \ + $(SPHINCS_PLUS_DIR)merkle.c \ + $(SPHINCS_PLUS_DIR)wots.c \ + $(SPHINCS_PLUS_DIR)wotsx1.c \ + $(SPHINCS_PLUS_DIR)utils.c \ + $(SPHINCS_PLUS_DIR)utilsx1.c \ + $(SPHINCS_PLUS_DIR)fors.c \ + $(SPHINCS_PLUS_DIR)sign.c \ + c/ckb-sphincsplus.c + +HEADERS = \ + $(SPHINCS_PLUS_DIR)params.h \ + $(SPHINCS_PLUS_DIR)address.h \ + $(SPHINCS_PLUS_DIR)merkle.h \ + $(SPHINCS_PLUS_DIR)wots.h \ + $(SPHINCS_PLUS_DIR)wotsx1.h \ + $(SPHINCS_PLUS_DIR)utils.h \ + $(SPHINCS_PLUS_DIR)utilsx1.h \ + $(SPHINCS_PLUS_DIR)fors.h \ + $(SPHINCS_PLUS_DIR)api.h \ + $(SPHINCS_PLUS_DIR)hash.h \ + $(SPHINCS_PLUS_DIR)thash.h \ + $(SPHINCS_PLUS_DIR)randombytes.h \ + c/ckb-sphincsplus.h + +ifneq (,$(findstring shake,$(PARAMS))) + SOURCES += \ + $(SPHINCS_PLUS_DIR)fips202.c \ + $(SPHINCS_PLUS_DIR)hash_shake.c \ + $(SPHINCS_PLUS_DIR)thash_shake_$(THASH).c + HEADERS += $(SPHINCS_PLUS_DIR)fips202.h +endif +ifneq (,$(findstring haraka,$(PARAMS))) + SOURCES += \ + $(SPHINCS_PLUS_DIR)haraka.c \ + $(SPHINCS_PLUS_DIR)hash_haraka.c \ + $(SPHINCS_PLUS_DIR)thash_haraka_$(THASH).c + HEADERS += $(SPHINCS_PLUS_DIR)haraka.h +endif +ifneq (,$(findstring sha2,$(PARAMS))) + SOURCES += \ + $(SPHINCS_PLUS_DIR)sha2.c \ + $(SPHINCS_PLUS_DIR)hash_sha2.c \ + $(SPHINCS_PLUS_DIR)thash_sha2_$(THASH).c + HEADERS += $(SPHINCS_PLUS_DIR)sha2.h +endif + +# CFLAGS := $(CFLAGS) -DCKB_C_STDLIB_PRINTF + +all: build/sphincsplus_lock + +build/sphincsplus_lock: c/ckb-sphincsplus-lock.c $(SOURCES) $(HEADERS) + mkdir -p build + $(CC) $(CFLAGS) -o $@ $(SOURCES) $< + cp $@ $@.debug + $(OBJCOPY) --strip-debug --strip-all $@ + +clean: + rm -rf build/sphincsplus_lock \ No newline at end of file diff --git a/tests/sphincsplus_rust/Cargo.lock b/tests/sphincsplus_rust/Cargo.lock index b7c6aaa..312095a 100644 --- a/tests/sphincsplus_rust/Cargo.lock +++ b/tests/sphincsplus_rust/Cargo.lock @@ -17,6 +17,54 @@ dependencies = [ "memchr", ] +[[package]] +name = "anstream" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "anyhow" version = "1.0.68" @@ -29,6 +77,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base64" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" + [[package]] name = "bit-vec" version = "0.6.3" @@ -402,9 +456,43 @@ checksum = "5445b62604e7ab2bf5abb37bf6cca7ac26b2e4a76fddb27ceb61850f24864d58" name = "ckb_sphincs_utils" version = "0.1.0" dependencies = [ + "base64", "cc", ] +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "convert_case" version = "0.4.0" @@ -753,7 +841,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -1062,18 +1150,26 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" name = "sphincsplus_rust_test" version = "0.1.0" dependencies = [ + "base64", "ckb-chain-spec", "ckb-hash", "ckb-script", "ckb-traits", "ckb-types", "ckb_sphincs_utils", + "clap", "lazy_static", "libc", "num_enum", "rand 0.8.5", ] +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "1.0.107" @@ -1137,6 +1233,12 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "walkdir" version = "2.3.2" @@ -1197,7 +1299,16 @@ version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-targets", + "windows-targets 0.42.1", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", ] [[package]] @@ -1206,13 +1317,29 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.42.1", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm 0.42.1", + "windows_x86_64_msvc 0.42.1", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -1221,38 +1348,86 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + [[package]] name = "windows_aarch64_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + [[package]] name = "windows_i686_gnu" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + [[package]] name = "windows_i686_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + [[package]] name = "windows_x86_64_gnu" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + [[package]] name = "windows_x86_64_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/tests/sphincsplus_rust/Cargo.toml b/tests/sphincsplus_rust/Cargo.toml index bec5f9c..fc2f384 100644 --- a/tests/sphincsplus_rust/Cargo.toml +++ b/tests/sphincsplus_rust/Cargo.toml @@ -21,6 +21,7 @@ hash_options_s = ["ckb_sphincs_utils/hash_options_s"] thashes_robust = ["ckb_sphincs_utils/thashes_robust"] thashes_simple = ["ckb_sphincs_utils/thashes_simple"] +serialize_key = ["ckb_sphincs_utils/serialize_key", "dep:clap", "dep:base64"] [dependencies] ckb_sphincs_utils = { path = "../../tools/ckb-sphincs-utils", default-features = false } @@ -33,3 +34,14 @@ lazy_static = "1.4.0" libc = "0.2.139" num_enum = "0.5.10" rand = "0.8.5" +clap = { version = "4.3.2", optional = true } +base64 = { version = "0.22.0", optional = true } + + +[[bin]] +name = "generate_fix_infos" +required-features = ["serialize_key"] + +[[bin]] +name = "run_brenchmark" +required-features = ["serialize_key"] diff --git a/tests/sphincsplus_rust/run_benchmark.sh b/tests/sphincsplus_rust/run_benchmark.sh new file mode 100755 index 0000000..b2e5110 --- /dev/null +++ b/tests/sphincsplus_rust/run_benchmark.sh @@ -0,0 +1,57 @@ +if [ ! -n "$1" ] ;then + HASH_NAME="shake" + HASH_SIZE="256" + THASH="robust" + HASH_OPTION="f" +else + HASH_NAME=$1 + HASH_SIZE=$2 + THASH=$3 + HASH_OPTION=$4 +fi +PARAMS="sphincs-$HASH_NAME-$HASH_SIZE$HASH_OPTION" + +#!/bin/bash +workdir=$( + cd $(dirname $0)/../../ + pwd +) + +export BENCH_ARGS=`./target/debug/generate_fix_infos` + +cd $workdir +rm -rf build/* +mkdir -p build +make -f Makefile.clang all PARAMS=$PARAMS THASH=$THASH +if (($? == 0)); then + echo "make success" +else + exit 1 +fi +cd $workdir/tests/sphincsplus_rust +cargo clean +cargo build --no-default-features --features "serialize_key $HASH_NAME hash_$HASH_SIZE hash_options_$HASH_OPTION thashes_$THASH" +./target/debug/run_brenchmark $BENCH_ARGS +if (($? == 0)); then + echo "success" +else + exit 1 +fi + +cd $workdir +rm -rf build/* +mkdir -p build +make all-via-docker PARAMS=$PARAMS THASH=$THASH +if (($? == 0)); then + echo "make success" +else + exit 1 +fi +cd $workdir/tests/sphincsplus_rust +cargo build --no-default-features --features "serialize_key $HASH_NAME hash_$HASH_SIZE hash_options_$HASH_OPTION thashes_$THASH" +./target/debug/run_brenchmark $BENCH_ARGS +if (($? == 0)); then + echo "success" +else + exit 1 +fi diff --git a/tests/sphincsplus_rust/run_rust_with_clang.sh b/tests/sphincsplus_rust/run_rust_with_clang.sh new file mode 100755 index 0000000..06eb1f9 --- /dev/null +++ b/tests/sphincsplus_rust/run_rust_with_clang.sh @@ -0,0 +1,39 @@ +if [ ! -n "$1" ] ;then + HASH_NAME="shake" + HASH_SIZE="256" + THASH="robust" + HASH_OPTION="f" +else + HASH_NAME=$1 + HASH_SIZE=$2 + THASH=$3 + HASH_OPTION=$4 +fi +PARAMS="sphincs-$HASH_NAME-$HASH_SIZE$HASH_OPTION" + +#!/bin/bash +workdir=$( + cd $(dirname $0)/../../ + pwd +) + +cd $workdir + +rm -rf build/* +mkdir -p build + +make -f Makefile.clang all PARAMS=$PARAMS THASH=$THASH +if (($? == 0)); then + echo "make success" +else + exit 1 +fi + +cd tests/sphincsplus_rust +cargo clean +cargo test --no-default-features --features "$HASH_NAME hash_$HASH_SIZE hash_options_$HASH_OPTION thashes_$THASH" +if (($? == 0)); then + echo "success" +else + exit 1 +fi diff --git a/tests/sphincsplus_rust/src/bin/generate_fix_infos.rs b/tests/sphincsplus_rust/src/bin/generate_fix_infos.rs new file mode 100644 index 0000000..8060729 --- /dev/null +++ b/tests/sphincsplus_rust/src/bin/generate_fix_infos.rs @@ -0,0 +1,17 @@ +use ckb_sphincs_utils::SphincsPlus; +use sphincsplus_rust_test::dummy_data_loader::DummyDataLoader; +use sphincsplus_rust_test::utils::*; + +fn main() { + let key: SphincsPlus = SphincsPlus::new(); + print!("--key {} ", key.serialize_key()); + + let mut config = TestConfig::new_with_key(key); + config.print_sign = true; + config.fixed_rand = true; + + let mut dummy = DummyDataLoader::new(); + + let tx = gen_tx(&mut dummy, &mut config); + sign_tx(&mut dummy, tx, &mut config); +} diff --git a/tests/sphincsplus_rust/src/bin/run_brenchmark.rs b/tests/sphincsplus_rust/src/bin/run_brenchmark.rs new file mode 100644 index 0000000..1295a64 --- /dev/null +++ b/tests/sphincsplus_rust/src/bin/run_brenchmark.rs @@ -0,0 +1,43 @@ +use ckb_script::TransactionScriptsVerifier; +use ckb_sphincs_utils::SphincsPlus; +use ckb_types::packed::Byte32; +use clap::{arg, Command}; +use sphincsplus_rust_test::dummy_data_loader::DummyDataLoader; +use sphincsplus_rust_test::utils::*; + +pub fn debug_printer(_script: &Byte32, msg: &str) { + print!("{}", msg); +} + +pub const MAX_CYCLES: u64 = std::u64::MAX; + +fn main() { + let args = Command::new("run brenchmark") + .arg(arg!(--key "sphincsplus keys")) + .arg(arg!(--sign "sphincsplus sign")) + .get_matches(); + let args_key = args.get_one::("key").unwrap(); + + use base64::prelude::*; + let args_sign = BASE64_STANDARD + .decode(args.get_one::("sign").unwrap()) + .unwrap(); + + let mut config = TestConfig::new_with_key(SphincsPlus::deserialize_key(args_key)); + config.print_time = true; + config.fixed_rand = true; + config.sign = Some(args_sign); + + let mut dummy = DummyDataLoader::new(); + + let tx = gen_tx(&mut dummy, &mut config); + let tx = sign_tx(&mut dummy, tx, &mut config); + + let resolved_tx = build_resolved_tx(&dummy, &tx); + let mut verifier = TransactionScriptsVerifier::new(&resolved_tx, &dummy); + + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + let res = verify_result.expect("pass verification"); + println!("cycles: {} ({:.2?}M)", res, (res as f64) / 1024.0 / 1024.0); +} diff --git a/tests/sphincsplus_rust/src/utils.rs b/tests/sphincsplus_rust/src/utils.rs index a46be72..7b2b484 100644 --- a/tests/sphincsplus_rust/src/utils.rs +++ b/tests/sphincsplus_rust/src/utils.rs @@ -1,6 +1,6 @@ use super::dummy_data_loader::DummyDataLoader; -use ckb_sphincs_utils::sphincsplus::*; use ckb_hash::blake2b_256; +use ckb_sphincs_utils::sphincsplus::*; use ckb_types::core::{ cell::{CellMetaBuilder, ResolvedTransaction}, TransactionView, @@ -31,6 +31,10 @@ pub struct TestConfig { pub message_error: bool, rng: ThreadRng, pub print_time: bool, + pub print_sign: bool, + pub fixed_rand: bool, + rng_count: usize, + pub sign: Option>, } impl TestConfig { @@ -43,6 +47,27 @@ impl TestConfig { message_error: false, rng: thread_rng(), print_time: false, + print_sign: false, + fixed_rand: false, + rng_count: 0, + sign: None, + } + } + + #[cfg(feature = "serialize_key")] + pub fn new_with_key(key: SphincsPlus) -> Self { + Self { + key, + sign_error: false, + pubkey_hash_error: false, + pubkey_error: false, + message_error: false, + rng: thread_rng(), + print_time: false, + print_sign: false, + fixed_rand: false, + rng_count: 0, + sign: None, } } @@ -50,8 +75,14 @@ impl TestConfig { let mut buf = Vec::::with_capacity(len); buf.resize(len, 0); - self.rng.fill(buf.as_mut_slice()); - + if !self.fixed_rand { + self.rng.fill(buf.as_mut_slice()); + } else { + for i in buf.iter_mut() { + *i = self.rng_count as u8; + } + self.rng_count += 1; + } buf } } @@ -196,13 +227,27 @@ pub fn sign_tx_by_input_group( let mut witness_buf = Vec::new(); witness_buf.resize(sign_info_len, 0); - witness_buf[..config.key.get_sign_len()].copy_from_slice( - &if config.sign_error { + witness_buf[..config.key.get_sign_len()].copy_from_slice(&if config + .sign + .is_none() + { + if config.sign_error { config.gen_rand_buf(config.key.get_sign_len()) } else { - config.key.sign(&message) - }, - ); + config.key.sign(&message).to_vec() + } + } else { + config.sign.as_ref().unwrap().to_vec() + }); + + #[cfg(feature = "serialize_key")] + if config.print_sign { + use base64::prelude::*; + print!( + "--sign {}", + BASE64_STANDARD.encode(&witness_buf[..config.key.get_sign_len()]) + ) + } witness_buf[config.key.get_sign_len()..].copy_from_slice( &if config.pubkey_error { diff --git a/tools/ckb-sphincs-utils/Cargo.lock b/tools/ckb-sphincs-utils/Cargo.lock index cb02785..2cc2f6c 100644 --- a/tools/ckb-sphincs-utils/Cargo.lock +++ b/tools/ckb-sphincs-utils/Cargo.lock @@ -2,15 +2,22 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "base64" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" + [[package]] name = "cc" -version = "1.0.79" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" [[package]] name = "ckb_sphincs_utils" version = "0.1.0" dependencies = [ + "base64", "cc", ] diff --git a/tools/ckb-sphincs-utils/Cargo.toml b/tools/ckb-sphincs-utils/Cargo.toml index 2179df5..6e1bb39 100644 --- a/tools/ckb-sphincs-utils/Cargo.toml +++ b/tools/ckb-sphincs-utils/Cargo.toml @@ -21,7 +21,10 @@ hash_options_s = [] thashes_robust = [] thashes_simple = [] +serialize_key = ["dep:base64"] + [dependencies] +base64 = { version = "0.22.0", optional = true } [build-dependencies] cc = "1.0.79" diff --git a/tools/ckb-sphincs-utils/src/lib.rs b/tools/ckb-sphincs-utils/src/lib.rs index 45e742e..2faf3ee 100644 --- a/tools/ckb-sphincs-utils/src/lib.rs +++ b/tools/ckb-sphincs-utils/src/lib.rs @@ -1,3 +1,3 @@ pub mod sphincsplus; -pub use sphincsplus::SphincsPlus; +pub use sphincsplus::SphincsPlus; \ No newline at end of file diff --git a/tools/ckb-sphincs-utils/src/sphincsplus.rs b/tools/ckb-sphincs-utils/src/sphincsplus.rs index ee81a5a..9a748f8 100644 --- a/tools/ckb-sphincs-utils/src/sphincsplus.rs +++ b/tools/ckb-sphincs-utils/src/sphincsplus.rs @@ -64,6 +64,35 @@ impl SphincsPlus { s } + #[cfg(feature = "serialize_key")] + pub fn deserialize_key(s: &str) -> Self { + use base64::prelude::*; + let buf = BASE64_STANDARD.decode(s).expect("decode base64"); + + let pk_len = unsafe { sphincs_plus_get_pk_size() as usize }; + let sk_len = unsafe { sphincs_plus_get_sk_size() as usize }; + assert_eq!(buf.len(), pk_len + sk_len); + + Self { + pk: buf[0..pk_len].to_vec(), + sk: buf[pk_len..].to_vec(), + } + } + + #[cfg(feature = "serialize_key")] + pub fn serialize_key(&self) -> String { + let buf_len = self.pk.len() + self.sk.len(); + let mut buf = Vec::with_capacity(buf_len); + + buf.resize(buf_len, 0); + + buf[0..self.pk.len()].copy_from_slice(&self.pk); + buf[self.pk.len()..].copy_from_slice(&self.sk); + + use base64::prelude::*; + BASE64_STANDARD.encode(&buf) + } + pub fn sign(&self, msg: &[u8]) -> Vec { let mut s = Vec::new(); s.resize(self.get_sign_len(), 0);