Merge remote-tracking branch 'origin/main' into add-redpallas
This commit is contained in:
commit
3d9b8e30b3
|
@ -23,7 +23,7 @@ jobs:
|
|||
RUST_BACKTRACE: full
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.5.3
|
||||
- uses: actions/checkout@v4.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.5.3
|
||||
- uses: actions/checkout@v4.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
@ -50,7 +50,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.5.3
|
||||
- uses: actions/checkout@v4.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
@ -71,7 +71,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v3.5.3
|
||||
- uses: actions/checkout@v4.0.0
|
||||
- uses: reviewdog/action-actionlint@v1.37.1
|
||||
with:
|
||||
level: warning
|
||||
|
|
|
@ -4,9 +4,9 @@ version = 3
|
|||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
|
||||
checksum = "86b8f9420f797f2d9e935edf629310eb938a0d839f984e25327f3c7eed22300c"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
@ -70,9 +70,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.3.3"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
|
||||
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
|
@ -137,9 +137,12 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||
checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
|
@ -176,18 +179,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.3.15"
|
||||
version = "4.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f644d0dac522c8b05ddc39aaaccc5b136d5dc4ff216610c5641e3be5becf56c"
|
||||
checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.3.15"
|
||||
version = "4.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af410122b9778e024f9e0fb35682cc09cc3f85cad5e8d3ba8f47a9702df6e73d"
|
||||
checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
|
@ -344,7 +347,7 @@ checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -392,15 +395,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.1"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
|
||||
checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
|
@ -435,12 +438,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.9.0"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
|
||||
|
||||
[[package]]
|
||||
name = "ff"
|
||||
|
@ -594,26 +594,6 @@ version = "0.3.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.9"
|
||||
|
@ -621,7 +601,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"rustix 0.38.4",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
|
@ -692,15 +672,9 @@ checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
|
|||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.8"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0"
|
||||
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
|
@ -725,9 +699,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"libm",
|
||||
|
@ -866,9 +840,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.31"
|
||||
version = "1.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0"
|
||||
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
@ -969,9 +943,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.9.1"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
|
||||
checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
|
@ -981,9 +955,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.3.3"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
|
||||
checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
|
@ -1013,28 +987,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.37.23"
|
||||
version = "0.38.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
|
||||
checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"errno",
|
||||
"io-lifetimes",
|
||||
"libc",
|
||||
"linux-raw-sys 0.3.8",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5"
|
||||
dependencies = [
|
||||
"bitflags 2.3.3",
|
||||
"bitflags 2.4.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.3",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
|
@ -1079,29 +1039,29 @@ checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.171"
|
||||
version = "1.0.183"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9"
|
||||
checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.171"
|
||||
version = "1.0.183"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682"
|
||||
checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.103"
|
||||
version = "1.0.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b"
|
||||
checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
|
@ -1154,9 +1114,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.26"
|
||||
version = "2.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970"
|
||||
checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1171,36 +1131,35 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
|||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.6.0"
|
||||
version = "3.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6"
|
||||
checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"redox_syscall",
|
||||
"rustix 0.37.23",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.43"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42"
|
||||
checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.43"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f"
|
||||
checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1308,7 +1267,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"syn 2.0.28",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
@ -1330,7 +1289,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"syn 2.0.28",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
@ -1474,5 +1433,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
|
23
README.md
23
README.md
|
@ -1,7 +1,5 @@
|
|||
# Zcash Foundation FROST Demos
|
||||
|
||||
TODO
|
||||
|
||||
This will be part of a set of demos and a proof of concept application that uses the FROST libraries and reference implementation. The purpose of these demos is to:
|
||||
|
||||
1. identify gaps in our documentation
|
||||
|
@ -18,9 +16,20 @@ schemes in general assume that an adversary can corrupt strictly fewer than a th
|
|||
[Two-Round Threshold Schnorr Signatures with FROST](https://datatracker.ietf.org/doc/draft-irtf-cfrg-frost/) presents a variant of a Flexible Round-Optimized Schnorr Threshold (FROST) signature scheme originally defined in [FROST20](https://eprint.iacr.org/2020/852.pdf). FROST reduces network overhead during threshold
|
||||
signing operations while employing a novel technique to protect against forgery attacks applicable to prior Schnorr-based threshold signature constructions. This variant of FROST requires two rounds to compute a signature, and implements signing efficiency improvements described by [Schnorr21](https://eprint.iacr.org/2021/1375.pdf). Single-round signing with FROST is not implemented here.
|
||||
|
||||
## Projects
|
||||
|
||||
This repo contains 4 projects:
|
||||
1. [Trusted Dealer](https://github.com/ZcashFoundation/frost-zcash-demo/tree/main/trusted-dealer)
|
||||
2. [DKG](https://github.com/ZcashFoundation/frost-zcash-demo/tree/main/dkg)
|
||||
3. [Coordinator](https://github.com/ZcashFoundation/frost-zcash-demo/tree/main/coordinator)
|
||||
4. [Participant](https://github.com/ZcashFoundation/frost-zcash-demo/tree/main/participant)
|
||||
|
||||
## Status ⚠
|
||||
|
||||
TODO
|
||||
Trusted Dealer demo - WIP
|
||||
DKG demo - WIP
|
||||
Coordinator demo - WIP
|
||||
Participant demo - WIP
|
||||
|
||||
## Usage
|
||||
|
||||
|
@ -31,11 +40,13 @@ You will need to have [Rust and Cargo](https://doc.rust-lang.org/cargo/getting-s
|
|||
To run:
|
||||
1. Clone the repo. Run `git clone https://github.com/ZcashFoundation/frost-zcash-demo.git`
|
||||
2. Run `cargo install`
|
||||
3. Run `cargo run`
|
||||
|
||||
## Developer information
|
||||
and in separate terminals:
|
||||
3. Run `cargo run --bin trusted-dealer` or `cargo run --bin dkg`
|
||||
4. Run `cargo run --bin coordinator`
|
||||
5. Run `cargo run --bin participants`. Do this in separate terminals for separate participants.
|
||||
|
||||
TODO
|
||||
## Developer Information
|
||||
|
||||
### Pre-commit checks
|
||||
|
||||
|
|
|
@ -1,22 +1,6 @@
|
|||
# FROST Coordinator Demo
|
||||
|
||||
TODO
|
||||
|
||||
This will be part of a set of demos and a proof of concept application that uses the FROST libraries and reference implementation. The purpose of these demos is to:
|
||||
|
||||
1. identify gaps in our documentation
|
||||
2. provide usage examples for developer facing documentation
|
||||
3. provide reference implementations for developers wanting to use FROST in a “real world” scenario.
|
||||
|
||||
This demo uses the (Ed25519, SHA-512) ciphersuite. The crate can be found [here](https://crates.io/crates/frost-ed25519).
|
||||
|
||||
## About FROST (Flexible Round-Optimised Schnorr Threshold signatures)
|
||||
|
||||
Unlike signatures in a single-party setting, threshold signatures require cooperation among a threshold number of signers, each holding a share of a common private key. The security of threshold
|
||||
schemes in general assume that an adversary can corrupt strictly fewer than a threshold number of participants.
|
||||
|
||||
[Two-Round Threshold Schnorr Signatures with FROST](https://datatracker.ietf.org/doc/draft-irtf-cfrg-frost/) presents a variant of a Flexible Round-Optimized Schnorr Threshold (FROST) signature scheme originally defined in [FROST20](https://eprint.iacr.org/2020/852.pdf). FROST reduces network overhead during threshold
|
||||
signing operations while employing a novel technique to protect against forgery attacks applicable to prior Schnorr-based threshold signature constructions. This variant of FROST requires two rounds to compute a signature, and implements signing efficiency improvements described by [Schnorr21](https://eprint.iacr.org/2021/1375.pdf). Single-round signing with FROST is not implemented here.
|
||||
[Overview of demos](https://github.com/ZcashFoundation/frost-zcash-demo/blob/main/README.md)
|
||||
|
||||
## Status ⚠
|
||||
|
||||
|
@ -31,18 +15,51 @@ You will need to have [Rust and Cargo](https://doc.rust-lang.org/cargo/getting-s
|
|||
To run:
|
||||
1. Clone the repo. Run `git clone https://github.com/ZcashFoundation/frost-zcash-demo.git`
|
||||
2. Run `cargo install`
|
||||
3. Run `cargo run`
|
||||
3. Run `cargo run --bin coordinator`
|
||||
|
||||
TODO
|
||||
### Step 1
|
||||
|
||||
## Using the output
|
||||
The coordinator CLI will prompt for:
|
||||
|
||||
TODO
|
||||
1. The public key package
|
||||
2. The number of signers participating and their corresponding identifiers
|
||||
|
||||
### Communication round
|
||||
|
||||
Each participant will send their commitments
|
||||
|
||||
### Step 2
|
||||
|
||||
The coordinator CLI will prompt for:
|
||||
|
||||
1. A message
|
||||
2. The commitments for each participant
|
||||
|
||||
The coordinator CLI will then use that data to generate:
|
||||
|
||||
1. Signing package
|
||||
|
||||
### Communication round
|
||||
|
||||
The signing package will be sent to all participants
|
||||
The coordinator will receive each participant's signature shares
|
||||
|
||||
### Step 3
|
||||
|
||||
The coordinator CLI will prompt for:
|
||||
|
||||
1. Signature shares for ecah participant
|
||||
|
||||
The coordinator CLI will then use that data to generate:
|
||||
|
||||
1. The group signature
|
||||
|
||||
### Communication round
|
||||
|
||||
The group signature will then be sent to all participants
|
||||
|
||||
## Developer information
|
||||
|
||||
TODO
|
||||
|
||||
### Pre-commit checks
|
||||
|
||||
1. Run `cargo make all`
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// use rand::thread_rng;
|
||||
// use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
// // #[test]
|
||||
// #[test]
|
||||
// fn check_keygen_with_dealer() {
|
||||
// let mut rng = thread_rng();
|
||||
// let (shares, pubkeys) =
|
||||
|
@ -17,7 +17,7 @@
|
|||
// let (nonces, commitments) = round_1(2, &mut rng, &key_packages);
|
||||
// let message = "i am a message".as_bytes();
|
||||
|
||||
// let signing_packages = step_2()
|
||||
// let signing_packages = step_2();
|
||||
|
||||
// let signature_shares = round_2(nonces, &key_packages, signing_packages);
|
||||
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
# FROST DKG Demo
|
||||
|
||||
[Overview of demos](https://github.com/ZcashFoundation/frost-zcash-demo/blob/main/README.md)
|
||||
|
||||
## Status ⚠
|
||||
|
||||
The DKG Demo is a WIP
|
||||
|
||||
## Usage
|
||||
|
||||
NOTE: This is for demo purposes only and should not be used in production.
|
||||
|
||||
You will need to have [Rust and Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) installed.
|
||||
|
||||
To run:
|
||||
1. Clone the repo. Run `git clone https://github.com/ZcashFoundation/frost-zcash-demo.git`
|
||||
2. Run `cargo install`
|
||||
3. Run `cargo run --bin dkg`
|
||||
|
||||
### Round 1 send package
|
||||
|
||||
The DKG demo will prompt for:
|
||||
|
||||
1. Minimum number of signers (>= 2) i.e. The threshold number of signers for the secret sharing scheme.
|
||||
2. Maximum number of signers i.e. the number of shares to generate
|
||||
3. An identifier
|
||||
|
||||
The dkg CLI will then use that data to generate:
|
||||
|
||||
1. A round 1 package to send to all other signers
|
||||
|
||||
### Round 2 send packages
|
||||
|
||||
The DKG demo will prompt for:
|
||||
|
||||
1. Identifiers of all signers
|
||||
2. Their corresponding round 1 package
|
||||
|
||||
The dkg CLI will then use that data to generate:
|
||||
|
||||
1. A round 2 package to send to other users
|
||||
|
||||
### Round 2 receive packages
|
||||
|
||||
The DKG demo will prompt for:
|
||||
|
||||
1. Identifiers of all signers
|
||||
2. Their corresponding round 2 package
|
||||
|
||||
The dkg CLI will then use that data to generate:
|
||||
|
||||
1. A key package
|
||||
2. A public key package
|
||||
|
||||
## Using the output
|
||||
|
||||
To generate a key package the participant requires:
|
||||
|
||||
* The signer's identifier
|
||||
* The signer's secret share
|
||||
* The signer's public key
|
||||
* The public signing key that represents the entire group
|
||||
|
||||
## Developer information
|
||||
|
||||
### Pre-commit checks
|
||||
|
||||
1. Run `cargo make all`
|
||||
|
||||
### Coverage
|
||||
|
||||
Test coverage checks are performed in the pipeline. This is configured here: `.github/workflows/coverage.yaml`
|
||||
To run these locally:
|
||||
1. Install coverage tool by running `cargo install cargo-llvm-cov`
|
||||
2. Run `cargo make cov` (you may be asked if you want to install `llvm-tools-preview`, if so type `Y`)
|
|
@ -1,22 +1,6 @@
|
|||
# FROST Participant Demo
|
||||
|
||||
TODO
|
||||
|
||||
This will be part of a set of demos and a proof of concept application that uses the FROST libraries and reference implementation. The purpose of these demos is to:
|
||||
|
||||
1. identify gaps in our documentation
|
||||
2. provide usage examples for developer facing documentation
|
||||
3. provide reference implementations for developers wanting to use FROST in a “real world” scenario.
|
||||
|
||||
This demo uses the (Ed25519, SHA-512) ciphersuite. The crate can be found [here](https://crates.io/crates/frost-ed25519).
|
||||
|
||||
## About FROST (Flexible Round-Optimised Schnorr Threshold signatures)
|
||||
|
||||
Unlike signatures in a single-party setting, threshold signatures require cooperation among a threshold number of signers, each holding a share of a common private key. The security of threshold
|
||||
schemes in general assume that an adversary can corrupt strictly fewer than a threshold number of participants.
|
||||
|
||||
[Two-Round Threshold Schnorr Signatures with FROST](https://datatracker.ietf.org/doc/draft-irtf-cfrg-frost/) presents a variant of a Flexible Round-Optimized Schnorr Threshold (FROST) signature scheme originally defined in [FROST20](https://eprint.iacr.org/2020/852.pdf). FROST reduces network overhead during threshold
|
||||
signing operations while employing a novel technique to protect against forgery attacks applicable to prior Schnorr-based threshold signature constructions. This variant of FROST requires two rounds to compute a signature, and implements signing efficiency improvements described by [Schnorr21](https://eprint.iacr.org/2021/1375.pdf). Single-round signing with FROST is not implemented here.
|
||||
[Overview of demos](https://github.com/ZcashFoundation/frost-zcash-demo/blob/main/README.md)
|
||||
|
||||
## Status ⚠
|
||||
|
||||
|
@ -31,18 +15,41 @@ You will need to have [Rust and Cargo](https://doc.rust-lang.org/cargo/getting-s
|
|||
To run:
|
||||
1. Clone the repo. Run `git clone https://github.com/ZcashFoundation/frost-zcash-demo.git`
|
||||
2. Run `cargo install`
|
||||
3. Run `cargo run`
|
||||
3. Run `cargo run --bin participant`
|
||||
|
||||
TODO
|
||||
### Round 1
|
||||
|
||||
## Using the output
|
||||
The participant CLI will prompt for:
|
||||
|
||||
TODO
|
||||
1. Your secret share or key package
|
||||
|
||||
The participant CLI will then use that data to generate:
|
||||
|
||||
1. Signing nonces
|
||||
2. Signing commitments
|
||||
|
||||
### Communication round
|
||||
|
||||
The signing commitments will be sent to the coordinator
|
||||
The coordinator will then send the signing package
|
||||
|
||||
### Round 2
|
||||
|
||||
The participant CLI will prompt for:
|
||||
|
||||
1. Signing package
|
||||
|
||||
The participant CLI will then use that data to generate:
|
||||
|
||||
1. Signature share
|
||||
|
||||
### Communication round
|
||||
|
||||
The signature share will be sent to the coordinator
|
||||
The coordinator will then send the Group signature
|
||||
|
||||
## Developer information
|
||||
|
||||
TODO
|
||||
|
||||
### Pre-commit checks
|
||||
|
||||
1. Run `cargo make all`
|
||||
|
|
|
@ -19,10 +19,6 @@ pub struct Round1Config {
|
|||
pub key_package: KeyPackage,
|
||||
}
|
||||
|
||||
// pub trait Logger {
|
||||
// fn log(&mut self, value: String);
|
||||
// }
|
||||
|
||||
// TODO: refactor to generate config
|
||||
pub fn request_inputs(
|
||||
input: &mut impl BufRead,
|
||||
|
@ -35,7 +31,7 @@ pub fn request_inputs(
|
|||
input.read_line(&mut json).unwrap();
|
||||
|
||||
let key_package = if let Ok(secret_share) = serde_json::from_str::<SecretShare>(&json) {
|
||||
KeyPackage::try_from(secret_share.clone())?
|
||||
KeyPackage::try_from(secret_share)?
|
||||
} else {
|
||||
// TODO: Improve error
|
||||
serde_json::from_str::<KeyPackage>(&json).map_err(|_| Error::InvalidSecretShare)?
|
||||
|
|
|
@ -1,153 +1,119 @@
|
|||
// #[cfg(test)]
|
||||
// use frost::Identifier;
|
||||
// use frost::{
|
||||
// keys::{
|
||||
// KeyPackage, SecretShare, SigningShare, VerifiableSecretSharingCommitment, VerifyingShare,
|
||||
// },
|
||||
// VerifyingKey,
|
||||
// };
|
||||
// use frost_ed25519 as frost;
|
||||
// use hex::FromHex;
|
||||
// use participant::round1::{request_inputs, Round1Config};
|
||||
#[cfg(test)]
|
||||
use frost::Identifier;
|
||||
use frost::{
|
||||
keys::{KeyPackage, SigningShare, VerifyingShare},
|
||||
round1, VerifyingKey,
|
||||
};
|
||||
use frost_ed25519 as frost;
|
||||
use hex::FromHex;
|
||||
use participant::round1::{print_values, request_inputs, Round1Config};
|
||||
|
||||
// use participant::Logger;
|
||||
use participant::Logger;
|
||||
use rand::thread_rng;
|
||||
|
||||
// const PUBLIC_KEY: &str = "adf6ab1f882d04988eadfaa52fb175bf37b6247785d7380fde3fb9d68032470d";
|
||||
// const GROUP_PUBLIC_KEY: &str = "087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e";
|
||||
// const SIGNING_SHARE: &str = "ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104";
|
||||
// const VSS_COMMITMENT: [&str; 3] = [
|
||||
// "087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e",
|
||||
// "926d5910e146dccb9148ca39dc7607f4f7123ff1c0ffaf109add1d165c568bf2",
|
||||
// "291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc",
|
||||
// ];
|
||||
// const SECRET_SHARE_JSON: &str = r#"{"identifier":"0100000000000000000000000000000000000000000000000000000000000000","value":"ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104","commitment":["087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e","926d5910e146dccb9148ca39dc7607f4f7123ff1c0ffaf109add1d165c568bf2", "291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc"],"ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
const PUBLIC_KEY: &str = "adf6ab1f882d04988eadfaa52fb175bf37b6247785d7380fde3fb9d68032470d";
|
||||
const GROUP_PUBLIC_KEY: &str = "087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e";
|
||||
const SIGNING_SHARE: &str = "ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104";
|
||||
const SECRET_SHARE_JSON: &str = r#"{"identifier":"0100000000000000000000000000000000000000000000000000000000000000","value":"ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104","commitment":["087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e","926d5910e146dccb9148ca39dc7607f4f7123ff1c0ffaf109add1d165c568bf2", "291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc"],"ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
|
||||
// pub struct TestLogger(Vec<String>);
|
||||
pub struct TestLogger(Vec<String>);
|
||||
|
||||
// impl Logger for TestLogger {
|
||||
// fn log(&mut self, value: String) {
|
||||
// self.0.push(value);
|
||||
// }
|
||||
// }
|
||||
impl Logger for TestLogger {
|
||||
fn log(&mut self, value: String) {
|
||||
self.0.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn check_valid_round_1_inputs() {
|
||||
// let config = Round1Config {
|
||||
// secret_share: SecretShare::new(
|
||||
// Identifier::try_from(1).unwrap(),
|
||||
// SigningShare::deserialize(<[u8; 32]>::from_hex(SIGNING_SHARE).unwrap()).unwrap(),
|
||||
// VerifiableSecretSharingCommitment::deserialize(
|
||||
// VSS_COMMITMENT
|
||||
// .iter()
|
||||
// .map(|s| hex::decode(s).unwrap().try_into().unwrap())
|
||||
// .collect(),
|
||||
// )
|
||||
// .unwrap(),
|
||||
// ),
|
||||
// };
|
||||
fn build_key_package() -> KeyPackage {
|
||||
KeyPackage::new(
|
||||
Identifier::try_from(1).unwrap(),
|
||||
SigningShare::deserialize(<[u8; 32]>::from_hex(SIGNING_SHARE).unwrap()).unwrap(),
|
||||
VerifyingShare::deserialize(<[u8; 32]>::from_hex(PUBLIC_KEY).unwrap()).unwrap(),
|
||||
VerifyingKey::from_hex(GROUP_PUBLIC_KEY).unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
// let mut test_logger = TestLogger(Vec::new());
|
||||
#[test]
|
||||
fn check_valid_round_1_inputs() {
|
||||
let config = Round1Config {
|
||||
key_package: build_key_package(),
|
||||
};
|
||||
|
||||
// let input = SECRET_SHARE_JSON;
|
||||
// let mut valid_input = input.as_bytes();
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
|
||||
// let expected = request_inputs(&mut valid_input, &mut test_logger).unwrap();
|
||||
let input = SECRET_SHARE_JSON;
|
||||
let mut valid_input = input.as_bytes();
|
||||
|
||||
// assert_eq!(expected, config);
|
||||
// }
|
||||
let expected = request_inputs(&mut valid_input, &mut test_logger).unwrap();
|
||||
|
||||
// #[test]
|
||||
// fn check_0_input_for_identifier() {
|
||||
// let mut test_logger = TestLogger(Vec::new());
|
||||
assert_eq!(expected, config);
|
||||
}
|
||||
|
||||
// let input = r#"{"identifier":"0000000000000000000000000000000000000000000000000000000000000000","value":"ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104","commitment":["087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e","291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc"],"ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
// let mut invalid_input = input.as_bytes();
|
||||
#[test]
|
||||
fn check_0_input_for_identifier() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
|
||||
// let expected = request_inputs(&mut invalid_input, &mut test_logger);
|
||||
let input = r#"{"identifier":"0000000000000000000000000000000000000000000000000000000000000000","value":"ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104","commitment":["087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e","291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc"],"ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
let mut invalid_input = input.as_bytes();
|
||||
|
||||
// assert!(expected.is_err());
|
||||
// }
|
||||
let expected = request_inputs(&mut invalid_input, &mut test_logger);
|
||||
|
||||
// #[test]
|
||||
// fn check_invalid_length_signing_share() {
|
||||
// let mut test_logger = TestLogger(Vec::new());
|
||||
assert!(expected.is_err());
|
||||
}
|
||||
|
||||
// let input = r#"{"identifier":"0100000000000000000000000000000000000000000000000000000000000000","value":"ed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104","commitment":["087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e","291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc"],"ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
#[test]
|
||||
fn check_invalid_length_signing_share() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
|
||||
// let mut invalid_input = input.as_bytes();
|
||||
let input = r#"{"identifier":"0100000000000000000000000000000000000000000000000000000000000000","value":"ed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104","commitment":["087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e","291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc"],"ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
|
||||
// let expected = request_inputs(&mut invalid_input, &mut test_logger);
|
||||
let mut invalid_input = input.as_bytes();
|
||||
|
||||
// assert!(expected.is_err());
|
||||
// }
|
||||
let expected = request_inputs(&mut invalid_input, &mut test_logger);
|
||||
|
||||
// // TODO: Handle this error differently
|
||||
// #[test]
|
||||
// fn check_invalid_length_vss_commitment() {
|
||||
// let mut test_logger = TestLogger(Vec::new());
|
||||
assert!(expected.is_err());
|
||||
}
|
||||
|
||||
// let input = r#"{"identifier":"0100000000000000000000000000000000000000000000000000000000000000","value":"ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104","commitment":["7e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e","291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc"],"ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
#[test]
|
||||
fn check_invalid_round_1_inputs() {
|
||||
let input = r#"{"value":"ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104","commitment":["087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e","926d5910e146dccb9148ca39dc7607f4f7123ff1c0ffaf109add1d165c568bf2", "291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc"],"ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
|
||||
// let mut invalid_input = input.as_bytes();
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
|
||||
// let expected = request_inputs(&mut invalid_input, &mut test_logger);
|
||||
// assert!(expected.is_err())
|
||||
// }
|
||||
let mut valid_input = input.as_bytes();
|
||||
|
||||
// #[test]
|
||||
// fn check_key_package_generation() {
|
||||
// let config = Round1Config {
|
||||
// secret_share: serde_json::from_str(SECRET_SHARE_JSON).unwrap(),
|
||||
// };
|
||||
let expected = request_inputs(&mut valid_input, &mut test_logger);
|
||||
assert!(expected.is_err());
|
||||
}
|
||||
|
||||
// let expected = KeyPackage::new(
|
||||
// Identifier::try_from(1).unwrap(),
|
||||
// SigningShare::deserialize(<[u8; 32]>::from_hex(SIGNING_SHARE).unwrap()).unwrap(),
|
||||
// VerifyingShare::deserialize(<[u8; 32]>::from_hex(PUBLIC_KEY).unwrap()).unwrap(),
|
||||
// VerifyingKey::from_hex(GROUP_PUBLIC_KEY).unwrap(),
|
||||
// );
|
||||
// let key_package = generate_key_package(&config).unwrap();
|
||||
// TODO: Handle this error differently
|
||||
#[test]
|
||||
fn check_invalid_length_vss_commitment() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
|
||||
// assert!(expected == key_package)
|
||||
// }
|
||||
let input = r#"{"identifier":"0100000000000000000000000000000000000000000000000000000000000000","value":"ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104","commitment":["7e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e","291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc"],"ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
|
||||
// #[test]
|
||||
// fn check_key_package_generation_fails_with_invalid_secret_share() {
|
||||
// let input = r#"{"identifier":"0100000000000000000000000000000000000000000000000000000000000000","value":"afc0ba51fd450297725f9efe714400d51a1180a273177b5dd8ad3b8cba41560d","commitment":["087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e","291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc"],"ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
// let config = Round1Config {
|
||||
// secret_share: serde_json::from_str(input).unwrap(),
|
||||
// };
|
||||
// let key_package = generate_key_package(&config);
|
||||
// assert!(key_package.is_err());
|
||||
// }
|
||||
let mut invalid_input = input.as_bytes();
|
||||
|
||||
// #[test]
|
||||
// fn check_print_values() {
|
||||
// let mut test_logger = TestLogger(Vec::new());
|
||||
// let signing_share =
|
||||
// SigningShare::deserialize(<[u8; 32]>::from_hex(SIGNING_SHARE).unwrap()).unwrap();
|
||||
// let mut rng = thread_rng();
|
||||
// let (nonces, commitments) = round1::commit(&signing_share, &mut rng);
|
||||
let expected = request_inputs(&mut invalid_input, &mut test_logger);
|
||||
assert!(expected.is_err())
|
||||
}
|
||||
|
||||
// print_values(commitments, &mut test_logger);
|
||||
#[test]
|
||||
fn check_print_values() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let signing_share =
|
||||
SigningShare::deserialize(<[u8; 32]>::from_hex(SIGNING_SHARE).unwrap()).unwrap();
|
||||
let mut rng = thread_rng();
|
||||
let (_nonces, commitments) = round1::commit(&signing_share, &mut rng);
|
||||
|
||||
// let log = [
|
||||
// "=== Round 1 ===".to_string(),
|
||||
// format!("Hiding nonce: {}", hex::encode(nonces.hiding().serialize())),
|
||||
// format!(
|
||||
// "Binding nonce: {}",
|
||||
// hex::encode(nonces.binding().serialize())
|
||||
// ),
|
||||
// format!(
|
||||
// "Hiding commitment: {}",
|
||||
// hex::encode(commitments.hiding().serialize())
|
||||
// ),
|
||||
// format!(
|
||||
// "Binding commitment: {}",
|
||||
// hex::encode(commitments.binding().serialize())
|
||||
// ),
|
||||
// "=== Round 1 Completed ===".to_string(),
|
||||
// "Please send your Hiding and Binding Commitments to the coordinator".to_string(),
|
||||
// ];
|
||||
// assert_eq!(test_logger.0, log)
|
||||
// }
|
||||
print_values(commitments, &mut test_logger); // TODO: Run test without random
|
||||
|
||||
let log = [
|
||||
"=== Round 1 ===",
|
||||
"SigningNonces were generated and stored in memory",
|
||||
&format!("SigningCommitments:\n{{\"hiding\":\"{}\",\"binding\":\"{}\",\"ciphersuite\":\"FROST(Ed25519, SHA-512)\"}}", &hex::encode(commitments.hiding().serialize()), &hex::encode(commitments.binding().serialize())),
|
||||
"=== Round 1 Completed ===",
|
||||
"Please send your SigningCommitments to the coordinator"];
|
||||
assert_eq!(test_logger.0, log)
|
||||
}
|
||||
|
|
|
@ -1,172 +1,147 @@
|
|||
// use std::collections::BTreeMap;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
// #[cfg(test)]
|
||||
// use frost::Identifier;
|
||||
// use frost::{
|
||||
// keys::{KeyPackage, SigningShare, VerifyingShare},
|
||||
// round1::{self, NonceCommitment, SigningCommitments},
|
||||
// round2::SignatureShare,
|
||||
// VerifyingKey,
|
||||
// };
|
||||
// use frost_ed25519 as frost;
|
||||
// use hex::FromHex;
|
||||
// use participant::round2::{generate_signature, round_2_request_inputs, Round2Config};
|
||||
// use participant::Logger;
|
||||
// use participant::{round1::Round1Config, round2::print_values_round_2};
|
||||
// use rand::thread_rng;
|
||||
#[cfg(test)]
|
||||
use frost::Identifier;
|
||||
use frost::{
|
||||
keys::{KeyPackage, SigningShare, VerifyingShare},
|
||||
round1::{self, NonceCommitment, SigningCommitments},
|
||||
round2::SignatureShare,
|
||||
SigningPackage, VerifyingKey,
|
||||
};
|
||||
use frost_ed25519 as frost;
|
||||
use hex::FromHex;
|
||||
use participant::round2::print_values_round_2;
|
||||
use participant::round2::{generate_signature, round_2_request_inputs, Round2Config};
|
||||
use participant::Logger;
|
||||
use rand::thread_rng;
|
||||
|
||||
// pub struct TestLogger(Vec<String>);
|
||||
pub struct TestLogger(Vec<String>);
|
||||
|
||||
// impl Logger for TestLogger {
|
||||
// fn log(&mut self, value: String) {
|
||||
// self.0.push(value);
|
||||
// }
|
||||
// }
|
||||
impl Logger for TestLogger {
|
||||
fn log(&mut self, value: String) {
|
||||
self.0.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
// const PUBLIC_KEY: &str = "adf6ab1f882d04988eadfaa52fb175bf37b6247785d7380fde3fb9d68032470d";
|
||||
// const GROUP_PUBLIC_KEY: &str = "087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e";
|
||||
// const SIGNING_SHARE: &str = "ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104";
|
||||
// const VSS_COMMITMENT : &str = "03087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e926d5910e146dccb9148ca39dc7607f4f7123ff1c0ffaf109add1d165c568bf2291bb78d7e4ef124f5aa6a36cbcf8c276e70fbb4e208212e916d762fc42c1bbc";
|
||||
// const MESSAGE: &str = "15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673";
|
||||
// const MY_HIDING_COMMITMENT: &str =
|
||||
// "44105304351ceddc58e15ddea35b2cb48e60ced54ceb22c3b0e5d42d098aa1d8";
|
||||
// const MY_BINDING_COMMITMENT: &str =
|
||||
// "b8274b18a12f2cef74ae42f876cec1e31daab5cb162f95a56cd2487409c9d1dd";
|
||||
// const IDENTIFIER_2: &str = "2";
|
||||
// const HIDING_COMMITMENT_2: &str =
|
||||
// "30f3f03bd739024dc5b1e9d422745a7f32b0971d5cef302106b30bd9f5642d70";
|
||||
// const BINDING_COMMITMENT_2: &str =
|
||||
// "a7ccae3750846fbd7d132efec85e96236a711b2097a6f03b1afa04f6029458cc";
|
||||
// const IDENTIFIER_3: &str = "3";
|
||||
// const HIDING_COMMITMENT_3: &str =
|
||||
// "d31bd81ce216b1c83912803a574a0285796275cb8b14f6dc92c8b09a6951f0a2";
|
||||
// const BINDING_COMMITMENT_3: &str =
|
||||
// "e1c863cfd08df775b6747ef2456e9bf9a03cc281a479a95261dc39137fcf0967";
|
||||
const PUBLIC_KEY: &str = "adf6ab1f882d04988eadfaa52fb175bf37b6247785d7380fde3fb9d68032470d";
|
||||
const GROUP_PUBLIC_KEY: &str = "087e22f970daf6ac5b07b55bd7fc0af6dea199ab847dc34fc92a6f8641a1bb8e";
|
||||
const SIGNING_SHARE: &str = "ceed7dd148a1a1ec2e65b50ecab6a7c453ccbd38c397c3506a540b7cf0dd9104";
|
||||
const MESSAGE: &str = "15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673";
|
||||
const MY_HIDING_COMMITMENT: &str =
|
||||
"beb81feb53ed75a2695b07f377b464a88c4c2824e7d7b63911b745df01dc2d87";
|
||||
const MY_BINDING_COMMITMENT: &str =
|
||||
"d2102c5f8b8abb7ad2f1706f47a4aab3be6ede28e408f3e74baeff1f6fbcd5c0";
|
||||
const HIDING_COMMITMENT_2: &str =
|
||||
"cc9e9503921cdd3f4d64f2c9e7b22c9ab6d7c940111ce36f84e4a114331c6edd";
|
||||
const BINDING_COMMITMENT_2: &str =
|
||||
"b0e13794eaf00be2e430b16ec7f72ab0b6579e52ca604d17406a4fd1597afd66";
|
||||
|
||||
// #[test]
|
||||
// fn check_valid_round_2_inputs() {
|
||||
// // TODO: refactor
|
||||
// let my_signer_commitments = SigningCommitments::new(
|
||||
// NonceCommitment::deserialize(<[u8; 32]>::from_hex(MY_HIDING_COMMITMENT).unwrap()).unwrap(),
|
||||
// NonceCommitment::deserialize(<[u8; 32]>::from_hex(MY_BINDING_COMMITMENT).unwrap()).unwrap(),
|
||||
// );
|
||||
pub fn nonce_commitment(input: &str) -> NonceCommitment {
|
||||
NonceCommitment::deserialize(<[u8; 32]>::from_hex(input).unwrap()).unwrap()
|
||||
}
|
||||
|
||||
// let signer_commitments_2 = SigningCommitments::new(
|
||||
// NonceCommitment::deserialize(<[u8; 32]>::from_hex(HIDING_COMMITMENT_2).unwrap()).unwrap(),
|
||||
// NonceCommitment::deserialize(<[u8; 32]>::from_hex(BINDING_COMMITMENT_2).unwrap()).unwrap(),
|
||||
// );
|
||||
// let signer_commitments_3 = SigningCommitments::new(
|
||||
// NonceCommitment::deserialize(<[u8; 32]>::from_hex(HIDING_COMMITMENT_3).unwrap()).unwrap(),
|
||||
// NonceCommitment::deserialize(<[u8; 32]>::from_hex(BINDING_COMMITMENT_3).unwrap()).unwrap(),
|
||||
// );
|
||||
#[test]
|
||||
fn check_valid_round_2_inputs() {
|
||||
// TODO: refactor
|
||||
|
||||
// let mut signer_commitments = BTreeMap::new();
|
||||
// signer_commitments.insert(Identifier::try_from(1).unwrap(), my_signer_commitments);
|
||||
// signer_commitments.insert(Identifier::try_from(2).unwrap(), signer_commitments_2);
|
||||
// signer_commitments.insert(Identifier::try_from(3).unwrap(), signer_commitments_3);
|
||||
// Generate commitments
|
||||
|
||||
// let config = Round2Config {
|
||||
// message: hex::decode("15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673")
|
||||
// .unwrap(),
|
||||
// signer_commitments,
|
||||
// };
|
||||
let my_signer_commitments = SigningCommitments::new(
|
||||
nonce_commitment(MY_HIDING_COMMITMENT),
|
||||
nonce_commitment(MY_BINDING_COMMITMENT),
|
||||
);
|
||||
|
||||
// let mut test_logger = TestLogger(Vec::new());
|
||||
let signer_commitments_2 = SigningCommitments::new(
|
||||
nonce_commitment(HIDING_COMMITMENT_2),
|
||||
nonce_commitment(BINDING_COMMITMENT_2),
|
||||
);
|
||||
|
||||
// let input = format!(
|
||||
// "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n",
|
||||
// "3",
|
||||
// MESSAGE,
|
||||
// IDENTIFIER_2,
|
||||
// HIDING_COMMITMENT_2,
|
||||
// BINDING_COMMITMENT_2,
|
||||
// IDENTIFIER_3,
|
||||
// HIDING_COMMITMENT_3,
|
||||
// BINDING_COMMITMENT_3
|
||||
// );
|
||||
// let mut valid_input = input.as_bytes();
|
||||
let mut signer_commitments = BTreeMap::new();
|
||||
signer_commitments.insert(Identifier::try_from(1).unwrap(), my_signer_commitments);
|
||||
signer_commitments.insert(Identifier::try_from(2).unwrap(), signer_commitments_2);
|
||||
|
||||
// let expected = round_2_request_inputs(
|
||||
// Identifier::try_from(1).unwrap(),
|
||||
// my_signer_commitments,
|
||||
// &mut valid_input,
|
||||
// &mut test_logger,
|
||||
// )
|
||||
// .unwrap();
|
||||
let message = <[u8; 32]>::from_hex(MESSAGE).unwrap();
|
||||
|
||||
// assert_eq!(expected.message, config.message);
|
||||
// // TODO: This is easily resolved in the latest release of Frost which includes the Debug trait
|
||||
// // assert_eq!(expected.signer_commitments[&Identifier::try_from(1).unwrap()], config.signer_commitments[&Identifier::try_from(1).unwrap()]);
|
||||
// }
|
||||
let signing_package = r#"{"signing_commitments":{"0100000000000000000000000000000000000000000000000000000000000000":{"hiding":"beb81feb53ed75a2695b07f377b464a88c4c2824e7d7b63911b745df01dc2d87","binding":"d2102c5f8b8abb7ad2f1706f47a4aab3be6ede28e408f3e74baeff1f6fbcd5c0","ciphersuite":"FROST(Ed25519, SHA-512)"},"0200000000000000000000000000000000000000000000000000000000000000":{"hiding":"cc9e9503921cdd3f4d64f2c9e7b22c9ab6d7c940111ce36f84e4a114331c6edd","binding":"b0e13794eaf00be2e430b16ec7f72ab0b6579e52ca604d17406a4fd1597afd66","ciphersuite":"FROST(Ed25519, SHA-512)"}},"message":"15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673","ciphersuite":"FROST(Ed25519, SHA-512)"}"#;
|
||||
|
||||
// // TODO: test for invalid inputs
|
||||
let expected = Round2Config {
|
||||
signing_package: SigningPackage::new(signer_commitments, &message),
|
||||
};
|
||||
|
||||
// #[test]
|
||||
// fn check_sign() {
|
||||
// let config = Round1Config {
|
||||
// identifier: Identifier::try_from(1).unwrap(),
|
||||
// public_key: VerifyingShare::deserialize(<[u8; 32]>::from_hex(PUBLIC_KEY).unwrap()).unwrap(),
|
||||
// group_public_key: VerifyingKey::from_hex(GROUP_PUBLIC_KEY).unwrap(),
|
||||
// signing_share: SigningShare::deserialize(<[u8; 32]>::from_hex(SIGNING_SHARE).unwrap())
|
||||
// .unwrap(),
|
||||
// vss_commitment: hex::decode(VSS_COMMITMENT).unwrap(),
|
||||
// };
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
|
||||
// let key_package = KeyPackage::new(
|
||||
// config.identifier,
|
||||
// config.signing_share,
|
||||
// config.public_key,
|
||||
// config.group_public_key,
|
||||
// );
|
||||
let input = format!("{}\n", signing_package);
|
||||
let mut valid_input = input.as_bytes();
|
||||
|
||||
// let mut rng = thread_rng();
|
||||
println!("After valid input");
|
||||
|
||||
// // TODO: Nonce doesn't seem to be exported. Look into this to improve these tests
|
||||
// let (nonces, my_commitments) =
|
||||
// round1::commit(&SigningShare::from_hex(SIGNING_SHARE).unwrap(), &mut rng);
|
||||
let round_2_config = round_2_request_inputs(&mut valid_input, &mut test_logger);
|
||||
|
||||
// let signer_commitments_2 = SigningCommitments::new(
|
||||
// NonceCommitment::deserialize(<[u8; 32]>::from_hex(HIDING_COMMITMENT_2).unwrap()).unwrap(),
|
||||
// NonceCommitment::deserialize(<[u8; 32]>::from_hex(BINDING_COMMITMENT_2).unwrap()).unwrap(),
|
||||
// );
|
||||
assert!(round_2_config.is_ok());
|
||||
assert_eq!(
|
||||
expected.signing_package,
|
||||
round_2_config.unwrap().signing_package
|
||||
)
|
||||
}
|
||||
|
||||
// let signer_commitments_3 = SigningCommitments::new(
|
||||
// NonceCommitment::deserialize(<[u8; 32]>::from_hex(HIDING_COMMITMENT_3).unwrap()).unwrap(),
|
||||
// NonceCommitment::deserialize(<[u8; 32]>::from_hex(BINDING_COMMITMENT_3).unwrap()).unwrap(),
|
||||
// );
|
||||
// TODO: test for invalid inputs
|
||||
|
||||
// let mut signer_commitments = BTreeMap::new();
|
||||
// signer_commitments.insert(Identifier::try_from(1).unwrap(), my_commitments);
|
||||
// signer_commitments.insert(Identifier::try_from(2).unwrap(), signer_commitments_2);
|
||||
// signer_commitments.insert(Identifier::try_from(3).unwrap(), signer_commitments_3);
|
||||
#[test]
|
||||
fn check_sign() {
|
||||
let key_package = KeyPackage::new(
|
||||
Identifier::try_from(1).unwrap(),
|
||||
SigningShare::deserialize(<[u8; 32]>::from_hex(SIGNING_SHARE).unwrap()).unwrap(),
|
||||
VerifyingShare::deserialize(<[u8; 32]>::from_hex(PUBLIC_KEY).unwrap()).unwrap(),
|
||||
VerifyingKey::from_hex(GROUP_PUBLIC_KEY).unwrap(),
|
||||
);
|
||||
|
||||
// let config = Round2Config {
|
||||
// message: hex::decode("15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673")
|
||||
// .unwrap(),
|
||||
// signer_commitments,
|
||||
// };
|
||||
// let config = Round1Config {
|
||||
// key_package
|
||||
// };
|
||||
|
||||
// let signature = generate_signature(config, &key_package, &nonces);
|
||||
let mut rng = thread_rng();
|
||||
|
||||
// assert!(signature.is_ok()) // TODO: Should be able to test this more specifically when I remove randomness from the test
|
||||
// }
|
||||
// TODO: Nonce doesn't seem to be exported. Look into this to improve these tests
|
||||
let (nonces, my_commitments) =
|
||||
round1::commit(&SigningShare::from_hex(SIGNING_SHARE).unwrap(), &mut rng);
|
||||
|
||||
// #[test]
|
||||
// fn check_print_values_round_2() {
|
||||
// let mut test_logger = TestLogger(Vec::new());
|
||||
let signer_commitments_2 = SigningCommitments::new(
|
||||
NonceCommitment::deserialize(<[u8; 32]>::from_hex(HIDING_COMMITMENT_2).unwrap()).unwrap(),
|
||||
NonceCommitment::deserialize(<[u8; 32]>::from_hex(BINDING_COMMITMENT_2).unwrap()).unwrap(),
|
||||
);
|
||||
|
||||
// const SIGNATURE_SHARE: &str =
|
||||
// "44055c54d0604cbd006f0d1713a22474d7735c5e8816b1878f62ca94bf105900";
|
||||
// let signature_response =
|
||||
// SignatureShare::deserialize(<[u8; 32]>::from_hex(SIGNATURE_SHARE).unwrap()).unwrap();
|
||||
let mut signer_commitments = BTreeMap::new();
|
||||
signer_commitments.insert(Identifier::try_from(1).unwrap(), my_commitments);
|
||||
signer_commitments.insert(Identifier::try_from(2).unwrap(), signer_commitments_2);
|
||||
|
||||
// print_values_round_2(signature_response, &mut test_logger);
|
||||
let message =
|
||||
<[u8; 32]>::from_hex("15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040d380fb9738673")
|
||||
.unwrap();
|
||||
|
||||
// let log = [
|
||||
// "Please send the following to the Coordinator".to_string(),
|
||||
// format!("Signature share: {}", SIGNATURE_SHARE),
|
||||
// "=== End of Round 2 ===".to_string(),
|
||||
// ];
|
||||
let signing_package = SigningPackage::new(signer_commitments, &message);
|
||||
|
||||
// assert_eq!(test_logger.0, log);
|
||||
// }
|
||||
let config = Round2Config { signing_package };
|
||||
|
||||
let signature = generate_signature(config, &key_package, &nonces);
|
||||
|
||||
assert!(signature.is_ok()) // TODO: Should be able to test this more specifically when I remove randomness from the test
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_print_values_round_2() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
|
||||
const SIGNATURE_SHARE: &str =
|
||||
"44055c54d0604cbd006f0d1713a22474d7735c5e8816b1878f62ca94bf105900";
|
||||
let signature_response =
|
||||
SignatureShare::deserialize(<[u8; 32]>::from_hex(SIGNATURE_SHARE).unwrap()).unwrap();
|
||||
|
||||
print_values_round_2(signature_response, &mut test_logger);
|
||||
|
||||
let log = [
|
||||
"Please send the following to the Coordinator",
|
||||
"SignatureShare:\n{\"share\":\"44055c54d0604cbd006f0d1713a22474d7735c5e8816b1878f62ca94bf105900\",\"ciphersuite\":\"FROST(Ed25519, SHA-512)\"}",
|
||||
"=== End of Round 2 ==="];
|
||||
|
||||
assert_eq!(test_logger.0, log);
|
||||
}
|
||||
|
|
|
@ -1,84 +1,62 @@
|
|||
// use std::collections::{BTreeMap, HashMap};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
// use frost::keys::IdentifierList;
|
||||
// use frost::{aggregate, SigningPackage};
|
||||
// use frost_ed25519 as frost;
|
||||
// use participant::round1::Round1Config;
|
||||
// use participant::round2::{generate_signature, Round2Config};
|
||||
// use rand::thread_rng;
|
||||
use frost::keys::IdentifierList;
|
||||
use frost::{aggregate, SigningPackage};
|
||||
use frost_ed25519 as frost;
|
||||
use participant::round2::{generate_signature, Round2Config};
|
||||
use rand::thread_rng;
|
||||
|
||||
// fn encode_commitment_helper(commitment: Vec<[u8; 32]>) -> String {
|
||||
// let len_test = commitment.len() as u8;
|
||||
// let mut out = hex::encode([len_test]);
|
||||
// for c in commitment {
|
||||
// out = out + &hex::encode(c)
|
||||
// }
|
||||
// out
|
||||
// }
|
||||
#[test]
|
||||
fn check_participant() {
|
||||
let mut rng = thread_rng();
|
||||
let (shares, pubkeys) =
|
||||
frost::keys::generate_with_dealer(3, 2, IdentifierList::Default, &mut rng).unwrap();
|
||||
|
||||
// #[test]
|
||||
// fn check_participant() {
|
||||
// let mut rng = thread_rng();
|
||||
// let (shares, pubkeys) =
|
||||
// frost::keys::generate_with_dealer(3, 2, IdentifierList::Default, &mut rng).unwrap();
|
||||
let mut key_packages: HashMap<_, _> = HashMap::new();
|
||||
|
||||
// let mut key_packages: HashMap<_, _> = HashMap::new();
|
||||
for (identifier, secret_share) in &shares {
|
||||
let key_package = frost::keys::KeyPackage::try_from(secret_share.clone()).unwrap();
|
||||
key_packages.insert(identifier, key_package);
|
||||
}
|
||||
|
||||
// for (identifier, secret_share) in &shares {
|
||||
// let key_package = frost::keys::KeyPackage::try_from(secret_share.clone()).unwrap();
|
||||
// key_packages.insert(identifier, key_package);
|
||||
// }
|
||||
// Round 1
|
||||
|
||||
// // Round 1
|
||||
let mut nonces = HashMap::new();
|
||||
let mut commitments = BTreeMap::new();
|
||||
|
||||
// let mut nonces = HashMap::new();
|
||||
// let mut commitments = BTreeMap::new();
|
||||
for i in shares.keys() {
|
||||
let (nonce, commitment) = frost::round1::commit(key_packages[&i].secret_share(), &mut rng);
|
||||
nonces.insert(*i, nonce);
|
||||
commitments.insert(*i, commitment);
|
||||
}
|
||||
|
||||
// for i in shares.keys() {
|
||||
// let config = Round1Config {
|
||||
// identifier: *i,
|
||||
// public_key: pubkeys.signer_pubkeys()[i],
|
||||
// group_public_key: *pubkeys.group_public(),
|
||||
// signing_share: *shares[i].secret(),
|
||||
// vss_commitment: hex::decode(encode_commitment_helper(
|
||||
// shares[i].commitment().serialize(),
|
||||
// ))
|
||||
// .unwrap(),
|
||||
// };
|
||||
// let (nonce, commitment) =
|
||||
// frost::round1::commit(key_packages[&config.identifier].secret_share(), &mut rng);
|
||||
// nonces.insert(config.identifier, nonce);
|
||||
// commitments.insert(config.identifier, commitment);
|
||||
// }
|
||||
// Coordinator sends message
|
||||
|
||||
// // Coordinator sends message
|
||||
let message = "a message".as_bytes().to_vec();
|
||||
|
||||
// let message = "a message".as_bytes().to_vec();
|
||||
// Round 2
|
||||
|
||||
// // Round 2
|
||||
let mut signature_shares = HashMap::new();
|
||||
|
||||
// let mut signature_shares = HashMap::new();
|
||||
for participant_identifier in nonces.keys() {
|
||||
let config = Round2Config {
|
||||
signing_package: SigningPackage::new(commitments.clone(), &message),
|
||||
};
|
||||
let signature = generate_signature(
|
||||
config,
|
||||
&key_packages[participant_identifier],
|
||||
&nonces[participant_identifier],
|
||||
)
|
||||
.unwrap();
|
||||
signature_shares.insert(*participant_identifier, signature);
|
||||
}
|
||||
|
||||
// for participant_identifier in nonces.keys() {
|
||||
// let config = Round2Config {
|
||||
// message: message.clone(),
|
||||
// signer_commitments: commitments.clone(),
|
||||
// };
|
||||
// let signature = generate_signature(
|
||||
// config,
|
||||
// &key_packages[participant_identifier],
|
||||
// &nonces[participant_identifier],
|
||||
// )
|
||||
// .unwrap();
|
||||
// signature_shares.insert(*participant_identifier, signature);
|
||||
// }
|
||||
// Coordinator aggregates signatures
|
||||
|
||||
// // Coordinator aggregates signatures
|
||||
let signing_package = SigningPackage::new(commitments, &message);
|
||||
|
||||
// let signing_package = SigningPackage::new(commitments, &message);
|
||||
let group_signature = aggregate(&signing_package, &signature_shares, &pubkeys).unwrap();
|
||||
let verify_signature = pubkeys.group_public().verify(&message, &group_signature);
|
||||
|
||||
// let group_signature = aggregate(&signing_package, &signature_shares, &pubkeys).unwrap();
|
||||
// let verify_signature = pubkeys.group_public().verify(&message, &group_signature);
|
||||
|
||||
// assert!(verify_signature.is_ok());
|
||||
// }
|
||||
assert!(verify_signature.is_ok());
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
frost-ed25519 = "0.6.0"
|
||||
frost-ed25519 = { version = "0.6.0", features = ["serde"] }
|
||||
reddsa = { git = "https://github.com/ZcashFoundation/reddsa.git", rev = "8534e283acf0015cc2450e2a6b49685a3bb3145d", features = ["frost"] }
|
||||
thiserror = "1.0"
|
||||
rand = "0.8"
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
# Frost Trusted Dealer Demo
|
||||
|
||||
[Overview of demos](https://github.com/ZcashFoundation/frost-zcash-demo/blob/main/README.md)
|
||||
|
||||
## Status ⚠
|
||||
|
||||
The Trusted Dealer demo is a WIP.
|
||||
|
||||
## Usage
|
||||
|
||||
NOTE: This is for demo purposes only and should not be used in production.
|
||||
|
||||
You will need to have [Rust and Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) installed.
|
||||
|
||||
To run:
|
||||
1. Clone the repo. Run `git clone https://github.com/ZcashFoundation/frost-zcash-demo.git`
|
||||
2. Run `cargo install`
|
||||
3. Run `cargo run --bin trusted-dealer`
|
||||
|
||||
On startup, the Trusted Dealer demo will prompt for:
|
||||
|
||||
1. Minimum number of signers (>= 2) i.e. The threshold number of signers for the secret sharing scheme.
|
||||
|
||||
2. Maximum number of signers i.e. the number of shares to generate
|
||||
|
||||
```
|
||||
> cargo run
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.05s
|
||||
Running 'target/debug/frost-trusted-dealer-demo
|
||||
The minimum number of signers: (2 or more)
|
||||
2
|
||||
The maximum number of signers: (must be greater than minimum number of signers)
|
||||
5
|
||||
```
|
||||
|
||||
The dealer CLI will then use that data to generate:
|
||||
|
||||
1. The group public key
|
||||
2. A commitment to the secret
|
||||
3. Each signer's public key
|
||||
4. Each signer's secret share
|
||||
5. An identifier for each signer
|
||||
|
||||
In a "real world" scenario, the secret share should be delivered securely to each participant. For the purposes of the Trusted Dealer demo only, the above data will be output to the terminal.
|
||||
|
||||
In the next round, all signers will receive the data but only the individual signers will receive their personal secret share.
|
||||
|
||||
## Using the output
|
||||
|
||||
To generate a key package the participant requires:
|
||||
|
||||
* The signer's identifier
|
||||
* The signer's secret share
|
||||
* The signer's public key
|
||||
* The public signing key that represents the entire group
|
||||
|
||||
The commitment is used to verify the signer's secret share and to generate the group commitment.
|
||||
|
||||
The dealer should use a secure broadcast channel to ensure each participant has a consistent view of this commitment and each participant must [verify the commitments](https://github.com/ZcashFoundation/frost/blob/4055cb9439df2814800c678c8da1760a0f86dc10/frost-core/src/frost/keys.rs#L297).
|
||||
The trusted dealer MUST delete the secret_key (used during calculation) and secret_share upon completion.
|
||||
Use of this method for key generation requires a mutually authenticated secure channel between the dealer and participants to send secret key shares, wherein the channel provides confidentiality and integrity. Mutually authenticated TLS is one possible deployment option.
|
||||
|
||||
NOTE: A signer is a participant that generates a signing share which is aggregated with the signing shares of other signers to obtain the final group signature.
|
||||
|
||||
## Developer information
|
||||
|
||||
### Pre-commit checks
|
||||
|
||||
1. Run `cargo make all`
|
||||
|
||||
### Coverage
|
||||
|
||||
Test coverage checks are performed in the pipeline. This is configured here: `.github/workflows/coverage.yaml`
|
||||
To run these locally:
|
||||
1. Install coverage tool by running `cargo install cargo-llvm-cov`
|
||||
2. Run `cargo cov` (you may be asked if you want to install `llvm-tools-preview`, if so type `Y`)
|
|
@ -1,329 +1,109 @@
|
|||
// use frost::keys::IdentifierList;
|
||||
// use frost::Identifier;
|
||||
// use frost_ed25519 as frost;
|
||||
// use rand::thread_rng;
|
||||
use frost::keys::IdentifierList;
|
||||
use frost_ed25519 as frost;
|
||||
use rand::thread_rng;
|
||||
|
||||
// use crate::inputs::Config;
|
||||
// use crate::output::{print_values, Logger};
|
||||
// use crate::trusted_dealer_keygen::{split_secret, trusted_dealer_keygen};
|
||||
use crate::inputs::Config;
|
||||
use crate::output::{print_values, Logger};
|
||||
use crate::trusted_dealer_keygen::{split_secret, trusted_dealer_keygen};
|
||||
|
||||
// struct TestLogger(Vec<String>);
|
||||
struct TestLogger(Vec<String>);
|
||||
|
||||
// impl Logger for TestLogger {
|
||||
// fn log(&mut self, value: String) {
|
||||
// self.0.push(value);
|
||||
// }
|
||||
// }
|
||||
impl Logger for TestLogger {
|
||||
fn log(&mut self, value: String) {
|
||||
self.0.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
// fn encode_commitment_helper(commitment: Vec<[u8; 32]>) -> String {
|
||||
// let len_test = commitment.len() as u8;
|
||||
// let mut out = hex::encode([len_test]);
|
||||
// for c in commitment {
|
||||
// out = out + &hex::encode(c)
|
||||
// }
|
||||
// out
|
||||
// }
|
||||
#[test]
|
||||
fn check_output_without_secret() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let mut rng = thread_rng();
|
||||
let config = Config {
|
||||
min_signers: 2,
|
||||
max_signers: 3,
|
||||
secret: Vec::new(),
|
||||
};
|
||||
let (shares, pubkeys) =
|
||||
trusted_dealer_keygen(&config, IdentifierList::Default, &mut rng).unwrap();
|
||||
|
||||
// #[test]
|
||||
// fn check_output_without_secret() {
|
||||
// let mut test_logger = TestLogger(Vec::new());
|
||||
// let mut rng = thread_rng();
|
||||
// let config = Config {
|
||||
// min_signers: 2,
|
||||
// max_signers: 3,
|
||||
// secret: Vec::new(),
|
||||
// };
|
||||
// let (shares, pubkeys) =
|
||||
// trusted_dealer_keygen(&config, IdentifierList::Default, &mut rng).unwrap();
|
||||
print_values(&shares, &pubkeys, &mut test_logger); // TODO: do we need shares here?
|
||||
|
||||
// print_values(&shares, &pubkeys, &mut test_logger);
|
||||
let public_key_package = serde_json::to_string(&pubkeys).unwrap();
|
||||
|
||||
// let signer_1 = Identifier::try_from(1).unwrap();
|
||||
// let signer_2 = Identifier::try_from(2).unwrap();
|
||||
// let signer_3 = Identifier::try_from(3).unwrap();
|
||||
assert_eq!(
|
||||
test_logger.0[0],
|
||||
format!("Public key package:\n{}", public_key_package)
|
||||
);
|
||||
}
|
||||
|
||||
// let signer_1_id = "1";
|
||||
// let signer_2_id = "2";
|
||||
// let signer_3_id = "3";
|
||||
#[test]
|
||||
fn check_output_with_secret() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let mut rng = thread_rng();
|
||||
let secret: Vec<u8> = vec![
|
||||
123, 28, 51, 211, 245, 41, 29, 133, 222, 102, 72, 51, 190, 177, 173, 70, 159, 127, 182, 2,
|
||||
90, 14, 199, 139, 58, 121, 12, 110, 19, 169, 131, 4,
|
||||
];
|
||||
let config = Config {
|
||||
min_signers: 2,
|
||||
max_signers: 3,
|
||||
secret,
|
||||
};
|
||||
let (shares, pubkeys) = split_secret(&config, IdentifierList::Default, &mut rng).unwrap();
|
||||
|
||||
// assert_eq!(
|
||||
// test_logger.0[0],
|
||||
// format!(
|
||||
// "Group public key: {}",
|
||||
// hex::encode(pubkeys.group_public().serialize())
|
||||
// )
|
||||
// );
|
||||
print_values(&shares, &pubkeys, &mut test_logger);
|
||||
|
||||
// assert_eq!(test_logger.0[1], format!("Participant: {}", signer_1_id));
|
||||
// assert_eq!(
|
||||
// test_logger.0[2],
|
||||
// format!(
|
||||
// "Secret share: {}",
|
||||
// hex::encode(shares[&signer_1].value().serialize())
|
||||
// )
|
||||
// );
|
||||
// assert_eq!(
|
||||
// test_logger.0[3],
|
||||
// format!(
|
||||
// "Public key: {}",
|
||||
// hex::encode(pubkeys.signer_pubkeys()[&signer_1].serialize())
|
||||
// )
|
||||
// );
|
||||
// assert_eq!(
|
||||
// test_logger.0[4],
|
||||
// format!(
|
||||
// "Your verifiable secret sharing commitment: {}",
|
||||
// encode_commitment_helper(shares[&signer_1].commitment().serialize())
|
||||
// )
|
||||
// );
|
||||
let public_key_package = serde_json::to_string(&pubkeys).unwrap();
|
||||
|
||||
// assert_eq!(test_logger.0[5], format!("Participant: {}", signer_2_id));
|
||||
// assert_eq!(
|
||||
// test_logger.0[6],
|
||||
// format!(
|
||||
// "Secret share: {}",
|
||||
// hex::encode(shares[&signer_2].value().serialize())
|
||||
// )
|
||||
// );
|
||||
// assert_eq!(
|
||||
// test_logger.0[7],
|
||||
// format!(
|
||||
// "Public key: {}",
|
||||
// hex::encode(pubkeys.signer_pubkeys()[&signer_2].serialize())
|
||||
// )
|
||||
// );
|
||||
// assert_eq!(
|
||||
// test_logger.0[8],
|
||||
// format!(
|
||||
// "Your verifiable secret sharing commitment: {}",
|
||||
// encode_commitment_helper(shares[&signer_2].commitment().serialize())
|
||||
// )
|
||||
// );
|
||||
assert_eq!(
|
||||
test_logger.0[0],
|
||||
format!("Public key package:\n{}", public_key_package)
|
||||
);
|
||||
}
|
||||
|
||||
// assert_eq!(test_logger.0[9], format!("Participant: {}", signer_3_id));
|
||||
// assert_eq!(
|
||||
// test_logger.0[10],
|
||||
// format!(
|
||||
// "Secret share: {}",
|
||||
// hex::encode(shares[&signer_3].value().serialize())
|
||||
// )
|
||||
// );
|
||||
// assert_eq!(
|
||||
// test_logger.0[11],
|
||||
// format!(
|
||||
// "Public key: {}",
|
||||
// hex::encode(pubkeys.signer_pubkeys()[&signer_3].serialize())
|
||||
// )
|
||||
// );
|
||||
// assert_eq!(
|
||||
// test_logger.0[12],
|
||||
// format!(
|
||||
// "Your verifiable secret sharing commitment: {}",
|
||||
// encode_commitment_helper(shares[&signer_3].commitment().serialize())
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
#[test]
|
||||
fn check_output_with_large_num_of_signers() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let mut rng = thread_rng();
|
||||
let config = Config {
|
||||
min_signers: 10,
|
||||
max_signers: 20,
|
||||
secret: Vec::new(),
|
||||
};
|
||||
let (shares, pubkeys) =
|
||||
trusted_dealer_keygen(&config, IdentifierList::Default, &mut rng).unwrap();
|
||||
|
||||
// #[test]
|
||||
// fn check_output_with_secret() {
|
||||
// let mut test_logger = TestLogger(Vec::new());
|
||||
// let mut rng = thread_rng();
|
||||
// let secret: Vec<u8> = vec![
|
||||
// 123, 28, 51, 211, 245, 41, 29, 133, 222, 102, 72, 51, 190, 177, 173, 70, 159, 127, 182, 2,
|
||||
// 90, 14, 199, 139, 58, 121, 12, 110, 19, 169, 131, 4,
|
||||
// ];
|
||||
// let config = Config {
|
||||
// min_signers: 2,
|
||||
// max_signers: 3,
|
||||
// secret,
|
||||
// };
|
||||
// let (shares, pubkeys) = split_secret(&config, IdentifierList::Default, &mut rng).unwrap();
|
||||
print_values(&shares, &pubkeys, &mut test_logger);
|
||||
|
||||
// print_values(&shares, &pubkeys, &mut test_logger);
|
||||
let public_key_package = serde_json::to_string(&pubkeys).unwrap();
|
||||
|
||||
// let signer_1 = Identifier::try_from(1).unwrap();
|
||||
// let signer_2 = Identifier::try_from(2).unwrap();
|
||||
// let signer_3 = Identifier::try_from(3).unwrap();
|
||||
assert_eq!(
|
||||
test_logger.0[0],
|
||||
format!("Public key package:\n{}", public_key_package)
|
||||
);
|
||||
}
|
||||
|
||||
// let signer_1_id = "1";
|
||||
// let signer_2_id = "2";
|
||||
// let signer_3_id = "3";
|
||||
#[test]
|
||||
fn check_output_with_secret_with_large_num_of_signers() {
|
||||
let mut test_logger = TestLogger(Vec::new());
|
||||
let mut rng = thread_rng();
|
||||
let secret: Vec<u8> = vec![
|
||||
123, 28, 51, 211, 245, 41, 29, 133, 222, 102, 72, 51, 190, 177, 173, 70, 159, 127, 182, 2,
|
||||
90, 14, 199, 139, 58, 121, 12, 110, 19, 169, 131, 4,
|
||||
];
|
||||
let config = Config {
|
||||
min_signers: 10,
|
||||
max_signers: 20,
|
||||
secret,
|
||||
};
|
||||
let (shares, pubkeys) = split_secret(&config, IdentifierList::Default, &mut rng).unwrap();
|
||||
|
||||
// assert_eq!(
|
||||
// test_logger.0[0],
|
||||
// format!(
|
||||
// "Group public key: {}",
|
||||
// hex::encode(pubkeys.group_public().serialize())
|
||||
// )
|
||||
// );
|
||||
print_values(&shares, &pubkeys, &mut test_logger);
|
||||
|
||||
// assert_eq!(test_logger.0[1], format!("Participant: {}", signer_1_id));
|
||||
// assert_eq!(
|
||||
// test_logger.0[2],
|
||||
// format!(
|
||||
// "Secret share: {}",
|
||||
// hex::encode(shares[&signer_1].value().serialize())
|
||||
// )
|
||||
// );
|
||||
// assert_eq!(
|
||||
// test_logger.0[3],
|
||||
// format!(
|
||||
// "Public key: {}",
|
||||
// hex::encode(pubkeys.signer_pubkeys()[&signer_1].serialize())
|
||||
// )
|
||||
// );
|
||||
// assert_eq!(
|
||||
// test_logger.0[4],
|
||||
// format!(
|
||||
// "Your verifiable secret sharing commitment: {}",
|
||||
// encode_commitment_helper(shares[&signer_1].commitment().serialize())
|
||||
// )
|
||||
// );
|
||||
let public_key_package = serde_json::to_string(&pubkeys).unwrap();
|
||||
|
||||
// assert_eq!(test_logger.0[5], format!("Participant: {}", signer_2_id));
|
||||
// assert_eq!(
|
||||
// test_logger.0[6],
|
||||
// format!(
|
||||
// "Secret share: {}",
|
||||
// hex::encode(shares[&signer_2].value().serialize())
|
||||
// )
|
||||
// );
|
||||
// assert_eq!(
|
||||
// test_logger.0[7],
|
||||
// format!(
|
||||
// "Public key: {}",
|
||||
// hex::encode(pubkeys.signer_pubkeys()[&signer_2].serialize())
|
||||
// )
|
||||
// );
|
||||
// assert_eq!(
|
||||
// test_logger.0[8],
|
||||
// format!(
|
||||
// "Your verifiable secret sharing commitment: {}",
|
||||
// encode_commitment_helper(shares[&signer_2].commitment().serialize())
|
||||
// )
|
||||
// );
|
||||
|
||||
// assert_eq!(test_logger.0[9], format!("Participant: {}", signer_3_id));
|
||||
// assert_eq!(
|
||||
// test_logger.0[10],
|
||||
// format!(
|
||||
// "Secret share: {}",
|
||||
// hex::encode(shares[&signer_3].value().serialize())
|
||||
// )
|
||||
// );
|
||||
// assert_eq!(
|
||||
// test_logger.0[11],
|
||||
// format!(
|
||||
// "Public key: {}",
|
||||
// hex::encode(pubkeys.signer_pubkeys()[&signer_3].serialize())
|
||||
// )
|
||||
// );
|
||||
// assert_eq!(
|
||||
// test_logger.0[12],
|
||||
// format!(
|
||||
// "Your verifiable secret sharing commitment: {}",
|
||||
// encode_commitment_helper(shares[&signer_3].commitment().serialize())
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn check_output_with_large_num_of_signers() {
|
||||
// let mut test_logger = TestLogger(Vec::new());
|
||||
// let mut rng = thread_rng();
|
||||
// let config = Config {
|
||||
// min_signers: 10,
|
||||
// max_signers: 20,
|
||||
// secret: Vec::new(),
|
||||
// };
|
||||
// let (shares, pubkeys) =
|
||||
// trusted_dealer_keygen(&config, IdentifierList::Default, &mut rng).unwrap();
|
||||
|
||||
// print_values(&shares, &pubkeys, &mut test_logger);
|
||||
|
||||
// let signer_10 = Identifier::try_from(10).unwrap();
|
||||
// let signer_10_id = "10";
|
||||
|
||||
// assert_eq!(
|
||||
// test_logger.0[0],
|
||||
// format!(
|
||||
// "Group public key: {}",
|
||||
// hex::encode(pubkeys.group_public().serialize())
|
||||
// )
|
||||
// );
|
||||
|
||||
// assert_eq!(test_logger.0[37], format!("Participant: {}", signer_10_id));
|
||||
// assert_eq!(
|
||||
// test_logger.0[38],
|
||||
// format!(
|
||||
// "Secret share: {}",
|
||||
// hex::encode(shares[&signer_10].value().serialize())
|
||||
// )
|
||||
// );
|
||||
// assert_eq!(
|
||||
// test_logger.0[39],
|
||||
// format!(
|
||||
// "Public key: {}",
|
||||
// hex::encode(pubkeys.signer_pubkeys()[&signer_10].serialize())
|
||||
// )
|
||||
// );
|
||||
// assert_eq!(
|
||||
// test_logger.0[40],
|
||||
// format!(
|
||||
// "Your verifiable secret sharing commitment: {}",
|
||||
// encode_commitment_helper(shares[&signer_10].commitment().serialize())
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn check_output_with_secret_with_large_num_of_signers() {
|
||||
// let mut test_logger = TestLogger(Vec::new());
|
||||
// let mut rng = thread_rng();
|
||||
// let secret: Vec<u8> = vec![
|
||||
// 123, 28, 51, 211, 245, 41, 29, 133, 222, 102, 72, 51, 190, 177, 173, 70, 159, 127, 182, 2,
|
||||
// 90, 14, 199, 139, 58, 121, 12, 110, 19, 169, 131, 4,
|
||||
// ];
|
||||
// let config = Config {
|
||||
// min_signers: 10,
|
||||
// max_signers: 20,
|
||||
// secret,
|
||||
// };
|
||||
// let (shares, pubkeys) = split_secret(&config, IdentifierList::Default, &mut rng).unwrap();
|
||||
|
||||
// print_values(&shares, &pubkeys, &mut test_logger);
|
||||
|
||||
// let signer_10 = Identifier::try_from(10).unwrap();
|
||||
// let signer_10_id = "10";
|
||||
|
||||
// assert_eq!(
|
||||
// test_logger.0[0],
|
||||
// format!(
|
||||
// "Group public key: {}",
|
||||
// hex::encode(pubkeys.group_public().serialize())
|
||||
// )
|
||||
// );
|
||||
|
||||
// assert_eq!(test_logger.0[37], format!("Participant: {}", signer_10_id));
|
||||
// assert_eq!(
|
||||
// test_logger.0[38],
|
||||
// format!(
|
||||
// "Secret share: {}",
|
||||
// hex::encode(shares[&signer_10].value().serialize())
|
||||
// )
|
||||
// );
|
||||
// assert_eq!(
|
||||
// test_logger.0[39],
|
||||
// format!(
|
||||
// "Public key: {}",
|
||||
// hex::encode(pubkeys.signer_pubkeys()[&signer_10].serialize())
|
||||
// )
|
||||
// );
|
||||
// assert_eq!(
|
||||
// test_logger.0[40],
|
||||
// format!(
|
||||
// "Your verifiable secret sharing commitment: {}",
|
||||
// encode_commitment_helper(shares[&signer_10].commitment().serialize())
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
assert_eq!(
|
||||
test_logger.0[0],
|
||||
format!("Public key package:\n{}", public_key_package)
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue