diff --git a/.changelog/unreleased/features/278-secp256k1-support.md b/.changelog/unreleased/features/278-secp256k1-support.md new file mode 100644 index 0000000000..fb257152e4 --- /dev/null +++ b/.changelog/unreleased/features/278-secp256k1-support.md @@ -0,0 +1 @@ +- Added secp256k1 support ([#278](https://github.com/anoma/anoma/pull/278)) \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index cdcd3e6132..ef6dac4c3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -519,6 +519,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base64" version = "0.9.3" @@ -1101,6 +1107,12 @@ dependencies = [ "windows", ] +[[package]] +name = "const-oid" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -1272,6 +1284,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" +dependencies = [ + "generic-array 0.14.5", + "rand_core 0.6.3", + "subtle 2.4.1", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.3" @@ -1302,6 +1326,16 @@ dependencies = [ "subtle 2.4.1", ] +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array 0.14.5", + "subtle 2.4.1", +] + [[package]] name = "ct-codecs" version = "1.1.1" @@ -1484,6 +1518,15 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" +[[package]] +name = "der" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" +dependencies = [ + "const-oid", +] + [[package]] name = "derivative" version = "2.2.0" @@ -1646,6 +1689,18 @@ dependencies = [ "memmap2", ] +[[package]] +name = "ecdsa" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + [[package]] name = "ed25519" version = "1.5.2" @@ -1693,6 +1748,24 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "elliptic-curve" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "ff", + "generic-array 0.14.5", + "group", + "rand_core 0.6.3", + "sec1", + "subtle 2.4.1", + "zeroize", +] + [[package]] name = "embed-resource" version = "1.7.2" @@ -1888,6 +1961,16 @@ dependencies = [ "serde_bytes", ] +[[package]] +name = "ff" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924" +dependencies = [ + "rand_core 0.6.3", + "subtle 2.4.1", +] + [[package]] name = "file-lock" version = "2.1.4" @@ -2276,6 +2359,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "group" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" +dependencies = [ + "ff", + "rand_core 0.6.3", + "subtle 2.4.1", +] + [[package]] name = "group-threshold-cryptography" version = "0.1.0" @@ -2442,6 +2536,26 @@ dependencies = [ "digest 0.8.1", ] +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac 0.8.0", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac 0.11.1", + "digest 0.9.0", +] + [[package]] name = "hmac-drbg" version = "0.2.0" @@ -2450,7 +2564,18 @@ checksum = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" dependencies = [ "digest 0.8.1", "generic-array 0.12.4", - "hmac", + "hmac 0.7.1", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array 0.14.5", + "hmac 0.8.1", ] [[package]] @@ -2868,6 +2993,19 @@ dependencies = [ "serde_json", ] +[[package]] +name = "k256" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d" +dependencies = [ + "cfg-if 1.0.0", + "ecdsa", + "elliptic-curve", + "sec1", + "sha2 0.9.9", +] + [[package]] name = "keccak" version = "0.1.2" @@ -3017,7 +3155,7 @@ dependencies = [ "futures 0.3.21", "futures-timer", "lazy_static 1.4.0", - "libsecp256k1", + "libsecp256k1 0.3.5", "log 0.4.17", "multihash", "multistream-select", @@ -3401,13 +3539,57 @@ dependencies = [ "arrayref", "crunchy", "digest 0.8.1", - "hmac-drbg", + "hmac-drbg 0.2.0", "rand 0.7.3", "sha2 0.8.2", "subtle 2.4.1", "typenum", ] +[[package]] +name = "libsecp256k1" +version = "0.7.0" +source = "git+https://github.com/brentstone/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "arrayref", + "base64 0.13.0", + "digest 0.9.0", + "hmac-drbg 0.3.0", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.8.5", + "serde 1.0.137", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "git+https://github.com/brentstone/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle 2.4.1", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "git+https://github.com/brentstone/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "git+https://github.com/brentstone/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "libsecp256k1-core", +] + [[package]] name = "libssh2-sys" version = "0.2.23" @@ -3862,6 +4044,7 @@ dependencies = [ "ibc-proto", "ics23", "itertools 0.10.3", + "libsecp256k1 0.7.0", "loupe", "namada_proof_of_stake", "parity-wasm", @@ -5384,6 +5567,17 @@ dependencies = [ "quick-error 1.2.3", ] +[[package]] +name = "rfc6979" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" +dependencies = [ + "crypto-bigint", + "hmac 0.11.0", + "zeroize", +] + [[package]] name = "ring" version = "0.16.20" @@ -5683,6 +5877,18 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "sec1" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" +dependencies = [ + "der", + "generic-array 0.14.5", + "subtle 2.4.1", + "zeroize", +] + [[package]] name = "security-framework" version = "2.3.1" @@ -5984,9 +6190,13 @@ dependencies = [ [[package]] name = "signature" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" +checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" +dependencies = [ + "digest 0.9.0", + "rand_core 0.6.3", +] [[package]] name = "simple-error" @@ -6272,10 +6482,12 @@ dependencies = [ "ed25519-dalek", "flex-error", "futures 0.3.21", + "k256", "num-traits 0.2.15", "once_cell", "prost 0.9.0", "prost-types 0.9.0", + "ripemd160", "serde 1.0.137", "serde_bytes", "serde_json", diff --git a/apps/Cargo.toml b/apps/Cargo.toml index 7a4dffac76..9f9b65ffd5 100644 --- a/apps/Cargo.toml +++ b/apps/Cargo.toml @@ -46,7 +46,7 @@ std = ["ed25519-consensus/std", "rand/std", "rand_core/std"] testing = ["dev"] [dependencies] -namada = {path = "../shared", features = ["wasm-runtime", "ferveo-tpke", "rand"]} +namada = {path = "../shared", features = ["wasm-runtime", "ferveo-tpke", "rand", "secp256k1-sign-verify"]} ark-serialize = "0.3.0" ark-std = "0.3.0" async-std = {version = "1.9.0", features = ["unstable"]} @@ -105,7 +105,7 @@ sparse-merkle-tree = {git = "https://github.com/heliaxdev/sparse-merkle-tree", b sysinfo = {version = "=0.21.1", default-features = false} tar = "0.4.37" # temporarily using fork work-around -tendermint = {git = "https://github.com/heliaxdev/tendermint-rs", rev = "95c52476bc37927218374f94ac8e2a19bd35bec9"} +tendermint = {git = "https://github.com/heliaxdev/tendermint-rs", rev = "95c52476bc37927218374f94ac8e2a19bd35bec9", features = ["secp256k1"]} tendermint-config = {git = "https://github.com/heliaxdev/tendermint-rs", rev = "95c52476bc37927218374f94ac8e2a19bd35bec9"} tendermint-proto = {git = "https://github.com/heliaxdev/tendermint-rs", rev = "95c52476bc37927218374f94ac8e2a19bd35bec9"} tendermint-rpc = {git = "https://github.com/heliaxdev/tendermint-rs", rev = "95c52476bc37927218374f94ac8e2a19bd35bec9", features = ["http-client", "websocket-client"]} diff --git a/apps/src/bin/anoma-wallet/cli.rs b/apps/src/bin/anoma-wallet/cli.rs index 9807516a93..3889489956 100644 --- a/apps/src/bin/anoma-wallet/cli.rs +++ b/apps/src/bin/anoma-wallet/cli.rs @@ -45,12 +45,13 @@ pub fn main() -> Result<()> { fn key_and_address_gen( ctx: Context, args::KeyAndAddressGen { + scheme, alias, unsafe_dont_encrypt, }: args::KeyAndAddressGen, ) { let mut wallet = ctx.wallet; - let (alias, _key) = wallet.gen_key(alias, unsafe_dont_encrypt); + let (alias, _key) = wallet.gen_key(scheme, alias, unsafe_dont_encrypt); wallet.save().unwrap_or_else(|err| eprintln!("{}", err)); println!( "Successfully added a key and an address with alias: \"{}\"", diff --git a/apps/src/lib/cli.rs b/apps/src/lib/cli.rs index 5eef95b34d..f546860cfd 100644 --- a/apps/src/lib/cli.rs +++ b/apps/src/lib/cli.rs @@ -1457,6 +1457,8 @@ pub mod args { const REWARDS_CODE_PATH: ArgOpt = arg_opt("rewards-code-path"); const REWARDS_KEY: ArgOpt = arg_opt("rewards-key"); const RPC_SOCKET_ADDR: ArgOpt = arg_opt("rpc"); + const SCHEME: ArgDefault = + arg_default("scheme", DefaultFn(|| SchemeType::Ed25519)); const SIGNER: ArgOpt = arg_opt("signer"); const SIGNING_KEY_OPT: ArgOpt = SIGNING_KEY.opt(); const SIGNING_KEY: Arg = arg("signing-key"); @@ -1689,6 +1691,7 @@ pub mod args { pub struct TxInitValidator { pub tx: Tx, pub source: WalletAddress, + pub scheme: SchemeType, pub account_key: Option, pub consensus_key: Option, pub rewards_account_key: Option, @@ -1702,6 +1705,7 @@ pub mod args { fn parse(matches: &ArgMatches) -> Self { let tx = Tx::parse(matches); let source = SOURCE.parse(matches); + let scheme = SCHEME.parse(matches); let account_key = VALIDATOR_ACCOUNT_KEY.parse(matches); let consensus_key = VALIDATOR_CONSENSUS_KEY.parse(matches); let rewards_account_key = REWARDS_KEY.parse(matches); @@ -1712,6 +1716,7 @@ pub mod args { Self { tx, source, + scheme, account_key, consensus_key, rewards_account_key, @@ -1727,6 +1732,10 @@ pub mod args { .arg(SOURCE.def().about( "The source account's address that signs the transaction.", )) + .arg(SCHEME.def().about( + "The key scheme/type used for the validator keys. \ + Currently supports ed25519 and secp256k1.", + )) .arg(VALIDATOR_ACCOUNT_KEY.def().about( "A public key for the validator account. A new one will \ be generated if none given.", @@ -2721,6 +2730,8 @@ pub mod args { /// Wallet generate key and implicit address arguments #[derive(Clone, Debug)] pub struct KeyAndAddressGen { + /// Scheme type + pub scheme: SchemeType, /// Key alias pub alias: Option, /// Don't encrypt the keypair @@ -2729,16 +2740,23 @@ pub mod args { impl Args for KeyAndAddressGen { fn parse(matches: &ArgMatches) -> Self { + let scheme = SCHEME.parse(matches); let alias = ALIAS_OPT.parse(matches); let unsafe_dont_encrypt = UNSAFE_DONT_ENCRYPT.parse(matches); Self { + scheme, alias, unsafe_dont_encrypt, } } fn def(app: App) -> App { - app.arg(ALIAS_OPT.def().about( + app.arg(SCHEME.def().about( + "The type of key that should be generated. Argument must be \ + either ed25519 or secp256k1. If none provided, the default \ + key scheme is ed25519.", + )) + .arg(ALIAS_OPT.def().about( "The key and address alias. If none provided, the alias will \ be the public key hash.", )) @@ -3009,6 +3027,7 @@ pub mod args { pub alias: String, pub net_address: SocketAddr, pub unsafe_dont_encrypt: bool, + pub key_scheme: SchemeType, } impl Args for InitGenesisValidator { @@ -3016,10 +3035,12 @@ pub mod args { let alias = ALIAS.parse(matches); let net_address = NET_ADDRESS.parse(matches); let unsafe_dont_encrypt = UNSAFE_DONT_ENCRYPT.parse(matches); + let key_scheme = SCHEME.parse(matches); Self { alias, net_address, unsafe_dont_encrypt, + key_scheme, } } @@ -3034,6 +3055,10 @@ pub mod args { "UNSAFE: Do not encrypt the generated keypairs. Do not \ use this for keys used in a live network.", )) + .arg(SCHEME.def().about( + "The key scheme/type used for the validator keys. \ + Currently supports ed25519 and secp256k1.", + )) } } } diff --git a/apps/src/lib/client/tx.rs b/apps/src/lib/client/tx.rs index 6f1fd96707..1d41ebbc77 100644 --- a/apps/src/lib/client/tx.rs +++ b/apps/src/lib/client/tx.rs @@ -156,6 +156,7 @@ pub async fn submit_init_validator( args::TxInitValidator { tx: tx_args, source, + scheme, account_key, consensus_key, rewards_account_key, @@ -177,16 +178,33 @@ pub async fn submit_init_validator( let account_key = ctx.get_opt_cached(&account_key).unwrap_or_else(|| { println!("Generating validator account key..."); ctx.wallet - .gen_key(Some(validator_key_alias.clone()), unsafe_dont_encrypt) + .gen_key( + scheme, + Some(validator_key_alias.clone()), + unsafe_dont_encrypt, + ) .1 .ref_to() }); - let consensus_key = - ctx.get_opt_cached(&consensus_key).unwrap_or_else(|| { + let consensus_key = ctx + .get_opt_cached(&consensus_key) + .map(|key| match *key { + common::SecretKey::Ed25519(_) => key, + common::SecretKey::Secp256k1(_) => { + eprintln!("Consensus key can only be ed25519"); + safe_exit(1) + } + }) + .unwrap_or_else(|| { println!("Generating consensus key..."); ctx.wallet - .gen_key(Some(consensus_key_alias.clone()), unsafe_dont_encrypt) + .gen_key( + // Note that TM only allows ed25519 for consensus key + SchemeType::Ed25519, + Some(consensus_key_alias.clone()), + unsafe_dont_encrypt, + ) .1 }); @@ -194,7 +212,11 @@ pub async fn submit_init_validator( ctx.get_opt_cached(&rewards_account_key).unwrap_or_else(|| { println!("Generating staking reward account key..."); ctx.wallet - .gen_key(Some(rewards_key_alias.clone()), unsafe_dont_encrypt) + .gen_key( + scheme, + Some(rewards_key_alias.clone()), + unsafe_dont_encrypt, + ) .1 .ref_to() }); @@ -204,7 +226,8 @@ pub async fn submit_init_validator( println!("Generating protocol signing key..."); } // Generate the validator keys - let validator_keys = ctx.wallet.gen_validator_keys(protocol_key).unwrap(); + let validator_keys = + ctx.wallet.gen_validator_keys(protocol_key, scheme).unwrap(); let protocol_key = validator_keys.get_protocol_keypair().ref_to(); let dkg_key = validator_keys .dkg_keypair diff --git a/apps/src/lib/client/utils.rs b/apps/src/lib/client/utils.rs index c377648b65..9043a14db7 100644 --- a/apps/src/lib/client/utils.rs +++ b/apps/src/lib/client/utils.rs @@ -257,11 +257,13 @@ pub async fn join_network( if let Some((validator_alias, pre_genesis_wallet)) = validator_alias_and_pre_genesis_wallet { - let tendermint_node_key: ed25519::SecretKey = pre_genesis_wallet + let tendermint_node_key: common::SecretKey = pre_genesis_wallet .tendermint_node_key .try_to_sk() .unwrap_or_else(|_err| { - eprintln!("Tendermint node key must be ed25519"); + eprintln!( + "Tendermint node key must be common (need to change?)" + ); cli::safe_exit(1) }); @@ -351,10 +353,21 @@ pub async fn join_network( const TENDERMINT_NODE_ID_LENGTH: usize = 20; /// Derive Tendermint node ID from public key -fn id_from_pk(pk: &ed25519::PublicKey) -> TendermintNodeId { - let digest = Sha256::digest(pk.try_to_vec().unwrap().as_slice()); +fn id_from_pk(pk: &common::PublicKey) -> TendermintNodeId { let mut bytes = [0u8; TENDERMINT_NODE_ID_LENGTH]; - bytes.copy_from_slice(&digest[..TENDERMINT_NODE_ID_LENGTH]); + + match pk { + common::PublicKey::Ed25519(_) => { + let _pk: ed25519::PublicKey = pk.try_to_pk().unwrap(); + let digest = Sha256::digest(_pk.try_to_vec().unwrap().as_slice()); + bytes.copy_from_slice(&digest[..TENDERMINT_NODE_ID_LENGTH]); + } + common::PublicKey::Secp256k1(_) => { + let _pk: secp256k1::PublicKey = pk.try_to_pk().unwrap(); + let digest = Sha256::digest(_pk.try_to_vec().unwrap().as_slice()); + bytes.copy_from_slice(&digest[..TENDERMINT_NODE_ID_LENGTH]); + } + } TendermintNodeId::new(bytes) } @@ -440,10 +453,11 @@ pub fn init_network( format!("validator {name} Tendermint node key"), &config.tendermint_node_key, ) - .map(|pk| ed25519::PublicKey::try_from_pk(&pk).unwrap()) .unwrap_or_else(|| { - // Generate a node key - let node_sk = ed25519::SigScheme::generate(&mut rng); + // Generate a node key with ed25519 as default + let node_sk = common::SecretKey::Ed25519( + ed25519::SigScheme::generate(&mut rng), + ); let node_pk = write_tendermint_node_key(&tm_home_dir, node_sk); @@ -512,8 +526,11 @@ pub fn init_network( .unwrap_or_else(|| { let alias = format!("{}-consensus-key", name); println!("Generating validator {} consensus key...", name); - let (_alias, keypair) = - wallet.gen_key(Some(alias), unsafe_dont_encrypt); + let (_alias, keypair) = wallet.gen_key( + SchemeType::Ed25519, + Some(alias), + unsafe_dont_encrypt, + ); // Write consensus key for Tendermint tendermint_node::write_validator_key( @@ -532,8 +549,11 @@ pub fn init_network( .unwrap_or_else(|| { let alias = format!("{}-account-key", name); println!("Generating validator {} account key...", name); - let (_alias, keypair) = - wallet.gen_key(Some(alias), unsafe_dont_encrypt); + let (_alias, keypair) = wallet.gen_key( + SchemeType::Ed25519, + Some(alias), + unsafe_dont_encrypt, + ); keypair.ref_to() }); @@ -547,8 +567,11 @@ pub fn init_network( "Generating validator {} staking reward account key...", name ); - let (_alias, keypair) = - wallet.gen_key(Some(alias), unsafe_dont_encrypt); + let (_alias, keypair) = wallet.gen_key( + SchemeType::Ed25519, + Some(alias), + unsafe_dont_encrypt, + ); keypair.ref_to() }); @@ -559,8 +582,11 @@ pub fn init_network( .unwrap_or_else(|| { let alias = format!("{}-protocol-key", name); println!("Generating validator {} protocol signing key...", name); - let (_alias, keypair) = - wallet.gen_key(Some(alias), unsafe_dont_encrypt); + let (_alias, keypair) = wallet.gen_key( + SchemeType::Ed25519, + Some(alias), + unsafe_dont_encrypt, + ); keypair.ref_to() }); @@ -581,7 +607,10 @@ pub fn init_network( ); let validator_keys = wallet - .gen_validator_keys(Some(protocol_pk.clone())) + .gen_validator_keys( + Some(protocol_pk.clone()), + SchemeType::Ed25519, + ) .expect("Generating new validator keys should not fail"); let pk = validator_keys.dkg_keypair.as_ref().unwrap().public(); wallet.add_validator_data(address.clone(), validator_keys); @@ -715,8 +744,11 @@ pub fn init_network( "Generating implicit account {} key and address ...", name ); - let (_alias, keypair) = - wallet.gen_key(Some(name.clone()), unsafe_dont_encrypt); + let (_alias, keypair) = wallet.gen_key( + SchemeType::Ed25519, + Some(name.clone()), + unsafe_dont_encrypt, + ); let public_key = genesis_config::HexString(keypair.ref_to().to_string()); config.public_key = Some(public_key); @@ -1005,6 +1037,7 @@ fn init_established_account( if config.public_key.is_none() { println!("Generating established account {} key...", name.as_ref()); let (_alias, keypair) = wallet.gen_key( + SchemeType::Ed25519, Some(format!("{}-key", name.as_ref())), unsafe_dont_encrypt, ); @@ -1026,12 +1059,14 @@ pub fn init_genesis_validator( alias, net_address, unsafe_dont_encrypt, + key_scheme, }: args::InitGenesisValidator, ) { let pre_genesis_dir = validator_pre_genesis_dir(&global_args.base_dir, &alias); println!("Generating validator keys..."); let pre_genesis = pre_genesis::ValidatorWallet::gen_and_store( + key_scheme, unsafe_dont_encrypt, &pre_genesis_dir, ) @@ -1136,16 +1171,27 @@ fn network_configs_url_prefix(chain_id: &ChainId) -> String { fn write_tendermint_node_key( tm_home_dir: &Path, - node_sk: ed25519::SecretKey, -) -> ed25519::PublicKey { - let node_pk: ed25519::PublicKey = node_sk.ref_to(); - // Convert and write the keypair into Tendermint - // node_key.json file - let node_keypair = - [node_sk.try_to_vec().unwrap(), node_pk.try_to_vec().unwrap()].concat(); + node_sk: common::SecretKey, +) -> common::PublicKey { + let node_pk: common::PublicKey = node_sk.ref_to(); + + // Convert and write the keypair into Tendermint node_key.json file. + // Tendermint requires concatenating the private-public keys for ed25519 + // but does not for secp256k1. + let (node_keypair, key_str) = match node_sk { + common::SecretKey::Ed25519(sk) => ( + [sk.try_to_vec().unwrap(), sk.ref_to().try_to_vec().unwrap()] + .concat(), + "Ed25519", + ), + common::SecretKey::Secp256k1(sk) => { + (sk.try_to_vec().unwrap(), "Secp256k1") + } + }; + let tm_node_keypair_json = json!({ "priv_key": { - "type": "tendermint/PrivKeyEd25519", + "type": format!("tendermint/PrivKey{}",key_str), "value": base64::encode(node_keypair), } }); diff --git a/apps/src/lib/node/ledger/shell/mod.rs b/apps/src/lib/node/ledger/shell/mod.rs index d93ec23c56..eb47160f9c 100644 --- a/apps/src/lib/node/ledger/shell/mod.rs +++ b/apps/src/lib/node/ledger/shell/mod.rs @@ -65,11 +65,22 @@ use crate::node::ledger::{protocol, storage, tendermint_node}; use crate::wallet::ValidatorData; use crate::{config, wallet}; -fn key_to_tendermint( - pk: &PK, +fn key_to_tendermint( + pk: &common::PublicKey, ) -> std::result::Result { - ed25519::PublicKey::try_from_pk(pk) - .map(|pk| public_key::Sum::Ed25519(pk.try_to_vec().unwrap())) + println!("\nKEY TO TENDERMINT\n"); + match pk { + common::PublicKey::Ed25519(_) => { + println!("\nEd25519\n"); + ed25519::PublicKey::try_from_pk(pk) + .map(|pk| public_key::Sum::Ed25519(pk.try_to_vec().unwrap())) + } + common::PublicKey::Secp256k1(_) => { + println!("\nSecp256k1\n"); + secp256k1::PublicKey::try_from_pk(pk) + .map(|pk| public_key::Sum::Secp256k1(pk.try_to_vec().unwrap())) + } + } } #[derive(Error, Debug)] diff --git a/apps/src/lib/node/ledger/tendermint_node.rs b/apps/src/lib/node/ledger/tendermint_node.rs index 136f925df4..25dd49ba63 100644 --- a/apps/src/lib/node/ledger/tendermint_node.rs +++ b/apps/src/lib/node/ledger/tendermint_node.rs @@ -198,27 +198,43 @@ pub fn reset(tendermint_dir: impl AsRef) -> Result<()> { /// Convert a common signing scheme validator key into JSON for /// Tendermint -fn validator_key_to_json( +fn validator_key_to_json( address: &Address, - sk: &SK, + sk: &common::SecretKey, ) -> std::result::Result { let address = address.raw_hash().unwrap(); - ed25519::SecretKey::try_from_sk(sk).map(|sk| { - let pk: ed25519::PublicKey = sk.ref_to(); - let ck_arr = - [sk.try_to_vec().unwrap(), pk.try_to_vec().unwrap()].concat(); - json!({ - "address": address, - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": base64::encode(pk.try_to_vec().unwrap()), - }, - "priv_key": { - "type": "tendermint/PrivKeyEd25519", - "value": base64::encode(ck_arr), - } - }) - }) + + let (id_str, pk_arr, kp_arr) = match sk { + common::SecretKey::Ed25519(_) => { + let sk_ed: ed25519::SecretKey = sk.try_to_sk().unwrap(); + let keypair = [ + sk_ed.try_to_vec().unwrap(), + sk_ed.ref_to().try_to_vec().unwrap(), + ] + .concat(); + ("Ed25519", sk_ed.ref_to().try_to_vec().unwrap(), keypair) + } + common::SecretKey::Secp256k1(_) => { + let sk_sec: secp256k1::SecretKey = sk.try_to_sk().unwrap(); + ( + "Secp256k1", + sk_sec.ref_to().try_to_vec().unwrap(), + sk_sec.try_to_vec().unwrap(), + ) + } + }; + + Ok(json!({ + "address": address, + "pub_key": { + "type": format!("tendermint/PubKey{}",id_str), + "value": base64::encode(pk_arr), + }, + "priv_key": { + "type": format!("tendermint/PrivKey{}",id_str), + "value": base64::encode(kp_arr), + } + })) } /// Initialize validator private key for Tendermint diff --git a/apps/src/lib/wallet/mod.rs b/apps/src/lib/wallet/mod.rs index 5fec7dca98..b3048ef97d 100644 --- a/apps/src/lib/wallet/mod.rs +++ b/apps/src/lib/wallet/mod.rs @@ -101,11 +101,12 @@ impl Wallet { /// key. pub fn gen_key( &mut self, + scheme: SchemeType, alias: Option, unsafe_dont_encrypt: bool, ) -> (String, Rc) { let password = read_and_confirm_pwd(unsafe_dont_encrypt); - let (alias, key) = self.store.gen_key(alias, password); + let (alias, key) = self.store.gen_key(scheme, alias, password); // Cache the newly added key self.decrypted_key_cache.insert(alias.clone(), key.clone()); (alias.into(), key) @@ -118,6 +119,7 @@ impl Wallet { pub fn gen_validator_keys( &mut self, protocol_pk: Option, + scheme: SchemeType, ) -> Result { let protocol_keypair = protocol_pk.map(|pk| { self.find_key_by_pkh(&PublicKeyHash::from(&pk)) @@ -134,6 +136,7 @@ impl Wallet { Some(Err(err)) => Err(err), other => Ok(Store::gen_validator_keys( other.map(|res| res.unwrap().as_ref().clone()), + scheme, )), } } diff --git a/apps/src/lib/wallet/pre_genesis.rs b/apps/src/lib/wallet/pre_genesis.rs index 6ecb396004..72f719d1e4 100644 --- a/apps/src/lib/wallet/pre_genesis.rs +++ b/apps/src/lib/wallet/pre_genesis.rs @@ -4,7 +4,7 @@ use std::rc::Rc; use ark_serialize::{Read, Write}; use file_lock::{FileLock, FileOptions}; -use namada::types::key::common; +use namada::types::key::{common, SchemeType}; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -66,10 +66,11 @@ impl ValidatorWallet { /// Generate a new [`ValidatorWallet`] with required pre-genesis keys and /// store it as TOML at the given path. pub fn gen_and_store( + scheme: SchemeType, unsafe_dont_encrypt: bool, store_dir: &Path, ) -> std::io::Result { - let validator = Self::gen(unsafe_dont_encrypt); + let validator = Self::gen(scheme, unsafe_dont_encrypt); let data = validator.store.encode(); let wallet_path = validator_file_name(store_dir); // Make sure the dir exists @@ -140,14 +141,21 @@ impl ValidatorWallet { /// Generate a new [`Validator`] with required pre-genesis keys. Will prompt /// for password when `!unsafe_dont_encrypt`. - fn gen(unsafe_dont_encrypt: bool) -> Self { + fn gen(scheme: SchemeType, unsafe_dont_encrypt: bool) -> Self { let password = wallet::read_and_confirm_pwd(unsafe_dont_encrypt); - let (account_key, account_sk) = gen_key_to_store(&password); - let (consensus_key, consensus_sk) = gen_key_to_store(&password); - let (rewards_key, rewards_sk) = gen_key_to_store(&password); - let (tendermint_node_key, tendermint_node_sk) = - gen_key_to_store(&password); - let validator_keys = store::Store::gen_validator_keys(None); + let (account_key, account_sk) = gen_key_to_store(scheme, &password); + let (consensus_key, consensus_sk) = gen_key_to_store( + // Note that TM only allows ed25519 for consensus key + SchemeType::Ed25519, + &password, + ); + let (rewards_key, rewards_sk) = gen_key_to_store(scheme, &password); + let (tendermint_node_key, tendermint_node_sk) = gen_key_to_store( + // Note that TM only allows ed25519 for node IDs + SchemeType::Ed25519, + &password, + ); + let validator_keys = store::Store::gen_validator_keys(None, scheme); let store = ValidatorStore { account_key, consensus_key, @@ -180,9 +188,10 @@ impl ValidatorStore { } fn gen_key_to_store( + scheme: SchemeType, password: &Option, ) -> (StoredKeypair, Rc) { - let sk = store::gen_sk(); + let sk = store::gen_sk(scheme); StoredKeypair::new(sk, password.clone()) } diff --git a/apps/src/lib/wallet/store.rs b/apps/src/lib/wallet/store.rs index 95454d3d2a..76a2053419 100644 --- a/apps/src/lib/wallet/store.rs +++ b/apps/src/lib/wallet/store.rs @@ -259,10 +259,11 @@ impl Store { /// pointer to the key. pub fn gen_key( &mut self, + scheme: SchemeType, alias: Option, password: Option, ) -> (Alias, Rc) { - let sk = gen_sk(); + let sk = gen_sk(scheme); let pkh: PublicKeyHash = PublicKeyHash::from(&sk.ref_to()); let (keypair_to_store, raw_keypair) = StoredKeypair::new(sk, password); let address = Address::Implicit(ImplicitAddress(pkh.clone())); @@ -287,8 +288,10 @@ impl Store { /// Note that this removes the validator data. pub fn gen_validator_keys( protocol_keypair: Option, + scheme: SchemeType, ) -> ValidatorKeys { - let protocol_keypair = protocol_keypair.unwrap_or_else(gen_sk); + let protocol_keypair = + protocol_keypair.unwrap_or_else(|| gen_sk(scheme)); let dkg_keypair = ferveo_common::Keypair::::new( &mut StdRng::from_entropy(), ); @@ -500,12 +503,20 @@ pub fn wallet_file(store_dir: impl AsRef) -> PathBuf { } /// Generate a new secret key. -pub fn gen_sk() -> common::SecretKey { +pub fn gen_sk(scheme: SchemeType) -> common::SecretKey { use rand::rngs::OsRng; let mut csprng = OsRng {}; - ed25519::SigScheme::generate(&mut csprng) - .try_to_sk() - .unwrap() + match scheme { + SchemeType::Ed25519 => ed25519::SigScheme::generate(&mut csprng) + .try_to_sk() + .unwrap(), + SchemeType::Secp256k1 => secp256k1::SigScheme::generate(&mut csprng) + .try_to_sk() + .unwrap(), + SchemeType::Common => common::SigScheme::generate(&mut csprng) + .try_to_sk() + .unwrap(), + } } #[cfg(all(test, feature = "dev"))] @@ -513,9 +524,23 @@ mod test_wallet { use super::*; #[test] - fn test_toml_roundtrip() { + fn test_toml_roundtrip_ed25519() { + let mut store = Store::new(); + let validator_keys = + Store::gen_validator_keys(None, SchemeType::Ed25519); + store.add_validator_data( + Address::decode("atest1v4ehgw36x3prswzxggunzv6pxqmnvdj9xvcyzvpsggeyvs3cg9qnywf589qnwvfsg5erg3fkl09rg5").unwrap(), + validator_keys + ); + let data = store.encode(); + let _ = Store::decode(data).expect("Test failed"); + } + + #[test] + fn test_toml_roundtrip_secp256k1() { let mut store = Store::new(); - let validator_keys = Store::gen_validator_keys(None); + let validator_keys = + Store::gen_validator_keys(None, SchemeType::Secp256k1); store.add_validator_data( Address::decode("atest1v4ehgw36x3prswzxggunzv6pxqmnvdj9xvcyzvpsggeyvs3cg9qnywf589qnwvfsg5erg3fkl09rg5").unwrap(), validator_keys diff --git a/shared/Cargo.toml b/shared/Cargo.toml index 86a96aa743..d0ec9f87a9 100644 --- a/shared/Cargo.toml +++ b/shared/Cargo.toml @@ -41,6 +41,11 @@ wasm-runtime = [ "wasmer-vm", "wasmer", ] +# secp256k1 key signing and verification, disabled in WASM build by default as +# it bloats the build a lot +secp256k1-sign-verify = [ + "libsecp256k1/hmac", +] [dependencies] namada_proof_of_stake = {path = "../proof_of_stake"} @@ -64,6 +69,7 @@ ibc-proto = {git = "https://github.com/heliaxdev/ibc-rs", rev = "30b3495ac56c6c3 ics23 = "0.6.7" itertools = "0.10.0" loupe = {version = "0.1.3", optional = true} +libsecp256k1 = {git = "https://github.com/heliaxdev/libsecp256k1", rev = "bbb3bd44a49db361f21d9db80f9a087c194c0ae9", default-features = false, features = ["std", "static-context"]} parity-wasm = {version = "0.42.2", optional = true} # A fork with state machine testing proptest = {git = "https://github.com/heliaxdev/proptest", branch = "tomas/sm", optional = true} @@ -81,7 +87,7 @@ sha2 = "0.9.3" sparse-merkle-tree = {git = "https://github.com/heliaxdev/sparse-merkle-tree", branch = "yuji/prost-0.9", default-features = false, features = ["std", "borsh"]} tempfile = {version = "3.2.0", optional = true} # temporarily using fork work-around for https://github.com/informalsystems/tendermint-rs/issues/971 -tendermint = {git = "https://github.com/heliaxdev/tendermint-rs", rev = "95c52476bc37927218374f94ac8e2a19bd35bec9"} +tendermint = {git = "https://github.com/heliaxdev/tendermint-rs", rev = "95c52476bc37927218374f94ac8e2a19bd35bec9", features = ["secp256k1"]} tendermint-proto = {git = "https://github.com/heliaxdev/tendermint-rs", rev = "95c52476bc37927218374f94ac8e2a19bd35bec9"} thiserror = "1.0.30" tracing = "0.1.30" @@ -97,6 +103,7 @@ zeroize = "1.5.5" [dev-dependencies] assert_matches = "1.5.0" byte-unit = "4.0.13" +libsecp256k1 = {git = "https://github.com/heliaxdev/libsecp256k1", rev = "bbb3bd44a49db361f21d9db80f9a087c194c0ae9"} pretty_assertions = "0.7.2" # A fork with state machine testing proptest = {git = "https://github.com/heliaxdev/proptest", branch = "tomas/sm"} diff --git a/shared/src/types/key/common.rs b/shared/src/types/key/common.rs index 27e7c29b89..3cdec73bb9 100644 --- a/shared/src/types/key/common.rs +++ b/shared/src/types/key/common.rs @@ -9,8 +9,9 @@ use rand::{CryptoRng, RngCore}; use serde::{Deserialize, Serialize}; use super::{ - ed25519, ParsePublicKeyError, ParseSecretKeyError, ParseSignatureError, - RefTo, SchemeType, SigScheme as SigSchemeTrait, VerifySigError, + ed25519, secp256k1, ParsePublicKeyError, ParseSecretKeyError, + ParseSignatureError, RefTo, SchemeType, SigScheme as SigSchemeTrait, + VerifySigError, }; /// Public key @@ -31,6 +32,8 @@ use super::{ pub enum PublicKey { /// Encapsulate Ed25519 public keys Ed25519(ed25519::PublicKey), + /// Encapsulate Secp256k1 public keys + Secp256k1(secp256k1::PublicKey), } impl super::PublicKey for PublicKey { @@ -49,6 +52,13 @@ impl super::PublicKey for PublicKey { ) .map_err(ParsePublicKeyError::InvalidEncoding)?, )) + } else if PK::TYPE == secp256k1::PublicKey::TYPE { + Ok(Self::Secp256k1( + secp256k1::PublicKey::try_from_slice( + pk.try_to_vec().unwrap().as_slice(), + ) + .map_err(ParsePublicKeyError::InvalidEncoding)?, + )) } else { Err(ParsePublicKeyError::MismatchedScheme) } @@ -77,6 +87,8 @@ impl FromStr for PublicKey { pub enum SecretKey { /// Encapsulate Ed25519 secret keys Ed25519(ed25519::SecretKey), + /// Encapsulate Secp256k1 secret keys + Secp256k1(secp256k1::SecretKey), } impl Serialize for SecretKey { @@ -88,13 +100,12 @@ impl Serialize for SecretKey { S: serde::Serializer, { // String encoded, because toml doesn't support enums - match self { - ed25519_sk @ SecretKey::Ed25519(_) => { - let keypair_string = - format!("{}{}", "ED25519_SK_PREFIX", ed25519_sk); - Serialize::serialize(&keypair_string, serializer) - } - } + let prefix = match self { + SecretKey::Ed25519(_) => "ED25519_SK_PREFIX", + SecretKey::Secp256k1(_) => "SECP256K1_SK_PREFIX", + }; + let keypair_string = format!("{}{}", prefix, self); + Serialize::serialize(&keypair_string, serializer) } } @@ -110,6 +121,10 @@ impl<'de> Deserialize<'de> for SecretKey { .map_err(D::Error::custom)?; if let Some(raw) = keypair_string.strip_prefix("ED25519_SK_PREFIX") { SecretKey::from_str(raw).map_err(D::Error::custom) + } else if let Some(raw) = + keypair_string.strip_prefix("SECP256K1_SK_PREFIX") + { + SecretKey::from_str(raw).map_err(D::Error::custom) } else { Err(D::Error::custom( "Could not deserialize SecretKey do to invalid prefix", @@ -123,16 +138,23 @@ impl super::SecretKey for SecretKey { const TYPE: SchemeType = SigScheme::TYPE; - fn try_from_sk( - pk: &PK, + fn try_from_sk( + sk: &SK, ) -> Result { - if PK::TYPE == Self::TYPE { - Self::try_from_slice(pk.try_to_vec().unwrap().as_ref()) + if SK::TYPE == Self::TYPE { + Self::try_from_slice(sk.try_to_vec().unwrap().as_ref()) .map_err(ParseSecretKeyError::InvalidEncoding) - } else if PK::TYPE == ed25519::SecretKey::TYPE { + } else if SK::TYPE == ed25519::SecretKey::TYPE { Ok(Self::Ed25519( ed25519::SecretKey::try_from_slice( - pk.try_to_vec().unwrap().as_ref(), + sk.try_to_vec().unwrap().as_ref(), + ) + .map_err(ParseSecretKeyError::InvalidEncoding)?, + )) + } else if SK::TYPE == secp256k1::SecretKey::TYPE { + Ok(Self::Secp256k1( + secp256k1::SecretKey::try_from_slice( + sk.try_to_vec().unwrap().as_ref(), ) .map_err(ParseSecretKeyError::InvalidEncoding)?, )) @@ -146,6 +168,7 @@ impl RefTo for SecretKey { fn ref_to(&self) -> PublicKey { match self { SecretKey::Ed25519(sk) => PublicKey::Ed25519(sk.ref_to()), + SecretKey::Secp256k1(sk) => PublicKey::Secp256k1(sk.ref_to()), } } } @@ -183,21 +206,30 @@ impl FromStr for SecretKey { pub enum Signature { /// Encapsulate Ed25519 signatures Ed25519(ed25519::Signature), + /// Encapsulate Secp256k1 signatures + Secp256k1(secp256k1::Signature), } impl super::Signature for Signature { const TYPE: SchemeType = SigScheme::TYPE; - fn try_from_sig( - pk: &PK, + fn try_from_sig( + sig: &SIG, ) -> Result { - if PK::TYPE == Self::TYPE { - Self::try_from_slice(pk.try_to_vec().unwrap().as_slice()) + if SIG::TYPE == Self::TYPE { + Self::try_from_slice(sig.try_to_vec().unwrap().as_slice()) .map_err(ParseSignatureError::InvalidEncoding) - } else if PK::TYPE == ed25519::Signature::TYPE { + } else if SIG::TYPE == ed25519::Signature::TYPE { Ok(Self::Ed25519( ed25519::Signature::try_from_slice( - pk.try_to_vec().unwrap().as_slice(), + sig.try_to_vec().unwrap().as_slice(), + ) + .map_err(ParseSignatureError::InvalidEncoding)?, + )) + } else if SIG::TYPE == secp256k1::Signature::TYPE { + Ok(Self::Secp256k1( + secp256k1::Signature::try_from_slice( + sig.try_to_vec().unwrap().as_slice(), ) .map_err(ParseSignatureError::InvalidEncoding)?, )) @@ -248,6 +280,9 @@ impl super::SigScheme for SigScheme { SecretKey::Ed25519(kp) => { Signature::Ed25519(ed25519::SigScheme::sign(kp, data)) } + SecretKey::Secp256k1(kp) => { + Signature::Secp256k1(secp256k1::SigScheme::sign(kp, data)) + } } } @@ -259,7 +294,11 @@ impl super::SigScheme for SigScheme { match (pk, sig) { (PublicKey::Ed25519(pk), Signature::Ed25519(sig)) => { ed25519::SigScheme::verify_signature(pk, data, sig) - } // _ => Err(VerifySigError::MismatchedScheme), + } + (PublicKey::Secp256k1(pk), Signature::Secp256k1(sig)) => { + secp256k1::SigScheme::verify_signature(pk, data, sig) + } + _ => Err(VerifySigError::MismatchedScheme), } } @@ -271,7 +310,11 @@ impl super::SigScheme for SigScheme { match (pk, sig) { (PublicKey::Ed25519(pk), Signature::Ed25519(sig)) => { ed25519::SigScheme::verify_signature_raw(pk, data, sig) - } // _ => Err(VerifySigError::MismatchedScheme), + } + (PublicKey::Secp256k1(pk), Signature::Secp256k1(sig)) => { + secp256k1::SigScheme::verify_signature_raw(pk, data, sig) + } + _ => Err(VerifySigError::MismatchedScheme), } } } diff --git a/shared/src/types/key/ed25519.rs b/shared/src/types/key/ed25519.rs index 48db89005a..dbcf9fe04c 100644 --- a/shared/src/types/key/ed25519.rs +++ b/shared/src/types/key/ed25519.rs @@ -31,11 +31,9 @@ impl super::PublicKey for PublicKey { pk: &PK, ) -> Result { if PK::TYPE == super::common::PublicKey::TYPE { - // TODO remove once the wildcard match is used below - #[allow(clippy::bind_instead_of_map)] super::common::PublicKey::try_from_pk(pk).and_then(|x| match x { super::common::PublicKey::Ed25519(epk) => Ok(epk), - // _ => Err(ParsePublicKeyError::MismatchedScheme), + _ => Err(ParsePublicKeyError::MismatchedScheme), }) } else if PK::TYPE == Self::TYPE { Self::try_from_slice(pk.try_to_vec().unwrap().as_slice()) @@ -135,11 +133,9 @@ impl super::SecretKey for SecretKey { pk: &PK, ) -> Result { if PK::TYPE == super::common::SecretKey::TYPE { - // TODO remove once the wildcard match is used below - #[allow(clippy::bind_instead_of_map)] super::common::SecretKey::try_from_sk(pk).and_then(|x| match x { super::common::SecretKey::Ed25519(epk) => Ok(epk), - // _ => Err(ParseSecretKeyError::MismatchedScheme), + _ => Err(ParseSecretKeyError::MismatchedScheme), }) } else if PK::TYPE == Self::TYPE { Self::try_from_slice(pk.try_to_vec().unwrap().as_slice()) @@ -238,11 +234,9 @@ impl super::Signature for Signature { pk: &PK, ) -> Result { if PK::TYPE == super::common::Signature::TYPE { - // TODO remove once the wildcard match is used below - #[allow(clippy::bind_instead_of_map)] super::common::Signature::try_from_sig(pk).and_then(|x| match x { super::common::Signature::Ed25519(epk) => Ok(epk), - // _ => Err(ParseSignatureError::MismatchedScheme), + _ => Err(ParseSignatureError::MismatchedScheme), }) } else if PK::TYPE == Self::TYPE { Self::try_from_slice(pk.try_to_vec().unwrap().as_slice()) @@ -327,7 +321,7 @@ impl super::SigScheme for SigScheme { type SecretKey = SecretKey; type Signature = Signature; - const TYPE: SchemeType = SchemeType::Ed25519Consensus; + const TYPE: SchemeType = SchemeType::Ed25519; #[cfg(feature = "rand")] fn generate(csprng: &mut R) -> SecretKey diff --git a/shared/src/types/key/mod.rs b/shared/src/types/key/mod.rs index 9deccf75a9..666cc3fb5e 100644 --- a/shared/src/types/key/mod.rs +++ b/shared/src/types/key/mod.rs @@ -19,6 +19,7 @@ use crate::types::address; pub mod common; pub mod ed25519; +pub mod secp256k1; const PK_STORAGE_KEY: &str = "public_key"; const PROTOCOL_PK_STORAGE_KEY: &str = "protocol_public_key"; @@ -126,27 +127,42 @@ pub trait TryFromRef: Sized { } /// Type capturing signature scheme IDs -#[derive(PartialEq, Eq, Copy, Clone)] +#[derive(PartialEq, Eq, Copy, Clone, Debug)] pub enum SchemeType { - /// Type identifier for Ed25519-consensus - Ed25519Consensus, + /// Type identifier for Ed25519 scheme + Ed25519, + /// Type identifier for Secp256k1 scheme + Secp256k1, /// Type identifier for Common Common, } +impl FromStr for SchemeType { + type Err = (); + + fn from_str(input: &str) -> Result { + match input.to_lowercase().as_str() { + "ed25519" => Ok(Self::Ed25519), + "secp256k1" => Ok(Self::Secp256k1), + "common" => Ok(Self::Common), + _ => Err(()), + } + } +} + /// Represents a signature pub trait Signature: - Hash + PartialOrd + Serialize + BorshSerialize + BorshDeserialize + Hash + PartialOrd + Serialize + BorshSerialize + BorshDeserialize + BorshSchema { /// The scheme type of this implementation const TYPE: SchemeType; /// Convert from one Signature type to another - fn try_from_sig( - pk: &PK, + fn try_from_sig( + sig: &SIG, ) -> Result { - if PK::TYPE == Self::TYPE { - let sig_arr = pk.try_to_vec().unwrap(); + if SIG::TYPE == Self::TYPE { + let sig_arr = sig.try_to_vec().unwrap(); let res = Self::try_from_slice(sig_arr.as_ref()); res.map_err(ParseSignatureError::InvalidEncoding) } else { @@ -154,8 +170,8 @@ pub trait Signature: } } /// Convert from self to another SecretKey type - fn try_to_sig(&self) -> Result { - PK::try_from_sig(self) + fn try_to_sig(&self) -> Result { + SIG::try_from_sig(self) } } @@ -164,6 +180,7 @@ pub trait Signature: pub trait PublicKey: BorshSerialize + BorshDeserialize + + BorshSchema + Ord + Clone + Display @@ -188,7 +205,7 @@ pub trait PublicKey: Err(ParsePublicKeyError::MismatchedScheme) } } - /// Convert from self to another SecretKey type + /// Convert from self to another PublicKey type fn try_to_pk(&self) -> Result { PK::try_from_pk(self) } @@ -199,6 +216,7 @@ pub trait PublicKey: pub trait SecretKey: BorshSerialize + BorshDeserialize + + BorshSchema + Display + Debug + RefTo @@ -267,7 +285,8 @@ pub trait SigScheme: Eq + Ord + Debug + Serialize + Default { ) -> Result<(), VerifySigError>; } -/// Ed25519 public key hash +/// Public key hash derived from `common::Key` borsh encoded bytes (hex string +/// of the first 40 chars of sha256 hash) #[derive( Debug, Clone, @@ -415,12 +434,29 @@ macro_rules! sigscheme_test { println!("Public key: {}", public_key); println!("Secret key: {}", secret_key); } + + /// Sign a simple message and verify the signature. + #[test] + fn gen_sign_verify() { + use rand::prelude::ThreadRng; + use rand::thread_rng; + + let mut rng: ThreadRng = thread_rng(); + let sk = <$type>::generate(&mut rng); + let sig = <$type>::sign(&sk, b"hello"); + assert!( + <$type>::verify_signature_raw(&sk.ref_to(), b"hello", &sig) + .is_ok() + ); + } } }; } #[cfg(test)] sigscheme_test! {ed25519_test, ed25519::SigScheme} +#[cfg(test)] +sigscheme_test! {secp256k1_test, secp256k1::SigScheme} #[cfg(test)] mod more_tests { @@ -430,11 +466,10 @@ mod more_tests { fn zeroize_keypair_ed25519() { use rand::thread_rng; - let sk = ed25519::SecretKey(Box::new( - ed25519_consensus::SigningKey::new(thread_rng()), - )); - let len = sk.0.as_bytes().len(); - let ptr = sk.0.as_bytes().as_ptr(); + let sk = ed25519::SigScheme::generate(&mut thread_rng()); + let sk_bytes = sk.0.as_bytes(); + let len = sk_bytes.len(); + let ptr = sk_bytes.as_ptr(); drop(sk); @@ -442,4 +477,22 @@ mod more_tests { core::slice::from_raw_parts(ptr, len) }); } + + #[test] + fn zeroize_keypair_secp256k1() { + use rand::thread_rng; + + let mut sk = secp256k1::SigScheme::generate(&mut thread_rng()); + let sk_scalar = sk.0.to_scalar_ref(); + let len = sk_scalar.0.len(); + let ptr = sk_scalar.0.as_ref().as_ptr(); + + let original_data = sk_scalar.0; + + drop(sk); + + assert_ne!(&original_data, unsafe { + core::slice::from_raw_parts(ptr, len) + }); + } } diff --git a/shared/src/types/key/secp256k1.rs b/shared/src/types/key/secp256k1.rs new file mode 100644 index 0000000000..99bcbb3f67 --- /dev/null +++ b/shared/src/types/key/secp256k1.rs @@ -0,0 +1,503 @@ +//! secp256k1 keys and related functionality + +use std::fmt; +use std::fmt::{Debug, Display}; +use std::hash::{Hash, Hasher}; +use std::io::{ErrorKind, Write}; +use std::str::FromStr; + +use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; +#[cfg(feature = "rand")] +use rand::{CryptoRng, RngCore}; +use serde::de::{Error, SeqAccess, Visitor}; +use serde::ser::SerializeTuple; +use serde::{Deserialize, Serialize, Serializer}; + +use super::{ + ParsePublicKeyError, ParseSecretKeyError, ParseSignatureError, RefTo, + SchemeType, SigScheme as SigSchemeTrait, VerifySigError, +}; + +/// secp256k1 public key +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct PublicKey(pub libsecp256k1::PublicKey); + +impl super::PublicKey for PublicKey { + const TYPE: SchemeType = SigScheme::TYPE; + + fn try_from_pk( + pk: &PK, + ) -> Result { + if PK::TYPE == super::common::PublicKey::TYPE { + super::common::PublicKey::try_from_pk(pk).and_then(|x| match x { + super::common::PublicKey::Secp256k1(epk) => Ok(epk), + _ => Err(ParsePublicKeyError::MismatchedScheme), + }) + } else if PK::TYPE == Self::TYPE { + Self::try_from_slice(pk.try_to_vec().unwrap().as_slice()) + .map_err(ParsePublicKeyError::InvalidEncoding) + } else { + Err(ParsePublicKeyError::MismatchedScheme) + } + } +} + +impl BorshDeserialize for PublicKey { + fn deserialize(buf: &mut &[u8]) -> std::io::Result { + // deserialize the bytes first + let pk = libsecp256k1::PublicKey::parse_compressed( + buf.get(0..libsecp256k1::util::COMPRESSED_PUBLIC_KEY_SIZE) + .ok_or_else(|| std::io::Error::from(ErrorKind::UnexpectedEof))? + .try_into() + .unwrap(), + ) + .map_err(|e| { + std::io::Error::new( + ErrorKind::InvalidInput, + format!("Error decoding secp256k1 public key: {}", e), + ) + })?; + *buf = &buf[libsecp256k1::util::COMPRESSED_PUBLIC_KEY_SIZE..]; + Ok(PublicKey(pk)) + } +} + +impl BorshSerialize for PublicKey { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + writer.write_all(&self.0.serialize_compressed())?; + Ok(()) + } +} + +impl BorshSchema for PublicKey { + fn add_definitions_recursively( + definitions: &mut std::collections::HashMap< + borsh::schema::Declaration, + borsh::schema::Definition, + >, + ) { + // Encoded as `[u8; COMPRESSED_PUBLIC_KEY_SIZE]` + let elements = "u8".into(); + let length = libsecp256k1::util::COMPRESSED_PUBLIC_KEY_SIZE as u32; + let definition = borsh::schema::Definition::Array { elements, length }; + definitions.insert(Self::declaration(), definition); + } + + fn declaration() -> borsh::schema::Declaration { + "secp256k1::PublicKey".into() + } +} + +#[allow(clippy::derive_hash_xor_eq)] +impl Hash for PublicKey { + fn hash(&self, state: &mut H) { + self.0.serialize_compressed().hash(state); + } +} + +impl PartialOrd for PublicKey { + fn partial_cmp(&self, other: &Self) -> Option { + self.0 + .serialize_compressed() + .partial_cmp(&other.0.serialize_compressed()) + } +} + +impl Ord for PublicKey { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.0 + .serialize_compressed() + .cmp(&other.0.serialize_compressed()) + } +} + +impl Display for PublicKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", hex::encode(&self.0.serialize_compressed())) + } +} + +impl FromStr for PublicKey { + type Err = ParsePublicKeyError; + + fn from_str(s: &str) -> Result { + let vec = hex::decode(s).map_err(ParsePublicKeyError::InvalidHex)?; + BorshDeserialize::try_from_slice(&vec) + .map_err(ParsePublicKeyError::InvalidEncoding) + } +} + +impl From for PublicKey { + fn from(pk: libsecp256k1::PublicKey) -> Self { + Self(pk) + } +} + +/// Secp256k1 secret key +#[derive(Debug, Clone)] +pub struct SecretKey(pub Box); + +impl super::SecretKey for SecretKey { + type PublicKey = PublicKey; + + const TYPE: SchemeType = SigScheme::TYPE; + + fn try_from_sk( + pk: &PK, + ) -> Result { + if PK::TYPE == super::common::SecretKey::TYPE { + super::common::SecretKey::try_from_sk(pk).and_then(|x| match x { + super::common::SecretKey::Secp256k1(epk) => Ok(epk), + _ => Err(ParseSecretKeyError::MismatchedScheme), + }) + } else if PK::TYPE == Self::TYPE { + Self::try_from_slice(pk.try_to_vec().unwrap().as_slice()) + .map_err(ParseSecretKeyError::InvalidEncoding) + } else { + Err(ParseSecretKeyError::MismatchedScheme) + } + } +} + +impl Serialize for SecretKey { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let arr = self.0.serialize(); + serde::Serialize::serialize(&arr, serializer) + } +} + +impl<'de> Deserialize<'de> for SecretKey { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let arr_res: [u8; libsecp256k1::util::SECRET_KEY_SIZE] = + serde::Deserialize::deserialize(deserializer)?; + let key = libsecp256k1::SecretKey::parse_slice(&arr_res) + .map_err(D::Error::custom); + Ok(SecretKey(Box::new(key.unwrap()))) + } +} + +impl BorshDeserialize for SecretKey { + fn deserialize(buf: &mut &[u8]) -> std::io::Result { + // deserialize the bytes first + Ok(SecretKey(Box::new( + libsecp256k1::SecretKey::parse( + &(BorshDeserialize::deserialize(buf)?), + ) + .map_err(|e| { + std::io::Error::new( + ErrorKind::InvalidInput, + format!("Error decoding secp256k1 secret key: {}", e), + ) + })?, + ))) + } +} + +impl BorshSerialize for SecretKey { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + BorshSerialize::serialize(&self.0.serialize(), writer) + } +} + +impl BorshSchema for SecretKey { + fn add_definitions_recursively( + definitions: &mut std::collections::HashMap< + borsh::schema::Declaration, + borsh::schema::Definition, + >, + ) { + // Encoded as `[u8; SECRET_KEY_SIZE]` + let elements = "u8".into(); + let length = libsecp256k1::util::SECRET_KEY_SIZE as u32; + let definition = borsh::schema::Definition::Array { elements, length }; + definitions.insert(Self::declaration(), definition); + } + + fn declaration() -> borsh::schema::Declaration { + "secp256k1::SecretKey".into() + } +} + +impl Display for SecretKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", hex::encode(&self.0.serialize())) + } +} + +impl FromStr for SecretKey { + type Err = ParseSecretKeyError; + + fn from_str(s: &str) -> Result { + let vec = hex::decode(s).map_err(ParseSecretKeyError::InvalidHex)?; + BorshDeserialize::try_from_slice(&vec) + .map_err(ParseSecretKeyError::InvalidEncoding) + } +} + +impl RefTo for SecretKey { + fn ref_to(&self) -> PublicKey { + PublicKey(libsecp256k1::PublicKey::from_secret_key(&self.0)) + } +} + +/// Secp256k1 signature +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Signature(pub libsecp256k1::Signature); + +impl super::Signature for Signature { + const TYPE: SchemeType = SigScheme::TYPE; + + fn try_from_sig( + pk: &PK, + ) -> Result { + if PK::TYPE == super::common::Signature::TYPE { + super::common::Signature::try_from_sig(pk).and_then(|x| match x { + super::common::Signature::Secp256k1(epk) => Ok(epk), + _ => Err(ParseSignatureError::MismatchedScheme), + }) + } else if PK::TYPE == Self::TYPE { + Self::try_from_slice(pk.try_to_vec().unwrap().as_slice()) + .map_err(ParseSignatureError::InvalidEncoding) + } else { + Err(ParseSignatureError::MismatchedScheme) + } + } +} + +// Would ideally like Serialize, Deserialize to be implemented in libsecp256k1, +// may try to do so and merge upstream in the future. + +impl Serialize for Signature { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let arr = self.0.serialize(); + // TODO: implement the line below, currently cannot support [u8; 64] + // serde::Serialize::serialize(&arr, serializer) + + let mut seq = serializer.serialize_tuple(arr.len())?; + for elem in &arr[..] { + seq.serialize_element(elem)?; + } + seq.end() + } +} + +impl<'de> Deserialize<'de> for Signature { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct ByteArrayVisitor; + + impl<'de> Visitor<'de> for ByteArrayVisitor { + type Value = [u8; libsecp256k1::util::SIGNATURE_SIZE]; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(&format!( + "an array of length {}", + libsecp256k1::util::SIGNATURE_SIZE + )) + } + + fn visit_seq(self, mut seq: A) -> Result<[u8; 64], A::Error> + where + A: SeqAccess<'de>, + { + let mut arr = [0u8; libsecp256k1::util::SIGNATURE_SIZE]; + #[allow(clippy::needless_range_loop)] + for i in 0..libsecp256k1::util::SIGNATURE_SIZE { + arr[i] = seq + .next_element()? + .ok_or_else(|| Error::invalid_length(i, &self))?; + } + Ok(arr) + } + } + + let arr_res = deserializer.deserialize_tuple( + libsecp256k1::util::SIGNATURE_SIZE, + ByteArrayVisitor, + )?; + let sig = libsecp256k1::Signature::parse_standard(&arr_res) + .map_err(D::Error::custom); + Ok(Signature(sig.unwrap())) + } +} + +impl BorshDeserialize for Signature { + fn deserialize(buf: &mut &[u8]) -> std::io::Result { + // deserialize the bytes first + Ok(Signature( + libsecp256k1::Signature::parse_standard( + &(BorshDeserialize::deserialize(buf)?), + ) + .map_err(|e| { + std::io::Error::new( + ErrorKind::InvalidInput, + format!("Error decoding secp256k1 signature: {}", e), + ) + })?, + )) + } +} + +impl BorshSerialize for Signature { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + BorshSerialize::serialize(&self.0.serialize(), writer) + } +} + +impl BorshSchema for Signature { + fn add_definitions_recursively( + definitions: &mut std::collections::HashMap< + borsh::schema::Declaration, + borsh::schema::Definition, + >, + ) { + // Encoded as `[u8; SIGNATURE_SIZE]` + let elements = "u8".into(); + let length = libsecp256k1::util::SIGNATURE_SIZE as u32; + let definition = borsh::schema::Definition::Array { elements, length }; + definitions.insert(Self::declaration(), definition); + } + + fn declaration() -> borsh::schema::Declaration { + "secp256k1::Signature".into() + } +} + +#[allow(clippy::derive_hash_xor_eq)] +impl Hash for Signature { + fn hash(&self, state: &mut H) { + self.0.serialize().hash(state); + } +} + +impl PartialOrd for Signature { + fn partial_cmp(&self, other: &Self) -> Option { + self.0.serialize().partial_cmp(&other.0.serialize()) + } +} + +/// An implementation of the Secp256k1 signature scheme +#[derive( + Debug, + Clone, + BorshSerialize, + BorshDeserialize, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Serialize, + Deserialize, + Default, +)] +pub struct SigScheme; + +impl super::SigScheme for SigScheme { + type PublicKey = PublicKey; + type SecretKey = SecretKey; + type Signature = Signature; + + const TYPE: SchemeType = SchemeType::Secp256k1; + + #[cfg(feature = "rand")] + fn generate(csprng: &mut R) -> SecretKey + where + R: CryptoRng + RngCore, + { + SecretKey(Box::new(libsecp256k1::SecretKey::random(csprng))) + } + + /// Sign the data with a key + fn sign(keypair: &SecretKey, data: impl AsRef<[u8]>) -> Self::Signature { + #[cfg(not(any(test, features = "secp256k1-sign-verify")))] + { + // to avoid `unused-variables` warn + let _ = (keypair, data); + panic!("\"secp256k1-sign-verify\" feature must be enabled"); + } + + #[cfg(any(test, features = "secp256k1-sign-verify"))] + { + use sha2::{Digest, Sha256}; + let hash = Sha256::digest(data.as_ref()); + let message = libsecp256k1::Message::parse_slice(hash.as_ref()) + .expect("Message encoding should not fail"); + Signature(libsecp256k1::sign(&message, &keypair.0).0) + } + } + + fn verify_signature( + pk: &Self::PublicKey, + data: &T, + sig: &Self::Signature, + ) -> Result<(), VerifySigError> { + #[cfg(not(any(test, features = "secp256k1-sign-verify")))] + { + // to avoid `unused-variables` warn + let _ = (pk, data, sig); + panic!("\"secp256k1-sign-verify\" feature must be enabled"); + } + + #[cfg(any(test, features = "secp256k1-sign-verify"))] + { + use sha2::{Digest, Sha256}; + let bytes = &data + .try_to_vec() + .map_err(VerifySigError::DataEncodingError)?[..]; + let hash = Sha256::digest(bytes); + let message = &libsecp256k1::Message::parse_slice(hash.as_ref()) + .expect("Error parsing given data"); + let is_valid = libsecp256k1::verify(message, &sig.0, &pk.0); + if is_valid { + Ok(()) + } else { + Err(VerifySigError::SigVerifyError(format!( + "Error verifying secp256k1 signature: {}", + libsecp256k1::Error::InvalidSignature + ))) + } + } + } + + fn verify_signature_raw( + pk: &Self::PublicKey, + data: &[u8], + sig: &Self::Signature, + ) -> Result<(), VerifySigError> { + #[cfg(not(any(test, features = "secp256k1-sign-verify")))] + { + // to avoid `unused-variables` warn + let _ = (pk, data, sig); + panic!("\"secp256k1-sign-verify\" feature must be enabled"); + } + + #[cfg(any(test, features = "secp256k1-sign-verify"))] + { + use sha2::{Digest, Sha256}; + let hash = Sha256::digest(data); + let message = &libsecp256k1::Message::parse_slice(hash.as_ref()) + .expect("Error parsing raw data"); + let is_valid = libsecp256k1::verify(message, &sig.0, &pk.0); + if is_valid { + Ok(()) + } else { + Err(VerifySigError::SigVerifyError(format!( + "Error verifying secp256k1 signature: {}", + libsecp256k1::Error::InvalidSignature + ))) + } + } + } +} diff --git a/tests/src/e2e/ledger_tests.rs b/tests/src/e2e/ledger_tests.rs index 552e675e67..22eb4f4ac5 100644 --- a/tests/src/e2e/ledger_tests.rs +++ b/tests/src/e2e/ledger_tests.rs @@ -1540,7 +1540,8 @@ fn test_genesis_validators() -> Result<()> { // the given index let get_first_port = |ix: u8| net_address_port_0 + 6 * (ix as u16 + 1); - // 1. Setup 2 genesis validators + // 1. Setup 2 genesis validators, one with ed25519 keys (0) and one with + // secp256k1 keys (1) let validator_0_alias = "validator-0"; let validator_1_alias = "validator-1"; @@ -1552,6 +1553,8 @@ fn test_genesis_validators() -> Result<()> { "--unsafe-dont-encrypt", "--alias", validator_0_alias, + "--scheme", + "ed25519", "--net-address", &format!("127.0.0.1:{}", get_first_port(0)), ], @@ -1588,6 +1591,8 @@ fn test_genesis_validators() -> Result<()> { "--unsafe-dont-encrypt", "--alias", validator_1_alias, + "--scheme", + "secp256k1", "--net-address", &format!("127.0.0.1:{}", get_first_port(1)), ], diff --git a/wasm/checksums.json b/wasm/checksums.json index 91c2317ccf..b08f88838c 100644 --- a/wasm/checksums.json +++ b/wasm/checksums.json @@ -1,19 +1,19 @@ { - "tx_bond.wasm": "tx_bond.5aa466cd8ecbe9c5f9b777956052f4e0164f099c30260475f0e9cd71bbd99e0d.wasm", - "tx_from_intent.wasm": "tx_from_intent.95f421a3caa886186655c92aee1545e95d893ad6ce003e5317dc16ca5ef2076b.wasm", - "tx_ibc.wasm": "tx_ibc.c3c5dafe1a1740a848394c3264e8802184181658c12356f99ce95388922220e7.wasm", - "tx_init_account.wasm": "tx_init_account.9e70d6ca9ee4c0b9ca62a58b95f52321df145f5c84fff44f5a88bba0771a1a17.wasm", - "tx_init_nft.wasm": "tx_init_nft.7d57769d2da3d1dba1775763d6d33305335c8232220a459c847e512ef7ef1165.wasm", - "tx_init_proposal.wasm": "tx_init_proposal.20a4bb9daa9499b39b564124a4cc07421b24ba1c36f8c8f48fda6772b295f841.wasm", - "tx_init_validator.wasm": "tx_init_validator.a7cf7bbb695a3a8c618a8811a4a7c061231b0272b06234fdcfb5264e9938895d.wasm", - "tx_mint_nft.wasm": "tx_mint_nft.24272eface53a9a4c4d927ae33c6e139c56779ecae4854095153a0300da59cbc.wasm", - "tx_transfer.wasm": "tx_transfer.9f13d688b915a150dcfd2472c5ba698fddfc4a3a080e81f06b3a061af72508d9.wasm", - "tx_unbond.wasm": "tx_unbond.e9c6c5f9fd6987afd3213d533735d2bb6349a9a002f0f6d1b8fb1b6ea1581cfd.wasm", - "tx_update_vp.wasm": "tx_update_vp.d47bfe6ef55a86bce36093feeff74fe09ec7cffebf9696dd37658756a4eb793d.wasm", - "tx_vote_proposal.wasm": "tx_vote_proposal.e1c327bbe49d7b6b5445ad641d9f154813ae73c98ba8df7b85c5a06dc4ede41e.wasm", - "tx_withdraw.wasm": "tx_withdraw.7f83fe1f8bb0fa1864c64d329cec54c317524715644907066ab322f5b2be0056.wasm", - "vp_nft.wasm": "vp_nft.955cbe702d2925a209529cc5d7b810768fe3e6c597907a941417bc50ca31e42e.wasm", - "vp_testnet_faucet.wasm": "vp_testnet_faucet.35c7df353e7d4ffd986f92a81a2b49bd85f4b0265d85be9c38fe88c389d61ce3.wasm", - "vp_token.wasm": "vp_token.abbca3decf5ca2fb46b7de0589b52355c413c3281f6c8aa13868008747b41484.wasm", - "vp_user.wasm": "vp_user.e4a2076ebd3d458a2d57768007105a0e3baed597456e401b3a2787d4314e511f.wasm" + "tx_bond.wasm": "tx_bond.7cdd51f8b994d5116e6de12535afcb29df22519f4d3da7d507fe0367a2942a34.wasm", + "tx_from_intent.wasm": "tx_from_intent.6cdb481f546875239af11816d5cc1311306c8d5a325f1ad44921ec5eb2c5ab94.wasm", + "tx_ibc.wasm": "tx_ibc.4ae21c942a1c047949fb756b4f941149ad2d2f87af15afab78edd813a2e828ae.wasm", + "tx_init_account.wasm": "tx_init_account.a4a0bed00c70568a16a78cf8a802fcdc0ae29a062acec713ac39902d43ce6de8.wasm", + "tx_init_nft.wasm": "tx_init_nft.ea7f747f7f8532d53093bd4b54df1a45ab448b3b5202df390932a1e72e22ecbc.wasm", + "tx_init_proposal.wasm": "tx_init_proposal.34e1b8e27bfc0badbc13234520f8382d7caf697d35aa5a67faf62b3e8876523f.wasm", + "tx_init_validator.wasm": "tx_init_validator.123d7245003176581bf52f49da926113ff61774c937c390e2ed82583c79658fd.wasm", + "tx_mint_nft.wasm": "tx_mint_nft.8e9b3c5fdf814e2aea1858e30a14a9d226584b6ba3b32d7b6d535c790ebde93b.wasm", + "tx_transfer.wasm": "tx_transfer.3dcde1395e25c0399de2c6cb46cf8e2146a97c063a821ea555ddd086b7786419.wasm", + "tx_unbond.wasm": "tx_unbond.4a08ccb3c82d7bdbd6ca0d6b15ffe2086017e8779dfd15fd55d5cec241af02f7.wasm", + "tx_update_vp.wasm": "tx_update_vp.83d4caeb5a9ca3009cd899810493a6b87b4c07fa9ed36f297db99dc881fb9a1c.wasm", + "tx_vote_proposal.wasm": "tx_vote_proposal.cffcfd2414084def136f09d84a0a904898758a93925e09694fc688f6d1c2c4ee.wasm", + "tx_withdraw.wasm": "tx_withdraw.4dc442c9369e1831105eece71f73446b44f5712702ddf338756002669cd3166b.wasm", + "vp_nft.wasm": "vp_nft.4e865442cf80b77b71301a7b34ae95dad54947a39b24b7e80ff7bb9f5d3830b9.wasm", + "vp_testnet_faucet.wasm": "vp_testnet_faucet.e4d276346dcf0d920f91a4e1f67a3a941e055b6ea290bbdf0256fdac6212891f.wasm", + "vp_token.wasm": "vp_token.0612d2f42697fdd431bb503f3746e7092f8851c0600b377ad07e311c4d22fbca.wasm", + "vp_user.wasm": "vp_user.1d97195ab464b9dac70815a436ab8f7990b50b52bd6ff5042949d5dd14ac9a62.wasm" } \ No newline at end of file diff --git a/wasm/tx_template/Cargo.lock b/wasm/tx_template/Cargo.lock index 56d188bd09..d41c7c2f4f 100644 --- a/wasm/tx_template/Cargo.lock +++ b/wasm/tx_template/Cargo.lock @@ -205,6 +205,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base64" version = "0.13.0" @@ -403,6 +409,12 @@ dependencies = [ "syn", ] +[[package]] +name = "const-oid" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -531,6 +543,24 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" +dependencies = [ + "generic-array", + "rand_core 0.6.3", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.3" @@ -541,6 +571,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "curve25519-dalek" version = "3.2.0" @@ -602,6 +642,15 @@ dependencies = [ "syn", ] +[[package]] +name = "der" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" +dependencies = [ + "const-oid", +] + [[package]] name = "derivative" version = "2.2.0" @@ -670,6 +719,18 @@ dependencies = [ "memmap2", ] +[[package]] +name = "ecdsa" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + [[package]] name = "ed25519" version = "1.4.0" @@ -712,6 +773,24 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "elliptic-curve" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "ff", + "generic-array", + "group", + "rand_core 0.6.3", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "enum-iterator" version = "0.7.0" @@ -791,6 +870,16 @@ dependencies = [ "serde_bytes", ] +[[package]] +name = "ff" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924" +dependencies = [ + "rand_core 0.6.3", + "subtle", +] + [[package]] name = "fixedbitset" version = "0.4.1" @@ -922,6 +1011,17 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +[[package]] +name = "group" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" +dependencies = [ + "ff", + "rand_core 0.6.3", + "subtle", +] + [[package]] name = "gumdrop" version = "0.8.0" @@ -994,6 +1094,16 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + [[package]] name = "http" version = "0.2.6" @@ -1187,6 +1297,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "k256" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d" +dependencies = [ + "cfg-if 1.0.0", + "ecdsa", + "elliptic-curve", + "sec1", + "sha2 0.9.9", +] + [[package]] name = "keccak" version = "0.1.0" @@ -1221,6 +1344,48 @@ dependencies = [ "winapi", ] +[[package]] +name = "libsecp256k1" +version = "0.7.0" +source = "git+https://github.com/brentstone/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "arrayref", + "base64", + "digest 0.9.0", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand", + "serde", + "sha2 0.9.9", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "git+https://github.com/brentstone/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "git+https://github.com/brentstone/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "git+https://github.com/brentstone/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "libsecp256k1-core", +] + [[package]] name = "log" version = "0.4.14" @@ -1367,6 +1532,7 @@ dependencies = [ "ibc-proto", "ics23", "itertools", + "libsecp256k1", "loupe", "namada_proof_of_stake", "parity-wasm", @@ -1966,6 +2132,17 @@ dependencies = [ "bytecheck", ] +[[package]] +name = "rfc6979" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" +dependencies = [ + "crypto-bigint", + "hmac", + "zeroize", +] + [[package]] name = "ripemd160" version = "0.9.1" @@ -2126,6 +2303,18 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "sec1" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" +dependencies = [ + "der", + "generic-array", + "subtle", + "zeroize", +] + [[package]] name = "semver" version = "0.11.0" @@ -2242,9 +2431,13 @@ dependencies = [ [[package]] name = "signature" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" +checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" +dependencies = [ + "digest 0.9.0", + "rand_core 0.6.3", +] [[package]] name = "simple-error" @@ -2378,10 +2571,12 @@ dependencies = [ "ed25519-dalek", "flex-error", "futures", + "k256", "num-traits", "once_cell", "prost", "prost-types", + "ripemd160", "serde", "serde_bytes", "serde_json", diff --git a/wasm/vp_template/Cargo.lock b/wasm/vp_template/Cargo.lock index 6132ba7736..7fafa8a32c 100644 --- a/wasm/vp_template/Cargo.lock +++ b/wasm/vp_template/Cargo.lock @@ -205,6 +205,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base64" version = "0.13.0" @@ -403,6 +409,12 @@ dependencies = [ "syn", ] +[[package]] +name = "const-oid" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -531,6 +543,24 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" +dependencies = [ + "generic-array", + "rand_core 0.6.3", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.3" @@ -541,6 +571,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "curve25519-dalek" version = "3.2.0" @@ -602,6 +642,15 @@ dependencies = [ "syn", ] +[[package]] +name = "der" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" +dependencies = [ + "const-oid", +] + [[package]] name = "derivative" version = "2.2.0" @@ -670,6 +719,18 @@ dependencies = [ "memmap2", ] +[[package]] +name = "ecdsa" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + [[package]] name = "ed25519" version = "1.4.0" @@ -712,6 +773,24 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "elliptic-curve" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "ff", + "generic-array", + "group", + "rand_core 0.6.3", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "enum-iterator" version = "0.7.0" @@ -791,6 +870,16 @@ dependencies = [ "serde_bytes", ] +[[package]] +name = "ff" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924" +dependencies = [ + "rand_core 0.6.3", + "subtle", +] + [[package]] name = "fixedbitset" version = "0.4.1" @@ -922,6 +1011,17 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +[[package]] +name = "group" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" +dependencies = [ + "ff", + "rand_core 0.6.3", + "subtle", +] + [[package]] name = "gumdrop" version = "0.8.0" @@ -994,6 +1094,16 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + [[package]] name = "http" version = "0.2.6" @@ -1187,6 +1297,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "k256" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d" +dependencies = [ + "cfg-if 1.0.0", + "ecdsa", + "elliptic-curve", + "sec1", + "sha2 0.9.9", +] + [[package]] name = "keccak" version = "0.1.0" @@ -1221,6 +1344,48 @@ dependencies = [ "winapi", ] +[[package]] +name = "libsecp256k1" +version = "0.7.0" +source = "git+https://github.com/brentstone/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "arrayref", + "base64", + "digest 0.9.0", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand", + "serde", + "sha2 0.9.9", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "git+https://github.com/brentstone/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "git+https://github.com/brentstone/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "git+https://github.com/brentstone/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "libsecp256k1-core", +] + [[package]] name = "log" version = "0.4.14" @@ -1367,6 +1532,7 @@ dependencies = [ "ibc-proto", "ics23", "itertools", + "libsecp256k1", "loupe", "namada_proof_of_stake", "parity-wasm", @@ -1966,6 +2132,17 @@ dependencies = [ "bytecheck", ] +[[package]] +name = "rfc6979" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" +dependencies = [ + "crypto-bigint", + "hmac", + "zeroize", +] + [[package]] name = "ripemd160" version = "0.9.1" @@ -2126,6 +2303,18 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "sec1" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" +dependencies = [ + "der", + "generic-array", + "subtle", + "zeroize", +] + [[package]] name = "semver" version = "0.11.0" @@ -2242,9 +2431,13 @@ dependencies = [ [[package]] name = "signature" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" +checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" +dependencies = [ + "digest 0.9.0", + "rand_core 0.6.3", +] [[package]] name = "simple-error" @@ -2378,10 +2571,12 @@ dependencies = [ "ed25519-dalek", "flex-error", "futures", + "k256", "num-traits", "once_cell", "prost", "prost-types", + "ripemd160", "serde", "serde_bytes", "serde_json", diff --git a/wasm/wasm_source/Cargo.lock b/wasm/wasm_source/Cargo.lock index e6f814b267..e420c8d5df 100644 --- a/wasm/wasm_source/Cargo.lock +++ b/wasm/wasm_source/Cargo.lock @@ -205,6 +205,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base64" version = "0.13.0" @@ -403,6 +409,12 @@ dependencies = [ "syn", ] +[[package]] +name = "const-oid" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -531,6 +543,24 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" +dependencies = [ + "generic-array", + "rand_core 0.6.3", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.3" @@ -541,6 +571,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "curve25519-dalek" version = "3.2.0" @@ -602,6 +642,15 @@ dependencies = [ "syn", ] +[[package]] +name = "der" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" +dependencies = [ + "const-oid", +] + [[package]] name = "derivative" version = "2.2.0" @@ -670,6 +719,18 @@ dependencies = [ "memmap2", ] +[[package]] +name = "ecdsa" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + [[package]] name = "ed25519" version = "1.4.0" @@ -712,6 +773,24 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "elliptic-curve" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "ff", + "generic-array", + "group", + "rand_core 0.6.3", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "enum-iterator" version = "0.7.0" @@ -791,6 +870,16 @@ dependencies = [ "serde_bytes", ] +[[package]] +name = "ff" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924" +dependencies = [ + "rand_core 0.6.3", + "subtle", +] + [[package]] name = "fixedbitset" version = "0.4.1" @@ -922,6 +1011,17 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +[[package]] +name = "group" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" +dependencies = [ + "ff", + "rand_core 0.6.3", + "subtle", +] + [[package]] name = "gumdrop" version = "0.8.0" @@ -994,6 +1094,16 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + [[package]] name = "http" version = "0.2.6" @@ -1187,6 +1297,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "k256" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d" +dependencies = [ + "cfg-if 1.0.0", + "ecdsa", + "elliptic-curve", + "sec1", + "sha2 0.9.9", +] + [[package]] name = "keccak" version = "0.1.0" @@ -1221,6 +1344,48 @@ dependencies = [ "winapi", ] +[[package]] +name = "libsecp256k1" +version = "0.7.0" +source = "git+https://github.com/heliaxdev/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "arrayref", + "base64", + "digest 0.9.0", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand", + "serde", + "sha2 0.9.9", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "git+https://github.com/heliaxdev/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "git+https://github.com/heliaxdev/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "git+https://github.com/heliaxdev/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "libsecp256k1-core", +] + [[package]] name = "log" version = "0.4.14" @@ -1367,6 +1532,7 @@ dependencies = [ "ibc-proto", "ics23", "itertools", + "libsecp256k1", "loupe", "namada_proof_of_stake", "parity-wasm", @@ -1992,6 +2158,17 @@ dependencies = [ "bytecheck", ] +[[package]] +name = "rfc6979" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" +dependencies = [ + "crypto-bigint", + "hmac", + "zeroize", +] + [[package]] name = "ripemd160" version = "0.9.1" @@ -2152,6 +2329,18 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "sec1" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" +dependencies = [ + "der", + "generic-array", + "subtle", + "zeroize", +] + [[package]] name = "semver" version = "0.11.0" @@ -2268,9 +2457,13 @@ dependencies = [ [[package]] name = "signature" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" +checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" +dependencies = [ + "digest 0.9.0", + "rand_core 0.6.3", +] [[package]] name = "simple-error" @@ -2404,10 +2597,12 @@ dependencies = [ "ed25519-dalek", "flex-error", "futures", + "k256", "num-traits", "once_cell", "prost", "prost-types", + "ripemd160", "serde", "serde_bytes", "serde_json", diff --git a/wasm_for_tests/wasm_source/Cargo.lock b/wasm_for_tests/wasm_source/Cargo.lock index 162ff40653..9df5195b2f 100644 --- a/wasm_for_tests/wasm_source/Cargo.lock +++ b/wasm_for_tests/wasm_source/Cargo.lock @@ -205,6 +205,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base64" version = "0.13.0" @@ -403,6 +409,12 @@ dependencies = [ "syn", ] +[[package]] +name = "const-oid" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -532,6 +544,24 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" +dependencies = [ + "generic-array", + "rand_core 0.6.3", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.3" @@ -542,6 +572,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "curve25519-dalek" version = "3.2.0" @@ -603,6 +643,15 @@ dependencies = [ "syn", ] +[[package]] +name = "der" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" +dependencies = [ + "const-oid", +] + [[package]] name = "derivative" version = "2.2.0" @@ -671,6 +720,18 @@ dependencies = [ "memmap2", ] +[[package]] +name = "ecdsa" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + [[package]] name = "ed25519" version = "1.4.1" @@ -713,6 +774,24 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "elliptic-curve" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "ff", + "generic-array", + "group", + "rand_core 0.6.3", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "enum-iterator" version = "0.7.0" @@ -792,6 +871,16 @@ dependencies = [ "serde_bytes", ] +[[package]] +name = "ff" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924" +dependencies = [ + "rand_core 0.6.3", + "subtle", +] + [[package]] name = "fixedbitset" version = "0.4.1" @@ -923,6 +1012,17 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +[[package]] +name = "group" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" +dependencies = [ + "ff", + "rand_core 0.6.3", + "subtle", +] + [[package]] name = "gumdrop" version = "0.8.1" @@ -1004,6 +1104,16 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + [[package]] name = "http" version = "0.2.6" @@ -1197,6 +1307,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "k256" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d" +dependencies = [ + "cfg-if 1.0.0", + "ecdsa", + "elliptic-curve", + "sec1", + "sha2 0.9.9", +] + [[package]] name = "keccak" version = "0.1.0" @@ -1231,6 +1354,48 @@ dependencies = [ "winapi", ] +[[package]] +name = "libsecp256k1" +version = "0.7.0" +source = "git+https://github.com/brentstone/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "arrayref", + "base64", + "digest 0.9.0", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand", + "serde", + "sha2 0.9.9", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "git+https://github.com/brentstone/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "git+https://github.com/brentstone/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "git+https://github.com/brentstone/libsecp256k1?rev=bbb3bd44a49db361f21d9db80f9a087c194c0ae9#bbb3bd44a49db361f21d9db80f9a087c194c0ae9" +dependencies = [ + "libsecp256k1-core", +] + [[package]] name = "log" version = "0.4.16" @@ -1378,6 +1543,7 @@ dependencies = [ "ibc-proto", "ics23", "itertools", + "libsecp256k1", "loupe", "namada_proof_of_stake", "parity-wasm", @@ -1998,6 +2164,17 @@ dependencies = [ "bytecheck", ] +[[package]] +name = "rfc6979" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" +dependencies = [ + "crypto-bigint", + "hmac", + "zeroize", +] + [[package]] name = "ripemd160" version = "0.9.1" @@ -2158,6 +2335,18 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "sec1" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" +dependencies = [ + "der", + "generic-array", + "subtle", + "zeroize", +] + [[package]] name = "semver" version = "0.11.0" @@ -2274,9 +2463,13 @@ dependencies = [ [[package]] name = "signature" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" +checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" +dependencies = [ + "digest 0.9.0", + "rand_core 0.6.3", +] [[package]] name = "simple-error" @@ -2410,10 +2603,12 @@ dependencies = [ "ed25519-dalek", "flex-error", "futures", + "k256", "num-traits", "once_cell", "prost", "prost-types", + "ripemd160", "serde", "serde_bytes", "serde_json",