diff --git a/Cargo.lock b/Cargo.lock index d2e84d05c4..1eafeab0da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -333,6 +333,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.13.1" @@ -509,7 +515,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -533,6 +539,63 @@ dependencies = [ "serde", ] +[[package]] +name = "blsful" +version = "3.0.0-pre6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9de4566ea9f21109f6b3f11551b591ff22683ff47c3a30d97e2feb23257427" +dependencies = [ + "anyhow", + "arrayref", + "blstrs_plus", + "hex", + "hkdf", + "merlin", + "pairing", + "rand", + "rand_chacha", + "rand_core", + "serde", + "serde_bare", + "sha2", + "sha3", + "subtle", + "thiserror", + "uint-zigzag", + "vsss-rs", + "zeroize", +] + +[[package]] +name = "blst" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62dc83a094a71d43eeadd254b1ec2d24cb6a0bb6cadce00df51f0db594711a32" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + +[[package]] +name = "blstrs_plus" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a16dd4b0d6b4538e1fa0388843acb186363082713a8fc8416d802a04d013818" +dependencies = [ + "arrayref", + "blst", + "elliptic-curve", + "ff", + "group", + "pairing", + "rand_core", + "serde", + "subtle", + "zeroize", +] + [[package]] name = "borsh" version = "1.5.1" @@ -912,6 +975,15 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + [[package]] name = "cpufeatures" version = "0.2.13" @@ -1006,13 +1078,26 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array 0.14.7", + "rand_core", + "serdect", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -1146,14 +1231,14 @@ dependencies = [ [[package]] name = "dashcore" -version = "0.32.0" -source = "git+https://github.com/dashpay/rust-dashcore?tag=0.32.0#6a0ec164ca1bdcb8d19b29f40e946120e99473eb" +version = "0.33.1" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.33.1#eb700aeff1610188414d0250254d0a6daaa4db46" dependencies = [ "anyhow", "bech32", "bitflags 2.6.0", - "bls-signatures", - "dashcore-private", + "blsful", + "dashcore-private 0.1.0 (git+https://github.com/dashpay/rust-dashcore?tag=0.33.1)", "dashcore_hashes", "ed25519-dalek", "hex", @@ -1171,12 +1256,17 @@ name = "dashcore-private" version = "0.1.0" source = "git+https://github.com/dashpay/rust-dashcore?tag=0.32.0#6a0ec164ca1bdcb8d19b29f40e946120e99473eb" +[[package]] +name = "dashcore-private" +version = "0.1.0" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.33.1#eb700aeff1610188414d0250254d0a6daaa4db46" + [[package]] name = "dashcore-rpc" -version = "0.15.8" -source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.8#4d4d5b1488daa7f083d254a1f5acf03b550d5b10" +version = "0.15.9" +source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.9#dcfa6b34da596c52093ed6a1f26f15bcf2196c0d" dependencies = [ - "dashcore-private", + "dashcore-private 0.1.0 (git+https://github.com/dashpay/rust-dashcore?tag=0.32.0)", "dashcore-rpc-json", "env_logger 0.10.2", "hex", @@ -1188,8 +1278,8 @@ dependencies = [ [[package]] name = "dashcore-rpc-json" -version = "0.15.8" -source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.8#4d4d5b1488daa7f083d254a1f5acf03b550d5b10" +version = "0.15.9" +source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.9#dcfa6b34da596c52093ed6a1f26f15bcf2196c0d" dependencies = [ "bincode", "dashcore", @@ -1203,9 +1293,9 @@ dependencies = [ [[package]] name = "dashcore_hashes" version = "0.14.0" -source = "git+https://github.com/dashpay/rust-dashcore?tag=0.32.0#6a0ec164ca1bdcb8d19b29f40e946120e99473eb" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.33.1#eb700aeff1610188414d0250254d0a6daaa4db46" dependencies = [ - "dashcore-private", + "dashcore-private 0.1.0 (git+https://github.com/dashpay/rust-dashcore?tag=0.33.1)", "secp256k1", "serde", ] @@ -1461,6 +1551,7 @@ dependencies = [ "async-trait", "base64 0.22.1", "bincode", + "bls-signatures", "bs58", "chrono", "ciborium 0.2.0", @@ -1578,6 +1669,41 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array 0.14.7", + "group", + "hkdf", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "tap", + "zeroize", +] + +[[package]] +name = "elliptic-curve-tools" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48843edfbd0a370b3dd14cdbb4e446e9a8855311e6b2b57bf9a1fd1367bc317" +dependencies = [ + "elliptic-curve", + "heapless", + "hex", + "multiexp", + "serde", + "zeroize", +] + [[package]] name = "encoding_rs" version = "0.8.34" @@ -1738,6 +1864,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "bitvec", + "rand_core", + "subtle", +] + [[package]] name = "fiat-crypto" version = "0.2.9" @@ -1934,6 +2071,17 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", +] + +[[package]] +name = "generic-array" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96512db27971c2c3eece70a1e106fbe6c87760234e31e8f7e5634912fe52794a" +dependencies = [ + "serde", + "typenum", ] [[package]] @@ -1973,6 +2121,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand", + "rand_core", + "rand_xorshift", + "subtle", +] + [[package]] name = "grovedb" version = "2.1.0" @@ -2149,6 +2310,15 @@ dependencies = [ "crunchy", ] +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -2187,6 +2357,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.4.1" @@ -2241,6 +2421,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + [[package]] name = "hmac" version = "0.12.1" @@ -2481,7 +2670,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -2643,6 +2832,15 @@ dependencies = [ "uuid", ] +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -2782,6 +2980,18 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core", + "zeroize", +] + [[package]] name = "metrics" version = "0.23.0" @@ -2929,6 +3139,19 @@ dependencies = [ "uuid", ] +[[package]] +name = "multiexp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a383da1ae933078ddb1e4141f1dd617b512b4183779d6977e6451b0e644806" +dependencies = [ + "ff", + "group", + "rustversion", + "std-shims", + "zeroize", +] + [[package]] name = "multimap" version = "0.10.0" @@ -3006,6 +3229,8 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", + "rand", + "serde", ] [[package]] @@ -3021,6 +3246,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", + "rand", + "serde", ] [[package]] @@ -3069,6 +3296,7 @@ dependencies = [ "num-bigint", "num-integer", "num-traits", + "serde", ] [[package]] @@ -3203,6 +3431,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "pairing" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f" +dependencies = [ + "group", +] + [[package]] name = "parking" version = "2.2.0" @@ -3677,6 +3914,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + [[package]] name = "raw-cpuid" version = "11.1.0" @@ -4062,6 +4308,20 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array 0.14.7", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "secp256k1" version = "0.30.0" @@ -4131,6 +4391,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "serde_bare" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51c55386eed0f1ae957b091dc2ca8122f287b60c79c774cbe3d5f2b69fded660" +dependencies = [ + "serde", +] + [[package]] name = "serde_bytes" version = "0.11.15" @@ -4264,6 +4533,16 @@ dependencies = [ "syn 2.0.75", ] +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + [[package]] name = "sha1" version = "0.10.6" @@ -4286,6 +4565,16 @@ dependencies = [ "digest", ] +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -4377,6 +4666,9 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "spki" @@ -4397,6 +4689,22 @@ dependencies = [ "log", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "std-shims" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e49360f31b0b75a6a82a5205c6103ea07a79a60808d44f5cc879d303337926" +dependencies = [ + "hashbrown 0.14.5", + "spin", +] + [[package]] name = "strategy-tests" version = "1.5.0" @@ -4689,6 +4997,26 @@ dependencies = [ "syn 2.0.75", ] +[[package]] +name = "thiserror-impl-no-std" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58e6318948b519ba6dc2b442a6d0b904ebfb8d411a3ad3e07843615a72249758" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "thiserror-no-std" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3ad459d94dd517257cc96add8a43190ee620011bb6e6cdc82dafd97dfafafea" +dependencies = [ + "thiserror-impl-no-std", +] + [[package]] name = "thread_local" version = "1.1.8" @@ -4699,6 +5027,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + [[package]] name = "time" version = "0.3.36" @@ -5099,6 +5436,15 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "uint-zigzag" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abbf77aed65cb885a8ba07138c365879be3d9a93dce82bf6cc50feca9138ec15" +dependencies = [ + "core2", +] + [[package]] name = "unicase" version = "2.7.0" @@ -5225,6 +5571,26 @@ version = "0.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7302ac74a033bf17b6e609ceec0f891ca9200d502d31f02dc7908d3d98767c9d" +[[package]] +name = "vsss-rs" +version = "5.0.0-rc1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9860fb75908021ae4cc125917c9763134f7f236a716d181ed644627783230c5d" +dependencies = [ + "crypto-bigint", + "elliptic-curve", + "elliptic-curve-tools", + "generic-array 1.1.0", + "hex", + "num", + "rand_core", + "serde", + "sha3", + "subtle", + "thiserror-no-std", + "zeroize", +] + [[package]] name = "walkdir" version = "2.5.0" diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index ff377de748..8386ba22ba 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -28,9 +28,7 @@ dashcore = { git = "https://github.com/dashpay/rust-dashcore", features = [ "rand", "signer", "serde", - "bls", - "eddsa" -], default-features = false, tag = "0.32.0" } +], default-features = false, tag = "0.33.1" } env_logger = { version = "0.11" } getrandom = { version = "0.2", features = ["js"] } hex = { version = "0.4" } diff --git a/packages/rs-dpp/src/bls/native_bls.rs b/packages/rs-dpp/src/bls/native_bls.rs index 5dc7e2bc82..492f563511 100644 --- a/packages/rs-dpp/src/bls/native_bls.rs +++ b/packages/rs-dpp/src/bls/native_bls.rs @@ -1,12 +1,14 @@ +use crate::bls_signatures::{ + Bls12381G2Impl, Pairing, PublicKey, SecretKey, Signature, SignatureSchemes, +}; use crate::{BlsModule, ProtocolError, PublicKeyValidationError}; -use anyhow::anyhow; -use dashcore::bls_signatures::{self, PrivateKey, PublicKey}; +use std::array::TryFromSliceError; #[derive(Default)] pub struct NativeBlsModule; impl BlsModule for NativeBlsModule { fn validate_public_key(&self, pk: &[u8]) -> Result<(), PublicKeyValidationError> { - match PublicKey::from_bytes(pk) { + match PublicKey::::try_from(pk) { Ok(_) => Ok(()), Err(e) => Err(PublicKeyValidationError::new(e.to_string())), } @@ -18,31 +20,61 @@ impl BlsModule for NativeBlsModule { data: &[u8], public_key: &[u8], ) -> Result { - let public_key = PublicKey::from_bytes(public_key).map_err(anyhow::Error::msg)?; - let signature = - bls_signatures::Signature::from_bytes(signature).map_err(anyhow::Error::msg)?; - match public_key.verify(&signature, data) { - true => Ok(true), - // TODO change to specific error type - false => Err(anyhow!("Verification failed").into()), + let public_key = PublicKey::::try_from(public_key)?; + let signature_96_bytes = + signature + .try_into() + .map_err(|_| ProtocolError::BlsSignatureSizeError { + got: signature.len() as u32, + })?; + let Some(g2_element) = + ::Signature::from_compressed(&signature_96_bytes) + .into_option() + else { + return Ok(false); // We should not error because the signature could be given by an invalid source + }; + + let signature = Signature::Basic(g2_element); + + match signature.verify(&public_key, data) { + Ok(_) => Ok(true), + Err(_) => Ok(false), } } fn private_key_to_public_key(&self, private_key: &[u8]) -> Result, ProtocolError> { - let fixed_len_key: [u8; 32] = private_key - .try_into() - .map_err(|_| anyhow!("the BLS private key must be 32 bytes long"))?; - let pk = PrivateKey::from_bytes(&fixed_len_key, false).map_err(anyhow::Error::msg)?; - let public_key = pk.g1_element().map_err(anyhow::Error::msg)?; - let public_key_bytes = public_key.to_bytes().to_vec(); + let fixed_len_key: [u8; 32] = + private_key + .try_into() + .map_err(|_| ProtocolError::PrivateKeySizeError { + got: private_key.len() as u32, + })?; + let pk = SecretKey::::from_be_bytes(&fixed_len_key) + .into_option() + .ok_or(ProtocolError::InvalidBLSPrivateKeyError( + "key not valid".to_string(), + ))?; + let public_key = pk.public_key(); + let public_key_bytes = public_key.0.to_compressed().to_vec(); Ok(public_key_bytes) } fn sign(&self, data: &[u8], private_key: &[u8]) -> Result, ProtocolError> { - let fixed_len_key: [u8; 32] = private_key - .try_into() - .map_err(|_| anyhow!("the BLS private key must be 32 bytes long"))?; - let pk = PrivateKey::from_bytes(&fixed_len_key, false).map_err(anyhow::Error::msg)?; - Ok(pk.sign(data).to_bytes().to_vec()) + let fixed_len_key: [u8; 32] = + private_key + .try_into() + .map_err(|_| ProtocolError::PrivateKeySizeError { + got: private_key.len() as u32, + })?; + let pk = SecretKey::::from_be_bytes(&fixed_len_key) + .into_option() + .ok_or(ProtocolError::InvalidBLSPrivateKeyError( + "key not valid".to_string(), + ))?; + Ok(pk + .sign(SignatureSchemes::Basic, data)? + .as_raw_value() + .to_compressed() + .to_vec()) } } diff --git a/packages/rs-dpp/src/core_types/validator/mod.rs b/packages/rs-dpp/src/core_types/validator/mod.rs index 2261bac56f..01716ab044 100644 --- a/packages/rs-dpp/src/core_types/validator/mod.rs +++ b/packages/rs-dpp/src/core_types/validator/mod.rs @@ -1,4 +1,4 @@ -use crate::bls_signatures::PublicKey as BlsPublicKey; +use crate::bls_signatures::{Bls12381G2Impl, PublicKey as BlsPublicKey}; use crate::core_types::validator::v0::{ValidatorV0, ValidatorV0Getters, ValidatorV0Setters}; use dashcore::{ProTxHash, PubkeyHash}; #[cfg(feature = "core-types-serde-conversion")] @@ -25,7 +25,7 @@ impl ValidatorV0Getters for Validator { } } - fn public_key(&self) -> &Option { + fn public_key(&self) -> &Option> { match self { Validator::V0(v0) => v0.public_key(), } @@ -75,7 +75,7 @@ impl ValidatorV0Setters for Validator { } } - fn set_public_key(&mut self, public_key: Option) { + fn set_public_key(&mut self, public_key: Option>) { match self { Validator::V0(v0) => v0.set_public_key(public_key), } diff --git a/packages/rs-dpp/src/core_types/validator/v0/mod.rs b/packages/rs-dpp/src/core_types/validator/v0/mod.rs index b427431a04..fe45fe675d 100644 --- a/packages/rs-dpp/src/core_types/validator/v0/mod.rs +++ b/packages/rs-dpp/src/core_types/validator/v0/mod.rs @@ -1,7 +1,7 @@ use dashcore::{ProTxHash, PubkeyHash}; use std::fmt::{Debug, Formatter}; -use crate::bls_signatures::PublicKey as BlsPublicKey; +use crate::bls_signatures::{Bls12381G2Impl, PublicKey as BlsPublicKey}; #[cfg(feature = "core-types-serde-conversion")] use serde::{Deserialize, Serialize}; @@ -26,7 +26,7 @@ pub struct ValidatorV0 { /// The proTxHash pub pro_tx_hash: ProTxHash, /// The public key share of this validator for this quorum - pub public_key: Option, + pub public_key: Option>, /// The node address pub node_ip: String, /// The node id @@ -54,7 +54,7 @@ impl Encode for ValidatorV0 { match &self.public_key { Some(public_key) => { true.encode(encoder)?; // Indicate that public_key is present - public_key.to_bytes().encode(encoder)?; + public_key.0.to_compressed().encode(encoder)?; } None => { false.encode(encoder)?; // Indicate that public_key is not present @@ -94,9 +94,12 @@ impl Decode for ValidatorV0 { let has_public_key = bool::decode(decoder)?; let public_key = if has_public_key { let public_key_bytes = <[u8; 48]>::decode(decoder)?; - Some(BlsPublicKey::from_bytes(&public_key_bytes).map_err(|_| { - DecodeError::OtherString("Failed to decode BlsPublicKey".to_string()) - })?) + + Some( + BlsPublicKey::try_from(public_key_bytes.as_slice()).map_err(|_| { + DecodeError::OtherString("Failed to decode BlsPublicKey".to_string()) + })?, + ) } else { None }; @@ -150,7 +153,7 @@ pub trait ValidatorV0Getters { /// Returns the proTxHash of the validator. fn pro_tx_hash(&self) -> &ProTxHash; /// Returns the public key share of this validator for this quorum. - fn public_key(&self) -> &Option; + fn public_key(&self) -> &Option>; /// Returns the node address of the validator. fn node_ip(&self) -> &String; /// Returns the node id of the validator. @@ -170,7 +173,7 @@ pub trait ValidatorV0Setters { /// Sets the proTxHash of the validator. fn set_pro_tx_hash(&mut self, pro_tx_hash: ProTxHash); /// Sets the public key share of this validator for this quorum. - fn set_public_key(&mut self, public_key: Option); + fn set_public_key(&mut self, public_key: Option>); /// Sets the node address of the validator. fn set_node_ip(&mut self, node_ip: String); /// Sets the node id of the validator. @@ -190,7 +193,7 @@ impl ValidatorV0Getters for ValidatorV0 { &self.pro_tx_hash } - fn public_key(&self) -> &Option { + fn public_key(&self) -> &Option> { &self.public_key } @@ -224,7 +227,7 @@ impl ValidatorV0Setters for ValidatorV0 { self.pro_tx_hash = pro_tx_hash; } - fn set_public_key(&mut self, public_key: Option) { + fn set_public_key(&mut self, public_key: Option>) { self.public_key = public_key; } @@ -257,12 +260,16 @@ impl ValidatorV0Setters for ValidatorV0 { mod tests { use super::*; use bincode::config; + use dashcore::blsful::SecretKey; + use rand::prelude::StdRng; + use rand::SeedableRng; #[test] fn test_serialize_deserialize_validator_v0() { // Sample data for testing let pro_tx_hash = ProTxHash::from_slice(&[1; 32]).unwrap(); - let public_key = Some(BlsPublicKey::generate()); + let mut rng = StdRng::seed_from_u64(0); + let public_key = Some(SecretKey::::random(&mut rng).public_key()); let node_ip = "127.0.0.1".to_string(); let node_id = PubkeyHash::from_slice(&[3; 20]).unwrap(); let core_port = 9999; diff --git a/packages/rs-dpp/src/core_types/validator_set/mod.rs b/packages/rs-dpp/src/core_types/validator_set/mod.rs index 74b78fca05..0d56edbc6c 100644 --- a/packages/rs-dpp/src/core_types/validator_set/mod.rs +++ b/packages/rs-dpp/src/core_types/validator_set/mod.rs @@ -1,4 +1,4 @@ -use crate::bls_signatures::PublicKey as BlsPublicKey; +use crate::bls_signatures::{Bls12381G2Impl, PublicKey as BlsPublicKey}; use crate::core_types::validator::v0::ValidatorV0; use crate::core_types::validator_set::v0::{ ValidatorSetV0, ValidatorSetV0Getters, ValidatorSetV0Setters, @@ -80,7 +80,7 @@ impl ValidatorSetV0Getters for ValidatorSet { } } - fn threshold_public_key(&self) -> &BlsPublicKey { + fn threshold_public_key(&self) -> &BlsPublicKey { match self { ValidatorSet::V0(v0) => v0.threshold_public_key(), } @@ -112,7 +112,7 @@ impl ValidatorSetV0Setters for ValidatorSet { } } - fn set_threshold_public_key(&mut self, threshold_public_key: BlsPublicKey) { + fn set_threshold_public_key(&mut self, threshold_public_key: BlsPublicKey) { match self { ValidatorSet::V0(v0) => v0.set_threshold_public_key(threshold_public_key), } diff --git a/packages/rs-dpp/src/core_types/validator_set/v0/mod.rs b/packages/rs-dpp/src/core_types/validator_set/v0/mod.rs index dba9180e24..4789d53dd6 100644 --- a/packages/rs-dpp/src/core_types/validator_set/v0/mod.rs +++ b/packages/rs-dpp/src/core_types/validator_set/v0/mod.rs @@ -8,6 +8,7 @@ use bincode::enc::Encoder; use bincode::error::EncodeError; #[cfg(feature = "core-types-serialization")] use bincode::{BorrowDecode, Decode, Encode}; +use dashcore::blsful::Bls12381G2Impl; use dashcore::hashes::Hash; use dashcore::{ProTxHash, QuorumHash}; use itertools::Itertools; @@ -34,7 +35,7 @@ pub struct ValidatorSetV0 { /// The list of masternodes pub members: BTreeMap, /// The threshold quorum public key - pub threshold_public_key: BlsPublicKey, + pub threshold_public_key: BlsPublicKey, } impl Display for ValidatorSetV0 { @@ -61,7 +62,7 @@ impl Display for ValidatorSetV0 { pro_tx_hash, validator.node_ip )) .join(", "), - hex::encode(self.threshold_public_key.to_bytes().as_slice()) // Assuming BlsPublicKey is a byte array + hex::encode(self.threshold_public_key.0.to_compressed()) // Assuming BlsPublicKey is a byte array ) } } @@ -85,7 +86,7 @@ impl Encode for ValidatorSetV0 { // Custom encoding for BlsPublicKey if needed // Assuming BlsPublicKey can be serialized to a byte slice - let public_key_bytes = *self.threshold_public_key.to_bytes(); + let public_key_bytes = self.threshold_public_key.0.to_compressed(); public_key_bytes.encode(encoder)?; Ok(()) @@ -118,9 +119,13 @@ impl Decode for ValidatorSetV0 { let mut public_key_bytes = [0u8; 48]; let bytes = <[u8; 48]>::decode(decoder)?; public_key_bytes.copy_from_slice(&bytes); - let threshold_public_key = BlsPublicKey::from_bytes(&public_key_bytes).map_err(|_| { - bincode::error::DecodeError::OtherString("Failed to decode BlsPublicKey".to_string()) - })?; + let threshold_public_key = + BlsPublicKey::try_from(public_key_bytes.as_slice()).map_err(|e| { + bincode::error::DecodeError::OtherString(format!( + "Failed to decode BlsPublicKey: {}", + e + )) + })?; Ok(ValidatorSetV0 { quorum_hash: QuorumHash::from_byte_array(quorum_hash), @@ -162,11 +167,13 @@ impl<'de> BorrowDecode<'de> for ValidatorSetV0 { let mut public_key_bytes = [0u8; 48]; let bytes = <[u8; 48]>::decode(decoder)?; public_key_bytes.copy_from_slice(&bytes); - let threshold_public_key = BlsPublicKey::from_bytes(&public_key_bytes).map_err(|_| { - bincode::error::DecodeError::OtherString( - "Failed to decode BlsPublicKey in borrow decode".to_string(), - ) - })?; + let threshold_public_key = + BlsPublicKey::try_from(public_key_bytes.as_slice()).map_err(|e| { + bincode::error::DecodeError::OtherString(format!( + "Failed to decode BlsPublicKey in borrow decode: {}", + e + )) + })?; Ok(ValidatorSetV0 { quorum_hash: QuorumHash::from_byte_array(quorum_hash), @@ -211,7 +218,7 @@ pub trait ValidatorSetV0Getters { /// Returns the members of the validator set. fn members_owned(self) -> BTreeMap; /// Returns the threshold public key of the validator set. - fn threshold_public_key(&self) -> &BlsPublicKey; + fn threshold_public_key(&self) -> &BlsPublicKey; } /// Trait providing setter methods for `ValidatorSetV0` struct @@ -225,7 +232,7 @@ pub trait ValidatorSetV0Setters { /// Sets the members of the validator set. fn set_members(&mut self, members: BTreeMap); /// Sets the threshold public key of the validator set. - fn set_threshold_public_key(&mut self, threshold_public_key: BlsPublicKey); + fn set_threshold_public_key(&mut self, threshold_public_key: BlsPublicKey); } impl ValidatorSetV0Getters for ValidatorSetV0 { @@ -253,7 +260,7 @@ impl ValidatorSetV0Getters for ValidatorSetV0 { self.members } - fn threshold_public_key(&self) -> &BlsPublicKey { + fn threshold_public_key(&self) -> &BlsPublicKey { &self.threshold_public_key } } @@ -275,7 +282,7 @@ impl ValidatorSetV0Setters for ValidatorSetV0 { self.members = members; } - fn set_threshold_public_key(&mut self, threshold_public_key: BlsPublicKey) { + fn set_threshold_public_key(&mut self, threshold_public_key: BlsPublicKey) { self.threshold_public_key = threshold_public_key; } } @@ -284,7 +291,10 @@ impl ValidatorSetV0Setters for ValidatorSetV0 { mod tests { use super::*; use bincode::config; + use dashcore::blsful::SecretKey; use dashcore::PubkeyHash; + use rand::rngs::StdRng; + use rand::SeedableRng; use std::collections::BTreeMap; #[test] @@ -296,7 +306,8 @@ mod tests { // Create a sample ProTxHash and ValidatorV0 instance let pro_tx_hash = ProTxHash::from_slice(&[2; 32]).unwrap(); - let public_key = Some(BlsPublicKey::generate()); + let mut rng = StdRng::seed_from_u64(0); + let public_key = Some(SecretKey::::random(&mut rng).public_key()); let node_ip = "192.168.1.1".to_string(); let node_id = PubkeyHash::from_slice(&[4; 20]).unwrap(); let validator = ValidatorV0 { @@ -315,7 +326,7 @@ mod tests { members.insert(pro_tx_hash, validator); // Create a sample threshold public key - let threshold_public_key = BlsPublicKey::generate(); + let threshold_public_key = SecretKey::::random(&mut rng).public_key(); // Create the ValidatorSetV0 instance let validator_set = ValidatorSetV0 { diff --git a/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_instant_asset_lock_proof_signature_error.rs b/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_instant_asset_lock_proof_signature_error.rs index 8d72de7772..49403c9164 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_instant_asset_lock_proof_signature_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_instant_asset_lock_proof_signature_error.rs @@ -18,7 +18,7 @@ use bincode::{Decode, Encode}; PlatformSerialize, PlatformDeserialize, )] -#[error("Instant lock proof signature is invalid or wasn't created recently. Pleases try chain asset lock proof instead.")] +#[error("Instant lock proof signature is invalid or wasn't created recently. Please try chain asset lock proof instead.")] #[platform_serialize(unversioned)] pub struct InvalidInstantAssetLockProofSignatureError; diff --git a/packages/rs-dpp/src/errors/protocol_error.rs b/packages/rs-dpp/src/errors/protocol_error.rs index 2164b339f1..1ed9888821 100644 --- a/packages/rs-dpp/src/errors/protocol_error.rs +++ b/packages/rs-dpp/src/errors/protocol_error.rs @@ -1,3 +1,4 @@ +use std::array::TryFromSliceError; use thiserror::Error; use crate::consensus::basic::state_transition::InvalidStateTransitionTypeError; @@ -247,6 +248,20 @@ pub enum ProtocolError { /// Invalid CBOR error #[error("invalid cbor error: {0}")] InvalidCBOR(String), + + /// BLS signature error + #[cfg(feature = "bls-signatures")] + #[error(transparent)] + BlsError(#[from] dashcore::blsful::BlsError), + + #[error("Private key wrong size: expected 32, got {got}")] + PrivateKeySizeError { got: u32 }, + + #[error("Private key invalid error: {0}")] + InvalidBLSPrivateKeyError(String), + + #[error("Signature wrong size: expected 96, got {got}")] + BlsSignatureSizeError { got: u32 }, } impl From<&str> for ProtocolError { diff --git a/packages/rs-dpp/src/identity/identity_public_key/key_type.rs b/packages/rs-dpp/src/identity/identity_public_key/key_type.rs index e40437a33e..e87df348bb 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/key_type.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/key_type.rs @@ -8,13 +8,15 @@ use dashcore::secp256k1::rand::rngs::StdRng as EcdsaRng; #[cfg(feature = "random-public-keys")] use dashcore::secp256k1::rand::SeedableRng; use dashcore::secp256k1::Secp256k1; -use dashcore::{bls_signatures, ed25519_dalek, Network}; +use dashcore::Network; use itertools::Itertools; use lazy_static::lazy_static; +#[cfg(feature = "bls-signatures")] +use crate::bls_signatures::{self as bls_signatures, Bls12381G2Impl, BlsError}; use crate::fee::Credits; use crate::version::PlatformVersion; -use crate::{InvalidVectorSizeError, ProtocolError}; +use crate::ProtocolError; #[cfg(feature = "random-public-keys")] use rand::rngs::StdRng; #[cfg(feature = "random-public-keys")] @@ -165,13 +167,8 @@ impl KeyType { private_key.public_key(&secp).to_bytes() } KeyType::BLS12_381 => { - let private_key = bls_signatures::PrivateKey::generate_dash(rng) - .expect("expected to generate a bls private key"); // we assume this will never error - private_key - .g1_element() - .expect("expected to get a public key from a bls private key") - .to_bytes() - .to_vec() + let private_key = bls_signatures::SecretKey::::random(rng); + private_key.public_key().0.to_compressed().to_vec() } KeyType::ECDSA_HASH160 | KeyType::BIP13_SCRIPT_HASH | KeyType::EDDSA_25519_HASH160 => { (0..self.default_size()).map(|_| rng.gen::()).collect() @@ -204,13 +201,13 @@ impl KeyType { /// Gets the public key data for a private key depending on the key type pub fn public_key_data_from_private_key_data( &self, - private_key_bytes: &[u8], + private_key_bytes: &[u8; 32], network: Network, ) -> Result, ProtocolError> { match self { KeyType::ECDSA_SECP256K1 => { let secp = Secp256k1::new(); - let secret_key = dashcore::secp256k1::SecretKey::from_slice(private_key_bytes) + let secret_key = dashcore::secp256k1::SecretKey::from_byte_array(private_key_bytes) .map_err(|e| ProtocolError::Generic(e.to_string()))?; let private_key = dashcore::PrivateKey::new(secret_key, network); @@ -219,14 +216,18 @@ impl KeyType { KeyType::BLS12_381 => { #[cfg(feature = "bls-signatures")] { - let private_key = - bls_signatures::PrivateKey::from_bytes(private_key_bytes, false) - .map_err(|e| ProtocolError::Generic(e.to_string()))?; - let public_key_bytes = private_key - .g1_element() - .expect("expected to get a public key from a bls private key") - .to_bytes() - .to_vec(); + let private_key: Option> = + bls_signatures::SecretKey::::from_be_bytes( + private_key_bytes, + ) + .into(); + if private_key.is_none() { + return Err(ProtocolError::BlsError(BlsError::DeserializationError( + "private key bytes not a valid secret key".to_string(), + ))); + } + let private_key = private_key.expect("expected private key"); + let public_key_bytes = private_key.public_key().0.to_compressed().to_vec(); Ok(public_key_bytes) } #[cfg(not(feature = "bls-signatures"))] @@ -236,7 +237,7 @@ impl KeyType { } KeyType::ECDSA_HASH160 => { let secp = Secp256k1::new(); - let secret_key = dashcore::secp256k1::SecretKey::from_slice(private_key_bytes) + let secret_key = dashcore::secp256k1::SecretKey::from_byte_array(private_key_bytes) .map_err(|e| ProtocolError::Generic(e.to_string()))?; let private_key = dashcore::PrivateKey::new(secret_key, network); @@ -245,14 +246,8 @@ impl KeyType { KeyType::EDDSA_25519_HASH160 => { #[cfg(feature = "ed25519-dalek")] { - let key_pair = ed25519_dalek::SigningKey::from_bytes( - &private_key_bytes.try_into().map_err(|_| { - ProtocolError::InvalidVectorSizeError(InvalidVectorSizeError::new( - 32, - private_key_bytes.len(), - )) - })?, - ); + let key_pair = + dashcore::ed25519_dalek::SigningKey::from_bytes(private_key_bytes); Ok(ripemd160_sha256(key_pair.verifying_key().to_bytes().as_slice()).to_vec()) } #[cfg(not(feature = "ed25519-dalek"))] @@ -260,17 +255,15 @@ impl KeyType { "Converting a private key to a eddsa hash 160 is not supported without the ed25519-dalek feature".to_string(), )); } - KeyType::BIP13_SCRIPT_HASH => { - return Err(ProtocolError::NotSupported( - "Converting a private key to a script hash is not supported".to_string(), - )); - } + KeyType::BIP13_SCRIPT_HASH => Err(ProtocolError::NotSupported( + "Converting a private key to a script hash is not supported".to_string(), + )), } } #[cfg(feature = "random-public-keys")] /// Gets the default size of the public key - pub fn random_public_and_private_key_data_v0(&self, rng: &mut StdRng) -> (Vec, Vec) { + pub fn random_public_and_private_key_data_v0(&self, rng: &mut StdRng) -> (Vec, [u8; 32]) { match self { KeyType::ECDSA_SECP256K1 => { let secp = Secp256k1::new(); @@ -279,18 +272,13 @@ impl KeyType { let private_key = dashcore::PrivateKey::new(secret_key, Network::Dash); ( private_key.public_key(&secp).to_bytes(), - private_key.to_bytes(), + private_key.inner.secret_bytes(), ) } KeyType::BLS12_381 => { - let private_key = bls_signatures::PrivateKey::generate_dash(rng) - .expect("expected to generate a bls private key"); // we assume this will never error - let public_key_bytes = private_key - .g1_element() - .expect("expected to get a public key from a bls private key") - .to_bytes() - .to_vec(); - (public_key_bytes, private_key.to_bytes().to_vec()) + let private_key = dashcore::blsful::SecretKey::::random(rng); + let public_key_bytes = private_key.public_key().0.to_compressed().to_vec(); + (public_key_bytes, private_key.0.to_be_bytes()) } KeyType::ECDSA_HASH160 => { let secp = Secp256k1::new(); @@ -299,14 +287,14 @@ impl KeyType { let private_key = dashcore::PrivateKey::new(secret_key, Network::Dash); ( ripemd160_sha256(private_key.public_key(&secp).to_bytes().as_slice()).to_vec(), - private_key.to_bytes(), + private_key.inner.secret_bytes(), ) } KeyType::EDDSA_25519_HASH160 => { - let key_pair = ed25519_dalek::SigningKey::generate(rng); + let key_pair = dashcore::ed25519_dalek::SigningKey::generate(rng); ( ripemd160_sha256(key_pair.verifying_key().to_bytes().as_slice()).to_vec(), - key_pair.to_bytes().to_vec(), + key_pair.to_bytes(), ) } KeyType::BIP13_SCRIPT_HASH => { @@ -317,7 +305,7 @@ impl KeyType { let private_key = dashcore::PrivateKey::new(secret_key, Network::Dash); ( ripemd160_sha256(private_key.public_key(&secp).to_bytes().as_slice()).to_vec(), - private_key.to_bytes(), + private_key.inner.secret_bytes(), ) } } @@ -329,7 +317,7 @@ impl KeyType { &self, rng: &mut StdRng, platform_version: &PlatformVersion, - ) -> Result<(Vec, Vec), ProtocolError> { + ) -> Result<(Vec, [u8; 32]), ProtocolError> { match platform_version .dpp .identity_versions diff --git a/packages/rs-dpp/src/identity/identity_public_key/methods/hash/mod.rs b/packages/rs-dpp/src/identity/identity_public_key/methods/hash/mod.rs index b22a3f0c26..5cc4828dd7 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/methods/hash/mod.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/methods/hash/mod.rs @@ -14,7 +14,7 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKey { fn validate_private_key_bytes( &self, - private_key_bytes: &[u8], + private_key_bytes: &[u8; 32], network: Network, ) -> Result { match self { diff --git a/packages/rs-dpp/src/identity/identity_public_key/methods/hash/v0/mod.rs b/packages/rs-dpp/src/identity/identity_public_key/methods/hash/v0/mod.rs index b11c79c31f..dd2b975e88 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/methods/hash/v0/mod.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/methods/hash/v0/mod.rs @@ -8,7 +8,7 @@ pub trait IdentityPublicKeyHashMethodsV0 { /// Verifies that the private key bytes match this identity public key fn validate_private_key_bytes( &self, - private_key_bytes: &[u8], + private_key_bytes: &[u8; 32], network: Network, ) -> Result; } diff --git a/packages/rs-dpp/src/identity/identity_public_key/random.rs b/packages/rs-dpp/src/identity/identity_public_key/random.rs index dec286b927..6ed13153e4 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/random.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/random.rs @@ -138,7 +138,7 @@ impl IdentityPublicKey { id: KeyID, seed: Option, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { let mut rng = match seed { None => StdRng::from_entropy(), Some(seed_value) => StdRng::seed_from_u64(seed_value), @@ -176,7 +176,7 @@ impl IdentityPublicKey { rng: &mut StdRng, used_key_matrix: Option<(KeyCount, &mut UsedKeyMatrix)>, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { match platform_version .dpp .identity_versions @@ -272,7 +272,7 @@ impl IdentityPublicKey { key_type: KeyType, contract_bounds: Option, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { match platform_version .dpp .identity_versions @@ -318,7 +318,7 @@ impl IdentityPublicKey { id: KeyID, rng: &mut StdRng, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { match platform_version .dpp .identity_versions @@ -346,7 +346,7 @@ impl IdentityPublicKey { id: KeyID, rng: &mut StdRng, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { match platform_version .dpp .identity_versions @@ -384,7 +384,7 @@ impl IdentityPublicKey { id: KeyID, seed: Option, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { let mut rng = match seed { None => StdRng::from_entropy(), Some(seed_value) => StdRng::seed_from_u64(seed_value), @@ -411,7 +411,7 @@ impl IdentityPublicKey { id: KeyID, seed: Option, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { let mut rng = match seed { None => StdRng::from_entropy(), Some(seed_value) => StdRng::seed_from_u64(seed_value), @@ -442,7 +442,7 @@ impl IdentityPublicKey { id: KeyID, rng: &mut StdRng, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { match platform_version .dpp .identity_versions @@ -489,7 +489,7 @@ impl IdentityPublicKey { id: KeyID, seed: Option, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { let mut rng = match seed { None => StdRng::from_entropy(), Some(seed_value) => StdRng::seed_from_u64(seed_value), @@ -518,7 +518,7 @@ impl IdentityPublicKey { id: KeyID, rng: &mut StdRng, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { match platform_version .dpp .identity_versions @@ -558,7 +558,7 @@ impl IdentityPublicKey { id: KeyID, seed: Option, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { let mut rng = match seed { None => StdRng::from_entropy(), Some(seed_value) => StdRng::seed_from_u64(seed_value), @@ -587,7 +587,7 @@ impl IdentityPublicKey { id: KeyID, rng: &mut StdRng, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { match platform_version .dpp .identity_versions @@ -629,7 +629,7 @@ impl IdentityPublicKey { id: KeyID, seed: Option, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { let mut rng = match seed { None => StdRng::from_entropy(), Some(seed_value) => StdRng::seed_from_u64(seed_value), @@ -656,7 +656,7 @@ impl IdentityPublicKey { id: KeyID, rng: &mut StdRng, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { match platform_version .dpp .identity_versions @@ -703,7 +703,7 @@ impl IdentityPublicKey { key_count: KeyCount, rng: &mut StdRng, platform_version: &PlatformVersion, - ) -> Result)>, ProtocolError> { + ) -> Result, ProtocolError> { (start_id..(start_id + key_count)) .map(|i| { Self::random_authentication_key_with_private_key_with_rng( @@ -720,7 +720,7 @@ impl IdentityPublicKey { key_count: KeyCount, rng: &mut StdRng, platform_version: &PlatformVersion, - ) -> Result)>, ProtocolError> { + ) -> Result, ProtocolError> { if key_count < 2 { return Err(ProtocolError::PublicKeyGenerationError( "at least 2 keys must be created".to_string(), diff --git a/packages/rs-dpp/src/identity/identity_public_key/v0/methods/mod.rs b/packages/rs-dpp/src/identity/identity_public_key/v0/methods/mod.rs index 470dc92b9b..ea064e33b6 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/v0/methods/mod.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/v0/methods/mod.rs @@ -4,12 +4,15 @@ use crate::identity::KeyType; use crate::util::hash::ripemd160_sha256; use crate::ProtocolError; use anyhow::anyhow; +#[cfg(feature = "ed25519-dalek")] +use dashcore::ed25519_dalek; use dashcore::hashes::Hash; use dashcore::key::Secp256k1; use dashcore::secp256k1::SecretKey; -use dashcore::{bls_signatures, ed25519_dalek, Network, PublicKey as ECDSAPublicKey}; +use dashcore::{Network, PublicKey as ECDSAPublicKey}; use platform_value::Bytes20; - +#[cfg(feature = "bls-signatures")] +use {crate::bls_signatures, dashcore::blsful::Bls12381G2Impl}; impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { /// Get the original public key hash fn public_key_hash(&self) -> Result<[u8; 20], ProtocolError> { @@ -50,13 +53,13 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { fn validate_private_key_bytes( &self, - private_key_bytes: &[u8], + private_key_bytes: &[u8; 32], network: Network, ) -> Result { match self.key_type { KeyType::ECDSA_SECP256K1 => { let secp = Secp256k1::new(); - let secret_key = match SecretKey::from_slice(private_key_bytes) { + let secret_key = match SecretKey::from_byte_array(private_key_bytes) { Ok(secret_key) => secret_key, Err(_) => return Ok(false), }; @@ -67,17 +70,17 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { KeyType::BLS12_381 => { #[cfg(feature = "bls-signatures")] { - let private_key = - match bls_signatures::PrivateKey::from_bytes(private_key_bytes, false) { - Ok(secret_key) => secret_key, - Err(_) => return Ok(false), - }; - let g1_element = match private_key.g1_element() { - Ok(g1_element) => g1_element, - Err(_) => return Ok(false), - }; + let private_key: Option> = + bls_signatures::SecretKey::::from_be_bytes( + private_key_bytes, + ) + .into(); + if private_key.is_none() { + return Ok(false); + } + let private_key = private_key.expect("expected private key"); - Ok(g1_element.to_bytes().as_slice() == self.data.as_slice()) + Ok(private_key.public_key().0.to_compressed() == self.data.as_slice()) } #[cfg(not(feature = "bls-signatures"))] return Err(ProtocolError::NotSupported( @@ -86,7 +89,7 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { } KeyType::ECDSA_HASH160 => { let secp = Secp256k1::new(); - let secret_key = match SecretKey::from_slice(private_key_bytes) { + let secret_key = match SecretKey::from_byte_array(private_key_bytes) { Ok(secret_key) => secret_key, Err(_) => return Ok(false), }; @@ -101,11 +104,7 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { KeyType::EDDSA_25519_HASH160 => { #[cfg(feature = "ed25519-dalek")] { - let secret_key = match private_key_bytes.try_into() { - Ok(secret_key) => secret_key, - Err(_) => return Ok(false), - }; - let key_pair = ed25519_dalek::SigningKey::from_bytes(&secret_key); + let key_pair = ed25519_dalek::SigningKey::from_bytes(private_key_bytes); Ok( ripemd160_sha256(key_pair.verifying_key().to_bytes().as_slice()).as_slice() == self.data.as_slice(), @@ -116,11 +115,9 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { "Converting a private key to a eddsa hash 160 is not supported without the ed25519-dalek feature".to_string(), )); } - KeyType::BIP13_SCRIPT_HASH => { - return Err(ProtocolError::NotSupported( - "Converting a private key to a script hash is not supported".to_string(), - )); - } + KeyType::BIP13_SCRIPT_HASH => Err(ProtocolError::NotSupported( + "Converting a private key to a script hash is not supported".to_string(), + )), } } } @@ -129,11 +126,51 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { mod tests { use super::*; use crate::identity::{Purpose, SecurityLevel}; + use dashcore::blsful::{Bls12381G2Impl, Pairing, Signature, SignatureSchemes}; use dashcore::Network; use dpp::version::PlatformVersion; use rand::rngs::StdRng; use rand::SeedableRng; + #[test] + fn test_bls_serialization_deserialization() { + let mut rng = StdRng::seed_from_u64(5); + let (public_key_data, secret_key) = KeyType::BLS12_381 + .random_public_and_private_key_data(&mut rng, PlatformVersion::latest()) + .expect("expected to get keys"); + let decoded_secret_key = + dashcore::blsful::SecretKey::::from_be_bytes(&secret_key) + .expect("expected to get secret key"); + let public_key = decoded_secret_key.public_key(); + let decoded_public_key_data = public_key.0.to_compressed(); + assert_eq!( + public_key_data.as_slice(), + decoded_public_key_data.as_slice() + ) + } + + #[test] + fn test_bls_serialization_deserialization_signature() { + let mut rng = StdRng::seed_from_u64(5); + let (_, secret_key) = KeyType::BLS12_381 + .random_public_and_private_key_data(&mut rng, PlatformVersion::latest()) + .expect("expected to get keys"); + let decoded_secret_key = + dashcore::blsful::SecretKey::::from_be_bytes(&secret_key) + .expect("expected to get secret key"); + let signature = decoded_secret_key + .sign(SignatureSchemes::Basic, b"hello") + .expect("expected to sign"); + let compressed = signature.as_raw_value().to_compressed(); + let g2 = ::Signature::from_compressed(&compressed) + .expect("G2 projective"); + let decoded_signature = Signature::::Basic(g2); + assert_eq!( + compressed.as_slice(), + decoded_signature.as_raw_value().to_compressed().as_slice() + ) + } + #[cfg(feature = "random-public-keys")] #[test] fn test_validate_private_key_bytes_with_random_keys() { @@ -143,7 +180,7 @@ mod tests { // Test for ECDSA_SECP256K1 let key_type = KeyType::ECDSA_SECP256K1; let (public_key_data, private_key_data) = key_type - .random_public_and_private_key_data(&mut rng, &platform_version) + .random_public_and_private_key_data(&mut rng, platform_version) .expect("expected to generate random keys"); let identity_public_key = IdentityPublicKeyV0 { @@ -158,21 +195,15 @@ mod tests { }; // Validate that the private key matches the public key - assert_eq!( - identity_public_key - .validate_private_key_bytes(&private_key_data, Network::Testnet) - .unwrap(), - true - ); + assert!(identity_public_key + .validate_private_key_bytes(&private_key_data, Network::Testnet) + .unwrap(),); // Test with an invalid private key - let invalid_private_key_bytes = vec![0u8; private_key_data.len()]; - assert_eq!( - identity_public_key - .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) - .unwrap(), - false - ); + let invalid_private_key_bytes = [0u8; 32]; + assert!(!identity_public_key + .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) + .unwrap()); } #[cfg(all(feature = "random-public-keys", feature = "bls-signatures"))] @@ -184,7 +215,7 @@ mod tests { // Test for BLS12_381 let key_type = KeyType::BLS12_381; let (public_key_data, private_key_data) = key_type - .random_public_and_private_key_data(&mut rng, &platform_version) + .random_public_and_private_key_data(&mut rng, platform_version) .expect("expected to generate random keys"); let identity_public_key = IdentityPublicKeyV0 { @@ -199,21 +230,15 @@ mod tests { }; // Validate that the private key matches the public key - assert_eq!( - identity_public_key - .validate_private_key_bytes(&private_key_data, Network::Testnet) - .unwrap(), - true - ); + assert!(identity_public_key + .validate_private_key_bytes(&private_key_data, Network::Testnet) + .unwrap()); // Test with an invalid private key - let invalid_private_key_bytes = vec![0u8; private_key_data.len()]; - assert_eq!( - identity_public_key - .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) - .unwrap(), - false - ); + let invalid_private_key_bytes = [0u8; 32]; + assert!(!identity_public_key + .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) + .unwrap()); } #[cfg(all(feature = "random-public-keys", feature = "ed25519-dalek"))] @@ -225,7 +250,7 @@ mod tests { // Test for EDDSA_25519_HASH160 let key_type = KeyType::EDDSA_25519_HASH160; let (public_key_data, private_key_data) = key_type - .random_public_and_private_key_data(&mut rng, &platform_version) + .random_public_and_private_key_data(&mut rng, platform_version) .expect("expected to generate random keys"); let identity_public_key = IdentityPublicKeyV0 { @@ -240,20 +265,14 @@ mod tests { }; // Validate that the private key matches the public key - assert_eq!( - identity_public_key - .validate_private_key_bytes(&private_key_data, Network::Testnet) - .unwrap(), - true - ); + assert!(identity_public_key + .validate_private_key_bytes(&private_key_data, Network::Testnet) + .unwrap()); // Test with an invalid private key - let invalid_private_key_bytes = vec![0u8; private_key_data.len()]; - assert_eq!( - identity_public_key - .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) - .unwrap(), - false - ); + let invalid_private_key_bytes = [0u8; 32]; + assert!(!identity_public_key + .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) + .unwrap()); } } diff --git a/packages/rs-dpp/src/identity/identity_public_key/v0/random.rs b/packages/rs-dpp/src/identity/identity_public_key/v0/random.rs index 162e836e1b..a7ba471b3a 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/v0/random.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/v0/random.rs @@ -68,7 +68,7 @@ impl IdentityPublicKeyV0 { rng: &mut StdRng, used_key_matrix: Option<(KeyCount, &mut UsedKeyMatrix)>, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { // we have 16 different permutations possible let mut binding = [false; 16].to_vec(); let (key_count, key_matrix) = used_key_matrix.unwrap_or((0, &mut binding)); @@ -124,7 +124,7 @@ impl IdentityPublicKeyV0 { key_type: KeyType, contract_bounds: Option, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { let read_only = false; let (public_data, private_data) = key_type.random_public_and_private_key_data(rng, platform_version)?; @@ -197,7 +197,7 @@ impl IdentityPublicKeyV0 { id: KeyID, rng: &mut StdRng, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { let key_type = ECDSA_SECP256K1; let purpose = AUTHENTICATION; let security_level = MASTER; @@ -223,7 +223,7 @@ impl IdentityPublicKeyV0 { id: KeyID, rng: &mut StdRng, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { let key_type = ECDSA_HASH160; let purpose = VOTING; let security_level = MEDIUM; @@ -249,7 +249,7 @@ impl IdentityPublicKeyV0 { id: KeyID, rng: &mut StdRng, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { let key_type = ECDSA_HASH160; let purpose = OWNER; let security_level = CRITICAL; @@ -275,7 +275,7 @@ impl IdentityPublicKeyV0 { id: KeyID, rng: &mut StdRng, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { let key_type = ECDSA_HASH160; let purpose = TRANSFER; let security_level = CRITICAL; @@ -301,7 +301,7 @@ impl IdentityPublicKeyV0 { id: KeyID, rng: &mut StdRng, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { let key_type = ECDSA_SECP256K1; let purpose = AUTHENTICATION; let security_level = CRITICAL; @@ -327,7 +327,7 @@ impl IdentityPublicKeyV0 { id: KeyID, rng: &mut StdRng, platform_version: &PlatformVersion, - ) -> Result<(Self, Vec), ProtocolError> { + ) -> Result<(Self, [u8; 32]), ProtocolError> { let key_type = ECDSA_SECP256K1; let purpose = AUTHENTICATION; let security_level = HIGH; diff --git a/packages/rs-dpp/src/identity/random.rs b/packages/rs-dpp/src/identity/random.rs index d5f19f493a..c14525272c 100644 --- a/packages/rs-dpp/src/identity/random.rs +++ b/packages/rs-dpp/src/identity/random.rs @@ -66,8 +66,8 @@ impl Identity { ) -> Result<(Self, I), ProtocolError> where I: Default - + IntoIterator)> - + Extend<(IdentityPublicKey, Vec)>, + + IntoIterator + + Extend<(IdentityPublicKey, [u8; 32])>, { match platform_version .dpp @@ -234,8 +234,8 @@ impl Identity { ) -> Result<(Vec, I), ProtocolError> where I: Default - + FromIterator<(IdentityPublicKey, Vec)> - + Extend<(IdentityPublicKey, Vec)>, + + FromIterator<(IdentityPublicKey, [u8; 32])> + + Extend<(IdentityPublicKey, [u8; 32])>, { match platform_version .dpp diff --git a/packages/rs-dpp/src/identity/v0/random.rs b/packages/rs-dpp/src/identity/v0/random.rs index 2be4a34cfe..5733aeda9e 100644 --- a/packages/rs-dpp/src/identity/v0/random.rs +++ b/packages/rs-dpp/src/identity/v0/random.rs @@ -47,8 +47,8 @@ impl IdentityV0 { ) -> Result<(Self, I), ProtocolError> where I: Default - + IntoIterator)> - + Extend<(IdentityPublicKey, Vec)>, + + IntoIterator + + Extend<(IdentityPublicKey, [u8; 32])>, { let id = Identifier::new(rng.gen::<[u8; 32]>()); let revision = 0; @@ -126,11 +126,11 @@ impl IdentityV0 { ) -> Result<(Vec, I), ProtocolError> where I: Default - + FromIterator<(IdentityPublicKey, Vec)> - + Extend<(IdentityPublicKey, Vec)>, + + FromIterator<(IdentityPublicKey, [u8; 32])> + + Extend<(IdentityPublicKey, [u8; 32])>, { let mut vec: Vec = vec![]; - let mut private_key_map: Vec<(IdentityPublicKey, Vec)> = vec![]; + let mut private_key_map: Vec<(IdentityPublicKey, [u8; 32])> = vec![]; for _i in 0..count { let (identity, mut map) = Self::random_identity_with_main_keys_with_private_key( key_count, diff --git a/packages/rs-dpp/src/lib.rs b/packages/rs-dpp/src/lib.rs index a5d4ec177e..3ac800e827 100644 --- a/packages/rs-dpp/src/lib.rs +++ b/packages/rs-dpp/src/lib.rs @@ -89,8 +89,8 @@ pub mod prelude { } pub use bincode; -#[cfg(all(not(target_arch = "wasm32"), feature = "bls-signatures"))] -pub use dashcore::bls_signatures; +#[cfg(feature = "bls-signatures")] +pub use dashcore::blsful as bls_signatures; #[cfg(feature = "ed25519-dalek")] pub use dashcore::ed25519_dalek; #[cfg(feature = "system_contracts")] diff --git a/packages/rs-dpp/src/signing.rs b/packages/rs-dpp/src/signing.rs index d4f69942b6..d637c0480b 100644 --- a/packages/rs-dpp/src/signing.rs +++ b/packages/rs-dpp/src/signing.rs @@ -1,14 +1,20 @@ -#[cfg(feature = "message-signature-verification")] -use crate::consensus::signature::{ - BasicBLSError, BasicECDSAError, SignatureError, SignatureShouldNotBePresentError, -}; use crate::identity::KeyType; use crate::serialization::PlatformMessageSignable; #[cfg(feature = "message-signature-verification")] -use crate::validation::SimpleConsensusValidationResult; +use crate::{ + consensus::signature::{ + BasicBLSError, BasicECDSAError, SignatureError, SignatureShouldNotBePresentError, + }, + validation::SimpleConsensusValidationResult, +}; #[cfg(feature = "message-signing")] use crate::{BlsModule, ProtocolError}; -use dashcore::{bls_signatures, signer}; +use dashcore::signer; +#[cfg(feature = "bls-signatures")] +use { + crate::bls_signatures::{Bls12381G2Impl, Pairing}, + dashcore::{blsful as bls_signatures, blsful::Signature}, +}; impl PlatformMessageSignable for &[u8] { #[cfg(feature = "message-signature-verification")] @@ -38,25 +44,44 @@ impl PlatformMessageSignable for &[u8] { } } KeyType::BLS12_381 => { - let public_key = match bls_signatures::PublicKey::from_bytes(public_key_data) { - Ok(public_key) => public_key, - Err(e) => { - // dbg!(format!("bls public_key could not be recovered")); + let public_key = + match bls_signatures::PublicKey::::try_from(public_key_data) { + Ok(public_key) => public_key, + Err(e) => { + // dbg!(format!("bls public_key could not be recovered")); + return SimpleConsensusValidationResult::new_with_error( + SignatureError::BasicBLSError(BasicBLSError::new(e.to_string())) + .into(), + ); + } + }; + let signature_bytes: [u8; 96] = match signature.try_into() { + Ok(bytes) => bytes, + Err(_) => { return SimpleConsensusValidationResult::new_with_error( - SignatureError::BasicBLSError(BasicBLSError::new(e.to_string())).into(), - ); + SignatureError::BasicBLSError(BasicBLSError::new(format!( + "Signature was {} bytes, expected 96 bytes", + signature.len() + ))) + .into(), + ) } }; - let signature = match bls_signatures::Signature::from_bytes(signature) { - Ok(public_key) => public_key, - Err(e) => { - // dbg!(format!("bls signature could not be recovered")); + let g2 = match ::Signature::from_compressed( + &signature_bytes, + ) + .into_option() + { + Some(g2) => g2, + None => { return SimpleConsensusValidationResult::new_with_error( - SignatureError::BasicBLSError(BasicBLSError::new(e.to_string())).into(), + SignatureError::BasicBLSError(BasicBLSError::new("bls signature does not conform to proper bls signature serialization".to_string())).into(), ); } }; - if !public_key.verify(&signature, signable_data) { + let signature = Signature::::Basic(g2); + + if signature.verify(&public_key, signable_data).is_err() { SimpleConsensusValidationResult::new_with_error( SignatureError::BasicBLSError(BasicBLSError::new( "bls signature was incorrect".to_string(), diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/v0/mod.rs index eeb7104420..588fafe2c0 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/v0/mod.rs @@ -5,7 +5,6 @@ use crate::{ state_transition::StateTransition, ProtocolError, }; -use platform_value::Identifier; #[cfg(feature = "state-transition-signing")] use platform_version::version::{FeatureVersion, PlatformVersion}; @@ -15,7 +14,7 @@ pub trait IdentityCreditTransferTransitionMethodsV0 { #[cfg(feature = "state-transition-signing")] fn try_from_identity( identity: &Identity, - to_identity_with_identifier: Identifier, + to_identity_with_identifier: platform_value::Identifier, amount: u64, user_fee_increase: UserFeeIncrease, signer: S, diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index b1762b8706..5547a6c07e 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -28,7 +28,7 @@ rand = "0.8.5" tempfile = "3.3.0" hex = "0.4.3" indexmap = { version = "2.2.6", features = ["serde"] } -dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.8" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.9" } dpp = { path = "../rs-dpp", features = ["abci"] } simple-signer = { path = "../simple-signer" } rust_decimal = "1.2.5" @@ -73,6 +73,7 @@ tokio-util = { version = "0.7" } derive_more = { version = "1.0", features = ["from", "deref", "deref_mut"] } async-trait = "0.1.77" console-subscriber = { version = "0.4", optional = true } +bls-signatures = { git = "https://github.com/dashpay/bls-signatures", tag = "1.3.3" } [dev-dependencies] bs58 = { version = "0.5.0" } diff --git a/packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs b/packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs index 9c45694f6c..4cef4a48bc 100644 --- a/packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs @@ -272,7 +272,7 @@ where // Rebroadcast expired withdrawals if they exist self.rebroadcast_expired_withdrawal_documents( &block_info, - &last_committed_platform_state, + last_committed_platform_state, transaction, platform_version, )?; diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_operator_identity/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_operator_identity/v0/mod.rs index 898eec524c..7c901380b0 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_operator_identity/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_operator_identity/v0/mod.rs @@ -400,7 +400,7 @@ mod tests { use dashcore_rpc::dashcore_rpc_json::{MasternodeListItem, MasternodeType}; use dashcore_rpc::json::DMNState; use dpp::block::block_info::BlockInfo; - use dpp::bls_signatures::PrivateKey as BlsPrivateKey; + use dpp::bls_signatures::{Bls12381G2Impl, SecretKey as BlsPrivateKey}; use dpp::dashcore::hashes::Hash; use dpp::dashcore::Txid; use dpp::identifier::MasternodeIdentifiers; @@ -433,13 +433,15 @@ mod tests { let node_id_bytes: [u8; 20] = rng.gen(); // Create a public key operator and payout address - let private_key_operator = - BlsPrivateKey::generate_dash(rng).expect("expected to generate a private key"); - let pub_key_operator = private_key_operator - .g1_element() - .expect("expected to get public key") + let private_key_operator_bytes = bls_signatures::PrivateKey::generate_dash(rng) + .expect("expected to generate a private key") .to_bytes() .to_vec(); + let private_key_operator = BlsPrivateKey::::from_be_bytes( + &private_key_operator_bytes.try_into().expect("expected the secret key to be 32 bytes"), + ) + .expect("expected the conversion between bls signatures library and blsful to happen without failing"); + let pub_key_operator = private_key_operator.public_key().0.to_compressed().to_vec(); let operator_key: IdentityPublicKey = IdentityPublicKeyV0 { id: 0, @@ -950,13 +952,15 @@ mod tests { ) = create_operator_identity(&platform, &mut rng); // Generate a new public key operator - let new_private_key_operator = - BlsPrivateKey::generate_dash(&mut rng).expect("expected to generate a private key"); - let new_pub_key_operator = new_private_key_operator - .g1_element() - .expect("expected to get public key") + let private_key_operator_bytes = bls_signatures::PrivateKey::generate_dash(&mut rng) + .expect("expected to generate a private key") .to_bytes() .to_vec(); + let private_key_operator = BlsPrivateKey::::from_be_bytes( + &private_key_operator_bytes.try_into().expect("expected the secret key to be 32 bytes"), + ) + .expect("expected the conversion between bls signatures library and blsful to happen without failing"); + let new_pub_key_operator = private_key_operator.public_key().0.to_compressed().to_vec(); // Create an old masternode state let masternode_list_item = MasternodeListItem { @@ -1040,13 +1044,15 @@ mod tests { ) = create_operator_identity(&platform, &mut rng); // Generate a new public key operator - let new_private_key_operator = - BlsPrivateKey::generate_dash(&mut rng).expect("expected to generate a private key"); - let new_pub_key_operator = new_private_key_operator - .g1_element() - .expect("expected to get public key") + let private_key_operator_bytes = bls_signatures::PrivateKey::generate_dash(&mut rng) + .expect("expected to generate a private key") .to_bytes() .to_vec(); + let private_key_operator = BlsPrivateKey::::from_be_bytes( + &private_key_operator_bytes.try_into().expect("expected the secret key to be 32 bytes"), + ) + .expect("expected the conversion between bls signatures library and blsful to happen without failing"); + let new_pub_key_operator = private_key_operator.public_key().0.to_compressed().to_vec(); // Create an old masternode state with original public key operator let masternode_list_item = MasternodeListItem { diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_quorum_info/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_quorum_info/v0/mod.rs index 5ca6ce4070..14320ad1d2 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_quorum_info/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_quorum_info/v0/mod.rs @@ -386,7 +386,7 @@ where )?; let public_key = - match BlsPublicKey::from_bytes(quorum_info.quorum_public_key.as_slice()) + match BlsPublicKey::try_from(quorum_info.quorum_public_key.as_slice()) .map_err(ExecutionError::BlsErrorFromDashCoreResponse) { Ok(public_key) => public_key, diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/choose_quorum/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/choose_quorum/mod.rs index 3af3b3fbd2..397709ed19 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/choose_quorum/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/choose_quorum/mod.rs @@ -3,7 +3,7 @@ mod v0; use crate::error::execution::ExecutionError; use crate::error::Error; use dashcore_rpc::dashcore_rpc_json::QuorumType; -use dpp::bls_signatures::PublicKey as BlsPublicKey; +use dpp::bls_signatures::{Bls12381G2Impl, PublicKey as BlsPublicKey}; use dpp::dashcore::QuorumHash; use std::collections::BTreeMap; @@ -24,10 +24,10 @@ where // TODO: use CoreQuorumSet.select_quorums instead pub fn choose_quorum<'a>( llmq_quorum_type: QuorumType, - quorums: &'a BTreeMap, + quorums: &'a BTreeMap>, request_id: &[u8; 32], platform_version: &PlatformVersion, - ) -> Result, Error> { + ) -> Result)>, Error> { match platform_version .drive_abci .methods diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/choose_quorum/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/choose_quorum/v0/mod.rs index 0d8ac563e3..3b6d1f8673 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/choose_quorum/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/choose_quorum/v0/mod.rs @@ -1,5 +1,5 @@ use dashcore_rpc::dashcore_rpc_json::QuorumType; -use dpp::bls_signatures::PublicKey as BlsPublicKey; +use dpp::bls_signatures::{Bls12381G2Impl, PublicKey as BlsPublicKey}; use dpp::dashcore::hashes::{sha256d, Hash, HashEngine}; use dpp::dashcore::QuorumHash; use std::collections::BTreeMap; @@ -12,11 +12,15 @@ impl Platform { /// Based on DIP8 deterministically chooses a pseudorandom quorum from the list of quorums pub(super) fn choose_quorum_v0<'a>( llmq_quorum_type: QuorumType, - quorums: &'a BTreeMap, + quorums: &'a BTreeMap>, request_id: &[u8; 32], - ) -> Option<(ReversedQuorumHashBytes, &'a BlsPublicKey)> { + ) -> Option<(ReversedQuorumHashBytes, &'a BlsPublicKey)> { // Scoring system logic - let mut scores: Vec<(ReversedQuorumHashBytes, &BlsPublicKey, [u8; 32])> = Vec::new(); + let mut scores: Vec<( + ReversedQuorumHashBytes, + &BlsPublicKey, + [u8; 32], + )> = Vec::new(); for (quorum_hash, public_key) in quorums { let mut quorum_hash_bytes = quorum_hash.to_byte_array().to_vec(); @@ -92,9 +96,11 @@ mod tests { use crate::platform_types::platform::Platform; use crate::rpc::core::MockCoreRPCLike; use dashcore_rpc::dashcore_rpc_json::QuorumType; - use dpp::bls_signatures::PublicKey as BlsPublicKey; + use dpp::bls_signatures::SecretKey; use dpp::dashcore::hashes::Hash; use dpp::dashcore::QuorumHash; + use rand::rngs::StdRng; + use rand::SeedableRng; use std::collections::BTreeMap; #[test] @@ -124,11 +130,12 @@ mod tests { .as_slice(), ) .unwrap(); + let mut rng = StdRng::seed_from_u64(345); let quorums = BTreeMap::from([ - (quorum_hash1, BlsPublicKey::generate()), - (quorum_hash2, BlsPublicKey::generate()), - (quorum_hash3, BlsPublicKey::generate()), - (quorum_hash4, BlsPublicKey::generate()), + (quorum_hash1, SecretKey::random(&mut rng).public_key()), + (quorum_hash2, SecretKey::random(&mut rng).public_key()), + (quorum_hash3, SecretKey::random(&mut rng).public_key()), + (quorum_hash4, SecretKey::random(&mut rng).public_key()), ]); // diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/verify_chain_lock_locally/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/verify_chain_lock_locally/v0/mod.rs index a48fc30c67..cefe129e4d 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/verify_chain_lock_locally/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_chain_lock/verify_chain_lock_locally/v0/mod.rs @@ -1,4 +1,4 @@ -use dpp::bls_signatures::G2Element; +use dpp::bls_signatures::{Bls12381G2Impl, Pairing, Signature}; use dpp::dashcore::hashes::{sha256d, Hash, HashEngine}; use dpp::dashcore::{ChainLock, QuorumSigningRequestId}; @@ -37,10 +37,30 @@ where let quorum_config = quorum_set.config(); // First verify that the signature conforms to a signature - let Ok(signature) = G2Element::from_bytes(chain_lock.signature.as_bytes()) else { - return Ok(Some(false)); + + let decoded_sig = match ::Signature::from_compressed( + chain_lock.signature.as_bytes(), + ) + .into_option() + { + Some(signature) => signature, + None => { + tracing::error!( + ?chain_lock, + "chain lock signature was not deserializable: h:{} r:{}", + platform_state.last_committed_block_height() + 1, + round + ); + return Err(Error::BLSError( + dpp::bls_signatures::BlsError::DeserializationError( + "chain lock signature was not deserializable".to_string(), + ), + )); + } }; + let signature = Signature::Basic(decoded_sig); + // we attempt to verify the chain lock locally let chain_lock_height = chain_lock.block_height; @@ -119,9 +139,12 @@ where let message_digest = sha256d::Hash::from_engine(engine); - let mut chain_lock_verified = quorum - .public_key - .verify(&signature, message_digest.as_ref()); + let mut chain_lock_verified = signature + .verify( + &quorum.public_key, + message_digest.as_byte_array().as_slice(), + ) + .is_ok(); tracing::debug!( ?chain_lock, @@ -162,9 +185,12 @@ where let message_digest = sha256d::Hash::from_engine(engine); - chain_lock_verified = quorum - .public_key - .verify(&signature, message_digest.as_ref()); + chain_lock_verified = signature + .verify( + &quorum.public_key, + message_digest.as_byte_array().as_slice(), + ) + .is_ok(); tracing::debug!( ?chain_lock, @@ -210,6 +236,7 @@ where #[cfg(test)] mod tests { use crate::execution::platform_events::core_chain_lock::verify_chain_lock_locally::v0::CHAIN_LOCK_REQUEST_ID_PREFIX; + use dpp::bls_signatures::{Bls12381G2Impl, Pairing}; use dpp::dashcore::hashes::{sha256d, Hash, HashEngine}; use dpp::dashcore::QuorumSigningRequestId; @@ -279,4 +306,30 @@ mod tests { "5ec53e83b8ff390b970e28db21da5b8e45fbe3b69d9f11a2c39062769b1f5e47" ); } + + #[test] + // Verify that the signature can be deserialized + fn verify_signature() { + let signatures =vec![ + // local devnet + [ + 139, 91, 189, 131, 240, 161, 167, 171, 205, 251, 134, 2, 160, 27, 100, 46, 55, 162, 23, + 224, 18, 130, 100, 147, 255, 29, 128, 110, 111, 138, 195, 219, 243, 137, 110, 60, 243, + 176, 180, 242, 58, 223, 235, 59, 172, 168, 235, 146, 6, 243, 139, 112, 175, 99, 82, 69, + 144, 38, 15, 72, 250, 94, 82, 198, 52, 35, 126, 131, 37, 140, 25, 178, 33, 187, 71, + 167, 87, 81, 15, 210, 220, 201, 44, 245, 222, 66, 252, 70, 227, 109, 43, 60, 102, 187, + 144, 108, + ], + // mainnet + hex::decode("9609d7dea0812c0a6b72d6f20f988d269d3076324c5e51ff6042ce0506370a738bfce420f8174a4e0e34ded7e5792ac217a169b71c7dc3eefde5abba9feaf7d3c7c29fb36ade2e41bc5dfada13d7546c6061ef7e03e894e813f72dd20af8bcbb").unwrap().try_into().unwrap(), + ]; + + for signature in signatures { + assert!( + ::Signature::from_compressed(&signature) + .into_option() + .is_some(), + ); + } + } } diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_instant_send_lock/verify_recent_signature_locally/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_instant_send_lock/verify_recent_signature_locally/v0/mod.rs index 335e5cb201..0f3d38e5a8 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_instant_send_lock/verify_recent_signature_locally/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_instant_send_lock/verify_recent_signature_locally/v0/mod.rs @@ -1,4 +1,4 @@ -use dpp::bls_signatures::G2Element; +use dpp::bls_signatures::{Bls12381G2Impl, Pairing, Signature}; use std::fmt::{Debug, Formatter}; use dpp::dashcore::hashes::{sha256d, Hash, HashEngine}; @@ -20,15 +20,16 @@ pub(super) fn verify_recent_instant_lock_signature_locally_v0( platform_state: &PlatformState, ) -> Result { // First verify that the signature conforms to a signature - let signature = match G2Element::from_bytes(instant_lock.signature.as_bytes()) { - Ok(signature) => signature, - Err(e) => { + + let signature = match ::Signature::from_compressed( + instant_lock.signature.as_bytes(), + ) + .into_option() + { + Some(signature) => Signature::Basic(signature), + None => { tracing::trace!( - instant_lock = ?InstantLockDebug(instant_lock), - "Invalid instant Lock {} signature format: {}", - instant_lock.txid, - e, - ); + instant_lock = ?InstantLockDebug(instant_lock), "Invalid instant Lock {} signature format", instant_lock.txid, ); return Ok(false); } @@ -96,9 +97,12 @@ pub(super) fn verify_recent_instant_lock_signature_locally_v0( let message_digest = sha256d::Hash::from_engine(engine); - if quorum - .public_key - .verify(&signature, message_digest.as_ref()) + if signature + .verify( + &quorum.public_key, + message_digest.as_byte_array().as_slice(), + ) + .is_ok() { return Ok(true); } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/common/asset_lock/transaction/fetch_asset_lock_transaction_output_sync/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/common/asset_lock/transaction/fetch_asset_lock_transaction_output_sync/v0/mod.rs index 6347c9515c..0f11ba2a64 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/common/asset_lock/transaction/fetch_asset_lock_transaction_output_sync/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/common/asset_lock/transaction/fetch_asset_lock_transaction_output_sync/v0/mod.rs @@ -5,7 +5,7 @@ use dpp::consensus::basic::identity::{ IdentityAssetLockTransactionIsNotFoundError, IdentityAssetLockTransactionOutputNotFoundError, InvalidAssetLockProofTransactionHeightError, }; -use dpp::dashcore::secp256k1::ThirtyTwoByteHash; +use dpp::dashcore::hashes::Hash; use dpp::dashcore::TxOut; use dpp::identity::state_transition::asset_lock_proof::validate_asset_lock_transaction_structure::validate_asset_lock_transaction_structure; use dpp::prelude::{AssetLockProof, ConsensusValidationResult}; @@ -49,7 +49,7 @@ pub fn fetch_asset_lock_transaction_output_sync_v0( let Some(transaction_info) = maybe_transaction_info else { // Transaction hash bytes needs to be reversed to match actual transaction hash - let mut hash = transaction_hash.as_raw_hash().into_32(); + let mut hash: [u8; 32] = *transaction_hash.as_raw_hash().as_byte_array(); hash.reverse(); return Ok(ValidationResult::new_with_error( diff --git a/packages/rs-drive-abci/src/mimic/mod.rs b/packages/rs-drive-abci/src/mimic/mod.rs index 0fb866b107..f0c5f895bc 100644 --- a/packages/rs-drive-abci/src/mimic/mod.rs +++ b/packages/rs-drive-abci/src/mimic/mod.rs @@ -13,6 +13,7 @@ use crate::platform_types::withdrawal::unsigned_withdrawal_txs::v0::{ use crate::rpc::core::CoreRPCLike; use ciborium::Value as CborValue; use dpp::block::block_info::BlockInfo; +use dpp::bls_signatures::SignatureSchemes; use dpp::consensus::ConsensusError; use dpp::dashcore::hashes::Hash; use dpp::platform_value::btreemap_extensions::BTreeValueMapHelper; @@ -514,9 +515,12 @@ impl<'a, C: CoreRPCLike> FullAbciApplication<'a, C> { public_key = ?current_quorum.public_key, "Signing block" ); - let block_signature = current_quorum.private_key.sign(digest.as_slice()); + let block_signature = current_quorum + .private_key + .sign(SignatureSchemes::Basic, digest.as_slice()) + .expect("expected to be able to sign"); - commit_info.block_signature = block_signature.to_bytes().to_vec(); + commit_info.block_signature = block_signature.as_raw_value().to_compressed().to_vec(); } else { commit_info.block_signature = [0u8; 96].to_vec(); } diff --git a/packages/rs-drive-abci/src/mimic/test_quorum.rs b/packages/rs-drive-abci/src/mimic/test_quorum.rs index c1653183c6..389abf3bc1 100644 --- a/packages/rs-drive-abci/src/mimic/test_quorum.rs +++ b/packages/rs-drive-abci/src/mimic/test_quorum.rs @@ -3,8 +3,9 @@ use crate::platform_types::validator_set::v0::ValidatorSetV0; use dashcore_rpc::dashcore::hashes::Hash; use dashcore_rpc::dashcore::{ProTxHash, PubkeyHash, QuorumHash}; use dashcore_rpc::dashcore_rpc_json::{QuorumInfoResult, QuorumMember, QuorumType}; -use dpp::bls_signatures; -use dpp::bls_signatures::{PrivateKey as BlsPrivateKey, PublicKey as BlsPublicKey}; +use dpp::bls_signatures::{ + Bls12381G2Impl, PublicKey as BlsPublicKey, PublicKey, SecretKey as BlsPrivateKey, SecretKey, +}; use rand::rngs::StdRng; use rand::Rng; use std::collections::BTreeMap; @@ -17,9 +18,9 @@ pub struct ValidatorInQuorum { /// The hash of the transaction that identifies this validator in the network. pub pro_tx_hash: ProTxHash, /// The private key for this validator's BLS signature scheme. - pub private_key: BlsPrivateKey, + pub private_key: BlsPrivateKey, /// The public key for this validator's BLS signature scheme. - pub public_key: BlsPublicKey, + pub public_key: BlsPublicKey, /// The node address pub node_ip: String, /// The node id @@ -102,9 +103,9 @@ pub struct TestQuorumInfo { /// A map of validators indexed by their `ProTxHash` identifiers. pub validator_map: BTreeMap, /// The private key used to sign messages for the quorum (for testing purposes only). - pub private_key: BlsPrivateKey, + pub private_key: BlsPrivateKey, /// The public key corresponding to the private key used for signing. - pub public_key: BlsPublicKey, + pub public_key: BlsPublicKey, } fn random_ipv4_address(rng: &mut StdRng) -> Ipv4Addr { @@ -135,6 +136,7 @@ impl TestQuorumInfo { pro_tx_hashes: Vec, rng: &mut StdRng, ) -> Self { + // We test on purpose with the bls library that Dash Core uses let private_keys = bls_signatures::PrivateKey::generate_dash_many(pro_tx_hashes.len(), rng) .expect("expected to generate private keys"); let bls_id_private_key_pairs = private_keys @@ -154,8 +156,12 @@ impl TestQuorumInfo { ValidatorInQuorum { pro_tx_hash: ProTxHash::from_slice(pro_tx_hash.as_slice()) .expect("expected 32 bytes for pro_tx_hash"), - private_key: key, - public_key, + private_key: SecretKey::from_be_bytes( + &key.to_bytes().to_vec().try_into().expect("32 bytes"), + ) + .expect("expected conversion to work"), + public_key: PublicKey::try_from(public_key.to_bytes().as_slice()) + .expect("expected conversion to work"), node_ip: random_socket_addr(rng).to_string(), node_id: PubkeyHash::from_slice(pro_tx_hash.split_at(20).0).unwrap(), core_port: 1, @@ -178,8 +184,16 @@ impl TestQuorumInfo { quorum_index, validator_set, validator_map: map, - private_key: recovered_private_key, - public_key, + private_key: SecretKey::from_be_bytes( + &recovered_private_key + .to_bytes() + .to_vec() + .try_into() + .expect("32 bytes"), + ) + .expect("expected conversion to work"), + public_key: PublicKey::try_from(public_key.to_bytes().as_slice()) + .expect("expected conversion to work"), } } } @@ -255,7 +269,7 @@ impl From<&TestQuorumInfo> for QuorumInfoResult { pro_tx_hash: *pro_tx_hash, pub_key_operator: vec![], //doesn't matter valid: true, - pub_key_share: Some(public_key.to_bytes().to_vec()), + pub_key_share: Some(public_key.0.to_compressed().to_vec()), } }) .collect(); @@ -266,7 +280,7 @@ impl From<&TestQuorumInfo> for QuorumInfoResult { quorum_index: 0, mined_block: vec![], members, - quorum_public_key: public_key.to_bytes().to_vec(), + quorum_public_key: public_key.0.to_compressed().to_vec(), secret_key_share: None, } } diff --git a/packages/rs-drive-abci/src/platform_types/commit/mod.rs b/packages/rs-drive-abci/src/platform_types/commit/mod.rs index 1a24fddcd1..a903ce25d8 100644 --- a/packages/rs-drive-abci/src/platform_types/commit/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/commit/mod.rs @@ -5,6 +5,7 @@ use crate::platform_types::cleaned_abci_messages::{cleaned_block_id, cleaned_com use crate::platform_types::commit::v0::CommitV0; use dashcore_rpc::dashcore_rpc_json::QuorumType; use dpp::bls_signatures; +use dpp::bls_signatures::Bls12381G2Impl; use dpp::validation::SimpleValidationResult; use dpp::version::PlatformVersion; use tenderdash_abci::proto::abci::CommitInfo; @@ -82,7 +83,7 @@ impl Commit { pub fn verify_signature( &self, signature: &[u8; 96], - public_key: &bls_signatures::PublicKey, + public_key: &bls_signatures::PublicKey, ) -> SimpleValidationResult { match self { Commit::V0(v0) => v0.verify_signature(signature, public_key), diff --git a/packages/rs-drive-abci/src/platform_types/commit/v0/mod.rs b/packages/rs-drive-abci/src/platform_types/commit/v0/mod.rs index 403a3fff30..2f70aa8e5c 100644 --- a/packages/rs-drive-abci/src/platform_types/commit/v0/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/commit/v0/mod.rs @@ -6,6 +6,7 @@ use crate::abci::AbciError; use crate::platform_types::cleaned_abci_messages::{cleaned_block_id, cleaned_commit_info}; use dashcore_rpc::dashcore_rpc_json::QuorumType; use dpp::bls_signatures; +use dpp::bls_signatures::{Bls12381G2Impl, BlsError, Pairing, Signature}; use dpp::validation::{SimpleValidationResult, ValidationResult}; use tenderdash_abci::proto; use tenderdash_abci::proto::abci::CommitInfo; @@ -81,24 +82,27 @@ impl CommitV0 { pub(super) fn verify_signature( &self, signature: &[u8; 96], - public_key: &bls_signatures::PublicKey, + public_key: &bls_signatures::PublicKey, ) -> SimpleValidationResult { if signature == &[0; 96] { return ValidationResult::new_with_error(AbciError::BadRequest( "commit signature not initialized".to_string(), )); } + // We could have received a fake commit, so signature validation needs to be returned if error as a simple validation result - let signature = match bls_signatures::Signature::from_bytes(signature).map_err(|e| { - AbciError::BlsErrorOfTenderdashThresholdMechanism( - e, + let g2_element = match ::Signature::from_compressed(signature) + .into_option() + .ok_or(AbciError::BlsErrorOfTenderdashThresholdMechanism( + BlsError::InvalidSignature, "verification of a commit signature".to_string(), - ) - }) { + )) { Ok(signature) => signature, Err(e) => return ValidationResult::new_with_error(e), }; + let signature = Signature::Basic(g2_element); + //todo: maybe cache this to lower the chance of a hashing based attack (forcing the // same calculation each time) let quorum_hash = &self.inner.quorum_hash[..] @@ -120,11 +124,11 @@ impl CommitV0 { Err(e) => return ValidationResult::new_with_error(e), }; - match public_key.verify(&signature, &hash) { - true => ValidationResult::default(), - false => ValidationResult::new_with_error(AbciError::BadCommitSignature(format!( + match signature.verify(public_key, &hash) { + Ok(_) => ValidationResult::default(), + Err(_) => ValidationResult::new_with_error(AbciError::BadCommitSignature(format!( "commit signature {} is wrong", - hex::encode(signature.to_bytes().as_slice()) + signature ))), } } @@ -184,7 +188,7 @@ mod test { }; let pubkey = hex::decode("8d63d603fe858be4d7c14a8f308936bd3447c1f361148ad508a04df92f48cd3b2f2b374ef5d1ee8a75f5aeda2f6f3418").unwrap(); - let pubkey = PublicKey::from_bytes(pubkey.as_slice()).unwrap(); + let pubkey = PublicKey::try_from(pubkey.as_slice()).unwrap(); let signature = hex::decode("b95efd51c69a0baf09b130871e735b49cb1b9a0d566bc7ba8fd0fa149dbd28539ab3df435e87ed2a83c94ea714bc8e120504b1cba9363b32c3d58499ed85ecf14539e8e99329fa7952420e4ad9da80b3b28388d62be00770988e4aee705da830").unwrap(); let commit = CommitV0::new_from_cleaned( diff --git a/packages/rs-drive-abci/src/platform_types/platform_state/v0/mod.rs b/packages/rs-drive-abci/src/platform_types/platform_state/v0/mod.rs index d1c2ccd464..9bb41bf2d6 100644 --- a/packages/rs-drive-abci/src/platform_types/platform_state/v0/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/platform_state/v0/mod.rs @@ -1,3 +1,5 @@ +mod old_structures; + use crate::error::execution::ExecutionError; use crate::error::Error; use dashcore_rpc::dashcore::{ProTxHash, QuorumHash}; @@ -126,7 +128,7 @@ fn hex_encoded_validator_sets(validator_sets: &IndexMap, /// Information about the last block @@ -143,7 +145,7 @@ pub struct PlatformStateForSavingV0 { /// The validator set quorums are a subset of the quorums, but they also contain the list of /// all members #[bincode(with_serde)] - pub validator_sets: Vec<(Bytes32, ValidatorSet)>, + pub validator_sets: Vec<(Bytes32, old_structures::ValidatorSet)>, /// The quorums used for validating chain locks pub chain_lock_validating_quorums: SignatureVerificationQuorumSetForSaving, @@ -267,7 +269,7 @@ impl From for PlatformStateV0 { validator_sets: value .validator_sets .into_iter() - .map(|(k, v)| (QuorumHash::from_byte_array(k.to_buffer()), v)) + .map(|(k, v)| (QuorumHash::from_byte_array(k.to_buffer()), v.into())) .collect(), chain_lock_validating_quorums: value.chain_lock_validating_quorums.into(), instant_lock_validating_quorums: value.instant_lock_validating_quorums.into(), diff --git a/packages/rs-drive-abci/src/platform_types/platform_state/v0/old_structures/mod.rs b/packages/rs-drive-abci/src/platform_types/platform_state/v0/old_structures/mod.rs new file mode 100644 index 0000000000..ebd0e85875 --- /dev/null +++ b/packages/rs-drive-abci/src/platform_types/platform_state/v0/old_structures/mod.rs @@ -0,0 +1,103 @@ +use dpp::bls_signatures::PublicKey; +use dpp::dashcore::{ProTxHash, PubkeyHash, QuorumHash}; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub(super) enum ValidatorSet { + /// Version 0 + V0(ValidatorSetV0), +} + +impl From for dpp::core_types::validator_set::ValidatorSet { + fn from(value: ValidatorSet) -> Self { + match value { + ValidatorSet::V0(v0) => dpp::core_types::validator_set::ValidatorSet::V0(v0.into()), + } + } +} + +/// The validator set is only slightly different from a quorum as it does not contain non valid +/// members +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub(super) struct ValidatorSetV0 { + /// The quorum hash + pub quorum_hash: QuorumHash, + /// Rotation quorum index is available only for DIP24 quorums + pub quorum_index: Option, + /// Active height + pub core_height: u32, + /// The list of masternodes + pub members: BTreeMap, + /// The threshold quorum public key + pub threshold_public_key: bls_signatures::PublicKey, +} + +impl From for dpp::core_types::validator_set::v0::ValidatorSetV0 { + fn from(value: ValidatorSetV0) -> Self { + let ValidatorSetV0 { + quorum_hash, + quorum_index, + core_height, + members, + threshold_public_key, + } = value; + Self { + quorum_hash, + quorum_index, + core_height, + members: members + .into_iter() + .map(|(pro_tx_hash, validator)| (pro_tx_hash, validator.into())) + .collect(), + threshold_public_key: PublicKey::try_from(threshold_public_key.to_bytes().as_slice()) + .expect("this should not be possible to error as the threshold_public_key was already verified on disk"), + } + } +} + +/// A validator in the context of a quorum +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +pub(super) struct ValidatorV0 { + /// The proTxHash + pub pro_tx_hash: ProTxHash, + /// The public key share of this validator for this quorum + pub public_key: Option, + /// The node address + pub node_ip: String, + /// The node id + pub node_id: PubkeyHash, + /// Core port + pub core_port: u16, + /// Http port + pub platform_http_port: u16, + /// Tenderdash port + pub platform_p2p_port: u16, + /// Is the validator banned + pub is_banned: bool, +} + +impl From for dpp::core_types::validator::v0::ValidatorV0 { + fn from(value: ValidatorV0) -> Self { + let ValidatorV0 { + pro_tx_hash, + public_key, + node_ip, + node_id, + core_port, + platform_http_port, + platform_p2p_port, + is_banned, + } = value; + Self { + pro_tx_hash, + public_key: public_key.map(|pk| PublicKey::try_from(pk.to_bytes().as_slice()).expect("this should not be possible to error as the public_key was already verified on disk")), + node_ip, + node_id, + core_port, + platform_http_port, + platform_p2p_port, + is_banned, + } + } +} diff --git a/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/mod.rs b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/mod.rs index 8d0eac3c0a..a314829a7d 100644 --- a/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/mod.rs @@ -4,6 +4,7 @@ use crate::config::QuorumLikeConfig; use crate::error::execution::ExecutionError; use crate::error::Error; use crate::platform_types::signature_verification_quorum_set::v0::for_saving::SignatureVerificationQuorumSetForSavingV0; +use crate::platform_types::signature_verification_quorum_set::v0::for_saving_v1::SignatureVerificationQuorumSetForSavingV1; pub use crate::platform_types::signature_verification_quorum_set::v0::quorum_set::{ QuorumConfig, QuorumsWithConfig, SelectedQuorumSetIterator, SignatureVerificationQuorumSetV0, SignatureVerificationQuorumSetV0Methods, SIGN_OFFSET, @@ -118,13 +119,15 @@ impl SignatureVerificationQuorumSetV0Methods for SignatureVerificationQuorumSet pub enum SignatureVerificationQuorumSetForSaving { /// Version 0 of the signature verification quorums V0(SignatureVerificationQuorumSetForSavingV0), + /// Version 1 of the signature verification quorums + V1(SignatureVerificationQuorumSetForSavingV1), } impl From for SignatureVerificationQuorumSetForSaving { fn from(value: SignatureVerificationQuorumSet) -> Self { match value { SignatureVerificationQuorumSet::V0(v0) => { - SignatureVerificationQuorumSetForSaving::V0(v0.into()) + SignatureVerificationQuorumSetForSaving::V1(v0.into()) } } } @@ -136,6 +139,9 @@ impl From for SignatureVerificationQuor SignatureVerificationQuorumSetForSaving::V0(v0) => { SignatureVerificationQuorumSet::V0(v0.into()) } + SignatureVerificationQuorumSetForSaving::V1(v1) => { + SignatureVerificationQuorumSet::V0(v1.into()) + } } } } diff --git a/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/for_saving.rs b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/for_saving.rs index a1ce283885..de69aff56d 100644 --- a/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/for_saving.rs +++ b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/for_saving.rs @@ -3,7 +3,7 @@ use crate::platform_types::signature_verification_quorum_set::v0::quorum_set::{ }; use crate::platform_types::signature_verification_quorum_set::{ Quorums, SignatureVerificationQuorumSetForSaving, SignatureVerificationQuorumSetV0, - ThresholdBlsPublicKey, VerificationQuorum, + VerificationQuorum, }; use dashcore_rpc::dashcore::hashes::Hash; use dashcore_rpc::dashcore::QuorumHash; @@ -135,7 +135,7 @@ impl From for PreviousPastQuorumsV0 { pub struct QuorumForSavingV0 { hash: Bytes32, #[bincode(with_serde)] - public_key: ThresholdBlsPublicKey, + public_key: bls_signatures::PublicKey, index: Option, } @@ -145,7 +145,10 @@ impl From> for Quorums { ( QuorumHash::from_byte_array(quorum.hash.to_buffer()), VerificationQuorum { - public_key: quorum.public_key, + public_key: dpp::bls_signatures::PublicKey::try_from( + quorum.public_key.to_bytes().as_slice(), + ) + .expect("expected to convert between BLS key libraries (from chia)"), index: quorum.index, }, ) @@ -153,13 +156,16 @@ impl From> for Quorums { } } -#[allow(clippy::from_over_into)] -impl Into> for Quorums { - fn into(self) -> Vec { - self.into_iter() +impl From> for Vec { + fn from(quorums: Quorums) -> Self { + quorums + .into_iter() .map(|(hash, quorum)| QuorumForSavingV0 { hash: Bytes32::from(hash.as_byte_array()), - public_key: quorum.public_key, + public_key: bls_signatures::PublicKey::from_bytes( + &quorum.public_key.0.to_compressed(), + ) + .expect("expected to convert between BLS key libraries (to chia)"), index: quorum.index, }) .collect() diff --git a/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/for_saving_v1.rs b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/for_saving_v1.rs new file mode 100644 index 0000000000..bfb596e451 --- /dev/null +++ b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/for_saving_v1.rs @@ -0,0 +1,92 @@ +use crate::platform_types::signature_verification_quorum_set::v0::for_saving::{ + PreviousPastQuorumsForSavingV0, QuorumConfigForSavingV0, +}; +use crate::platform_types::signature_verification_quorum_set::{ + Quorums, SignatureVerificationQuorumSetForSaving, SignatureVerificationQuorumSetV0, + ThresholdBlsPublicKey, VerificationQuorum, +}; +use dashcore_rpc::dashcore::hashes::Hash; +use dashcore_rpc::dashcore::QuorumHash; +use dpp::bls_signatures::Bls12381G2Impl; +use dpp::identity::state_transition::asset_lock_proof::Encode; +use dpp::platform_serialization::de::Decode; +use dpp::platform_value::Bytes32; + +#[derive(Debug, Clone, Encode, Decode)] +pub struct SignatureVerificationQuorumSetForSavingV1 { + config: QuorumConfigForSavingV0, + current_quorums: Vec, + previous_quorums: Option, +} + +impl From for SignatureVerificationQuorumSetForSaving { + fn from(value: SignatureVerificationQuorumSetForSavingV1) -> Self { + SignatureVerificationQuorumSetForSaving::V1(value) + } +} + +impl From for SignatureVerificationQuorumSetForSavingV1 { + fn from(value: SignatureVerificationQuorumSetV0) -> Self { + let SignatureVerificationQuorumSetV0 { + config, + current_quorums, + previous, + } = value; + + Self { + config: config.into(), + current_quorums: current_quorums.into(), + previous_quorums: previous.map(|previous| previous.into()), + } + } +} + +impl From for SignatureVerificationQuorumSetV0 { + fn from(value: SignatureVerificationQuorumSetForSavingV1) -> Self { + let SignatureVerificationQuorumSetForSavingV1 { + config, + current_quorums, + previous_quorums, + } = value; + + Self { + config: config.into(), + current_quorums: current_quorums.into(), + previous: previous_quorums.map(|previous| previous.into()), + } + } +} + +#[derive(Debug, Clone, Encode, Decode)] +pub struct QuorumForSavingV1 { + hash: Bytes32, + #[bincode(with_serde)] + public_key: ThresholdBlsPublicKey, + index: Option, +} + +impl From> for Quorums { + fn from(value: Vec) -> Self { + Quorums::from_iter(value.into_iter().map(|quorum| { + ( + QuorumHash::from_byte_array(quorum.hash.to_buffer()), + VerificationQuorum { + public_key: quorum.public_key, + index: quorum.index, + }, + ) + })) + } +} +impl From> for Vec { + fn from(quorums: Quorums) -> Self { + quorums + .into_iter() + .map(|(hash, quorum)| QuorumForSavingV1 { + hash: Bytes32::from(hash.as_byte_array()), + public_key: quorum.public_key, + index: quorum.index, + }) + .collect() + } +} diff --git a/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/mod.rs b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/mod.rs index e78d6c1c7f..f38657c29c 100644 --- a/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/mod.rs @@ -1,3 +1,4 @@ pub mod for_saving; +pub mod for_saving_v1; pub mod quorum_set; pub mod quorums; diff --git a/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/quorums.rs b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/quorums.rs index 112b877a9b..7a38272f90 100644 --- a/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/quorums.rs +++ b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/quorums.rs @@ -1,13 +1,13 @@ use derive_more::{Deref, DerefMut, From}; -use dpp::bls_signatures::PrivateKey; +use dpp::bls_signatures; +pub use dpp::bls_signatures::PublicKey as ThresholdBlsPublicKey; +use dpp::bls_signatures::{Bls12381G2Impl, SignatureSchemes}; use dpp::dashcore::bls_sig_utils::BLSSignature; use dpp::dashcore::{QuorumHash, Txid}; use std::collections::BTreeMap; use std::convert::TryInto; use std::fmt::Debug; -pub use dpp::bls_signatures::PublicKey as ThresholdBlsPublicKey; - use crate::error::Error; use crate::platform_types::signature_verification_quorum_set::QuorumConfig; use dpp::dashcore::hashes::{sha256d, Hash, HashEngine}; @@ -149,17 +149,14 @@ pub struct VerificationQuorum { /// Quorum threshold public key is used to verify /// signatures produced by corresponding quorum - pub public_key: ThresholdBlsPublicKey, + pub public_key: ThresholdBlsPublicKey, } impl Debug for VerificationQuorum { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("VerificationQuorum") .field("index", &self.index) - .field( - "public_key", - &hex::encode(*self.public_key.to_bytes()).to_string(), - ) + .field("public_key", &self.public_key.to_string()) .finish() } } @@ -210,11 +207,21 @@ impl SigningQuorum { let message_digest = sha256d::Hash::from_engine(engine); let private_key = - PrivateKey::from_bytes(&self.private_key, false).map_err(Error::BLSError)?; - - let g2element = private_key.sign(message_digest.as_ref()); - let g2element_bytes = *g2element.to_bytes(); + bls_signatures::SecretKey::::from_be_bytes(&self.private_key) + .into_option() + .ok_or(Error::BLSError( + dpp::bls_signatures::BlsError::DeserializationError( + "Could not deserialize private key".to_string(), + ), + ))?; + + let signature = private_key + .sign( + SignatureSchemes::Basic, + message_digest.as_byte_array().as_slice(), + ) + .map_err(Error::BLSError)?; - Ok(BLSSignature::from(g2element_bytes)) + Ok(BLSSignature::from(signature.as_raw_value().to_compressed())) } } diff --git a/packages/rs-drive-abci/src/platform_types/validator/v0/mod.rs b/packages/rs-drive-abci/src/platform_types/validator/v0/mod.rs index 433fe506bf..798713b0e0 100644 --- a/packages/rs-drive-abci/src/platform_types/validator/v0/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/validator/v0/mod.rs @@ -1,14 +1,14 @@ use crate::platform_types::platform_state::v0::PlatformStateV0Methods; use crate::platform_types::platform_state::PlatformState; use dashcore_rpc::json::{DMNState, MasternodeListItem}; -use dpp::bls_signatures::PublicKey as BlsPublicKey; +use dpp::bls_signatures::{Bls12381G2Impl, PublicKey as BlsPublicKey}; pub use dpp::core_types::validator::v0::*; use dpp::dashcore::hashes::Hash; use dpp::dashcore::{ProTxHash, PubkeyHash}; pub(crate) trait NewValidatorIfMasternodeInState { fn new_validator_if_masternode_in_state( pro_tx_hash: ProTxHash, - public_key: Option, + public_key: Option>, state: &PlatformState, ) -> Option; } @@ -17,7 +17,7 @@ impl NewValidatorIfMasternodeInState for ValidatorV0 { /// Makes a validator if the masternode is in the list and is valid fn new_validator_if_masternode_in_state( pro_tx_hash: ProTxHash, - public_key: Option, + public_key: Option>, state: &PlatformState, ) -> Option { let MasternodeListItem { state, .. } = state.hpmn_masternode_list().get(&pro_tx_hash)?; diff --git a/packages/rs-drive-abci/src/platform_types/validator_set/v0/mod.rs b/packages/rs-drive-abci/src/platform_types/validator_set/v0/mod.rs index f7141d1ff4..6ce9f40c0b 100644 --- a/packages/rs-drive-abci/src/platform_types/validator_set/v0/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/validator_set/v0/mod.rs @@ -55,8 +55,8 @@ impl ValidatorSetMethodsV0 for ValidatorSetV0 { return Err(Error::Execution(ExecutionError::CorruptedCachedState( format!( "updating validator set doesn't match threshold public key ours: {} theirs: {}", - hex::encode(*self.threshold_public_key.to_bytes()), - hex::encode(*rhs.threshold_public_key.to_bytes()) + hex::encode(self.threshold_public_key.0.to_compressed()), + hex::encode(rhs.threshold_public_key.0.to_compressed()) ), ))); } @@ -99,7 +99,9 @@ impl ValidatorSetMethodsV0 for ValidatorSetV0 { Some(Ok(abci::ValidatorUpdate { pub_key: public_key.clone().map(|public_key| { crypto::PublicKey { - sum: Some(Bls12381(public_key.to_bytes().to_vec())), + sum: Some(Bls12381( + public_key.0.to_compressed().to_vec(), + )), } }), power: 100, @@ -131,7 +133,9 @@ impl ValidatorSetMethodsV0 for ValidatorSetV0 { Some(Ok(abci::ValidatorUpdate { pub_key: public_key.clone().map(|public_key| { crypto::PublicKey { - sum: Some(Bls12381(public_key.to_bytes().to_vec())), + sum: Some(Bls12381( + public_key.0.to_compressed().to_vec(), + )), } }), power: 100, @@ -148,7 +152,9 @@ impl ValidatorSetMethodsV0 for ValidatorSetV0 { Ok(ValidatorSetUpdate { validator_updates, threshold_public_key: Some(crypto::PublicKey { - sum: Some(Bls12381(self.threshold_public_key.to_bytes().to_vec())), + sum: Some(Bls12381( + self.threshold_public_key.0.to_compressed().to_vec(), + )), }), quorum_hash: self.quorum_hash.to_byte_array().to_vec(), }) @@ -186,7 +192,7 @@ impl ValidatorSetMethodsV0 for ValidatorSetV0 { ); Some(abci::ValidatorUpdate { pub_key: public_key.as_ref().map(|public_key| crypto::PublicKey { - sum: Some(Bls12381(public_key.to_bytes().to_vec())), + sum: Some(Bls12381(public_key.0.to_compressed().to_vec())), }), power: 100, pro_tx_hash: pro_tx_hash.to_byte_array().to_vec(), @@ -195,7 +201,7 @@ impl ValidatorSetMethodsV0 for ValidatorSetV0 { }) .collect(), threshold_public_key: Some(crypto::PublicKey { - sum: Some(Bls12381(threshold_public_key.to_bytes().to_vec())), + sum: Some(Bls12381(threshold_public_key.0.to_compressed().to_vec())), }), quorum_hash: quorum_hash.to_byte_array().to_vec(), } @@ -233,7 +239,7 @@ impl ValidatorSetMethodsV0 for ValidatorSetV0 { Some(abci::ValidatorUpdate { pub_key: public_key.map(|public_key| crypto::PublicKey { - sum: Some(Bls12381(public_key.to_bytes().to_vec())), + sum: Some(Bls12381(public_key.0.to_compressed().to_vec())), }), power: 100, pro_tx_hash: pro_tx_hash.to_byte_array().to_vec(), @@ -242,7 +248,7 @@ impl ValidatorSetMethodsV0 for ValidatorSetV0 { }) .collect(), threshold_public_key: Some(crypto::PublicKey { - sum: Some(Bls12381(threshold_public_key.to_bytes().to_vec())), + sum: Some(Bls12381(threshold_public_key.0.to_compressed().to_vec())), }), quorum_hash: quorum_hash.to_byte_array().to_vec(), } @@ -271,7 +277,7 @@ impl ValidatorSetMethodsV0 for ValidatorSetV0 { } let public_key = if let Some(public_key_share) = quorum_member.pub_key_share { - match BlsPublicKey::from_bytes(public_key_share.as_slice()) + match BlsPublicKey::try_from(public_key_share.as_slice()) .map_err(ExecutionError::BlsErrorFromDashCoreResponse) { Ok(public_key) => Some(public_key), @@ -290,7 +296,7 @@ impl ValidatorSetMethodsV0 for ValidatorSetV0 { }) .collect::, Error>>()?; - let threshold_public_key = BlsPublicKey::from_bytes(quorum_public_key.as_slice()) + let threshold_public_key = BlsPublicKey::try_from(quorum_public_key.as_slice()) .map_err(ExecutionError::BlsErrorFromDashCoreResponse)?; let optional_quorum_index = if quorum_index == 0 { diff --git a/packages/rs-drive-abci/src/query/system/current_quorums_info/v0/mod.rs b/packages/rs-drive-abci/src/query/system/current_quorums_info/v0/mod.rs index f512f4b8f0..bf75b0c522 100644 --- a/packages/rs-drive-abci/src/query/system/current_quorums_info/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/system/current_quorums_info/v0/mod.rs @@ -40,7 +40,11 @@ impl Platform { quorum_hash: validator_set.quorum_hash().as_byte_array().to_vec(), core_height: validator_set.core_height(), members, - threshold_public_key: validator_set.threshold_public_key().to_bytes().to_vec(), + threshold_public_key: validator_set + .threshold_public_key() + .0 + .to_compressed() + .to_vec(), } }) .collect(); diff --git a/packages/rs-drive-abci/tests/strategy_tests/execution.rs b/packages/rs-drive-abci/tests/strategy_tests/execution.rs index 777dc361a2..d02a11e950 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/execution.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/execution.rs @@ -20,7 +20,7 @@ use dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV use strategy_tests::operations::FinalizeBlockOperation::IdentityAddKeys; use dashcore_rpc::json::{ExtendedQuorumListResult, SoftforkInfo}; -use dpp::bls_signatures::PrivateKey; +use dpp::bls_signatures::{Bls12381G2Impl, SecretKey as BlsPrivateKey, SignatureSchemes}; use dpp::dashcore::consensus::Encodable; use dpp::dashcore::hashes::{sha256d, HashEngine}; use dpp::dashcore::{ChainLock, QuorumSigningRequestId, VarInt}; @@ -352,7 +352,7 @@ pub(crate) fn run_chain_for_strategy<'a>( instant_lock_quorums_infos .iter() .map(|(quorum_hash, info)| { - let bytes = info.private_key.to_bytes(); + let bytes = info.private_key.to_be_bytes(); let fixed_bytes: [u8; 32] = bytes .as_slice() .try_into() @@ -379,7 +379,7 @@ pub(crate) fn run_chain_for_strategy<'a>( let signing_quorums = validator_quorums .iter() .map(|(quorum_hash, info)| { - let bytes = info.private_key.to_bytes(); + let bytes = info.private_key.to_be_bytes(); let fixed_bytes: [u8; 32] = bytes .as_slice() .try_into() @@ -653,7 +653,7 @@ pub(crate) fn run_chain_for_strategy<'a>( let chain_lock_quorums_private_keys: BTreeMap = chain_lock_quorums .iter() .map(|(quorum_hash, info)| { - let bytes = info.private_key.to_bytes(); + let bytes = info.private_key.to_be_bytes(); let fixed_bytes: [u8; 32] = bytes .as_slice() .try_into() @@ -728,13 +728,18 @@ pub(crate) fn run_chain_for_strategy<'a>( let message_digest = sha256d::Hash::from_engine(engine); let quorum_private_key = - PrivateKey::from_bytes(quorum_private_key.as_slice(), false) + BlsPrivateKey::::from_be_bytes(quorum_private_key) .expect("expected to have a valid private key"); - let signature = quorum_private_key.sign(message_digest.as_byte_array()); + let signature = quorum_private_key + .sign( + SignatureSchemes::Basic, + message_digest.as_byte_array().as_slice(), + ) + .expect("expected to sign"); let chain_lock = ChainLock { block_height, block_hash: BlockHash::from_byte_array(*block_hash), - signature: (*signature.to_bytes()).into(), + signature: signature.as_raw_value().to_compressed().into(), }; Ok(chain_lock) @@ -847,7 +852,9 @@ pub(crate) fn start_chain_for_strategy( .map( |validator_in_quorum| tenderdash_abci::proto::abci::ValidatorUpdate { pub_key: Some(tenderdash_abci::proto::crypto::PublicKey { - sum: Some(Bls12381(validator_in_quorum.public_key.to_bytes().to_vec())), + sum: Some(Bls12381( + validator_in_quorum.public_key.0.to_compressed().to_vec(), + )), }), power: 100, pro_tx_hash: validator_in_quorum.pro_tx_hash.to_byte_array().to_vec(), @@ -857,7 +864,11 @@ pub(crate) fn start_chain_for_strategy( .collect(), threshold_public_key: Some(tenderdash_abci::proto::crypto::PublicKey { sum: Some(Bls12381( - current_quorum_with_test_info.public_key.to_bytes().to_vec(), + current_quorum_with_test_info + .public_key + .0 + .to_compressed() + .to_vec(), )), }), quorum_hash: current_validator_quorum_hash.to_byte_array().to_vec(), diff --git a/packages/rs-drive-abci/tests/strategy_tests/main.rs b/packages/rs-drive-abci/tests/strategy_tests/main.rs index 03bb92bc1a..4194e30689 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/main.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/main.rs @@ -3,7 +3,7 @@ extern crate core; -use dpp::bls_signatures::PrivateKey as BlsPrivateKey; +use dpp::bls_signatures::SecretKey as BlsPrivateKey; use drive_abci::test::helpers::setup::TestPlatformBuilder; use drive_abci::{config::PlatformConfig, test::helpers::setup::TempPlatform}; diff --git a/packages/rs-drive-abci/tests/strategy_tests/masternode_list_item_helpers.rs b/packages/rs-drive-abci/tests/strategy_tests/masternode_list_item_helpers.rs index f89be95ee1..4084e7f065 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/masternode_list_item_helpers.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/masternode_list_item_helpers.rs @@ -1,5 +1,6 @@ use crate::BlsPrivateKey; use dashcore_rpc::json::MasternodeListItem; +use dpp::bls_signatures::Bls12381G2Impl; use rand::prelude::IteratorRandom; use rand::rngs::StdRng; use rand::Rng; @@ -32,13 +33,16 @@ impl UpdateMasternodeListItem for MasternodeListItem { 1 => self.state.voting_address = rng.gen::<[u8; 20]>(), 2 => self.state.payout_address = rng.gen::<[u8; 20]>(), 3 => { - let private_key_operator = BlsPrivateKey::generate_dash(rng) - .expect("expected to generate a private key"); - let pub_key_operator = private_key_operator - .g1_element() - .expect("expected to get public key") + let private_key_operator_bytes = bls_signatures::PrivateKey::generate_dash(rng) + .expect("expected to generate a private key") .to_bytes() .to_vec(); + let private_key_operator = BlsPrivateKey::::from_be_bytes( + &private_key_operator_bytes.try_into().expect("expected the secret key to be 32 bytes"), + ) + .expect("expected the conversion between bls signatures library and blsful to happen without failing"); + let pub_key_operator = + private_key_operator.public_key().0.to_compressed().to_vec(); self.state.pub_key_operator = pub_key_operator; } 4 => { @@ -83,13 +87,15 @@ mod tests { let mut rng = StdRng::seed_from_u64(0); let i = 0; let pro_tx_hash = ProTxHash::from_byte_array(rng.gen::<[u8; 32]>()); - let private_key_operator = - BlsPrivateKey::generate_dash(&mut rng).expect("expected to generate a private key"); - let pub_key_operator = private_key_operator - .g1_element() - .expect("expected to get public key") + let private_key_operator_bytes = bls_signatures::PrivateKey::generate_dash(&mut rng) + .expect("expected to generate a private key") .to_bytes() .to_vec(); + let private_key_operator = BlsPrivateKey::::from_be_bytes( + &private_key_operator_bytes.try_into().expect("expected the secret key to be 32 bytes"), + ) + .expect("expected the conversion between bls signatures library and blsful to happen without failing"); + let pub_key_operator = private_key_operator.public_key().0.to_compressed().to_vec(); let masternode_list_item = MasternodeListItem { node_type: MasternodeType::Regular, pro_tx_hash, diff --git a/packages/rs-drive-abci/tests/strategy_tests/masternodes.rs b/packages/rs-drive-abci/tests/strategy_tests/masternodes.rs index 51693b5b60..02a647b66c 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/masternodes.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/masternodes.rs @@ -2,7 +2,7 @@ use crate::masternode_list_item_helpers::UpdateMasternodeListItem; use dashcore_rpc::dashcore::hashes::Hash; use dashcore_rpc::dashcore::{ProTxHash, QuorumHash, Txid}; use dashcore_rpc::dashcore_rpc_json::{DMNState, MasternodeListItem, MasternodeType}; -use dpp::bls_signatures::PrivateKey as BlsPrivateKey; +use dpp::bls_signatures::{Bls12381G2Impl, SecretKey as BlsPrivateKey}; use dpp::identity::hash::IdentityPublicKeyHashMethodsV0; use dpp::identity::IdentityPublicKey; use drive_abci::mimic::test_quorum::TestQuorumInfo; @@ -209,13 +209,15 @@ pub fn generate_test_masternodes( } for i in 0..masternode_count { - let private_key_operator = - BlsPrivateKey::generate_dash(rng).expect("expected to generate a private key"); - let pub_key_operator = private_key_operator - .g1_element() - .expect("expected to get public key") + let private_key_operator_bytes = bls_signatures::PrivateKey::generate_dash(rng) + .expect("expected to generate a private key") .to_bytes() .to_vec(); + let private_key_operator = BlsPrivateKey::::from_be_bytes( + &private_key_operator_bytes.try_into().expect("expected the secret key to be 32 bytes"), + ) + .expect("expected the conversion between bls signatures library and blsful to happen without failing"); + let pub_key_operator = private_key_operator.public_key().0.to_compressed().to_vec(); let pro_tx_hash = ProTxHash::from_byte_array(rng.gen::<[u8; 32]>()); let masternode_list_item = MasternodeListItem { node_type: MasternodeType::Regular, @@ -345,13 +347,15 @@ pub fn generate_test_masternodes( } for i in 0..hpmn_count { - let private_key_operator = - BlsPrivateKey::generate_dash(rng).expect("expected to generate a private key"); - let pub_key_operator = private_key_operator - .g1_element() - .expect("expected to get public key") + let private_key_operator_bytes = bls_signatures::PrivateKey::generate_dash(rng) + .expect("expected to generate a private key") .to_bytes() .to_vec(); + let private_key_operator = BlsPrivateKey::::from_be_bytes( + &private_key_operator_bytes.try_into().expect("expected the secret key to be 32 bytes"), + ) + .expect("expected the conversion between bls signatures library and blsful to happen without failing"); + let pub_key_operator = private_key_operator.public_key().0.to_compressed().to_vec(); let masternode_list_item = MasternodeListItem { node_type: MasternodeType::Evo, pro_tx_hash: ProTxHash::from_byte_array(rng.gen::<[u8; 32]>()), diff --git a/packages/rs-drive-abci/tests/strategy_tests/query.rs b/packages/rs-drive-abci/tests/strategy_tests/query.rs index a7b035dfdb..56f166ab74 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/query.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/query.rs @@ -5,6 +5,7 @@ use dapi_grpc::platform::v0::{ GetIdentityByPublicKeyHashRequest, Proof, }; use dashcore_rpc::dashcore_rpc_json::QuorumType; +use dpp::bls_signatures::{Bls12381G2Impl, BlsError, Pairing, Signature}; use dpp::identity::accessors::IdentityGettersV0; use dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; use dpp::identity::identity_public_key::methods::hash::IdentityPublicKeyHashMethodsV0; @@ -68,7 +69,7 @@ pub struct ProofVerification<'a> { pub signature: &'a [u8; 96], /// Threshold key used to verify the signature - pub public_key: &'a dpp::bls_signatures::PublicKey, + pub public_key: &'a dpp::bls_signatures::PublicKey, } impl<'a> ProofVerification<'a> { @@ -105,17 +106,20 @@ impl<'a> ProofVerification<'a> { Err(e) => return SimpleValidationResult::new_with_error(e.into()), }; // We could have received a fake commit, so signature validation needs to be returned if error as a simple validation result - let signature = match dpp::bls_signatures::Signature::from_bytes(self.signature) { - Ok(signature) => signature, - Err(e) => { - return SimpleValidationResult::new_with_error( - AbciError::BlsErrorOfTenderdashThresholdMechanism( - e, - format!("Malformed signature data: {}", hex::encode(self.signature)), - ), - ); - } - }; + let signature = + match ::Signature::from_compressed(self.signature) + .into_option() + { + Some(signature) => Signature::Basic(signature), + None => { + return SimpleValidationResult::new_with_error( + AbciError::BlsErrorOfTenderdashThresholdMechanism( + BlsError::InvalidSignature, + format!("malformed signature data: {}", hex::encode(self.signature)), + ), + ); + } + }; tracing::trace!( digest=hex::encode(&digest), ?state_id, @@ -123,14 +127,11 @@ impl<'a> ProofVerification<'a> { verification_context = ?self, "Proof verification" ); - match self.public_key.verify(&signature, &digest) { - true => SimpleValidationResult::default(), - false => { - SimpleValidationResult::new_with_error(AbciError::BadCommitSignature(format!( - "commit signature {} is wrong", - hex::encode(signature.to_bytes().as_slice()) - ))) - } + match signature.verify(self.public_key, &digest) { + Ok(_) => SimpleValidationResult::default(), + Err(e) => SimpleValidationResult::new_with_error(AbciError::BadCommitSignature( + format!("commit signature {} is wrong: {}", signature, e), + )), } } diff --git a/packages/rs-drive-proof-verifier/src/unproved.rs b/packages/rs-drive-proof-verifier/src/unproved.rs index cc7c63c83e..93e18b7e21 100644 --- a/packages/rs-drive-proof-verifier/src/unproved.rs +++ b/packages/rs-drive-proof-verifier/src/unproved.rs @@ -249,8 +249,8 @@ impl FromUnproved for CurrentQuorumsInfo quorum_index: None, // Assuming it's not provided here core_height: vs.core_height, members, - threshold_public_key: BlsPublicKey::from_bytes( - &vs.threshold_public_key, + threshold_public_key: BlsPublicKey::try_from( + vs.threshold_public_key.as_slice(), ) .map_err(|_| Error::ProtocolError { error: "Invalid BlsPublicKey format".to_string(), diff --git a/packages/rs-drive-proof-verifier/src/verify.rs b/packages/rs-drive-proof-verifier/src/verify.rs index 284efb5a89..6015999df2 100644 --- a/packages/rs-drive-proof-verifier/src/verify.rs +++ b/packages/rs-drive-proof-verifier/src/verify.rs @@ -1,13 +1,13 @@ use dapi_grpc::platform::v0::{Proof, ResponseMetadata}; use dpp::bls_signatures; +use crate::Error; +use dpp::bls_signatures::{Bls12381G2Impl, Pairing, Signature}; use tenderdash_abci::{ proto::types::{CanonicalVote, SignedMsgType, StateId}, signatures::{Hashable, Signable}, }; -use crate::Error; - use crate::ContextProvider; /// Verify cryptographic proof generated by Tenderdash @@ -92,11 +92,10 @@ pub(crate) fn verify_tenderdash_proof( } })?; - let pubkey = bls_signatures::PublicKey::from_bytes(&pubkey_bytes).map_err(|e| { - Error::InvalidPublicKey { + let pubkey = bls_signatures::PublicKey::::try_from(pubkey_bytes.as_slice()) + .map_err(|e| Error::InvalidPublicKey { error: e.to_string(), - } - })?; + })?; tracing::trace!( ?state_id, @@ -123,18 +122,20 @@ pub(crate) fn verify_tenderdash_proof( pub fn verify_signature_digest( sign_digest: &[u8], signature: &[u8; 96], - public_key: &bls_signatures::PublicKey, + public_key: &bls_signatures::PublicKey, ) -> Result { if signature == &[0; 96] { return Err(Error::SignatureVerificationError { error: "empty signature".to_string(), }); } - let signature = bls_signatures::Signature::from_bytes(signature).map_err(|e| { - Error::SignatureVerificationError { - error: e.to_string(), - } - })?; + let signature = Signature::Basic( + ::Signature::from_compressed(&signature) + .into_option() + .ok_or(Error::SignatureVerificationError { + error: "Could not verify signature digest".to_string(), + })?, + ); - Ok(public_key.verify(&signature, sign_digest)) + Ok(signature.verify(public_key, sign_digest).is_ok()) } diff --git a/packages/rs-sdk/Cargo.toml b/packages/rs-sdk/Cargo.toml index ed45b0d813..d323fa4118 100644 --- a/packages/rs-sdk/Cargo.toml +++ b/packages/rs-sdk/Cargo.toml @@ -35,7 +35,7 @@ envy = { version = "0.4.2", optional = true } futures = { version = "0.3.30" } derive_more = { version = "1.0", features = ["from"] } # dashcore-rpc is only needed for core rpc; TODO remove once we have correct core rpc impl -dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.8" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.9" } lru = { version = "0.12.3", optional = true } bip37-bloom-filter = { git = "https://github.com/dashpay/rs-bip37-bloom-filter", branch = "develop" } zeroize = { version = "1.8", features = ["derive"] } diff --git a/packages/rs-sdk/src/lib.rs b/packages/rs-sdk/src/lib.rs index f965730c83..fe2c51ab06 100644 --- a/packages/rs-sdk/src/lib.rs +++ b/packages/rs-sdk/src/lib.rs @@ -71,6 +71,7 @@ pub mod sdk; pub use error::Error; pub use sdk::{RequestSettings, Sdk, SdkBuilder}; +pub use dapi_grpc; pub use dashcore_rpc; pub use dpp; pub use drive; diff --git a/packages/simple-signer/Cargo.toml b/packages/simple-signer/Cargo.toml index 080f921ba7..15589f994d 100644 --- a/packages/simple-signer/Cargo.toml +++ b/packages/simple-signer/Cargo.toml @@ -8,6 +8,6 @@ rust-version.workspace = true [dependencies] bincode = { version = "2.0.0-rc.3", features = ["serde"] } -dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.8" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.9" } dpp = { path = "../rs-dpp", features = ["abci"] } base64 = { version = "0.22.1" } diff --git a/packages/simple-signer/src/signer.rs b/packages/simple-signer/src/signer.rs index 448e1a5c9c..d93acb5aee 100644 --- a/packages/simple-signer/src/signer.rs +++ b/packages/simple-signer/src/signer.rs @@ -2,6 +2,7 @@ use base64::prelude::BASE64_STANDARD; use base64::Engine; use dashcore_rpc::dashcore::signer; use dpp::bincode::{Decode, Encode}; +use dpp::bls_signatures::{Bls12381G2Impl, SignatureSchemes}; use dpp::ed25519_dalek::Signer as BlsSigner; use dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; use dpp::identity::signer::Signer; @@ -16,9 +17,9 @@ use std::fmt::{Debug, Formatter}; #[derive(Default, Clone, PartialEq, Encode, Decode)] pub struct SimpleSigner { /// Private keys is a map from the public key to the Private key bytes - pub private_keys: BTreeMap>, + pub private_keys: BTreeMap, /// Private keys to be added at the end of a block - pub private_keys_in_creation: BTreeMap>, + pub private_keys_in_creation: BTreeMap, } impl Debug for SimpleSigner { @@ -46,12 +47,12 @@ impl Debug for SimpleSigner { impl SimpleSigner { /// Add a key to the signer - pub fn add_key(&mut self, public_key: IdentityPublicKey, private_key: Vec) { + pub fn add_key(&mut self, public_key: IdentityPublicKey, private_key: [u8; 32]) { self.private_keys.insert(public_key, private_key); } /// Add keys to the signer - pub fn add_keys)>>(&mut self, keys: I) { + pub fn add_keys>(&mut self, keys: I) { self.private_keys.extend(keys) } @@ -81,13 +82,15 @@ impl Signer for SimpleSigner { Ok(signature.to_vec().into()) } KeyType::BLS12_381 => { - let pk = - bls_signatures::PrivateKey::from_bytes(private_key, false).map_err(|_e| { - ProtocolError::Generic( - "bls private key from bytes isn't correct".to_string(), - ) - })?; - Ok(pk.sign(data).to_bytes().to_vec().into()) + let pk = bls_signatures::SecretKey::::from_be_bytes(private_key) + .into_option() + .ok_or(ProtocolError::Generic( + "bls private key from bytes isn't correct".to_string(), + ))?; + let signature = pk + .sign(SignatureSchemes::Basic, data) + .map_err(|e| ProtocolError::Generic(format!("BLS signing failed {}", e)))?; + Ok(signature.as_raw_value().to_compressed().to_vec().into()) } KeyType::EDDSA_25519_HASH160 => { let key: [u8; 32] = private_key.clone().try_into().expect("expected 32 bytes");