From 33d6420b563fd52f0863578b979f1f34e116838e Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sat, 19 Oct 2024 11:17:08 +0700 Subject: [PATCH 01/29] replace bls library --- Cargo.lock | 368 +++++++++++++++++- packages/rs-dpp/Cargo.toml | 7 +- .../rs-dpp/src/core_types/validator/mod.rs | 5 +- .../rs-dpp/src/core_types/validator/v0/mod.rs | 28 +- .../src/core_types/validator_set/mod.rs | 5 +- .../src/core_types/validator_set/v0/mod.rs | 43 +- .../identity/identity_public_key/key_type.rs | 24 +- .../identity_public_key/methods/hash/mod.rs | 2 +- .../methods/hash/v0/mod.rs | 2 +- .../identity/identity_public_key/random.rs | 32 +- .../identity_public_key/v0/methods/mod.rs | 79 ++-- .../identity/identity_public_key/v0/random.rs | 16 +- packages/rs-dpp/src/identity/random.rs | 8 +- packages/rs-dpp/src/identity/v0/random.rs | 10 +- packages/rs-dpp/src/lib.rs | 2 +- packages/rs-drive-abci/Cargo.toml | 4 +- .../update_operator_identity/v0/mod.rs | 38 +- .../update_quorum_info/v0/mod.rs | 2 +- .../core_chain_lock/choose_quorum/mod.rs | 6 +- .../core_chain_lock/choose_quorum/v0/mod.rs | 25 +- .../verify_chain_lock_locally/v0/mod.rs | 25 +- .../verify_recent_signature_locally/v0/mod.rs | 36 +- .../v0/mod.rs | 4 +- packages/rs-drive-abci/src/mimic/mod.rs | 8 +- .../rs-drive-abci/src/mimic/test_quorum.rs | 38 +- .../src/platform_types/commit/mod.rs | 3 +- .../src/platform_types/commit/v0/mod.rs | 26 +- .../platform_types/platform_state/v0/mod.rs | 6 +- .../platform_state/v0/old_structures/mod.rs | 103 +++++ .../signature_verification_quorum_set/mod.rs | 8 +- .../v0/for_saving.rs | 14 +- .../v0/for_saving_v1.rs | 93 +++++ .../v0/mod.rs | 1 + .../v0/quorums.rs | 33 +- .../src/platform_types/validator/v0/mod.rs | 6 +- .../platform_types/validator_set/v0/mod.rs | 28 +- .../system/current_quorums_info/v0/mod.rs | 6 +- .../tests/strategy_tests/execution.rs | 29 +- .../tests/strategy_tests/main.rs | 2 +- .../masternode_list_item_helpers.rs | 26 +- .../tests/strategy_tests/masternodes.rs | 26 +- .../tests/strategy_tests/query.rs | 20 +- .../rs-drive-proof-verifier/src/unproved.rs | 4 +- .../rs-drive-proof-verifier/src/verify.rs | 27 +- packages/simple-signer/src/signer.rs | 25 +- 45 files changed, 1009 insertions(+), 294 deletions(-) create mode 100644 packages/rs-drive-abci/src/platform_types/platform_state/v0/old_structures/mod.rs create mode 100644 packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/for_saving_v1.rs diff --git a/Cargo.lock b/Cargo.lock index a6d1c8fd71..e1f0972af4 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", ] @@ -1369,6 +1454,7 @@ dependencies = [ "async-trait", "base64 0.22.1", "bincode", + "blsful", "bs58", "byteorder", "chrono", @@ -1460,6 +1546,7 @@ dependencies = [ "async-trait", "base64 0.22.1", "bincode", + "bls-signatures", "bs58", "chrono", "ciborium 0.2.0", @@ -1577,6 +1664,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" @@ -1737,6 +1859,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" @@ -1933,6 +2066,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]] @@ -1972,6 +2116,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" @@ -2148,6 +2305,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" @@ -2186,6 +2352,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" @@ -2240,6 +2416,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" @@ -2480,7 +2665,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]] @@ -2642,6 +2827,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" @@ -2781,6 +2975,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" @@ -2928,6 +3134,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" @@ -3005,6 +3224,8 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", + "rand", + "serde", ] [[package]] @@ -3020,6 +3241,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", + "rand", + "serde", ] [[package]] @@ -3068,6 +3291,7 @@ dependencies = [ "num-bigint", "num-integer", "num-traits", + "serde", ] [[package]] @@ -3202,6 +3426,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" @@ -3676,6 +3909,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" @@ -4061,6 +4303,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" @@ -4130,6 +4386,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" @@ -4263,6 +4528,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" @@ -4285,6 +4560,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" @@ -4376,6 +4661,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" @@ -4396,6 +4684,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.4.1" @@ -4688,6 +4992,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" @@ -4698,6 +5022,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" @@ -5098,6 +5431,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" @@ -5224,6 +5566,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 591a86701d..c11255e4b2 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -22,14 +22,13 @@ chrono = { version = "0.4.35", default-features = false, features = [ "clock", ] } ciborium = { git = "https://github.com/qrayven/ciborium", branch = "feat-ser-null-as-undefined", optional = true } +blsful = { version = "3.0.0-pre6" , optional = true } dashcore = { git = "https://github.com/dashpay/rust-dashcore", features = [ "std", "secp-recovery", "rand", "signer", - "serde", - "bls", - "eddsa" + "serde" ], default-features = false, tag = "0.32.0" } env_logger = { version = "0.11" } getrandom = { version = "0.2", features = ["js"] } @@ -75,7 +74,7 @@ once_cell = "1.7" [features] default = ["platform-value", "state-transitions"] -bls-signatures = ["dashcore/bls"] +bls-signatures = ["dashcore/bls", "blsful"] ed25519-dalek = ["dashcore/eddsa"] all_features = [ "json-object", diff --git a/packages/rs-dpp/src/core_types/validator/mod.rs b/packages/rs-dpp/src/core_types/validator/mod.rs index 2261bac56f..d5f985a3c1 100644 --- a/packages/rs-dpp/src/core_types/validator/mod.rs +++ b/packages/rs-dpp/src/core_types/validator/mod.rs @@ -1,5 +1,6 @@ use crate::bls_signatures::PublicKey as BlsPublicKey; use crate::core_types::validator::v0::{ValidatorV0, ValidatorV0Getters, ValidatorV0Setters}; +use blsful::Bls12381G2Impl; use dashcore::{ProTxHash, PubkeyHash}; #[cfg(feature = "core-types-serde-conversion")] use serde::{Deserialize, Serialize}; @@ -25,7 +26,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 +76,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..81f73a66af 100644 --- a/packages/rs-dpp/src/core_types/validator/v0/mod.rs +++ b/packages/rs-dpp/src/core_types/validator/v0/mod.rs @@ -2,6 +2,7 @@ use dashcore::{ProTxHash, PubkeyHash}; use std::fmt::{Debug, Formatter}; use crate::bls_signatures::PublicKey as BlsPublicKey; +use blsful::Bls12381G2Impl; #[cfg(feature = "core-types-serde-conversion")] use serde::{Deserialize, Serialize}; @@ -26,7 +27,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 +55,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 +95,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 +154,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 +174,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 +194,7 @@ impl ValidatorV0Getters for ValidatorV0 { &self.pro_tx_hash } - fn public_key(&self) -> &Option { + fn public_key(&self) -> &Option> { &self.public_key } @@ -224,7 +228,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 +261,16 @@ impl ValidatorV0Setters for ValidatorV0 { mod tests { use super::*; use bincode::config; + use 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..de5b515f9f 100644 --- a/packages/rs-dpp/src/core_types/validator_set/mod.rs +++ b/packages/rs-dpp/src/core_types/validator_set/mod.rs @@ -7,6 +7,7 @@ use crate::core_types::validator_set::v0::{ use crate::ProtocolError; #[cfg(feature = "core-types-serialization")] use bincode::{Decode, Encode}; +use blsful::Bls12381G2Impl; use dashcore::{ProTxHash, QuorumHash}; #[cfg(feature = "core-types-serialization")] use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; @@ -80,7 +81,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 +113,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..cf05bb3d14 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 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,12 @@ 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(|_| { + bincode::error::DecodeError::OtherString( + "Failed to decode BlsPublicKey".to_string(), + ) + })?; Ok(ValidatorSetV0 { quorum_hash: QuorumHash::from_byte_array(quorum_hash), @@ -162,11 +166,12 @@ 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(|_| { + bincode::error::DecodeError::OtherString( + "Failed to decode BlsPublicKey in borrow decode".to_string(), + ) + })?; Ok(ValidatorSetV0 { quorum_hash: QuorumHash::from_byte_array(quorum_hash), @@ -211,7 +216,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 +230,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 +258,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 +280,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 +289,10 @@ impl ValidatorSetV0Setters for ValidatorSetV0 { mod tests { use super::*; use bincode::config; + use blsful::SecretKey; use dashcore::PubkeyHash; + use rand::rngs::StdRng; + use rand::SeedableRng; use std::collections::BTreeMap; #[test] @@ -296,7 +304,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 +324,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/identity/identity_public_key/key_type.rs b/packages/rs-dpp/src/identity/identity_public_key/key_type.rs index e40437a33e..a1ead4a725 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 @@ -15,6 +15,7 @@ use lazy_static::lazy_static; use crate::fee::Credits; use crate::version::PlatformVersion; use crate::{InvalidVectorSizeError, ProtocolError}; +use blsful::Bls12381G2Impl; #[cfg(feature = "random-public-keys")] use rand::rngs::StdRng; #[cfg(feature = "random-public-keys")] @@ -270,7 +271,7 @@ impl KeyType { #[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 +280,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 = 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 +295,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); ( 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 +313,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 +325,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..4b64fe9f16 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,10 +4,11 @@ use crate::identity::KeyType; use crate::util::hash::ripemd160_sha256; use crate::ProtocolError; use anyhow::anyhow; +use blsful::Bls12381G2Impl; use dashcore::hashes::Hash; use dashcore::key::Secp256k1; use dashcore::secp256k1::SecretKey; -use dashcore::{bls_signatures, ed25519_dalek, Network, PublicKey as ECDSAPublicKey}; +use dashcore::{ed25519_dalek, Network, PublicKey as ECDSAPublicKey}; use platform_value::Bytes20; impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { @@ -50,13 +51,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 +68,15 @@ 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> = + blsful::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 +85,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 +100,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(), @@ -129,11 +124,51 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { mod tests { use super::*; use crate::identity::{Purpose, SecurityLevel}; + use 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 = + blsful::SecretKey::::from_be_bytes(&secret_key.try_into().unwrap()) + .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 = + blsful::SecretKey::::from_be_bytes(&secret_key.try_into().unwrap()) + .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() { @@ -166,7 +201,7 @@ mod tests { ); // Test with an invalid private key - let invalid_private_key_bytes = vec![0u8; private_key_data.len()]; + let invalid_private_key_bytes = [0u8; 32]; assert_eq!( identity_public_key .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) @@ -207,7 +242,7 @@ mod tests { ); // Test with an invalid private key - let invalid_private_key_bytes = vec![0u8; private_key_data.len()]; + let invalid_private_key_bytes = [0u8; 32]; assert_eq!( identity_public_key .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) @@ -248,7 +283,7 @@ mod tests { ); // Test with an invalid private key - let invalid_private_key_bytes = vec![0u8; private_key_data.len()]; + let invalid_private_key_bytes = [0u8; 32]; assert_eq!( identity_public_key .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) 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..9744e16455 100644 --- a/packages/rs-dpp/src/lib.rs +++ b/packages/rs-dpp/src/lib.rs @@ -90,7 +90,7 @@ pub mod prelude { pub use bincode; #[cfg(all(not(target_arch = "wasm32"), feature = "bls-signatures"))] -pub use dashcore::bls_signatures; +pub use blsful as bls_signatures; #[cfg(feature = "ed25519-dalek")] pub use dashcore::ed25519_dalek; #[cfg(feature = "system_contracts")] diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 7e8346fe95..6fc8d7b6be 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -73,8 +73,10 @@ 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", optional = true } [dev-dependencies] +bls-signatures = { git = "https://github.com/dashpay/bls-signatures", tag = "1.3.3" } bs58 = { version = "0.5.0" } base64 = "0.22.1" platform-version = { path = "../rs-platform-version", features = [ @@ -104,7 +106,7 @@ integer-encoding = { version = "4.0.0" } [features] default = ["mocks"] -mocks = ["mockall", "drive/fixtures-and-mocks"] +mocks = ["mockall", "drive/fixtures-and-mocks", "bls-signatures"] console = ["console-subscriber", "tokio/tracing"] testing-config = [] grovedbg = ["drive/grovedbg"] 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..1b3e5ef3dd 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().unwrap(), + ) + .unwrap(); + 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().unwrap(), + ) + .unwrap(); + 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().unwrap(), + ) + .unwrap(); + 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..85bc67ddd4 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, Signature}; use dpp::dashcore::hashes::{sha256d, Hash, HashEngine}; use dpp::dashcore::{ChainLock, QuorumSigningRequestId}; @@ -37,7 +37,10 @@ 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 { + + let Ok(signature) = + Signature::::try_from(chain_lock.signature.as_bytes().as_slice()) + else { return Ok(Some(false)); }; @@ -119,9 +122,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 +168,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, 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..a55f84ecf1 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, Signature}; use std::fmt::{Debug, Formatter}; use dpp::dashcore::hashes::{sha256d, Hash, HashEngine}; @@ -20,19 +20,20 @@ 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) => { - tracing::trace!( - instant_lock = ?InstantLockDebug(instant_lock), - "Invalid instant Lock {} signature format: {}", - instant_lock.txid, - e, - ); + let signature = + match Signature::::try_from(instant_lock.signature.as_bytes().as_slice()) { + Ok(signature) => signature, + Err(e) => { + tracing::trace!( + instant_lock = ?InstantLockDebug(instant_lock), + "Invalid instant Lock {} signature format: {}", + instant_lock.txid, + e, + ); - return Ok(false); - } - }; + return Ok(false); + } + }; let signing_height = platform_state.last_committed_core_height(); let verification_height = signing_height.saturating_sub(SIGN_OFFSET); @@ -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..25c57f441c 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..66ab8d427b 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}; @@ -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..d64e1e7723 --- /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()) + .unwrap(), + } + } +} + +/// 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()).unwrap()), + 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..38c00188ec 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 0 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..1c6a07db91 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, }, ) @@ -159,7 +162,10 @@ impl Into> for Quorums { self.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..c7e9bbaf10 --- /dev/null +++ b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/for_saving_v1.rs @@ -0,0 +1,93 @@ +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, + }, + ) + })) + } +} + +#[allow(clippy::from_over_into)] +impl Into> for Quorums { + fn into(self) -> Vec { + self.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 2312241cc6..3df889c469 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..bdd1ecc911 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().unwrap(), + ) + .unwrap(); + 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().unwrap(), + ) + .unwrap(); + 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..89a9697d44 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().unwrap(), + ) + .unwrap(); + 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().unwrap(), + ) + .unwrap(); + 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..969a969cbe 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, BlsResult}; 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,7 +106,9 @@ 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) { + let signature = match dpp::bls_signatures::Signature::::try_from( + self.signature.as_slice(), + ) { Ok(signature) => signature, Err(e) => { return SimpleValidationResult::new_with_error( @@ -123,14 +126,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/simple-signer/src/signer.rs b/packages/simple-signer/src/signer.rs index 448e1a5c9c..04a9b325d3 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!("unable to sign {}", 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"); From 91cbe4aac794115dae0ec58256403f5c52f1239d Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sat, 19 Oct 2024 16:51:14 +0700 Subject: [PATCH 02/29] more work --- Cargo.lock | 28 ++++++----- packages/rs-dpp/Cargo.toml | 5 +- packages/rs-dpp/src/bls/native_bls.rs | 46 +++++++++++------ .../rs-dpp/src/core_types/validator/mod.rs | 3 +- .../rs-dpp/src/core_types/validator/v0/mod.rs | 5 +- .../src/core_types/validator_set/mod.rs | 3 +- .../src/core_types/validator_set/v0/mod.rs | 4 +- packages/rs-dpp/src/errors/protocol_error.rs | 5 ++ .../identity/identity_public_key/key_type.rs | 50 ++++++++----------- .../identity_public_key/v0/methods/mod.rs | 28 ++++++----- packages/rs-dpp/src/lib.rs | 4 +- packages/rs-dpp/src/signing.rs | 45 ++++++++++------- packages/rs-drive-abci/Cargo.toml | 7 ++- .../platform_types/platform_state/v0/mod.rs | 2 +- packages/rs-sdk/Cargo.toml | 2 +- packages/simple-signer/Cargo.toml | 2 +- 16 files changed, 134 insertions(+), 105 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e1f0972af4..33c7c23bd9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1230,14 +1230,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", @@ -1255,12 +1255,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", @@ -1272,8 +1277,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", @@ -1287,9 +1292,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", ] @@ -1454,7 +1459,6 @@ dependencies = [ "async-trait", "base64 0.22.1", "bincode", - "blsful", "bs58", "byteorder", "chrono", diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index c11255e4b2..57d27c9600 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -22,14 +22,13 @@ chrono = { version = "0.4.35", default-features = false, features = [ "clock", ] } ciborium = { git = "https://github.com/qrayven/ciborium", branch = "feat-ser-null-as-undefined", optional = true } -blsful = { version = "3.0.0-pre6" , optional = true } dashcore = { git = "https://github.com/dashpay/rust-dashcore", features = [ "std", "secp-recovery", "rand", "signer", "serde" -], 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" } @@ -74,7 +73,7 @@ once_cell = "1.7" [features] default = ["platform-value", "state-transitions"] -bls-signatures = ["dashcore/bls", "blsful"] +bls-signatures = ["dashcore/bls"] ed25519-dalek = ["dashcore/eddsa"] all_features = [ "json-object", diff --git a/packages/rs-dpp/src/bls/native_bls.rs b/packages/rs-dpp/src/bls/native_bls.rs index 5dc7e2bc82..e8e1fd939f 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}; #[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,13 +20,21 @@ 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).map_err(anyhow::Error::msg)?; + let signature_96_bytes = signature + .try_into() + .map_err(|_| anyhow!("signature wrong size"))?; + let g2_element = + ::Signature::from_compressed(&signature_96_bytes) + .into_option() + .ok_or(anyhow!("signature derivation failed"))?; + + let signature = Signature::Basic(g2_element); + + match signature.verify(&public_key, data) { + Ok(_) => Ok(true), + Err(_) => Err(anyhow!("Verification failed").into()), } } @@ -32,9 +42,11 @@ impl BlsModule for NativeBlsModule { 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 pk = SecretKey::::from_be_bytes(&fixed_len_key) + .into_option() + .ok_or(anyhow!("Incorrect Priv Key"))?; + let public_key = pk.public_key(); + let public_key_bytes = public_key.0.to_compressed().to_vec(); Ok(public_key_bytes) } @@ -42,7 +54,13 @@ impl BlsModule for NativeBlsModule { 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 pk = SecretKey::::from_be_bytes(&fixed_len_key) + .into_option() + .ok_or(anyhow!("Incorrect Priv Key"))?; + 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 d5f985a3c1..01716ab044 100644 --- a/packages/rs-dpp/src/core_types/validator/mod.rs +++ b/packages/rs-dpp/src/core_types/validator/mod.rs @@ -1,6 +1,5 @@ -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 blsful::Bls12381G2Impl; use dashcore::{ProTxHash, PubkeyHash}; #[cfg(feature = "core-types-serde-conversion")] use serde::{Deserialize, Serialize}; 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 81f73a66af..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,8 +1,7 @@ use dashcore::{ProTxHash, PubkeyHash}; use std::fmt::{Debug, Formatter}; -use crate::bls_signatures::PublicKey as BlsPublicKey; -use blsful::Bls12381G2Impl; +use crate::bls_signatures::{Bls12381G2Impl, PublicKey as BlsPublicKey}; #[cfg(feature = "core-types-serde-conversion")] use serde::{Deserialize, Serialize}; @@ -261,7 +260,7 @@ impl ValidatorV0Setters for ValidatorV0 { mod tests { use super::*; use bincode::config; - use blsful::SecretKey; + use dashcore::blsful::SecretKey; use rand::prelude::StdRng; use rand::SeedableRng; 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 de5b515f9f..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, @@ -7,7 +7,6 @@ use crate::core_types::validator_set::v0::{ use crate::ProtocolError; #[cfg(feature = "core-types-serialization")] use bincode::{Decode, Encode}; -use blsful::Bls12381G2Impl; use dashcore::{ProTxHash, QuorumHash}; #[cfg(feature = "core-types-serialization")] use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; 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 cf05bb3d14..d500fb0426 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,7 +8,7 @@ use bincode::enc::Encoder; use bincode::error::EncodeError; #[cfg(feature = "core-types-serialization")] use bincode::{BorrowDecode, Decode, Encode}; -use blsful::Bls12381G2Impl; +use dashcore::blsful::Bls12381G2Impl; use dashcore::hashes::Hash; use dashcore::{ProTxHash, QuorumHash}; use itertools::Itertools; @@ -289,7 +289,7 @@ impl ValidatorSetV0Setters for ValidatorSetV0 { mod tests { use super::*; use bincode::config; - use blsful::SecretKey; + use dashcore::blsful::SecretKey; use dashcore::PubkeyHash; use rand::rngs::StdRng; use rand::SeedableRng; diff --git a/packages/rs-dpp/src/errors/protocol_error.rs b/packages/rs-dpp/src/errors/protocol_error.rs index 2164b339f1..99e83ba64b 100644 --- a/packages/rs-dpp/src/errors/protocol_error.rs +++ b/packages/rs-dpp/src/errors/protocol_error.rs @@ -1,3 +1,4 @@ +use dashcore::blsful::BlsError; use thiserror::Error; use crate::consensus::basic::state_transition::InvalidStateTransitionTypeError; @@ -247,6 +248,10 @@ pub enum ProtocolError { /// Invalid CBOR error #[error("invalid cbor error: {0}")] InvalidCBOR(String), + + /// Invalid CBOR error + #[error(transparent)] + BlsError(#[from] BlsError), } 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 a1ead4a725..e91cc6c3c3 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,14 +8,14 @@ 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::{blsful, ed25519_dalek, Network}; use itertools::Itertools; use lazy_static::lazy_static; +use crate::bls_signatures::{Bls12381G2Impl, BlsError}; use crate::fee::Credits; use crate::version::PlatformVersion; -use crate::{InvalidVectorSizeError, ProtocolError}; -use blsful::Bls12381G2Impl; +use crate::{bls_signatures, ProtocolError}; #[cfg(feature = "random-public-keys")] use rand::rngs::StdRng; #[cfg(feature = "random-public-keys")] @@ -166,13 +166,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() @@ -205,13 +200,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); @@ -220,14 +215,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"))] @@ -237,7 +236,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); @@ -246,14 +245,7 @@ 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 = 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"))] 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 4b64fe9f16..52357e89a2 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 @@ -2,9 +2,9 @@ use crate::identity::identity_public_key::methods::hash::IdentityPublicKeyHashMe use crate::identity::identity_public_key::v0::IdentityPublicKeyV0; use crate::identity::KeyType; use crate::util::hash::ripemd160_sha256; -use crate::ProtocolError; +use crate::{bls_signatures, ProtocolError}; use anyhow::anyhow; -use blsful::Bls12381G2Impl; +use dashcore::blsful::Bls12381G2Impl; use dashcore::hashes::Hash; use dashcore::key::Secp256k1; use dashcore::secp256k1::SecretKey; @@ -68,9 +68,11 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { KeyType::BLS12_381 => { #[cfg(feature = "bls-signatures")] { - let private_key: Option> = - blsful::SecretKey::::from_be_bytes(private_key_bytes) - .into(); + let private_key: Option> = + bls_signatures::SecretKey::::from_be_bytes( + private_key_bytes, + ) + .into(); if private_key.is_none() { return Ok(false); } @@ -124,7 +126,7 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { mod tests { use super::*; use crate::identity::{Purpose, SecurityLevel}; - use blsful::{Bls12381G2Impl, Pairing, Signature, SignatureSchemes}; + use dashcore::blsful::{Bls12381G2Impl, Pairing, Signature, SignatureSchemes}; use dashcore::Network; use dpp::version::PlatformVersion; use rand::rngs::StdRng; @@ -136,9 +138,10 @@ mod tests { 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 = - blsful::SecretKey::::from_be_bytes(&secret_key.try_into().unwrap()) - .expect("expected to get secret key"); + let decoded_secret_key = dashcore::blsful::SecretKey::::from_be_bytes( + &secret_key.try_into().unwrap(), + ) + .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!( @@ -153,9 +156,10 @@ mod tests { 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 = - blsful::SecretKey::::from_be_bytes(&secret_key.try_into().unwrap()) - .expect("expected to get secret key"); + let decoded_secret_key = dashcore::blsful::SecretKey::::from_be_bytes( + &secret_key.try_into().unwrap(), + ) + .expect("expected to get secret key"); let signature = decoded_secret_key .sign(SignatureSchemes::Basic, b"hello") .expect("expected to sign"); diff --git a/packages/rs-dpp/src/lib.rs b/packages/rs-dpp/src/lib.rs index 9744e16455..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 blsful as 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..336d17e29f 100644 --- a/packages/rs-dpp/src/signing.rs +++ b/packages/rs-dpp/src/signing.rs @@ -1,3 +1,4 @@ +use crate::bls_signatures::{Bls12381G2Impl, Pairing}; #[cfg(feature = "message-signature-verification")] use crate::consensus::signature::{ BasicBLSError, BasicECDSAError, SignatureError, SignatureShouldNotBePresentError, @@ -8,7 +9,8 @@ use crate::serialization::PlatformMessageSignable; use crate::validation::SimpleConsensusValidationResult; #[cfg(feature = "message-signing")] use crate::{BlsModule, ProtocolError}; -use dashcore::{bls_signatures, signer}; +use dashcore::blsful::Signature; +use dashcore::{blsful as bls_signatures, signer}; impl PlatformMessageSignable for &[u8] { #[cfg(feature = "message-signature-verification")] @@ -38,25 +40,34 @@ 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.to_vec().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")); - return SimpleConsensusValidationResult::new_with_error( - SignatureError::BasicBLSError(BasicBLSError::new(e.to_string())).into(), - ); - } - }; - if !public_key.verify(&signature, signable_data) { + let g2 = ::Signature::from_compressed(&signature_bytes) + .expect("G2 projective"); + let signature = Signature::::Basic(g2); + + if !signature.verify(&public_key, signable_data).is_ok() { SimpleConsensusValidationResult::new_with_error( SignatureError::BasicBLSError(BasicBLSError::new( "bls signature was incorrect".to_string(), diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 6fc8d7b6be..3a92a46df7 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,10 +73,9 @@ 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", optional = true } +bls-signatures = { git = "https://github.com/dashpay/bls-signatures", tag = "1.3.3" } [dev-dependencies] -bls-signatures = { git = "https://github.com/dashpay/bls-signatures", tag = "1.3.3" } bs58 = { version = "0.5.0" } base64 = "0.22.1" platform-version = { path = "../rs-platform-version", features = [ @@ -106,7 +105,7 @@ integer-encoding = { version = "4.0.0" } [features] default = ["mocks"] -mocks = ["mockall", "drive/fixtures-and-mocks", "bls-signatures"] +mocks = ["mockall", "drive/fixtures-and-mocks"] console = ["console-subscriber", "tokio/tracing"] testing-config = [] grovedbg = ["drive/grovedbg"] 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 66ab8d427b..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 @@ -128,7 +128,7 @@ fn hex_encoded_validator_sets(validator_sets: &IndexMap, /// Information about the last block diff --git a/packages/rs-sdk/Cargo.toml b/packages/rs-sdk/Cargo.toml index ebf783f652..b9fed51bae 100644 --- a/packages/rs-sdk/Cargo.toml +++ b/packages/rs-sdk/Cargo.toml @@ -33,7 +33,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/simple-signer/Cargo.toml b/packages/simple-signer/Cargo.toml index 12bb07870d..a1c06f26ba 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" } From 7f814ad6bcc667cae1dbb4cc2973d5cd114fb9cc Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Mon, 21 Oct 2024 03:46:11 +0700 Subject: [PATCH 03/29] exposed dapi-grpc in sdk --- packages/rs-sdk/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/rs-sdk/src/lib.rs b/packages/rs-sdk/src/lib.rs index 1f928ab6db..d6e29c9825 100644 --- a/packages/rs-sdk/src/lib.rs +++ b/packages/rs-sdk/src/lib.rs @@ -76,6 +76,7 @@ pub use dpp; pub use drive; pub use drive_proof_verifier::types as query_types; pub use rs_dapi_client as dapi_client; +pub use dapi_grpc; pub mod sync; /// Version of the SDK From 4506f9ff3f76dd9635e8e944794e291fd43b8c7a Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Mon, 21 Oct 2024 19:59:18 +0700 Subject: [PATCH 04/29] trial --- packages/rs-sdk/src/core/transaction.rs | 95 +++++++++++++------------ 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/packages/rs-sdk/src/core/transaction.rs b/packages/rs-sdk/src/core/transaction.rs index 39dd85e562..69343e8588 100644 --- a/packages/rs-sdk/src/core/transaction.rs +++ b/packages/rs-sdk/src/core/transaction.rs @@ -68,13 +68,13 @@ impl Sdk { ) -> Result { let transaction_id = transaction.txid(); - let _span = tracing::debug_span!( - "wait_for_asset_lock_proof_for_transaction", - transaction_id = transaction_id.to_string(), - ) - .entered(); - - tracing::debug!("waiting for messages from stream"); + // let _span = tracing::debug_span!( + // "wait_for_asset_lock_proof_for_transaction", + // transaction_id = transaction_id.to_string(), + // ) + // .entered(); + // + // tracing::debug!("waiting for messages from stream"); // Define an inner async block to handle the stream processing. let stream_processing = async { @@ -97,10 +97,10 @@ impl Sdk { instant_send_lock_messages, ), ) => { - tracing::debug!( - "received {} instant lock message(s)", - instant_send_lock_messages.messages.len() - ); + // tracing::debug!( + // "received {} instant lock message(s)", + // instant_send_lock_messages.messages.len() + // ); for instant_lock_bytes in instant_send_lock_messages.messages { let instant_lock = @@ -119,28 +119,29 @@ impl Sdk { output_index: 0, }); - tracing::debug!( - ?asset_lock_proof, - "instant lock is matching to the broadcasted transaction, returning instant asset lock proof" - ); + // tracing::debug!( + // ?asset_lock_proof, + // "instant lock is matching to the broadcasted transaction, returning instant asset lock proof" + // ); return Ok(asset_lock_proof); - } else { - tracing::debug!( - "instant lock is not matching, waiting for the next message" - ); - } + } + // else { + // tracing::debug!( + // "instant lock is not matching, waiting for the next message" + // ); + // } } } Some(transactions_with_proofs_response::Responses::RawMerkleBlock( raw_merkle_block, )) => { - tracing::debug!("received merkle block"); + // tracing::debug!("received merkle block"); let merkle_block = MerkleBlock::consensus_decode(&mut raw_merkle_block.as_slice()) .map_err(|e| { - tracing::error!("can't decode merkle block: {}", e); + // tracing::error!("can't decode merkle block: {}", e); Error::CoreError(e.into()) })?; @@ -152,16 +153,16 @@ impl Sdk { // Continue receiving messages until we find the transaction if !matches.contains(&transaction_id) { - tracing::debug!( - "merkle block doesn't contain the transaction, waiting for the next message" - ); + // tracing::debug!( + // "merkle block doesn't contain the transaction, waiting for the next message" + // ); continue; } - tracing::debug!( - "merkle block contains the transaction, obtaining core chain locked height" - ); + // tracing::debug!( + // "merkle block contains the transaction, obtaining core chain locked height" + // ); // TODO: This a temporary implementation until we have headers stream running in background // so we can always get actual height and chain locks @@ -188,15 +189,15 @@ impl Sdk { break; } - tracing::trace!("the transaction is on height {} but not chainlocked. try again in 1 sec", height); + // tracing::trace!("the transaction is on height {} but not chainlocked. try again in 1 sec", height); sleep(Duration::from_secs(1)).await; } - tracing::debug!( - "the transaction is chainlocked on height {}, waiting platform for reaching the same core height", - core_chain_locked_height - ); + // tracing::debug!( + // "the transaction is chainlocked on height {}, waiting platform for reaching the same core height", + // core_chain_locked_height + // ); // Wait until platform chain is on the block's chain locked height loop { @@ -207,11 +208,11 @@ impl Sdk { break; } - tracing::trace!( - "platform chain locked core height {} but we need {}. try again in 1 sec", - metadata.core_chain_locked_height, - core_chain_locked_height, - ); + // tracing::trace!( + // "platform chain locked core height {} but we need {}. try again in 1 sec", + // metadata.core_chain_locked_height, + // core_chain_locked_height, + // ); sleep(Duration::from_secs(1)).await; } @@ -224,19 +225,21 @@ impl Sdk { }, }); - tracing::debug!( - ?asset_lock_proof, - "merkle block contains the broadcasted transaction, returning chain asset lock proof" - ); + // tracing::debug!( + // ?asset_lock_proof, + // "merkle block contains the broadcasted transaction, returning chain asset lock proof" + // ); return Ok(asset_lock_proof); } Some(transactions_with_proofs_response::Responses::RawTransactions(_)) => { - tracing::trace!("received transaction(s), ignoring") + // tracing::trace!("received transaction(s), ignoring") } - None => tracing::trace!( - "received empty response as a workaround for the bug in tonic, ignoring" - ), + None => { + // tracing::trace!( + // "received empty response as a workaround for the bug in tonic, ignoring" + // ) + }, } } }; From efb43104974d692013cfdeffa4cd43b7c564eb63 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 27 Oct 2024 08:27:16 +0700 Subject: [PATCH 05/29] fix: add pagination support to sdk --- .../rs-sdk/src/platform/document_query.rs | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/rs-sdk/src/platform/document_query.rs b/packages/rs-sdk/src/platform/document_query.rs index a6b1f7c773..c8136cf0f1 100644 --- a/packages/rs-sdk/src/platform/document_query.rs +++ b/packages/rs-sdk/src/platform/document_query.rs @@ -19,7 +19,7 @@ use dpp::{ document::Document, platform_value::{platform_value, Value}, prelude::{DataContract, Identifier}, - ProtocolError, + InvalidVectorSizeError, ProtocolError, }; use drive::query::{DriveDocumentQuery, InternalClauses, OrderClause, WhereClause, WhereOperator}; use drive_proof_verifier::{types::Documents, ContextProvider, FromProof}; @@ -326,6 +326,26 @@ impl<'a> TryFrom<&'a DocumentQuery> for DriveDocumentQuery<'a> { } else { None }; + + let (start_at, start_at_included) = match request.start.as_ref() { + None => (None, false), + Some(Start::StartAt(at)) => ( + Some(at.clone().try_into().map_err(|_| { + ProtocolError::InvalidVectorSizeError(InvalidVectorSizeError::new(32, at.len())) + })?), + true, + ), + Some(Start::StartAfter(after)) => ( + Some(after.clone().try_into().map_err(|_| { + ProtocolError::InvalidVectorSizeError(InvalidVectorSizeError::new( + 32, + after.len(), + )) + })?), + true, + ), + }; + let query = Self { contract: &request.data_contract, document_type, @@ -338,8 +358,8 @@ impl<'a> TryFrom<&'a DocumentQuery> for DriveDocumentQuery<'a> { .into_iter() .map(|v| (v.field.clone(), v)) .collect(), - start_at: None, - start_at_included: false, + start_at, + start_at_included, block_time_ms: None, }; From 08e6e66fbd4e0e33c1a808e75f1021d71296fe83 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 27 Oct 2024 19:13:56 +0700 Subject: [PATCH 06/29] added more unit tests --- .../src/query/document_query/v0/mod.rs | 591 +++++++++++++++++- packages/rs-drive-abci/src/query/mod.rs | 44 +- 2 files changed, 632 insertions(+), 3 deletions(-) diff --git a/packages/rs-drive-abci/src/query/document_query/v0/mod.rs b/packages/rs-drive-abci/src/query/document_query/v0/mod.rs index 8af82e39cc..445b460caf 100644 --- a/packages/rs-drive-abci/src/query/document_query/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/document_query/v0/mod.rs @@ -180,9 +180,19 @@ impl Platform { #[cfg(test)] mod tests { use super::*; - use crate::query::tests::{assert_invalid_identifier, setup_platform, store_data_contract}; + use crate::query::tests::{ + assert_invalid_identifier, setup_platform, store_data_contract, store_document, + }; + use ciborium::value::Value as CborValue; use dpp::dashcore::Network; + use dpp::data_contract::document_type::random_document::CreateRandomDocument; + use dpp::document::{Document, DocumentV0, DocumentV0Getters}; use dpp::tests::fixtures::get_data_contract_fixture; + use drive::query::{InternalClauses, OrderClause, WhereClause, WhereOperator}; + use indexmap::IndexMap; + use rand::rngs::StdRng; + use rand::SeedableRng; + use std::collections::BTreeMap; #[test] fn test_invalid_document_id() { @@ -479,4 +489,583 @@ mod tests { }) )); } + + #[test] + fn test_documents_single_item_proof() { + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + + let platform_version = PlatformVersion::latest(); + let created_data_contract = get_data_contract_fixture(None, 0, version.protocol_version); + store_data_contract(&platform, created_data_contract.data_contract(), version); + + let data_contract_id = created_data_contract.data_contract().id(); + let document_type_name = "niceDocument"; + let document_type = created_data_contract + .data_contract() + .document_type_for_name(document_type_name) + .expect("expected document type"); + + let random_document = document_type + .random_document(Some(4), platform_version) + .expect("expected to get random document"); + + store_document( + &platform, + created_data_contract.data_contract(), + document_type, + &random_document, + platform_version, + ); + + let drive_document_query = DriveDocumentQuery { + contract: &created_data_contract.data_contract(), + document_type, + internal_clauses: Default::default(), + offset: None, + limit: Some(1), + order_by: Default::default(), + start_at: None, + start_at_included: false, + block_time_ms: None, + }; + + let request = GetDocumentsRequestV0 { + data_contract_id: data_contract_id.to_vec(), + document_type: document_type_name.to_string(), + r#where: vec![], + limit: 1, + order_by: vec![], + prove: true, + start: None, + }; + + let result = platform + .query_documents_v0(request, &state, version) + .expect("expected query to succeed"); + + let Some(GetDocumentsResponseV0 { + result: Some(get_documents_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) = result.data + else { + panic!("expected proof") + }; + + let (_, documents) = drive_document_query + .verify_proof(&proof.grovedb_proof, platform_version) + .expect("expected to verify proof"); + + assert_eq!(documents.len(), 1); + assert_eq!(documents.get(0).expect("first"), &random_document); + } + + #[test] + fn test_documents_range_proof() { + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + + let platform_version = PlatformVersion::latest(); + let created_data_contract = get_data_contract_fixture(None, 0, version.protocol_version); + store_data_contract(&platform, created_data_contract.data_contract(), version); + + let data_contract_id = created_data_contract.data_contract().id(); + let document_type_name = "niceDocument"; + let document_type = created_data_contract + .data_contract() + .document_type_for_name(document_type_name) + .expect("expected document type"); + + let mut std_rng = StdRng::seed_from_u64(393); + let mut documents_by_id = BTreeMap::new(); + for _i in 0..20 { + let random_document = document_type + .random_document_with_rng(&mut std_rng, platform_version) + .expect("expected to get random document"); + store_document( + &platform, + created_data_contract.data_contract(), + document_type, + &random_document, + platform_version, + ); + documents_by_id.insert(random_document.id(), random_document); + } + + let drive_document_query = DriveDocumentQuery { + contract: &created_data_contract.data_contract(), + document_type, + internal_clauses: Default::default(), + offset: None, + limit: Some(10), + order_by: Default::default(), + start_at: None, + start_at_included: false, + block_time_ms: None, + }; + + let request = GetDocumentsRequestV0 { + data_contract_id: data_contract_id.to_vec(), + document_type: document_type_name.to_string(), + r#where: vec![], + limit: 10, + order_by: vec![], + prove: true, + start: None, + }; + + let result = platform + .query_documents_v0(request, &state, version) + .expect("expected query to succeed"); + + let Some(GetDocumentsResponseV0 { + result: Some(get_documents_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) = result.data + else { + panic!("expected proof") + }; + + let (_, queried_documents) = drive_document_query + .verify_proof(&proof.grovedb_proof, platform_version) + .expect("expected to verify proof"); + + assert_eq!(queried_documents.len(), 10); + assert_eq!( + queried_documents.get(9).expect("first"), + documents_by_id + .values() + .nth(9) + .expect("expected to get 9th document") + ); + } + + #[test] + fn test_documents_start_after_proof_primary_index() { + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + + let platform_version = PlatformVersion::latest(); + let created_data_contract = get_data_contract_fixture(None, 0, version.protocol_version); + store_data_contract(&platform, created_data_contract.data_contract(), version); + + let data_contract_id = created_data_contract.data_contract().id(); + let document_type_name = "niceDocument"; + let document_type = created_data_contract + .data_contract() + .document_type_for_name(document_type_name) + .expect("expected document type"); + + let mut std_rng = StdRng::seed_from_u64(393); + let mut documents_by_id = BTreeMap::new(); + for _i in 0..20 { + let random_document = document_type + .random_document_with_rng(&mut std_rng, platform_version) + .expect("expected to get random document"); + store_document( + &platform, + created_data_contract.data_contract(), + document_type, + &random_document, + platform_version, + ); + documents_by_id.insert(random_document.id(), random_document); + } + + let after = documents_by_id + .keys() + .nth(9) + .expect("expected to get 9th document") + .to_buffer(); + + let drive_document_query = DriveDocumentQuery { + contract: &created_data_contract.data_contract(), + document_type, + internal_clauses: Default::default(), + offset: None, + limit: Some(10), + order_by: Default::default(), + start_at: Some(after), + start_at_included: false, + block_time_ms: None, + }; + + let request = GetDocumentsRequestV0 { + data_contract_id: data_contract_id.to_vec(), + document_type: document_type_name.to_string(), + r#where: vec![], + limit: 10, + order_by: vec![], + prove: true, + start: Some(Start::StartAfter(after.to_vec())), + }; + + let result = platform + .query_documents_v0(request, &state, version) + .expect("expected query to succeed"); + + let Some(GetDocumentsResponseV0 { + result: Some(get_documents_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) = result.data + else { + panic!("expected proof") + }; + + let (_, queried_documents) = drive_document_query + .verify_proof(&proof.grovedb_proof, platform_version) + .expect("expected to verify proof"); + + assert_eq!(queried_documents.len(), 10); + assert_eq!( + queried_documents.get(9).expect("last"), + documents_by_id + .values() + .nth(19) + .expect("expected to get 9th document") + ); + } + + fn serialize_vec_to_cbor>(input: Vec) -> Result, Error> { + let values = Value::Array( + input + .into_iter() + .map(|v| v.into() as Value) + .collect::>(), + ); + + let cbor_values: CborValue = TryInto::::try_into(values) + .map_err(|e| Error::Protocol(dpp::ProtocolError::EncodingError(e.to_string())))?; + + let mut serialized = Vec::new(); + ciborium::ser::into_writer(&cbor_values, &mut serialized) + .map_err(|e| Error::Protocol(dpp::ProtocolError::EncodingError(e.to_string())))?; + + Ok(serialized) + } + + #[test] + fn test_documents_start_after_proof_secondary_index() { + let (platform, state, version) = setup_platform(Some((1, 1)), Network::Testnet, None); + + let platform_version = PlatformVersion::latest(); + let withdrawals = platform + .drive + .cache + .system_data_contracts + .load_withdrawals(); + + let data_contract_id = withdrawals.id(); + let document_type_name = "withdrawal"; + let document_type = withdrawals + .document_type_for_name(document_type_name) + .expect("expected document type"); + + let mut std_rng = StdRng::seed_from_u64(393); + let mut documents_by_created_at = BTreeMap::new(); + + // Define the base time as the current system time + let base_time = 1730028481000; + + for i in 0..20 { + let created_at = base_time + i * 20000; + // Create a Document with the desired properties + let random_document: Document = DocumentV0 { + id: Identifier::random_with_rng(&mut std_rng), + owner_id: Identifier::random_with_rng(&mut std_rng), + properties: { + let mut properties = BTreeMap::new(); + properties.insert("status".to_string(), Value::I64(0)); // Always queued + properties.insert("pooling".to_string(), Value::I64(0)); // Always 0 + properties.insert("coreFeePerByte".to_string(), Value::I64(1)); // Always 1 + properties.insert("amount".to_string(), Value::I64(1000)); // Set a minimum amount of 1000 + properties.insert("outputScript".to_string(), Value::Bytes(vec![])); // Set an empty output script + properties + }, + revision: Some(1), // Example revision + created_at: Some(created_at), // Set created_at + updated_at: Some(created_at), // Set updated_at + transferred_at: None, + created_at_block_height: None, + updated_at_block_height: None, + transferred_at_block_height: None, + created_at_core_block_height: None, + updated_at_core_block_height: None, + transferred_at_core_block_height: None, + } + .into(); + store_document( + &platform, + &withdrawals, + document_type, + &random_document, + platform_version, + ); + documents_by_created_at.insert(created_at, random_document); + } + + let after = documents_by_created_at + .values() + .nth(9) + .expect("expected to get 9th document") + .id(); + + let drive_document_query = DriveDocumentQuery { + contract: &withdrawals, + document_type, + internal_clauses: InternalClauses { + primary_key_in_clause: None, + primary_key_equal_clause: None, + in_clause: None, + range_clause: None, + equal_clauses: BTreeMap::from([ + ( + "status".to_string(), + WhereClause { + field: "status".to_string(), + operator: WhereOperator::Equal, + value: Value::I64(0), + }, + ), + ( + "pooling".to_string(), + WhereClause { + field: "pooling".to_string(), + operator: WhereOperator::Equal, + value: Value::I64(0), + }, + ), + ( + "coreFeePerByte".to_string(), + WhereClause { + field: "coreFeePerByte".to_string(), + operator: WhereOperator::Equal, + value: Value::I64(1), + }, + ), + ]), + }, + offset: None, + limit: Some(10), + order_by: IndexMap::from([( + "$updatedAt".to_string(), + OrderClause { + field: "$updatedAt".to_string(), + ascending: true, + }, + )]), + start_at: Some(after.to_buffer()), + start_at_included: false, + block_time_ms: None, + }; + + let where_clauses = serialize_vec_to_cbor( + drive_document_query + .internal_clauses + .equal_clauses + .values() + .cloned() + .collect(), + ) + .expect("where clauses serialization should never fail"); + let order_by = + serialize_vec_to_cbor(drive_document_query.order_by.values().cloned().collect()) + .expect("order by clauses serialization should never fail"); + + let request = GetDocumentsRequestV0 { + data_contract_id: data_contract_id.to_vec(), + document_type: document_type_name.to_string(), + r#where: where_clauses, + limit: 10, + order_by, + prove: true, + start: Some(Start::StartAfter(after.to_vec())), + }; + + let result = platform + .query_documents_v0(request, &state, version) + .expect("expected query to succeed"); + + let Some(GetDocumentsResponseV0 { + result: Some(get_documents_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) = result.data + else { + panic!("expected proof") + }; + + let (_, queried_documents) = drive_document_query + .verify_proof(&proof.grovedb_proof, platform_version) + .expect("expected to verify proof"); + + assert_eq!(queried_documents.len(), 10); + assert_eq!( + queried_documents.get(9).expect("last"), + documents_by_created_at + .values() + .nth(19) + .expect("expected to get 9th document") + ); + } + + #[test] + fn test_documents_start_after_proof_secondary_index_many_statuses() { + let (platform, state, version) = setup_platform(Some((1, 1)), Network::Testnet, None); + + let platform_version = PlatformVersion::latest(); + let withdrawals = platform + .drive + .cache + .system_data_contracts + .load_withdrawals(); + + let data_contract_id = withdrawals.id(); + let document_type_name = "withdrawal"; + let document_type = withdrawals + .document_type_for_name(document_type_name) + .expect("expected document type"); + + let mut std_rng = StdRng::seed_from_u64(393); + let mut documents_by_created_at = BTreeMap::new(); + + // Define the base time as the current system time + let base_time = 1730028481000; + + for i in 0..20 { + let created_at = base_time + i * 20000; + // Create a Document with the desired properties + let random_document: Document = DocumentV0 { + id: Identifier::random_with_rng(&mut std_rng), + owner_id: Identifier::random_with_rng(&mut std_rng), + properties: { + let mut properties = BTreeMap::new(); + properties.insert("status".to_string(), Value::I64(i as i64 % 4)); // Always queued + properties.insert("pooling".to_string(), Value::I64(0)); // Always 0 + properties.insert("coreFeePerByte".to_string(), Value::I64(1)); // Always 1 + properties.insert("amount".to_string(), Value::I64(1000)); // Set a minimum amount of 1000 + properties.insert("outputScript".to_string(), Value::Bytes(vec![])); // Set an empty output script + properties + }, + revision: Some(1), // Example revision + created_at: Some(created_at), // Set created_at + updated_at: Some(created_at), // Set updated_at + transferred_at: None, + created_at_block_height: None, + updated_at_block_height: None, + transferred_at_block_height: None, + created_at_core_block_height: None, + updated_at_core_block_height: None, + transferred_at_core_block_height: None, + } + .into(); + store_document( + &platform, + &withdrawals, + document_type, + &random_document, + platform_version, + ); + documents_by_created_at.insert(created_at, random_document); + } + + let after = documents_by_created_at + .values() + .nth(9) + .expect("expected to get 9th document") + .id(); + + let drive_document_query = DriveDocumentQuery { + contract: &withdrawals, + document_type, + internal_clauses: InternalClauses { + primary_key_in_clause: None, + primary_key_equal_clause: None, + in_clause: None, + range_clause: None, + equal_clauses: BTreeMap::from([ + ( + "status".to_string(), + WhereClause { + field: "status".to_string(), + operator: WhereOperator::Equal, + value: Value::I64(0), + }, + ), + ( + "pooling".to_string(), + WhereClause { + field: "pooling".to_string(), + operator: WhereOperator::Equal, + value: Value::I64(0), + }, + ), + ( + "coreFeePerByte".to_string(), + WhereClause { + field: "coreFeePerByte".to_string(), + operator: WhereOperator::Equal, + value: Value::I64(1), + }, + ), + ]), + }, + offset: None, + limit: Some(3), + order_by: IndexMap::from([( + "$updatedAt".to_string(), + OrderClause { + field: "$updatedAt".to_string(), + ascending: true, + }, + )]), + start_at: Some(after.to_buffer()), + start_at_included: false, + block_time_ms: None, + }; + + let where_clauses = serialize_vec_to_cbor( + drive_document_query + .internal_clauses + .equal_clauses + .values() + .cloned() + .collect(), + ) + .expect("where clauses serialization should never fail"); + let order_by = + serialize_vec_to_cbor(drive_document_query.order_by.values().cloned().collect()) + .expect("order by clauses serialization should never fail"); + + let request = GetDocumentsRequestV0 { + data_contract_id: data_contract_id.to_vec(), + document_type: document_type_name.to_string(), + r#where: where_clauses, + limit: 3, + order_by, + prove: true, + start: Some(Start::StartAfter(after.to_vec())), + }; + + let result = platform + .query_documents_v0(request, &state, version) + .expect("expected query to succeed"); + + let Some(GetDocumentsResponseV0 { + result: Some(get_documents_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) = result.data + else { + panic!("expected proof") + }; + + let (_, queried_documents) = drive_document_query + .verify_proof(&proof.grovedb_proof, platform_version) + .expect("expected to verify proof"); + + assert_eq!(queried_documents.len(), 2); + assert_eq!( + queried_documents.get(1).expect("last"), + documents_by_created_at + .values() + .nth(16) + .expect("expected to get 2nd document") + ); + } } diff --git a/packages/rs-drive-abci/src/query/mod.rs b/packages/rs-drive-abci/src/query/mod.rs index a7d58c7358..6be97cc1cf 100644 --- a/packages/rs-drive-abci/src/query/mod.rs +++ b/packages/rs-drive-abci/src/query/mod.rs @@ -32,9 +32,15 @@ pub(crate) mod tests { use crate::config::PlatformConfig; use dpp::dashcore::Network; + use dpp::data_contract::document_type::DocumentTypeRef; + use dpp::document::Document; use dpp::prelude::{CoreBlockHeight, TimestampMillis}; - use drive::util::batch::DataContractOperationType; - use drive::util::batch::DriveOperation::DataContractOperation; + use drive::util::batch::DriveOperation::{DataContractOperation, DocumentOperation}; + use drive::util::batch::{DataContractOperationType, DocumentOperationType}; + use drive::util::object_size_info::{ + DataContractInfo, DocumentInfo, DocumentTypeInfo, OwnedDocumentInfo, + }; + use drive::util::storage_flags::StorageFlags; use platform_version::version::{PlatformVersion, ProtocolVersion}; use std::borrow::Cow; use std::sync::Arc; @@ -108,6 +114,40 @@ pub(crate) mod tests { .expect("expected to apply drive operations"); } + pub fn store_document( + platform: &Platform, + data_contract: &DataContract, + document_type: DocumentTypeRef, + document: &Document, + platform_version: &PlatformVersion, + ) { + let storage_flags = Some(Cow::Owned(StorageFlags::SingleEpoch(0))); + + let operation = DocumentOperation(DocumentOperationType::AddDocument { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((document, storage_flags)), + owner_id: None, + }, + contract_info: DataContractInfo::BorrowedDataContract(data_contract), + document_type_info: DocumentTypeInfo::DocumentTypeRef(document_type), + override_document: false, + }); + + let block_info = BlockInfo::genesis(); + + platform + .drive + .apply_drive_operations( + vec![operation], + true, + &block_info, + None, + platform_version, + None, + ) + .expect("expected to apply drive operations"); + } + pub fn assert_invalid_identifier( validation_result: QueryValidationResult, ) { From 12373185369b5919c415f09f5b8be4d0c7b72966 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sun, 27 Oct 2024 19:19:28 +0700 Subject: [PATCH 07/29] temp --- .../src/verify/document/verify_proof_keep_serialized/v0/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/rs-drive/src/verify/document/verify_proof_keep_serialized/v0/mod.rs b/packages/rs-drive/src/verify/document/verify_proof_keep_serialized/v0/mod.rs index dc362c7ead..1399925375 100644 --- a/packages/rs-drive/src/verify/document/verify_proof_keep_serialized/v0/mod.rs +++ b/packages/rs-drive/src/verify/document/verify_proof_keep_serialized/v0/mod.rs @@ -39,6 +39,7 @@ impl<'a> DriveDocumentQuery<'a> { } else { self.construct_path_query(None, platform_version) }?; + println!("path query is {}", path_query); let (root_hash, proved_key_values) = if self.start_at.is_some() { GroveDb::verify_subset_query(proof, &path_query, &platform_version.drive.grove_version)? } else { From 7c77c400a546b40b88c2a31a9913dcc8075b87b3 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Mon, 28 Oct 2024 05:42:56 +0700 Subject: [PATCH 08/29] more fixes --- .../src/query/document_query/v0/mod.rs | 507 ++++++++++++++++++ packages/rs-drive/src/query/mod.rs | 169 +++++- .../verify_proof_keep_serialized/v0/mod.rs | 1 + packages/rs-drive/tests/query_tests.rs | 6 +- .../contract/withdrawals/withdrawals.json | 141 +++++ 5 files changed, 814 insertions(+), 10 deletions(-) create mode 100644 packages/rs-drive/tests/supporting_files/contract/withdrawals/withdrawals.json diff --git a/packages/rs-drive-abci/src/query/document_query/v0/mod.rs b/packages/rs-drive-abci/src/query/document_query/v0/mod.rs index 445b460caf..b725855ec1 100644 --- a/packages/rs-drive-abci/src/query/document_query/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/document_query/v0/mod.rs @@ -131,6 +131,8 @@ impl Platform { &self.config.drive, )); + println!("{:?}", drive_query); + let response = if prove { let proof = match drive_query.execute_with_proof(&self.drive, None, None, platform_version) { @@ -183,6 +185,7 @@ mod tests { use crate::query::tests::{ assert_invalid_identifier, setup_platform, store_data_contract, store_document, }; + use assert_matches::assert_matches; use ciborium::value::Value as CborValue; use dpp::dashcore::Network; use dpp::data_contract::document_type::random_document::CreateRandomDocument; @@ -1068,4 +1071,508 @@ mod tests { .expect("expected to get 2nd document") ); } + + #[test] + fn test_documents_proof_secondary_index_in_query() { + let (platform, state, version) = setup_platform(Some((1, 1)), Network::Testnet, None); + + let platform_version = PlatformVersion::latest(); + let withdrawals = platform + .drive + .cache + .system_data_contracts + .load_withdrawals(); + + let data_contract_id = withdrawals.id(); + let document_type_name = "withdrawal"; + let document_type = withdrawals + .document_type_for_name(document_type_name) + .expect("expected document type"); + + let mut std_rng = StdRng::seed_from_u64(393); + let mut documents_by_id = BTreeMap::new(); + + // Define the base time as the current system time + let base_time = 1730028481000; + + for i in 0..20 { + let created_at = base_time + i * 20000; + // Create a Document with the desired properties + let random_document: Document = DocumentV0 { + id: Identifier::random_with_rng(&mut std_rng), + owner_id: Identifier::random_with_rng(&mut std_rng), + properties: { + let mut properties = BTreeMap::new(); + properties.insert("status".to_string(), Value::I64(i as i64 % 4)); // Always queued + properties.insert("pooling".to_string(), Value::I64(0)); // Always 0 + properties.insert("coreFeePerByte".to_string(), Value::I64(1)); // Always 1 + properties.insert("amount".to_string(), Value::I64(1000)); // Set a minimum amount of 1000 + properties.insert("outputScript".to_string(), Value::Bytes(vec![])); // Set an empty output script + properties + }, + revision: Some(1), // Example revision + created_at: Some(created_at), // Set created_at + updated_at: Some(created_at), // Set updated_at + transferred_at: None, + created_at_block_height: None, + updated_at_block_height: None, + transferred_at_block_height: None, + created_at_core_block_height: None, + updated_at_core_block_height: None, + transferred_at_core_block_height: None, + } + .into(); + store_document( + &platform, + &withdrawals, + document_type, + &random_document, + platform_version, + ); + documents_by_id.insert(random_document.id(), random_document); + } + + let drive_document_query = DriveDocumentQuery { + contract: &withdrawals, + document_type, + internal_clauses: InternalClauses { + primary_key_in_clause: None, + primary_key_equal_clause: None, + in_clause: Some(WhereClause { + field: "status".to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![ + Value::I64(0), + Value::I64(1), + Value::I64(2), + Value::I64(3), + Value::I64(4), + ]), + }), + range_clause: None, + equal_clauses: BTreeMap::default(), + }, + offset: None, + limit: Some(3), + order_by: IndexMap::from([ + ( + "status".to_string(), + OrderClause { + field: "status".to_string(), + ascending: true, + }, + ), + ( + "transactionIndex".to_string(), + OrderClause { + field: "transactionIndex".to_string(), + ascending: true, + }, + ), + ]), + start_at: None, + start_at_included: false, + block_time_ms: None, + }; + + let mut where_clauses: Vec<_> = drive_document_query + .internal_clauses + .equal_clauses + .values() + .cloned() + .collect(); + + where_clauses.insert( + 0, + drive_document_query + .internal_clauses + .in_clause + .clone() + .unwrap(), + ); + + let where_clauses_serialized = serialize_vec_to_cbor(where_clauses) + .expect("where clauses serialization should never fail"); + let order_by = + serialize_vec_to_cbor(drive_document_query.order_by.values().cloned().collect()) + .expect("order by clauses serialization should never fail"); + + let request = GetDocumentsRequestV0 { + data_contract_id: data_contract_id.to_vec(), + document_type: document_type_name.to_string(), + r#where: where_clauses_serialized, + limit: 3, + order_by, + prove: true, + start: None, + }; + + let result = platform + .query_documents_v0(request, &state, version) + .expect("expected query to succeed"); + + assert!(result.errors.is_empty(), "errors are {:?}", result.errors); + + let Some(GetDocumentsResponseV0 { + result: Some(get_documents_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) = result.data + else { + panic!("expected proof") + }; + + let (_, queried_documents) = drive_document_query + .verify_proof(&proof.grovedb_proof, platform_version) + .expect("expected to verify proof"); + + assert_eq!(queried_documents.len(), 3); + } + + #[test] + fn test_documents_start_after_proof_secondary_index_in_query() { + let (platform, state, version) = setup_platform(Some((1, 1)), Network::Testnet, None); + + let platform_version = PlatformVersion::latest(); + let withdrawals = platform + .drive + .cache + .system_data_contracts + .load_withdrawals(); + + let data_contract_id = withdrawals.id(); + let document_type_name = "withdrawal"; + let document_type = withdrawals + .document_type_for_name(document_type_name) + .expect("expected document type"); + + let mut std_rng = StdRng::seed_from_u64(393); + let mut documents_by_created_at = BTreeMap::new(); + + // Define the base time as the current system time + let base_time = 1730028481000; + + for i in 0..20 { + let created_at = base_time + i * 20000; + // Create a Document with the desired properties + let random_document: Document = DocumentV0 { + id: Identifier::random_with_rng(&mut std_rng), + owner_id: Identifier::random_with_rng(&mut std_rng), + properties: { + let mut properties = BTreeMap::new(); + properties.insert("status".to_string(), Value::I64(i as i64 % 4)); // Always queued + properties.insert("pooling".to_string(), Value::I64(0)); // Always 0 + properties.insert("coreFeePerByte".to_string(), Value::I64(1)); // Always 1 + properties.insert("amount".to_string(), Value::I64(1000)); // Set a minimum amount of 1000 + properties.insert("outputScript".to_string(), Value::Bytes(vec![])); // Set an empty output script + properties + }, + revision: Some(1), // Example revision + created_at: Some(created_at), // Set created_at + updated_at: Some(created_at), // Set updated_at + transferred_at: None, + created_at_block_height: None, + updated_at_block_height: None, + transferred_at_block_height: None, + created_at_core_block_height: None, + updated_at_core_block_height: None, + transferred_at_core_block_height: None, + } + .into(); + store_document( + &platform, + &withdrawals, + document_type, + &random_document, + platform_version, + ); + documents_by_created_at.insert(created_at, random_document); + } + + let after = documents_by_created_at + .values() + .nth(4) + .expect("expected to get 9th document") + .id(); + + let drive_document_query = DriveDocumentQuery { + contract: &withdrawals, + document_type, + internal_clauses: InternalClauses { + primary_key_in_clause: None, + primary_key_equal_clause: None, + in_clause: Some(WhereClause { + field: "status".to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![ + Value::I64(0), + Value::I64(1), + Value::I64(2), + Value::I64(3), + Value::I64(4), + ]), + }), + range_clause: None, + equal_clauses: BTreeMap::default(), + }, + offset: None, + limit: Some(3), + order_by: IndexMap::from([ + ( + "status".to_string(), + OrderClause { + field: "status".to_string(), + ascending: true, + }, + ), + ( + "transactionIndex".to_string(), + OrderClause { + field: "transactionIndex".to_string(), + ascending: true, + }, + ), + ]), + start_at: Some(after.to_buffer()), + start_at_included: false, + block_time_ms: None, + }; + + let mut where_clauses: Vec<_> = drive_document_query + .internal_clauses + .equal_clauses + .values() + .cloned() + .collect(); + + where_clauses.insert( + 0, + drive_document_query + .internal_clauses + .in_clause + .clone() + .unwrap(), + ); + + let where_clauses_serialized = serialize_vec_to_cbor(where_clauses) + .expect("where clauses serialization should never fail"); + let order_by = + serialize_vec_to_cbor(drive_document_query.order_by.values().cloned().collect()) + .expect("order by clauses serialization should never fail"); + + let request = GetDocumentsRequestV0 { + data_contract_id: data_contract_id.to_vec(), + document_type: document_type_name.to_string(), + r#where: where_clauses_serialized, + limit: 3, + order_by, + prove: true, + start: Some(Start::StartAfter(after.to_vec())), + }; + + let result = platform + .query_documents_v0(request, &state, version) + .expect("expected query to succeed"); + + assert!(result.errors.is_empty(), "errors are {:?}", result.errors); + + let Some(GetDocumentsResponseV0 { + result: Some(get_documents_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) = result.data + else { + panic!("expected proof") + }; + + let (_, queried_documents) = drive_document_query + .verify_proof(&proof.grovedb_proof, platform_version) + .expect("expected to verify proof"); + + assert_eq!(queried_documents.len(), 3); + assert_eq!( + queried_documents.get(1).expect("last"), + documents_by_created_at + .values() + .nth(16) + .expect("expected to get 2nd document") + ); + } + + //todo: this should be possible + #[test] + #[ignore] + fn test_documents_start_after_proof_secondary_index_in_query_2() { + let (platform, state, version) = setup_platform(Some((1, 1)), Network::Testnet, None); + + let platform_version = PlatformVersion::latest(); + let withdrawals = platform + .drive + .cache + .system_data_contracts + .load_withdrawals(); + + let data_contract_id = withdrawals.id(); + let document_type_name = "withdrawal"; + let document_type = withdrawals + .document_type_for_name(document_type_name) + .expect("expected document type"); + + let mut std_rng = StdRng::seed_from_u64(393); + let mut documents_by_created_at = BTreeMap::new(); + + // Define the base time as the current system time + let base_time = 1730028481000; + + for i in 0..20 { + let created_at = base_time + i * 20000; + // Create a Document with the desired properties + let random_document: Document = DocumentV0 { + id: Identifier::random_with_rng(&mut std_rng), + owner_id: Identifier::random_with_rng(&mut std_rng), + properties: { + let mut properties = BTreeMap::new(); + properties.insert("status".to_string(), Value::I64(i as i64 % 4)); // Always queued + properties.insert("pooling".to_string(), Value::I64(0)); // Always 0 + properties.insert("coreFeePerByte".to_string(), Value::I64(1)); // Always 1 + properties.insert("amount".to_string(), Value::I64(1000)); // Set a minimum amount of 1000 + properties.insert("outputScript".to_string(), Value::Bytes(vec![])); // Set an empty output script + properties + }, + revision: Some(1), // Example revision + created_at: Some(created_at), // Set created_at + updated_at: Some(created_at), // Set updated_at + transferred_at: None, + created_at_block_height: None, + updated_at_block_height: None, + transferred_at_block_height: None, + created_at_core_block_height: None, + updated_at_core_block_height: None, + transferred_at_core_block_height: None, + } + .into(); + store_document( + &platform, + &withdrawals, + document_type, + &random_document, + platform_version, + ); + documents_by_created_at.insert(created_at, random_document); + } + + let after = documents_by_created_at + .values() + .nth(9) + .expect("expected to get 9th document") + .id(); + + let drive_document_query = DriveDocumentQuery { + contract: &withdrawals, + document_type, + internal_clauses: InternalClauses { + primary_key_in_clause: None, + primary_key_equal_clause: None, + in_clause: Some(WhereClause { + field: "status".to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![ + Value::I64(0), + Value::I64(1), + Value::I64(2), + Value::I64(3), + Value::I64(4), + ]), + }), + range_clause: None, + equal_clauses: BTreeMap::from([ + ( + "pooling".to_string(), + WhereClause { + field: "pooling".to_string(), + operator: WhereOperator::Equal, + value: Value::I64(0), + }, + ), + ( + "coreFeePerByte".to_string(), + WhereClause { + field: "coreFeePerByte".to_string(), + operator: WhereOperator::Equal, + value: Value::I64(1), + }, + ), + ]), + }, + offset: None, + limit: Some(3), + order_by: IndexMap::from([( + "$updatedAt".to_string(), + OrderClause { + field: "$updatedAt".to_string(), + ascending: true, + }, + )]), + start_at: Some(after.to_buffer()), + start_at_included: false, + block_time_ms: None, + }; + + let mut where_clauses: Vec<_> = drive_document_query + .internal_clauses + .equal_clauses + .values() + .cloned() + .collect(); + + where_clauses.insert( + 0, + drive_document_query + .internal_clauses + .in_clause + .clone() + .unwrap(), + ); + + let where_clauses_serialized = serialize_vec_to_cbor(where_clauses) + .expect("where clauses serialization should never fail"); + let order_by = + serialize_vec_to_cbor(drive_document_query.order_by.values().cloned().collect()) + .expect("order by clauses serialization should never fail"); + + let request = GetDocumentsRequestV0 { + data_contract_id: data_contract_id.to_vec(), + document_type: document_type_name.to_string(), + r#where: where_clauses_serialized, + limit: 3, + order_by, + prove: true, + start: Some(Start::StartAfter(after.to_vec())), + }; + + let result = platform + .query_documents_v0(request, &state, version) + .expect("expected query to succeed"); + + assert!(result.errors.is_empty(), "errors are {:?}", result.errors); + + let Some(GetDocumentsResponseV0 { + result: Some(get_documents_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) = result.data + else { + panic!("expected proof") + }; + + let (_, queried_documents) = drive_document_query + .verify_proof(&proof.grovedb_proof, platform_version) + .expect("expected to verify proof"); + + assert_eq!(queried_documents.len(), 2); + assert_eq!( + queried_documents.get(1).expect("last"), + documents_by_created_at + .values() + .nth(16) + .expect("expected to get 2nd document") + ); + } } diff --git a/packages/rs-drive/src/query/mod.rs b/packages/rs-drive/src/query/mod.rs index 1d7cf24371..393883856f 100644 --- a/packages/rs-drive/src/query/mod.rs +++ b/packages/rs-drive/src/query/mod.rs @@ -1275,23 +1275,39 @@ impl<'a> DriveDocumentQuery<'a> { #[cfg(any(feature = "server", feature = "verify"))] /// Returns a `Query` that either starts at or after the given key. fn inner_query_starts_from_key( - start_at_key: Vec, + start_at_key: Option>, left_to_right: bool, included: bool, ) -> Query { // We only need items after the start at document let mut inner_query = Query::new_with_direction(left_to_right); + if left_to_right { - if included { - inner_query.insert_range_from(start_at_key..); + if let Some(start_at_key) = start_at_key { + if included { + inner_query.insert_range_from(start_at_key..); + } else { + inner_query.insert_range_after(start_at_key..); + } } else { - inner_query.insert_range_after(start_at_key..); + inner_query.insert_all(); } } else if included { - inner_query.insert_range_to_inclusive(..=start_at_key); + if let Some(start_at_key) = start_at_key { + inner_query.insert_range_to_inclusive(..=start_at_key); + } else { + inner_query.insert_key(vec![]); + } } else { - inner_query.insert_range_to(..start_at_key); + if let Some(start_at_key) = start_at_key { + inner_query.insert_range_to(..start_at_key); + } else { + //todo: really not sure if this is correct + // Should investigate more + inner_query.insert_key(vec![]); + } } + inner_query } @@ -1434,11 +1450,11 @@ impl<'a> DriveDocumentQuery<'a> { platform_version, ) .ok() - .flatten() - .unwrap_or_default(); + .flatten(); // We should always include if we have left_over - let non_conditional_included = !left_over.is_empty() | *included; + let non_conditional_included = + !left_over.is_empty() | *included | start_at_key.is_none(); let mut non_conditional_query = Self::inner_query_starts_from_key( start_at_key, @@ -1849,6 +1865,7 @@ impl<'a> DriveDocumentQuery<'a> { drive_operations, platform_version, )?; + println!("path_query {}", path_query); let query_result = drive.grove_get_path_query_serialized_results( &path_query, transaction, @@ -1976,6 +1993,8 @@ mod tests { use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; use dpp::prelude::Identifier; + use grovedb::Query; + use indexmap::IndexMap; use rand::prelude::StdRng; use rand::SeedableRng; use serde_json::json; @@ -1998,6 +2017,7 @@ mod tests { use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; use dpp::block::block_info::BlockInfo; use dpp::data_contract::accessors::v0::DataContractV0Getters; + use dpp::document::DocumentV0; use dpp::platform_value::string_encoding::Encoding; use dpp::platform_value::Value; use dpp::tests::fixtures::{get_data_contract_fixture, get_dpns_data_contract_fixture}; @@ -2037,6 +2057,38 @@ mod tests { (drive, contract) } + fn setup_withdrawal_contract() -> (Drive, DataContract) { + let tmp_dir = TempDir::new().unwrap(); + + let (drive, _) = Drive::open(tmp_dir, None).expect("expected to open Drive successfully"); + + let platform_version = PlatformVersion::latest(); + + drive + .create_initial_state_structure(None, platform_version) + .expect("expected to create root tree successfully"); + + let contract_path = "tests/supporting_files/contract/withdrawals/withdrawals.json"; + + // let's construct the grovedb structure for the dashpay data contract + let contract = json_document_to_contract(contract_path, false, platform_version) + .expect("expected to get document"); + + let storage_flags = Some(Cow::Owned(StorageFlags::SingleEpoch(0))); + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + storage_flags, + None, + platform_version, + ) + .expect("expected to apply contract successfully"); + + (drive, contract) + } + fn setup_family_birthday_contract() -> (Drive, DataContract) { let drive = setup_drive_with_initial_state_structure(None); @@ -2667,4 +2719,103 @@ mod tests { ) .expect_err("starts with can not start with an empty string"); } + + #[test] + fn test_withdrawal_query_with_missing_transaction_index() { + // Setup the withdrawal contract + let (_, contract) = setup_withdrawal_contract(); + let platform_version = PlatformVersion::latest(); + + let document_type_name = "withdrawal"; + let document_type = contract + .document_type_for_name(document_type_name) + .expect("expected to get document type"); + + // Create a DriveDocumentQuery that simulates missing 'transactionIndex' in documents + let drive_document_query = DriveDocumentQuery { + contract: &contract, + document_type, + internal_clauses: InternalClauses { + primary_key_in_clause: None, + primary_key_equal_clause: None, + in_clause: Some(WhereClause { + field: "status".to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![ + Value::U64(0), + Value::U64(1), + Value::U64(2), + Value::U64(3), + Value::U64(4), + ]), + }), + range_clause: None, + equal_clauses: BTreeMap::default(), + }, + offset: None, + limit: Some(3), + order_by: IndexMap::from([ + ( + "status".to_string(), + OrderClause { + field: "status".to_string(), + ascending: true, + }, + ), + ( + "transactionIndex".to_string(), + OrderClause { + field: "transactionIndex".to_string(), + ascending: true, + }, + ), + ]), + start_at: Some([3u8; 32]), + start_at_included: false, + block_time_ms: None, + }; + + println!("{:?}", &drive_document_query); + + // Create a document that we are starting at, which may be missing 'transactionIndex' + let mut properties = BTreeMap::new(); + properties.insert("status".to_string(), Value::U64(0)); + // We intentionally omit 'transactionIndex' to simulate missing field + + let starts_at_document = DocumentV0 { + id: Identifier::from([3u8; 32]), // The same as start_at + owner_id: Identifier::random(), + properties, + revision: None, + created_at: None, + updated_at: None, + transferred_at: None, + created_at_block_height: None, + updated_at_block_height: None, + transferred_at_block_height: None, + created_at_core_block_height: None, + updated_at_core_block_height: None, + transferred_at_core_block_height: None, + } + .into(); + + // Attempt to construct the path query + let result = drive_document_query + .construct_path_query(Some(starts_at_document), platform_version) + .expect("expected to construct a path query"); + + println!("Generated PathQuery: {}", result); + + assert_eq!( + result + .clone() + .query + .query + .default_subquery_branch + .subquery + .expect("expected subquery") + .items, + Query::new_range_full().items + ); + } } diff --git a/packages/rs-drive/src/verify/document/verify_proof_keep_serialized/v0/mod.rs b/packages/rs-drive/src/verify/document/verify_proof_keep_serialized/v0/mod.rs index dc362c7ead..a0a714cbb8 100644 --- a/packages/rs-drive/src/verify/document/verify_proof_keep_serialized/v0/mod.rs +++ b/packages/rs-drive/src/verify/document/verify_proof_keep_serialized/v0/mod.rs @@ -39,6 +39,7 @@ impl<'a> DriveDocumentQuery<'a> { } else { self.construct_path_query(None, platform_version) }?; + println!("{}", &path_query); let (root_hash, proved_key_values) = if self.start_at.is_some() { GroveDb::verify_subset_query(proof, &path_query, &platform_version.drive.grove_version)? } else { diff --git a/packages/rs-drive/tests/query_tests.rs b/packages/rs-drive/tests/query_tests.rs index 5c792aa873..312d078f62 100644 --- a/packages/rs-drive/tests/query_tests.rs +++ b/packages/rs-drive/tests/query_tests.rs @@ -4342,6 +4342,8 @@ fn test_dpns_query_start_after_with_null_id() { let domain1_id = Identifier::random_with_rng(&mut rng); + assert!(domain0_id > domain1_id); + let domain1 = Domain { id: domain1_id, owner_id: Identifier::random_with_rng(&mut rng), @@ -4428,7 +4430,7 @@ fn test_dpns_query_start_after_with_null_id() { ["normalizedParentDomainName", "==", "dash"] ], "startAfter": encoded_start_at, - "limit": 2, + "limit": 3, "orderBy": [ ["normalizedLabel", "asc"] ] @@ -4446,6 +4448,8 @@ fn test_dpns_query_start_after_with_null_id() { ) .expect("query should be built"); + println!("{:?}", query); + // We are commenting this out on purpose to make it easier to find // let mut query_operations: Vec = vec![]; // let path_query = query diff --git a/packages/rs-drive/tests/supporting_files/contract/withdrawals/withdrawals.json b/packages/rs-drive/tests/supporting_files/contract/withdrawals/withdrawals.json new file mode 100644 index 0000000000..fbadb59824 --- /dev/null +++ b/packages/rs-drive/tests/supporting_files/contract/withdrawals/withdrawals.json @@ -0,0 +1,141 @@ +{ + "$format_version": "0", + "id": "BnqN3oupH6uCogzgZMvSjjpKxmcdNXAShnNY4Kor33aL", + "ownerId": "BnqN3oupH6uCogzgZMvSjjpKxmcdNXAShnNY4Kor33aL", + "version": 1, + "documentSchemas": { + "withdrawal": { + "description": "Withdrawal document to track underlying withdrawal transactions. Withdrawals should be created with IdentityWithdrawalTransition", + "creationRestrictionMode": 2, + "type": "object", + "indices": [ + { + "name": "identityStatus", + "properties": [ + { + "$ownerId": "asc" + }, + { + "status": "asc" + }, + { + "$createdAt": "asc" + } + ], + "unique": false + }, + { + "name": "identityRecent", + "properties": [ + { + "$ownerId": "asc" + }, + { + "$updatedAt": "asc" + }, + { + "status": "asc" + } + ], + "unique": false + }, + { + "name": "pooling", + "properties": [ + { + "status": "asc" + }, + { + "pooling": "asc" + }, + { + "coreFeePerByte": "asc" + }, + { + "$updatedAt": "asc" + } + ], + "unique": false + }, + { + "name": "transaction", + "properties": [ + { + "status": "asc" + }, + { + "transactionIndex": "asc" + } + ], + "unique": false + } + ], + "properties": { + "transactionIndex": { + "type": "integer", + "description": "Sequential index of asset unlock (withdrawal) transaction. Populated when a withdrawal pooled into withdrawal transaction", + "minimum": 1, + "position": 0 + }, + "transactionSignHeight": { + "type": "integer", + "description": "The Core height on which transaction was signed", + "minimum": 1, + "position": 1 + }, + "amount": { + "type": "integer", + "description": "The amount to be withdrawn", + "minimum": 1000, + "position": 2 + }, + "coreFeePerByte": { + "type": "integer", + "description": "This is the fee that you are willing to spend for this transaction in Duffs/Byte", + "minimum": 1, + "maximum": 4294967295, + "position": 3 + }, + "pooling": { + "type": "integer", + "description": "This indicated the level at which Platform should try to pool this transaction", + "enum": [ + 0, + 1, + 2 + ], + "position": 4 + }, + "outputScript": { + "type": "array", + "byteArray": true, + "minItems": 23, + "maxItems": 25, + "position": 5 + }, + "status": { + "type": "integer", + "enum": [ + 0, + 1, + 2, + 3, + 4 + ], + "description": "0 - Pending, 1 - Signed, 2 - Broadcasted, 3 - Complete, 4 - Expired", + "position": 6 + } + }, + "additionalProperties": false, + "required": [ + "$createdAt", + "$updatedAt", + "amount", + "coreFeePerByte", + "pooling", + "outputScript", + "status" + ] + } + } +} From bb18327dfb681abdd0939571d68fdc2ff7789d38 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Wed, 30 Oct 2024 23:30:52 +0700 Subject: [PATCH 09/29] updated rust dash core --- Cargo.lock | 25 ++++++++++--------------- packages/rs-dpp/Cargo.toml | 2 +- packages/rs-drive-abci/Cargo.toml | 2 +- packages/rs-sdk/Cargo.toml | 2 +- packages/simple-signer/Cargo.toml | 2 +- 5 files changed, 14 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4d8d9133d1..d0658845cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1231,14 +1231,14 @@ dependencies = [ [[package]] name = "dashcore" -version = "0.33.1" -source = "git+https://github.com/dashpay/rust-dashcore?tag=0.33.1#eb700aeff1610188414d0250254d0a6daaa4db46" +version = "0.33.2" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.33.2#078ae448e65647df3b5d77e4376ed5c83ba957de" dependencies = [ "anyhow", "bech32", "bitflags 2.6.0", "blsful", - "dashcore-private 0.1.0 (git+https://github.com/dashpay/rust-dashcore?tag=0.33.1)", + "dashcore-private", "dashcore_hashes", "ed25519-dalek", "hex", @@ -1254,19 +1254,14 @@ dependencies = [ [[package]] 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" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.33.2#078ae448e65647df3b5d77e4376ed5c83ba957de" [[package]] name = "dashcore-rpc" version = "0.15.9" -source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.9#dcfa6b34da596c52093ed6a1f26f15bcf2196c0d" +source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.10#7cd04868dbcb255366a0ea391537433de5d35bc8" dependencies = [ - "dashcore-private 0.1.0 (git+https://github.com/dashpay/rust-dashcore?tag=0.32.0)", + "dashcore-private", "dashcore-rpc-json", "env_logger 0.10.2", "hex", @@ -1278,8 +1273,8 @@ dependencies = [ [[package]] name = "dashcore-rpc-json" -version = "0.15.9" -source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.9#dcfa6b34da596c52093ed6a1f26f15bcf2196c0d" +version = "0.15.10" +source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.10#7cd04868dbcb255366a0ea391537433de5d35bc8" dependencies = [ "bincode", "dashcore", @@ -1293,9 +1288,9 @@ dependencies = [ [[package]] name = "dashcore_hashes" version = "0.14.0" -source = "git+https://github.com/dashpay/rust-dashcore?tag=0.33.1#eb700aeff1610188414d0250254d0a6daaa4db46" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.33.2#078ae448e65647df3b5d77e4376ed5c83ba957de" dependencies = [ - "dashcore-private 0.1.0 (git+https://github.com/dashpay/rust-dashcore?tag=0.33.1)", + "dashcore-private", "secp256k1", "serde", ] diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index 57d27c9600..6e03eb6c41 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -28,7 +28,7 @@ dashcore = { git = "https://github.com/dashpay/rust-dashcore", features = [ "rand", "signer", "serde" -], default-features = false, tag = "0.33.1" } +], default-features = false, tag = "0.33.2" } env_logger = { version = "0.11" } getrandom = { version = "0.2", features = ["js"] } hex = { version = "0.4" } diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 3a92a46df7..d28330fcf1 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.9" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.10" } dpp = { path = "../rs-dpp", features = ["abci"] } simple-signer = { path = "../simple-signer" } rust_decimal = "1.2.5" diff --git a/packages/rs-sdk/Cargo.toml b/packages/rs-sdk/Cargo.toml index c634047b4d..931aa5f62f 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.9" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.10" } 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/simple-signer/Cargo.toml b/packages/simple-signer/Cargo.toml index a1c06f26ba..1581055d97 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.9" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.10" } dpp = { path = "../rs-dpp", features = ["abci"] } base64 = { version = "0.22.1" } From ae8257c92d013c10ca650baac12dad21af5a9af3 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Fri, 1 Nov 2024 14:47:13 +0100 Subject: [PATCH 10/29] more fixes --- Cargo.lock | 16 ++++++++-------- packages/rs-dpp/Cargo.toml | 2 +- packages/rs-drive-abci/Cargo.toml | 2 +- packages/rs-sdk/Cargo.toml | 2 +- packages/simple-signer/Cargo.toml | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0658845cb..8d73f89922 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1231,8 +1231,8 @@ dependencies = [ [[package]] name = "dashcore" -version = "0.33.2" -source = "git+https://github.com/dashpay/rust-dashcore?tag=0.33.2#078ae448e65647df3b5d77e4376ed5c83ba957de" +version = "0.33.3" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.33.3#d224400d34b5b0ab9089c26698c5ee39645867ff" dependencies = [ "anyhow", "bech32", @@ -1254,12 +1254,12 @@ dependencies = [ [[package]] name = "dashcore-private" version = "0.1.0" -source = "git+https://github.com/dashpay/rust-dashcore?tag=0.33.2#078ae448e65647df3b5d77e4376ed5c83ba957de" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.33.3#d224400d34b5b0ab9089c26698c5ee39645867ff" [[package]] name = "dashcore-rpc" -version = "0.15.9" -source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.10#7cd04868dbcb255366a0ea391537433de5d35bc8" +version = "0.15.12" +source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.12#677d6e50e13ced4095ff35248ef22edecf3b9962" dependencies = [ "dashcore-private", "dashcore-rpc-json", @@ -1273,8 +1273,8 @@ dependencies = [ [[package]] name = "dashcore-rpc-json" -version = "0.15.10" -source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.10#7cd04868dbcb255366a0ea391537433de5d35bc8" +version = "0.15.12" +source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.12#677d6e50e13ced4095ff35248ef22edecf3b9962" dependencies = [ "bincode", "dashcore", @@ -1288,7 +1288,7 @@ dependencies = [ [[package]] name = "dashcore_hashes" version = "0.14.0" -source = "git+https://github.com/dashpay/rust-dashcore?tag=0.33.2#078ae448e65647df3b5d77e4376ed5c83ba957de" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.33.3#d224400d34b5b0ab9089c26698c5ee39645867ff" dependencies = [ "dashcore-private", "secp256k1", diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index 6e03eb6c41..376ab5dcc6 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -28,7 +28,7 @@ dashcore = { git = "https://github.com/dashpay/rust-dashcore", features = [ "rand", "signer", "serde" -], default-features = false, tag = "0.33.2" } +], default-features = false, tag = "0.33.3" } env_logger = { version = "0.11" } getrandom = { version = "0.2", features = ["js"] } hex = { version = "0.4" } diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index d28330fcf1..400d3d6a8a 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.10" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.12" } dpp = { path = "../rs-dpp", features = ["abci"] } simple-signer = { path = "../simple-signer" } rust_decimal = "1.2.5" diff --git a/packages/rs-sdk/Cargo.toml b/packages/rs-sdk/Cargo.toml index 931aa5f62f..52a733a530 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.10" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.12" } 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/simple-signer/Cargo.toml b/packages/simple-signer/Cargo.toml index 1581055d97..f740616e83 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.10" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.12" } dpp = { path = "../rs-dpp", features = ["abci"] } base64 = { version = "0.22.1" } From 272f5acf35f90ea6bea68bb58456244fda62b9b4 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Fri, 8 Nov 2024 10:21:47 +0100 Subject: [PATCH 11/29] more fixes --- .../identity_public_key/methods/hash/mod.rs | 8 +++++++- .../methods/hash/v0/mod.rs | 5 ++++- .../identity_public_key/v0/methods/mod.rs | 20 ++++++++++++++++++- packages/rs-drive/src/query/mod.rs | 6 +++--- packages/rs-sdk/src/core/transaction.rs | 12 +++++------ packages/rs-sdk/src/lib.rs | 2 +- 6 files changed, 40 insertions(+), 13 deletions(-) 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 5cc4828dd7..a7b4803e2d 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 @@ -2,7 +2,7 @@ mod v0; use crate::identity::IdentityPublicKey; use crate::ProtocolError; -use dashcore::Network; +use dashcore::{Address, Network}; pub use v0::*; impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKey { @@ -12,6 +12,12 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKey { } } + fn address(&self, network: Network) -> Result { + match self { + IdentityPublicKey::V0(v0) => v0.address(network), + } + } + fn validate_private_key_bytes( &self, private_key_bytes: &[u8; 32], 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 dd2b975e88..504d5187e7 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 @@ -1,10 +1,13 @@ use crate::ProtocolError; -use dashcore::Network; +use dashcore::{Address, Network}; pub trait IdentityPublicKeyHashMethodsV0 { /// Get the original public key hash fn public_key_hash(&self) -> Result<[u8; 20], ProtocolError>; + /// Get the address + fn address(&self, network: Network) -> Result; + /// Verifies that the private key bytes match this identity public key fn validate_private_key_bytes( &self, 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 52357e89a2..b015fabbc1 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,11 +4,12 @@ use crate::identity::KeyType; use crate::util::hash::ripemd160_sha256; use crate::{bls_signatures, ProtocolError}; use anyhow::anyhow; +use dashcore::address::Payload; use dashcore::blsful::Bls12381G2Impl; use dashcore::hashes::Hash; use dashcore::key::Secp256k1; use dashcore::secp256k1::SecretKey; -use dashcore::{ed25519_dalek, Network, PublicKey as ECDSAPublicKey}; +use dashcore::{ed25519_dalek, Address, Network, PubkeyHash, PublicKey as ECDSAPublicKey}; use platform_value::Bytes20; impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { @@ -49,6 +50,23 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { } } + fn address(&self, network: Network) -> Result { + match self.key_type { + KeyType::BIP13_SCRIPT_HASH => { + return Err(ProtocolError::NotSupported( + "Can not get an address from a single script hash key".to_string(), + )) + } + _ => { + let public_key_hash = self.public_key_hash()?; + Ok(Address::new( + network, + Payload::PubkeyHash(PubkeyHash::from_byte_array(public_key_hash)), + )) + } + } + } + fn validate_private_key_bytes( &self, private_key_bytes: &[u8; 32], diff --git a/packages/rs-drive/src/query/mod.rs b/packages/rs-drive/src/query/mod.rs index a2495dc938..0bb841649f 100644 --- a/packages/rs-drive/src/query/mod.rs +++ b/packages/rs-drive/src/query/mod.rs @@ -2070,7 +2070,7 @@ mod tests { drive .create_initial_state_structure(None, platform_version) .expect("expected to create root tree successfully"); - + // let's construct the grovedb structure for the dashpay data contract let contract = load_system_data_contract(SystemDataContract::Withdrawals, platform_version) .expect("load system contact"); @@ -2775,7 +2775,7 @@ mod tests { start_at_included: false, block_time_ms: None, }; - + // Create a document that we are starting at, which may be missing 'transactionIndex' let mut properties = BTreeMap::new(); properties.insert("status".to_string(), Value::U64(0)); @@ -2802,7 +2802,7 @@ mod tests { let result = drive_document_query .construct_path_query(Some(starts_at_document), platform_version) .expect("expected to construct a path query"); - + assert_eq!( result .clone() diff --git a/packages/rs-sdk/src/core/transaction.rs b/packages/rs-sdk/src/core/transaction.rs index 47bba9c4b5..0ce9202c20 100644 --- a/packages/rs-sdk/src/core/transaction.rs +++ b/packages/rs-sdk/src/core/transaction.rs @@ -74,7 +74,7 @@ impl Sdk { // transaction_id = transaction_id.to_string(), // ) // .entered(); - // + // // tracing::debug!("waiting for messages from stream"); // Define an inner async block to handle the stream processing. @@ -126,7 +126,7 @@ impl Sdk { // ); return Ok(asset_lock_proof); - } + } // else { // tracing::debug!( // "instant lock is not matching, waiting for the next message" @@ -238,10 +238,10 @@ impl Sdk { // tracing::trace!("received transaction(s), ignoring") } None => { - // tracing::trace!( - // "received empty response as a workaround for the bug in tonic, ignoring" - // ) - }, + // tracing::trace!( + // "received empty response as a workaround for the bug in tonic, ignoring" + // ) + } } } }; diff --git a/packages/rs-sdk/src/lib.rs b/packages/rs-sdk/src/lib.rs index d6e29c9825..23bdedc2fb 100644 --- a/packages/rs-sdk/src/lib.rs +++ b/packages/rs-sdk/src/lib.rs @@ -71,12 +71,12 @@ 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; pub use drive_proof_verifier::types as query_types; pub use rs_dapi_client as dapi_client; -pub use dapi_grpc; pub mod sync; /// Version of the SDK From ddf1c8bb9407f5367a82d14d81f8903bca8c5c47 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Tue, 12 Nov 2024 00:56:14 +0100 Subject: [PATCH 12/29] retry calls to core in sdk --- packages/rs-sdk/src/core/dash_core_client.rs | 120 ++++++++++++++----- 1 file changed, 90 insertions(+), 30 deletions(-) diff --git a/packages/rs-sdk/src/core/dash_core_client.rs b/packages/rs-sdk/src/core/dash_core_client.rs index d59af4207c..11c1749cff 100644 --- a/packages/rs-sdk/src/core/dash_core_client.rs +++ b/packages/rs-sdk/src/core/dash_core_client.rs @@ -13,6 +13,7 @@ use dashcore_rpc::{ use dpp::dashcore::ProTxHash; use dpp::prelude::CoreBlockHeight; use drive_proof_verifier::error::ContextProviderError; +use std::time::Duration; use std::{fmt::Debug, sync::Mutex}; use zeroize::Zeroizing; @@ -27,6 +28,69 @@ pub struct LowLevelDashCoreClient { core_port: u16, } +/// Client still warming up +pub const CORE_RPC_ERROR_IN_WARMUP: i32 = -28; +/// Dash is not connected +pub const CORE_RPC_CLIENT_NOT_CONNECTED: i32 = -9; +/// Still downloading initial blocks +pub const CORE_RPC_CLIENT_IN_INITIAL_DOWNLOAD: i32 = -10; + +macro_rules! retry { + ($action:expr) => {{ + /// Maximum number of retry attempts + const MAX_RETRIES: u32 = 4; + /// // Multiplier for Fibonacci sequence + const FIB_MULTIPLIER: u64 = 1; + + const BASE_TIME_MS: u64 = 40; + + fn fibonacci(n: u32) -> u64 { + match n { + 0 => 0, + 1 => 1, + _ => fibonacci(n - 1) + fibonacci(n - 2), + } + } + + let mut final_result = None; + for i in 0..MAX_RETRIES { + match $action { + Ok(result) => { + final_result = Some(Ok(result)); + break; + } + Err(e) => { + match e { + dashcore_rpc::Error::JsonRpc( + // Retry on transport connection error + dashcore_rpc::jsonrpc::error::Error::Transport(_) + | dashcore_rpc::jsonrpc::error::Error::Rpc( + // Retry on Core RPC "not ready" errors + dashcore_rpc::jsonrpc::error::RpcError { + code: + CORE_RPC_ERROR_IN_WARMUP + | CORE_RPC_CLIENT_NOT_CONNECTED + | CORE_RPC_CLIENT_IN_INITIAL_DOWNLOAD, + .. + }, + ), + ) => { + if i == MAX_RETRIES - 1 { + final_result = + Some(Err(ContextProviderError::Generic(e.to_string()))); + } + let delay = fibonacci(i + 2) * FIB_MULTIPLIER; + std::thread::sleep(Duration::from_millis(delay * BASE_TIME_MS)); + } + _ => return Err(ContextProviderError::Generic(e.to_string())), + }; + } + } + } + final_result.expect("expected a final result") + }}; +} + impl Clone for LowLevelDashCoreClient { // As Client does not implement Clone, we just create a new instance of CoreClient here. fn clone(&self) -> Self { @@ -98,28 +162,23 @@ impl LowLevelDashCoreClient { pub fn list_unspent( &self, minimum_sum_satoshi: Option, - ) -> Result, Error> { + ) -> Result, ContextProviderError> { let options = json::ListUnspentQueryOptions { minimum_sum_amount: minimum_sum_satoshi.map(Amount::from_sat), ..Default::default() }; - self.core - .lock() - .expect("Core lock poisoned") - .list_unspent(None, None, None, None, Some(options)) - .map_err(Error::CoreClientError) + let core = self.core.lock().expect("Core lock poisoned"); + + retry!(core.list_unspent(None, None, None, None, Some(options.clone()))) } /// Return address to which change of transaction can be sent. #[allow(dead_code)] #[deprecated(note = "This function is marked as unused.")] - pub fn get_balance(&self) -> Result { - self.core - .lock() - .expect("Core lock poisoned") - .get_balance(None, None) - .map_err(Error::CoreClientError) + pub fn get_balance(&self) -> Result { + let core = self.core.lock().expect("Core lock poisoned"); + retry!(core.get_balance(None, None)) } /// Retrieve quorum public key from core. @@ -132,15 +191,19 @@ impl LowLevelDashCoreClient { .map_err(|e| ContextProviderError::InvalidQuorum(e.to_string()))?; let core = self.core.lock().expect("Core lock poisoned"); - let quorum_info = core - .get_quorum_info(json::QuorumType::from(quorum_type), &quorum_hash, None) - .map_err(|e: dashcore_rpc::Error| ContextProviderError::Generic(e.to_string()))?; + + // Retrieve the quorum info + let quorum_info: json::QuorumInfoResult = + retry!(core.get_quorum_info(json::QuorumType::from(quorum_type), &quorum_hash, None))?; + + // Extract the quorum public key and attempt to convert it let key = quorum_info.quorum_public_key; - let pubkey = as TryInto<[u8; 48]>>::try_into(key).map_err(|_e| { + let pubkey = as TryInto<[u8; 48]>>::try_into(key).map_err(|_| { ContextProviderError::InvalidQuorum( "quorum public key is not 48 bytes long".to_string(), ) })?; + Ok(pubkey) } @@ -148,13 +211,11 @@ impl LowLevelDashCoreClient { pub fn get_platform_activation_height(&self) -> Result { let core = self.core.lock().expect("Core lock poisoned"); - let fork_info = core - .get_blockchain_info() - .map(|blockchain_info| blockchain_info.softforks.get("mn_rr").cloned()) - .map_err(|e: dashcore_rpc::Error| ContextProviderError::Generic(e.to_string()))? - .ok_or(ContextProviderError::ActivationForkError( - "no fork info for mn_rr".to_string(), - ))?; + let blockchain_info = retry!(core.get_blockchain_info())?; + + let fork_info = blockchain_info.softforks.get("mn_rr").ok_or( + ContextProviderError::ActivationForkError("no fork info for mn_rr".to_string()), + )?; fork_info .height @@ -171,15 +232,14 @@ impl LowLevelDashCoreClient { &self, height: Option, protx_type: Option, - ) -> Result, Error> { + ) -> Result, ContextProviderError> { let core = self.core.lock().expect("Core lock poisoned"); - let pro_tx_hashes = - core.get_protx_list(protx_type, Some(false), height) - .map(|x| match x { - ProTxList::Hex(hex) => hex, - ProTxList::Info(info) => info.into_iter().map(|v| v.pro_tx_hash).collect(), - })?; + let pro_tx_list = retry!(core.get_protx_list(protx_type.clone(), Some(false), height))?; + let pro_tx_hashes = match pro_tx_list { + ProTxList::Hex(hex) => hex, + ProTxList::Info(info) => info.into_iter().map(|v| v.pro_tx_hash).collect(), + }; Ok(pro_tx_hashes) } From 0c1ce6d4cc35fa53bb5f81972aa7a9357dddab55 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sat, 19 Oct 2024 11:17:08 +0700 Subject: [PATCH 13/29] replace bls library --- Cargo.lock | 368 +++++++++++++++++- packages/rs-dpp/Cargo.toml | 7 +- .../rs-dpp/src/core_types/validator/mod.rs | 5 +- .../rs-dpp/src/core_types/validator/v0/mod.rs | 28 +- .../src/core_types/validator_set/mod.rs | 5 +- .../src/core_types/validator_set/v0/mod.rs | 43 +- .../identity/identity_public_key/key_type.rs | 24 +- .../identity_public_key/methods/hash/mod.rs | 2 +- .../methods/hash/v0/mod.rs | 2 +- .../identity/identity_public_key/random.rs | 32 +- .../identity_public_key/v0/methods/mod.rs | 79 ++-- .../identity/identity_public_key/v0/random.rs | 16 +- packages/rs-dpp/src/identity/random.rs | 8 +- packages/rs-dpp/src/identity/v0/random.rs | 10 +- packages/rs-dpp/src/lib.rs | 2 +- packages/rs-drive-abci/Cargo.toml | 4 +- .../update_operator_identity/v0/mod.rs | 38 +- .../update_quorum_info/v0/mod.rs | 2 +- .../core_chain_lock/choose_quorum/mod.rs | 6 +- .../core_chain_lock/choose_quorum/v0/mod.rs | 25 +- .../verify_chain_lock_locally/v0/mod.rs | 25 +- .../verify_recent_signature_locally/v0/mod.rs | 36 +- .../v0/mod.rs | 4 +- packages/rs-drive-abci/src/mimic/mod.rs | 8 +- .../rs-drive-abci/src/mimic/test_quorum.rs | 38 +- .../src/platform_types/commit/mod.rs | 3 +- .../src/platform_types/commit/v0/mod.rs | 26 +- .../platform_types/platform_state/v0/mod.rs | 6 +- .../platform_state/v0/old_structures/mod.rs | 103 +++++ .../signature_verification_quorum_set/mod.rs | 8 +- .../v0/for_saving.rs | 14 +- .../v0/for_saving_v1.rs | 93 +++++ .../v0/mod.rs | 1 + .../v0/quorums.rs | 33 +- .../src/platform_types/validator/v0/mod.rs | 6 +- .../platform_types/validator_set/v0/mod.rs | 28 +- .../system/current_quorums_info/v0/mod.rs | 6 +- .../tests/strategy_tests/execution.rs | 29 +- .../tests/strategy_tests/main.rs | 2 +- .../masternode_list_item_helpers.rs | 26 +- .../tests/strategy_tests/masternodes.rs | 26 +- .../tests/strategy_tests/query.rs | 20 +- .../rs-drive-proof-verifier/src/unproved.rs | 4 +- .../rs-drive-proof-verifier/src/verify.rs | 27 +- packages/simple-signer/src/signer.rs | 25 +- 45 files changed, 1009 insertions(+), 294 deletions(-) create mode 100644 packages/rs-drive-abci/src/platform_types/platform_state/v0/old_structures/mod.rs create mode 100644 packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/for_saving_v1.rs diff --git a/Cargo.lock b/Cargo.lock index c59d07d2b4..50a561805e 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", ] @@ -1370,6 +1455,7 @@ dependencies = [ "async-trait", "base64 0.22.1", "bincode", + "blsful", "bs58", "byteorder", "chrono", @@ -1461,6 +1547,7 @@ dependencies = [ "async-trait", "base64 0.22.1", "bincode", + "bls-signatures", "bs58", "chrono", "ciborium 0.2.0", @@ -1578,6 +1665,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 +1860,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 +2067,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 +2117,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 +2306,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 +2353,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 +2417,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 +2666,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 +2828,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 +2976,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 +3135,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 +3225,8 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", + "rand", + "serde", ] [[package]] @@ -3021,6 +3242,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", + "rand", + "serde", ] [[package]] @@ -3069,6 +3292,7 @@ dependencies = [ "num-bigint", "num-integer", "num-traits", + "serde", ] [[package]] @@ -3203,6 +3427,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 +3910,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 +4304,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 +4387,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 +4529,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 +4561,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 +4662,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 +4685,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 +4993,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 +5023,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 +5432,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 +5567,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..68aa734639 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -22,14 +22,13 @@ chrono = { version = "0.4.35", default-features = false, features = [ "clock", ] } ciborium = { git = "https://github.com/qrayven/ciborium", branch = "feat-ser-null-as-undefined", optional = true } +blsful = { version = "3.0.0-pre6" , optional = true } dashcore = { git = "https://github.com/dashpay/rust-dashcore", features = [ "std", "secp-recovery", "rand", "signer", - "serde", - "bls", - "eddsa" + "serde" ], default-features = false, tag = "0.32.0" } env_logger = { version = "0.11" } getrandom = { version = "0.2", features = ["js"] } @@ -75,7 +74,7 @@ once_cell = "1.7" [features] default = ["platform-value", "state-transitions"] -bls-signatures = ["dashcore/bls"] +bls-signatures = ["dashcore/bls", "blsful"] ed25519-dalek = ["dashcore/eddsa"] all_features = [ "json-object", diff --git a/packages/rs-dpp/src/core_types/validator/mod.rs b/packages/rs-dpp/src/core_types/validator/mod.rs index 2261bac56f..d5f985a3c1 100644 --- a/packages/rs-dpp/src/core_types/validator/mod.rs +++ b/packages/rs-dpp/src/core_types/validator/mod.rs @@ -1,5 +1,6 @@ use crate::bls_signatures::PublicKey as BlsPublicKey; use crate::core_types::validator::v0::{ValidatorV0, ValidatorV0Getters, ValidatorV0Setters}; +use blsful::Bls12381G2Impl; use dashcore::{ProTxHash, PubkeyHash}; #[cfg(feature = "core-types-serde-conversion")] use serde::{Deserialize, Serialize}; @@ -25,7 +26,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 +76,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..81f73a66af 100644 --- a/packages/rs-dpp/src/core_types/validator/v0/mod.rs +++ b/packages/rs-dpp/src/core_types/validator/v0/mod.rs @@ -2,6 +2,7 @@ use dashcore::{ProTxHash, PubkeyHash}; use std::fmt::{Debug, Formatter}; use crate::bls_signatures::PublicKey as BlsPublicKey; +use blsful::Bls12381G2Impl; #[cfg(feature = "core-types-serde-conversion")] use serde::{Deserialize, Serialize}; @@ -26,7 +27,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 +55,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 +95,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 +154,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 +174,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 +194,7 @@ impl ValidatorV0Getters for ValidatorV0 { &self.pro_tx_hash } - fn public_key(&self) -> &Option { + fn public_key(&self) -> &Option> { &self.public_key } @@ -224,7 +228,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 +261,16 @@ impl ValidatorV0Setters for ValidatorV0 { mod tests { use super::*; use bincode::config; + use 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..de5b515f9f 100644 --- a/packages/rs-dpp/src/core_types/validator_set/mod.rs +++ b/packages/rs-dpp/src/core_types/validator_set/mod.rs @@ -7,6 +7,7 @@ use crate::core_types::validator_set::v0::{ use crate::ProtocolError; #[cfg(feature = "core-types-serialization")] use bincode::{Decode, Encode}; +use blsful::Bls12381G2Impl; use dashcore::{ProTxHash, QuorumHash}; #[cfg(feature = "core-types-serialization")] use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; @@ -80,7 +81,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 +113,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..cf05bb3d14 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 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,12 @@ 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(|_| { + bincode::error::DecodeError::OtherString( + "Failed to decode BlsPublicKey".to_string(), + ) + })?; Ok(ValidatorSetV0 { quorum_hash: QuorumHash::from_byte_array(quorum_hash), @@ -162,11 +166,12 @@ 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(|_| { + bincode::error::DecodeError::OtherString( + "Failed to decode BlsPublicKey in borrow decode".to_string(), + ) + })?; Ok(ValidatorSetV0 { quorum_hash: QuorumHash::from_byte_array(quorum_hash), @@ -211,7 +216,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 +230,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 +258,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 +280,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 +289,10 @@ impl ValidatorSetV0Setters for ValidatorSetV0 { mod tests { use super::*; use bincode::config; + use blsful::SecretKey; use dashcore::PubkeyHash; + use rand::rngs::StdRng; + use rand::SeedableRng; use std::collections::BTreeMap; #[test] @@ -296,7 +304,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 +324,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/identity/identity_public_key/key_type.rs b/packages/rs-dpp/src/identity/identity_public_key/key_type.rs index e40437a33e..a1ead4a725 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 @@ -15,6 +15,7 @@ use lazy_static::lazy_static; use crate::fee::Credits; use crate::version::PlatformVersion; use crate::{InvalidVectorSizeError, ProtocolError}; +use blsful::Bls12381G2Impl; #[cfg(feature = "random-public-keys")] use rand::rngs::StdRng; #[cfg(feature = "random-public-keys")] @@ -270,7 +271,7 @@ impl KeyType { #[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 +280,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 = 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 +295,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); ( 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 +313,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 +325,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..4b64fe9f16 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,10 +4,11 @@ use crate::identity::KeyType; use crate::util::hash::ripemd160_sha256; use crate::ProtocolError; use anyhow::anyhow; +use blsful::Bls12381G2Impl; use dashcore::hashes::Hash; use dashcore::key::Secp256k1; use dashcore::secp256k1::SecretKey; -use dashcore::{bls_signatures, ed25519_dalek, Network, PublicKey as ECDSAPublicKey}; +use dashcore::{ed25519_dalek, Network, PublicKey as ECDSAPublicKey}; use platform_value::Bytes20; impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { @@ -50,13 +51,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 +68,15 @@ 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> = + blsful::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 +85,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 +100,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(), @@ -129,11 +124,51 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { mod tests { use super::*; use crate::identity::{Purpose, SecurityLevel}; + use 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 = + blsful::SecretKey::::from_be_bytes(&secret_key.try_into().unwrap()) + .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 = + blsful::SecretKey::::from_be_bytes(&secret_key.try_into().unwrap()) + .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() { @@ -166,7 +201,7 @@ mod tests { ); // Test with an invalid private key - let invalid_private_key_bytes = vec![0u8; private_key_data.len()]; + let invalid_private_key_bytes = [0u8; 32]; assert_eq!( identity_public_key .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) @@ -207,7 +242,7 @@ mod tests { ); // Test with an invalid private key - let invalid_private_key_bytes = vec![0u8; private_key_data.len()]; + let invalid_private_key_bytes = [0u8; 32]; assert_eq!( identity_public_key .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) @@ -248,7 +283,7 @@ mod tests { ); // Test with an invalid private key - let invalid_private_key_bytes = vec![0u8; private_key_data.len()]; + let invalid_private_key_bytes = [0u8; 32]; assert_eq!( identity_public_key .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) 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..9744e16455 100644 --- a/packages/rs-dpp/src/lib.rs +++ b/packages/rs-dpp/src/lib.rs @@ -90,7 +90,7 @@ pub mod prelude { pub use bincode; #[cfg(all(not(target_arch = "wasm32"), feature = "bls-signatures"))] -pub use dashcore::bls_signatures; +pub use blsful as bls_signatures; #[cfg(feature = "ed25519-dalek")] pub use dashcore::ed25519_dalek; #[cfg(feature = "system_contracts")] diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index b1762b8706..b39852843b 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -73,8 +73,10 @@ 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", optional = true } [dev-dependencies] +bls-signatures = { git = "https://github.com/dashpay/bls-signatures", tag = "1.3.3" } bs58 = { version = "0.5.0" } base64 = "0.22.1" platform-version = { path = "../rs-platform-version", features = [ @@ -104,7 +106,7 @@ integer-encoding = { version = "4.0.0" } [features] default = ["mocks"] -mocks = ["mockall", "drive/fixtures-and-mocks"] +mocks = ["mockall", "drive/fixtures-and-mocks", "bls-signatures"] console = ["console-subscriber", "tokio/tracing"] testing-config = [] grovedbg = ["drive/grovedbg"] 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..1b3e5ef3dd 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().unwrap(), + ) + .unwrap(); + 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().unwrap(), + ) + .unwrap(); + 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().unwrap(), + ) + .unwrap(); + 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..85bc67ddd4 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, Signature}; use dpp::dashcore::hashes::{sha256d, Hash, HashEngine}; use dpp::dashcore::{ChainLock, QuorumSigningRequestId}; @@ -37,7 +37,10 @@ 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 { + + let Ok(signature) = + Signature::::try_from(chain_lock.signature.as_bytes().as_slice()) + else { return Ok(Some(false)); }; @@ -119,9 +122,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 +168,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, 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..a55f84ecf1 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, Signature}; use std::fmt::{Debug, Formatter}; use dpp::dashcore::hashes::{sha256d, Hash, HashEngine}; @@ -20,19 +20,20 @@ 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) => { - tracing::trace!( - instant_lock = ?InstantLockDebug(instant_lock), - "Invalid instant Lock {} signature format: {}", - instant_lock.txid, - e, - ); + let signature = + match Signature::::try_from(instant_lock.signature.as_bytes().as_slice()) { + Ok(signature) => signature, + Err(e) => { + tracing::trace!( + instant_lock = ?InstantLockDebug(instant_lock), + "Invalid instant Lock {} signature format: {}", + instant_lock.txid, + e, + ); - return Ok(false); - } - }; + return Ok(false); + } + }; let signing_height = platform_state.last_committed_core_height(); let verification_height = signing_height.saturating_sub(SIGN_OFFSET); @@ -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..25c57f441c 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..66ab8d427b 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}; @@ -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..d64e1e7723 --- /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()) + .unwrap(), + } + } +} + +/// 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()).unwrap()), + 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..38c00188ec 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 0 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..1c6a07db91 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, }, ) @@ -159,7 +162,10 @@ impl Into> for Quorums { self.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..c7e9bbaf10 --- /dev/null +++ b/packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/for_saving_v1.rs @@ -0,0 +1,93 @@ +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, + }, + ) + })) + } +} + +#[allow(clippy::from_over_into)] +impl Into> for Quorums { + fn into(self) -> Vec { + self.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..bdd1ecc911 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().unwrap(), + ) + .unwrap(); + 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().unwrap(), + ) + .unwrap(); + 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..89a9697d44 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().unwrap(), + ) + .unwrap(); + 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().unwrap(), + ) + .unwrap(); + 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..969a969cbe 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, BlsResult}; 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,7 +106,9 @@ 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) { + let signature = match dpp::bls_signatures::Signature::::try_from( + self.signature.as_slice(), + ) { Ok(signature) => signature, Err(e) => { return SimpleValidationResult::new_with_error( @@ -123,14 +126,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/simple-signer/src/signer.rs b/packages/simple-signer/src/signer.rs index 448e1a5c9c..04a9b325d3 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!("unable to sign {}", 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"); From 46d96987557abb24883219968e0f758f5a1671e5 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Sat, 19 Oct 2024 16:51:14 +0700 Subject: [PATCH 14/29] more work --- Cargo.lock | 28 ++++++----- packages/rs-dpp/Cargo.toml | 5 +- packages/rs-dpp/src/bls/native_bls.rs | 46 +++++++++++------ .../rs-dpp/src/core_types/validator/mod.rs | 3 +- .../rs-dpp/src/core_types/validator/v0/mod.rs | 5 +- .../src/core_types/validator_set/mod.rs | 3 +- .../src/core_types/validator_set/v0/mod.rs | 4 +- packages/rs-dpp/src/errors/protocol_error.rs | 5 ++ .../identity/identity_public_key/key_type.rs | 50 ++++++++----------- .../identity_public_key/v0/methods/mod.rs | 28 ++++++----- packages/rs-dpp/src/lib.rs | 4 +- packages/rs-dpp/src/signing.rs | 45 ++++++++++------- packages/rs-drive-abci/Cargo.toml | 7 ++- .../platform_types/platform_state/v0/mod.rs | 2 +- packages/rs-sdk/Cargo.toml | 2 +- packages/simple-signer/Cargo.toml | 2 +- 16 files changed, 134 insertions(+), 105 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 50a561805e..390413e0af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1231,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", @@ -1256,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", @@ -1273,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", @@ -1288,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", ] @@ -1455,7 +1460,6 @@ dependencies = [ "async-trait", "base64 0.22.1", "bincode", - "blsful", "bs58", "byteorder", "chrono", diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index 68aa734639..b2886970ba 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -22,14 +22,13 @@ chrono = { version = "0.4.35", default-features = false, features = [ "clock", ] } ciborium = { git = "https://github.com/qrayven/ciborium", branch = "feat-ser-null-as-undefined", optional = true } -blsful = { version = "3.0.0-pre6" , optional = true } dashcore = { git = "https://github.com/dashpay/rust-dashcore", features = [ "std", "secp-recovery", "rand", "signer", "serde" -], 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" } @@ -74,7 +73,7 @@ once_cell = "1.7" [features] default = ["platform-value", "state-transitions"] -bls-signatures = ["dashcore/bls", "blsful"] +bls-signatures = ["dashcore/bls"] ed25519-dalek = ["dashcore/eddsa"] all_features = [ "json-object", diff --git a/packages/rs-dpp/src/bls/native_bls.rs b/packages/rs-dpp/src/bls/native_bls.rs index 5dc7e2bc82..e8e1fd939f 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}; #[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,13 +20,21 @@ 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).map_err(anyhow::Error::msg)?; + let signature_96_bytes = signature + .try_into() + .map_err(|_| anyhow!("signature wrong size"))?; + let g2_element = + ::Signature::from_compressed(&signature_96_bytes) + .into_option() + .ok_or(anyhow!("signature derivation failed"))?; + + let signature = Signature::Basic(g2_element); + + match signature.verify(&public_key, data) { + Ok(_) => Ok(true), + Err(_) => Err(anyhow!("Verification failed").into()), } } @@ -32,9 +42,11 @@ impl BlsModule for NativeBlsModule { 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 pk = SecretKey::::from_be_bytes(&fixed_len_key) + .into_option() + .ok_or(anyhow!("Incorrect Priv Key"))?; + let public_key = pk.public_key(); + let public_key_bytes = public_key.0.to_compressed().to_vec(); Ok(public_key_bytes) } @@ -42,7 +54,13 @@ impl BlsModule for NativeBlsModule { 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 pk = SecretKey::::from_be_bytes(&fixed_len_key) + .into_option() + .ok_or(anyhow!("Incorrect Priv Key"))?; + 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 d5f985a3c1..01716ab044 100644 --- a/packages/rs-dpp/src/core_types/validator/mod.rs +++ b/packages/rs-dpp/src/core_types/validator/mod.rs @@ -1,6 +1,5 @@ -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 blsful::Bls12381G2Impl; use dashcore::{ProTxHash, PubkeyHash}; #[cfg(feature = "core-types-serde-conversion")] use serde::{Deserialize, Serialize}; 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 81f73a66af..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,8 +1,7 @@ use dashcore::{ProTxHash, PubkeyHash}; use std::fmt::{Debug, Formatter}; -use crate::bls_signatures::PublicKey as BlsPublicKey; -use blsful::Bls12381G2Impl; +use crate::bls_signatures::{Bls12381G2Impl, PublicKey as BlsPublicKey}; #[cfg(feature = "core-types-serde-conversion")] use serde::{Deserialize, Serialize}; @@ -261,7 +260,7 @@ impl ValidatorV0Setters for ValidatorV0 { mod tests { use super::*; use bincode::config; - use blsful::SecretKey; + use dashcore::blsful::SecretKey; use rand::prelude::StdRng; use rand::SeedableRng; 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 de5b515f9f..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, @@ -7,7 +7,6 @@ use crate::core_types::validator_set::v0::{ use crate::ProtocolError; #[cfg(feature = "core-types-serialization")] use bincode::{Decode, Encode}; -use blsful::Bls12381G2Impl; use dashcore::{ProTxHash, QuorumHash}; #[cfg(feature = "core-types-serialization")] use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; 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 cf05bb3d14..d500fb0426 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,7 +8,7 @@ use bincode::enc::Encoder; use bincode::error::EncodeError; #[cfg(feature = "core-types-serialization")] use bincode::{BorrowDecode, Decode, Encode}; -use blsful::Bls12381G2Impl; +use dashcore::blsful::Bls12381G2Impl; use dashcore::hashes::Hash; use dashcore::{ProTxHash, QuorumHash}; use itertools::Itertools; @@ -289,7 +289,7 @@ impl ValidatorSetV0Setters for ValidatorSetV0 { mod tests { use super::*; use bincode::config; - use blsful::SecretKey; + use dashcore::blsful::SecretKey; use dashcore::PubkeyHash; use rand::rngs::StdRng; use rand::SeedableRng; diff --git a/packages/rs-dpp/src/errors/protocol_error.rs b/packages/rs-dpp/src/errors/protocol_error.rs index 2164b339f1..99e83ba64b 100644 --- a/packages/rs-dpp/src/errors/protocol_error.rs +++ b/packages/rs-dpp/src/errors/protocol_error.rs @@ -1,3 +1,4 @@ +use dashcore::blsful::BlsError; use thiserror::Error; use crate::consensus::basic::state_transition::InvalidStateTransitionTypeError; @@ -247,6 +248,10 @@ pub enum ProtocolError { /// Invalid CBOR error #[error("invalid cbor error: {0}")] InvalidCBOR(String), + + /// Invalid CBOR error + #[error(transparent)] + BlsError(#[from] BlsError), } 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 a1ead4a725..e91cc6c3c3 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,14 +8,14 @@ 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::{blsful, ed25519_dalek, Network}; use itertools::Itertools; use lazy_static::lazy_static; +use crate::bls_signatures::{Bls12381G2Impl, BlsError}; use crate::fee::Credits; use crate::version::PlatformVersion; -use crate::{InvalidVectorSizeError, ProtocolError}; -use blsful::Bls12381G2Impl; +use crate::{bls_signatures, ProtocolError}; #[cfg(feature = "random-public-keys")] use rand::rngs::StdRng; #[cfg(feature = "random-public-keys")] @@ -166,13 +166,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() @@ -205,13 +200,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); @@ -220,14 +215,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"))] @@ -237,7 +236,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); @@ -246,14 +245,7 @@ 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 = 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"))] 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 4b64fe9f16..52357e89a2 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 @@ -2,9 +2,9 @@ use crate::identity::identity_public_key::methods::hash::IdentityPublicKeyHashMe use crate::identity::identity_public_key::v0::IdentityPublicKeyV0; use crate::identity::KeyType; use crate::util::hash::ripemd160_sha256; -use crate::ProtocolError; +use crate::{bls_signatures, ProtocolError}; use anyhow::anyhow; -use blsful::Bls12381G2Impl; +use dashcore::blsful::Bls12381G2Impl; use dashcore::hashes::Hash; use dashcore::key::Secp256k1; use dashcore::secp256k1::SecretKey; @@ -68,9 +68,11 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { KeyType::BLS12_381 => { #[cfg(feature = "bls-signatures")] { - let private_key: Option> = - blsful::SecretKey::::from_be_bytes(private_key_bytes) - .into(); + let private_key: Option> = + bls_signatures::SecretKey::::from_be_bytes( + private_key_bytes, + ) + .into(); if private_key.is_none() { return Ok(false); } @@ -124,7 +126,7 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { mod tests { use super::*; use crate::identity::{Purpose, SecurityLevel}; - use blsful::{Bls12381G2Impl, Pairing, Signature, SignatureSchemes}; + use dashcore::blsful::{Bls12381G2Impl, Pairing, Signature, SignatureSchemes}; use dashcore::Network; use dpp::version::PlatformVersion; use rand::rngs::StdRng; @@ -136,9 +138,10 @@ mod tests { 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 = - blsful::SecretKey::::from_be_bytes(&secret_key.try_into().unwrap()) - .expect("expected to get secret key"); + let decoded_secret_key = dashcore::blsful::SecretKey::::from_be_bytes( + &secret_key.try_into().unwrap(), + ) + .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!( @@ -153,9 +156,10 @@ mod tests { 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 = - blsful::SecretKey::::from_be_bytes(&secret_key.try_into().unwrap()) - .expect("expected to get secret key"); + let decoded_secret_key = dashcore::blsful::SecretKey::::from_be_bytes( + &secret_key.try_into().unwrap(), + ) + .expect("expected to get secret key"); let signature = decoded_secret_key .sign(SignatureSchemes::Basic, b"hello") .expect("expected to sign"); diff --git a/packages/rs-dpp/src/lib.rs b/packages/rs-dpp/src/lib.rs index 9744e16455..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 blsful as 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..336d17e29f 100644 --- a/packages/rs-dpp/src/signing.rs +++ b/packages/rs-dpp/src/signing.rs @@ -1,3 +1,4 @@ +use crate::bls_signatures::{Bls12381G2Impl, Pairing}; #[cfg(feature = "message-signature-verification")] use crate::consensus::signature::{ BasicBLSError, BasicECDSAError, SignatureError, SignatureShouldNotBePresentError, @@ -8,7 +9,8 @@ use crate::serialization::PlatformMessageSignable; use crate::validation::SimpleConsensusValidationResult; #[cfg(feature = "message-signing")] use crate::{BlsModule, ProtocolError}; -use dashcore::{bls_signatures, signer}; +use dashcore::blsful::Signature; +use dashcore::{blsful as bls_signatures, signer}; impl PlatformMessageSignable for &[u8] { #[cfg(feature = "message-signature-verification")] @@ -38,25 +40,34 @@ 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.to_vec().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")); - return SimpleConsensusValidationResult::new_with_error( - SignatureError::BasicBLSError(BasicBLSError::new(e.to_string())).into(), - ); - } - }; - if !public_key.verify(&signature, signable_data) { + let g2 = ::Signature::from_compressed(&signature_bytes) + .expect("G2 projective"); + let signature = Signature::::Basic(g2); + + if !signature.verify(&public_key, signable_data).is_ok() { SimpleConsensusValidationResult::new_with_error( SignatureError::BasicBLSError(BasicBLSError::new( "bls signature was incorrect".to_string(), diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index b39852843b..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,10 +73,9 @@ 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", optional = true } +bls-signatures = { git = "https://github.com/dashpay/bls-signatures", tag = "1.3.3" } [dev-dependencies] -bls-signatures = { git = "https://github.com/dashpay/bls-signatures", tag = "1.3.3" } bs58 = { version = "0.5.0" } base64 = "0.22.1" platform-version = { path = "../rs-platform-version", features = [ @@ -106,7 +105,7 @@ integer-encoding = { version = "4.0.0" } [features] default = ["mocks"] -mocks = ["mockall", "drive/fixtures-and-mocks", "bls-signatures"] +mocks = ["mockall", "drive/fixtures-and-mocks"] console = ["console-subscriber", "tokio/tracing"] testing-config = [] grovedbg = ["drive/grovedbg"] 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 66ab8d427b..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 @@ -128,7 +128,7 @@ fn hex_encoded_validator_sets(validator_sets: &IndexMap, /// Information about the last block 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/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" } From 7d44dcb5e8fb5bdd13c4d05e8e8d9b8a05c868a9 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Mon, 21 Oct 2024 03:46:11 +0700 Subject: [PATCH 15/29] exposed dapi-grpc in sdk --- packages/rs-sdk/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/rs-sdk/src/lib.rs b/packages/rs-sdk/src/lib.rs index 1f928ab6db..d6e29c9825 100644 --- a/packages/rs-sdk/src/lib.rs +++ b/packages/rs-sdk/src/lib.rs @@ -76,6 +76,7 @@ pub use dpp; pub use drive; pub use drive_proof_verifier::types as query_types; pub use rs_dapi_client as dapi_client; +pub use dapi_grpc; pub mod sync; /// Version of the SDK From 2b93932f44732f1aafa9a29cedec0967bb06f3fd Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Wed, 13 Nov 2024 11:47:05 +0100 Subject: [PATCH 16/29] fix(sdk): broken import fails compilation --- packages/rs-sdk/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/rs-sdk/src/lib.rs b/packages/rs-sdk/src/lib.rs index b463ad8346..23bdedc2fb 100644 --- a/packages/rs-sdk/src/lib.rs +++ b/packages/rs-sdk/src/lib.rs @@ -77,7 +77,6 @@ pub use dpp; pub use drive; pub use drive_proof_verifier::types as query_types; pub use rs_dapi_client as dapi_client; -pub use dapi_grpc; pub mod sync; /// Version of the SDK From ab743551c0153babcde5e2d03d4c4b412216f87b Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 14 Nov 2024 10:52:20 +0100 Subject: [PATCH 17/29] chore(dpp): fix bls signatures --- .../rs-dpp/src/identity/identity_public_key/v0/methods/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 52357e89a2..fa06cd32b4 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 @@ -1,8 +1,10 @@ +#[cfg(feature = "bls-signatures")] +use crate::bls_signatures; use crate::identity::identity_public_key::methods::hash::IdentityPublicKeyHashMethodsV0; use crate::identity::identity_public_key::v0::IdentityPublicKeyV0; use crate::identity::KeyType; use crate::util::hash::ripemd160_sha256; -use crate::{bls_signatures, ProtocolError}; +use crate::ProtocolError; use anyhow::anyhow; use dashcore::blsful::Bls12381G2Impl; use dashcore::hashes::Hash; From e6bda11e29607e5e0600d7f25f341d0c82889460 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:02:23 +0100 Subject: [PATCH 18/29] chore(dpp): fix build errors and some lint warnings --- packages/rs-dpp/src/errors/protocol_error.rs | 6 +- .../identity/identity_public_key/key_type.rs | 20 ++-- .../identity_public_key/v0/methods/mod.rs | 96 ++++++++----------- .../methods/v0/mod.rs | 3 +- 4 files changed, 53 insertions(+), 72 deletions(-) diff --git a/packages/rs-dpp/src/errors/protocol_error.rs b/packages/rs-dpp/src/errors/protocol_error.rs index 99e83ba64b..0d4f6cae6a 100644 --- a/packages/rs-dpp/src/errors/protocol_error.rs +++ b/packages/rs-dpp/src/errors/protocol_error.rs @@ -1,4 +1,3 @@ -use dashcore::blsful::BlsError; use thiserror::Error; use crate::consensus::basic::state_transition::InvalidStateTransitionTypeError; @@ -249,9 +248,10 @@ pub enum ProtocolError { #[error("invalid cbor error: {0}")] InvalidCBOR(String), - /// Invalid CBOR error + /// BLS signature error + #[cfg(feature = "bls-signatures")] #[error(transparent)] - BlsError(#[from] BlsError), + BlsError(#[from] dashcore::blsful::BlsError), } 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 e91cc6c3c3..eabfb7e13d 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,14 +8,13 @@ use dashcore::secp256k1::rand::rngs::StdRng as EcdsaRng; #[cfg(feature = "random-public-keys")] use dashcore::secp256k1::rand::SeedableRng; use dashcore::secp256k1::Secp256k1; -use dashcore::{blsful, ed25519_dalek, Network}; +use dashcore::Network; use itertools::Itertools; use lazy_static::lazy_static; -use crate::bls_signatures::{Bls12381G2Impl, BlsError}; use crate::fee::Credits; use crate::version::PlatformVersion; -use crate::{bls_signatures, ProtocolError}; +use crate::ProtocolError; #[cfg(feature = "random-public-keys")] use rand::rngs::StdRng; #[cfg(feature = "random-public-keys")] @@ -23,6 +22,11 @@ use rand::Rng; use serde_repr::{Deserialize_repr, Serialize_repr}; use std::collections::HashMap; use std::convert::TryFrom; +#[cfg(feature = "bls-signatures")] +use { + crate::bls_signatures::{self as bls_signatures, Bls12381G2Impl, BlsError}, + dashcore::{blsful, ed25519_dalek}, +}; #[allow(non_camel_case_types)] #[repr(u8)] @@ -245,7 +249,7 @@ impl KeyType { KeyType::EDDSA_25519_HASH160 => { #[cfg(feature = "ed25519-dalek")] { - let key_pair = ed25519_dalek::SigningKey::from_bytes(&private_key_bytes); + let key_pair = 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"))] @@ -253,11 +257,9 @@ 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(), + )), } } 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 fa06cd32b4..df9e2ff87b 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 @@ -1,17 +1,19 @@ -#[cfg(feature = "bls-signatures")] -use crate::bls_signatures; use crate::identity::identity_public_key::methods::hash::IdentityPublicKeyHashMethodsV0; use crate::identity::identity_public_key::v0::IdentityPublicKeyV0; use crate::identity::KeyType; use crate::util::hash::ripemd160_sha256; use crate::ProtocolError; use anyhow::anyhow; -use dashcore::blsful::Bls12381G2Impl; use dashcore::hashes::Hash; use dashcore::key::Secp256k1; use dashcore::secp256k1::SecretKey; -use dashcore::{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, ed25519_dalek}, +}; impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { /// Get the original public key hash @@ -80,7 +82,7 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { } let private_key = private_key.expect("expected private key"); - Ok(&private_key.public_key().0.to_compressed() == 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( @@ -104,7 +106,7 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { KeyType::EDDSA_25519_HASH160 => { #[cfg(feature = "ed25519-dalek")] { - let key_pair = ed25519_dalek::SigningKey::from_bytes(&private_key_bytes); + 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(), @@ -115,11 +117,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(), + )), } } } @@ -140,10 +140,9 @@ mod tests { 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.try_into().unwrap(), - ) - .expect("expected to get secret key"); + 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!( @@ -158,10 +157,9 @@ mod tests { 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.try_into().unwrap(), - ) - .expect("expected to get secret key"); + 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"); @@ -184,7 +182,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 { @@ -199,21 +197,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 = [0u8; 32]; - assert_eq!( - identity_public_key - .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) - .unwrap(), - false - ); + assert!(!identity_public_key + .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) + .unwrap()); } #[cfg(all(feature = "random-public-keys", feature = "bls-signatures"))] @@ -225,7 +217,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 { @@ -240,21 +232,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 = [0u8; 32]; - assert_eq!( - identity_public_key - .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) - .unwrap(), - false - ); + assert!(!identity_public_key + .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) + .unwrap()); } #[cfg(all(feature = "random-public-keys", feature = "ed25519-dalek"))] @@ -266,7 +252,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 { @@ -281,20 +267,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 = [0u8; 32]; - assert_eq!( - identity_public_key - .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) - .unwrap(), - false - ); + assert!(!identity_public_key + .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) + .unwrap()); } } 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, From 5859848af148262aa7abb918a085641c21ddf447 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:21:42 +0100 Subject: [PATCH 19/29] chore(sdk): fmt --- packages/rs-sdk/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rs-sdk/src/lib.rs b/packages/rs-sdk/src/lib.rs index d6e29c9825..23bdedc2fb 100644 --- a/packages/rs-sdk/src/lib.rs +++ b/packages/rs-sdk/src/lib.rs @@ -71,12 +71,12 @@ 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; pub use drive_proof_verifier::types as query_types; pub use rs_dapi_client as dapi_client; -pub use dapi_grpc; pub mod sync; /// Version of the SDK From b86245e4be16c2bfc14ad181b7b67f6de987edf8 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:31:58 +0100 Subject: [PATCH 20/29] chore(dpp): fix feature build issues --- packages/rs-dpp/Cargo.toml | 2 +- .../src/identity/identity_public_key/key_type.rs | 14 ++++++-------- .../identity/identity_public_key/v0/methods/mod.rs | 8 +++----- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index b2886970ba..8386ba22ba 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -27,7 +27,7 @@ dashcore = { git = "https://github.com/dashpay/rust-dashcore", features = [ "secp-recovery", "rand", "signer", - "serde" + "serde", ], default-features = false, tag = "0.33.1" } env_logger = { version = "0.11" } getrandom = { version = "0.2", features = ["js"] } 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 eabfb7e13d..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 @@ -12,6 +12,8 @@ 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::ProtocolError; @@ -22,11 +24,6 @@ use rand::Rng; use serde_repr::{Deserialize_repr, Serialize_repr}; use std::collections::HashMap; use std::convert::TryFrom; -#[cfg(feature = "bls-signatures")] -use { - crate::bls_signatures::{self as bls_signatures, Bls12381G2Impl, BlsError}, - dashcore::{blsful, ed25519_dalek}, -}; #[allow(non_camel_case_types)] #[repr(u8)] @@ -249,7 +246,8 @@ impl KeyType { KeyType::EDDSA_25519_HASH160 => { #[cfg(feature = "ed25519-dalek")] { - let key_pair = ed25519_dalek::SigningKey::from_bytes(private_key_bytes); + 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"))] @@ -278,7 +276,7 @@ impl KeyType { ) } KeyType::BLS12_381 => { - let private_key = blsful::SecretKey::::random(rng); + 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()) } @@ -293,7 +291,7 @@ impl KeyType { ) } 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(), 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 df9e2ff87b..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,17 +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::{Network, PublicKey as ECDSAPublicKey}; use platform_value::Bytes20; #[cfg(feature = "bls-signatures")] -use { - crate::bls_signatures, - dashcore::{blsful::Bls12381G2Impl, ed25519_dalek}, -}; - +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> { From ae22fb82cd1a7b357c25e3a6ba8a9dfc895d6d57 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 14 Nov 2024 13:01:38 +0100 Subject: [PATCH 21/29] build: experimental: use build base image --- Dockerfile | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/Dockerfile b/Dockerfile index d03f82d895..acf2599a17 100644 --- a/Dockerfile +++ b/Dockerfile @@ -254,35 +254,39 @@ WORKDIR /platform # Download and install cargo-binstall ENV BINSTALL_VERSION=1.10.11 -RUN set -ex; \ - if [ "$TARGETARCH" = "amd64" ]; then \ - CARGO_BINSTALL_ARCH="x86_64-unknown-linux-musl"; \ - elif [ "$TARGETARCH" = "arm64" ]; then \ - CARGO_BINSTALL_ARCH="aarch64-unknown-linux-musl"; \ - else \ - echo "Unsupported architecture: $TARGETARCH"; exit 1; \ - fi; \ - # Construct download URL - DOWNLOAD_URL="https://github.com/cargo-bins/cargo-binstall/releases/download/v${BINSTALL_VERSION}/cargo-binstall-${CARGO_BINSTALL_ARCH}.tgz"; \ - # Download and extract the cargo-binstall binary - curl -A "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/81.0" -L --proto '=https' --tlsv1.2 -sSf "$DOWNLOAD_URL" | tar -xvzf -; \ - ./cargo-binstall -y --force cargo-binstall; \ - rm ./cargo-binstall; \ - source $HOME/.cargo/env; \ - cargo binstall -V - -RUN source $HOME/.cargo/env; \ - cargo binstall wasm-bindgen-cli@0.2.86 cargo-chef@0.1.67 \ +RUN < Date: Thu, 14 Nov 2024 13:09:16 +0100 Subject: [PATCH 22/29] chore(dpp): fix features --- packages/rs-dpp/src/signing.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/rs-dpp/src/signing.rs b/packages/rs-dpp/src/signing.rs index 336d17e29f..1986cb16ea 100644 --- a/packages/rs-dpp/src/signing.rs +++ b/packages/rs-dpp/src/signing.rs @@ -1,16 +1,20 @@ -use crate::bls_signatures::{Bls12381G2Impl, Pairing}; -#[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::blsful::Signature; -use dashcore::{blsful as 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")] @@ -67,7 +71,7 @@ impl PlatformMessageSignable for &[u8] { .expect("G2 projective"); let signature = Signature::::Basic(g2); - if !signature.verify(&public_key, signable_data).is_ok() { + if signature.verify(&public_key, signable_data).is_err() { SimpleConsensusValidationResult::new_with_error( SignatureError::BasicBLSError(BasicBLSError::new( "bls signature was incorrect".to_string(), From 98c021504ad7928746a8ebf2d1bc15b4d1aa4127 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 14 Nov 2024 13:45:29 +0100 Subject: [PATCH 23/29] Revert "build: experimental: use build base image" This reverts commit ae22fb82cd1a7b357c25e3a6ba8a9dfc895d6d57. --- Dockerfile | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/Dockerfile b/Dockerfile index acf2599a17..d03f82d895 100644 --- a/Dockerfile +++ b/Dockerfile @@ -254,39 +254,35 @@ WORKDIR /platform # Download and install cargo-binstall ENV BINSTALL_VERSION=1.10.11 -RUN < Date: Fri, 15 Nov 2024 17:23:23 +0100 Subject: [PATCH 24/29] fix(drive-abci): invalid chainlock sig deserialization --- .../engine/run_block_proposal/v0/mod.rs | 2 +- .../verify_chain_lock_locally/v0/mod.rs | 54 +++++++++++++++++-- 2 files changed, 50 insertions(+), 6 deletions(-) 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_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 85bc67ddd4..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::{Bls12381G2Impl, Signature}; +use dpp::bls_signatures::{Bls12381G2Impl, Pairing, Signature}; use dpp::dashcore::hashes::{sha256d, Hash, HashEngine}; use dpp::dashcore::{ChainLock, QuorumSigningRequestId}; @@ -38,12 +38,29 @@ where // First verify that the signature conforms to a signature - let Ok(signature) = - Signature::::try_from(chain_lock.signature.as_bytes().as_slice()) - 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; @@ -219,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; @@ -288,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(), + ); + } + } } From f7458579adfa6b415e74c5bea8dcef1d268b00dc Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 18 Nov 2024 09:51:39 +0100 Subject: [PATCH 25/29] fix(drive-abci): invalid signature decoding --- ...nstant_asset_lock_proof_signature_error.rs | 2 +- .../verify_recent_signature_locally/v0/mod.rs | 28 +++++++++--------- .../src/platform_types/commit/v0/mod.rs | 4 +-- .../tests/strategy_tests/query.rs | 29 ++++++++++--------- 4 files changed, 32 insertions(+), 31 deletions(-) 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-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 a55f84ecf1..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::{Bls12381G2Impl, Signature}; +use dpp::bls_signatures::{Bls12381G2Impl, Pairing, Signature}; use std::fmt::{Debug, Formatter}; use dpp::dashcore::hashes::{sha256d, Hash, HashEngine}; @@ -20,20 +20,20 @@ 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 Signature::::try_from(instant_lock.signature.as_bytes().as_slice()) { - Ok(signature) => signature, - Err(e) => { - tracing::trace!( - instant_lock = ?InstantLockDebug(instant_lock), - "Invalid instant Lock {} signature format: {}", - instant_lock.txid, - e, - ); - return Ok(false); - } - }; + 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, ); + + return Ok(false); + } + }; let signing_height = platform_state.last_committed_core_height(); let verification_height = signing_height.saturating_sub(SIGN_OFFSET); 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 25c57f441c..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 @@ -91,7 +91,7 @@ impl CommitV0 { } // We could have received a fake commit, so signature validation needs to be returned if error as a simple validation result - let g2_element = match ::Signature::from_compressed(&signature) + let g2_element = match ::Signature::from_compressed(signature) .into_option() .ok_or(AbciError::BlsErrorOfTenderdashThresholdMechanism( BlsError::InvalidSignature, @@ -124,7 +124,7 @@ impl CommitV0 { Err(e) => return ValidationResult::new_with_error(e), }; - match signature.verify(&public_key, &hash) { + match signature.verify(public_key, &hash) { Ok(_) => ValidationResult::default(), Err(_) => ValidationResult::new_with_error(AbciError::BadCommitSignature(format!( "commit signature {} is wrong", diff --git a/packages/rs-drive-abci/tests/strategy_tests/query.rs b/packages/rs-drive-abci/tests/strategy_tests/query.rs index 969a969cbe..56f166ab74 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/query.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/query.rs @@ -5,7 +5,7 @@ use dapi_grpc::platform::v0::{ GetIdentityByPublicKeyHashRequest, Proof, }; use dashcore_rpc::dashcore_rpc_json::QuorumType; -use dpp::bls_signatures::{Bls12381G2Impl, BlsResult}; +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; @@ -106,19 +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::::try_from( - self.signature.as_slice(), - ) { - 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, From 9f9c12346b34992dc903c0ab797a1f61d17a7e06 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Wed, 20 Nov 2024 21:55:28 +0100 Subject: [PATCH 26/29] fixes for coderabbit --- packages/rs-dpp/src/bls/native_bls.rs | 48 ++++++++++++------- .../src/core_types/validator_set/v0/mod.rs | 18 +++---- packages/rs-dpp/src/errors/protocol_error.rs | 10 ++++ packages/rs-dpp/src/signing.rs | 16 +++++-- .../update_operator_identity/v0/mod.rs | 12 ++--- .../platform_state/v0/old_structures/mod.rs | 4 +- .../signature_verification_quorum_set/mod.rs | 2 +- .../v0/for_saving.rs | 8 ++-- .../v0/for_saving_v1.rs | 9 ++-- .../masternode_list_item_helpers.rs | 8 ++-- .../tests/strategy_tests/masternodes.rs | 8 ++-- packages/simple-signer/src/signer.rs | 2 +- 12 files changed, 90 insertions(+), 55 deletions(-) diff --git a/packages/rs-dpp/src/bls/native_bls.rs b/packages/rs-dpp/src/bls/native_bls.rs index e8e1fd939f..492f563511 100644 --- a/packages/rs-dpp/src/bls/native_bls.rs +++ b/packages/rs-dpp/src/bls/native_bls.rs @@ -2,7 +2,7 @@ use crate::bls_signatures::{ Bls12381G2Impl, Pairing, PublicKey, SecretKey, Signature, SignatureSchemes, }; use crate::{BlsModule, ProtocolError, PublicKeyValidationError}; -use anyhow::anyhow; +use std::array::TryFromSliceError; #[derive(Default)] pub struct NativeBlsModule; @@ -20,43 +20,57 @@ impl BlsModule for NativeBlsModule { data: &[u8], public_key: &[u8], ) -> Result { - let public_key = - PublicKey::::try_from(public_key).map_err(anyhow::Error::msg)?; - let signature_96_bytes = signature - .try_into() - .map_err(|_| anyhow!("signature wrong size"))?; - let g2_element = + 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() - .ok_or(anyhow!("signature derivation failed"))?; + 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(_) => Err(anyhow!("Verification failed").into()), + 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 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(anyhow!("Incorrect Priv Key"))?; + .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 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(anyhow!("Incorrect Priv Key"))?; + .ok_or(ProtocolError::InvalidBLSPrivateKeyError( + "key not valid".to_string(), + ))?; Ok(pk .sign(SignatureSchemes::Basic, data)? .as_raw_value() 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 d500fb0426..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 @@ -120,10 +120,11 @@ impl Decode for ValidatorSetV0 { let bytes = <[u8; 48]>::decode(decoder)?; public_key_bytes.copy_from_slice(&bytes); let threshold_public_key = - BlsPublicKey::try_from(public_key_bytes.as_slice()).map_err(|_| { - bincode::error::DecodeError::OtherString( - "Failed to decode BlsPublicKey".to_string(), - ) + BlsPublicKey::try_from(public_key_bytes.as_slice()).map_err(|e| { + bincode::error::DecodeError::OtherString(format!( + "Failed to decode BlsPublicKey: {}", + e + )) })?; Ok(ValidatorSetV0 { @@ -167,10 +168,11 @@ impl<'de> BorrowDecode<'de> for ValidatorSetV0 { let bytes = <[u8; 48]>::decode(decoder)?; public_key_bytes.copy_from_slice(&bytes); let threshold_public_key = - BlsPublicKey::try_from(public_key_bytes.as_slice()).map_err(|_| { - bincode::error::DecodeError::OtherString( - "Failed to decode BlsPublicKey in borrow decode".to_string(), - ) + 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 { diff --git a/packages/rs-dpp/src/errors/protocol_error.rs b/packages/rs-dpp/src/errors/protocol_error.rs index 0d4f6cae6a..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; @@ -252,6 +253,15 @@ pub enum ProtocolError { #[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/signing.rs b/packages/rs-dpp/src/signing.rs index 1986cb16ea..d637c0480b 100644 --- a/packages/rs-dpp/src/signing.rs +++ b/packages/rs-dpp/src/signing.rs @@ -55,7 +55,7 @@ impl PlatformMessageSignable for &[u8] { ); } }; - let signature_bytes: [u8; 96] = match signature.to_vec().try_into() { + let signature_bytes: [u8; 96] = match signature.try_into() { Ok(bytes) => bytes, Err(_) => { return SimpleConsensusValidationResult::new_with_error( @@ -67,8 +67,18 @@ impl PlatformMessageSignable for &[u8] { ) } }; - let g2 = ::Signature::from_compressed(&signature_bytes) - .expect("G2 projective"); + let g2 = match ::Signature::from_compressed( + &signature_bytes, + ) + .into_option() + { + Some(g2) => g2, + None => { + return SimpleConsensusValidationResult::new_with_error( + SignatureError::BasicBLSError(BasicBLSError::new("bls signature does not conform to proper bls signature serialization".to_string())).into(), + ); + } + }; let signature = Signature::::Basic(g2); if signature.verify(&public_key, signable_data).is_err() { 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 1b3e5ef3dd..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 @@ -438,9 +438,9 @@ mod tests { .to_bytes() .to_vec(); let private_key_operator = BlsPrivateKey::::from_be_bytes( - &private_key_operator_bytes.try_into().unwrap(), + &private_key_operator_bytes.try_into().expect("expected the secret key to be 32 bytes"), ) - .unwrap(); + .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 { @@ -957,9 +957,9 @@ mod tests { .to_bytes() .to_vec(); let private_key_operator = BlsPrivateKey::::from_be_bytes( - &private_key_operator_bytes.try_into().unwrap(), + &private_key_operator_bytes.try_into().expect("expected the secret key to be 32 bytes"), ) - .unwrap(); + .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 @@ -1049,9 +1049,9 @@ mod tests { .to_bytes() .to_vec(); let private_key_operator = BlsPrivateKey::::from_be_bytes( - &private_key_operator_bytes.try_into().unwrap(), + &private_key_operator_bytes.try_into().expect("expected the secret key to be 32 bytes"), ) - .unwrap(); + .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 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 index d64e1e7723..ebd0e85875 100644 --- 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 @@ -51,7 +51,7 @@ impl From for dpp::core_types::validator_set::v0::ValidatorSetV0 .map(|(pro_tx_hash, validator)| (pro_tx_hash, validator.into())) .collect(), threshold_public_key: PublicKey::try_from(threshold_public_key.to_bytes().as_slice()) - .unwrap(), + .expect("this should not be possible to error as the threshold_public_key was already verified on disk"), } } } @@ -91,7 +91,7 @@ impl From for dpp::core_types::validator::v0::ValidatorV0 { } = value; Self { pro_tx_hash, - public_key: public_key.map(|pk| PublicKey::try_from(pk.to_bytes().as_slice()).unwrap()), + 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, 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 38c00188ec..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 @@ -119,7 +119,7 @@ impl SignatureVerificationQuorumSetV0Methods for SignatureVerificationQuorumSet pub enum SignatureVerificationQuorumSetForSaving { /// Version 0 of the signature verification quorums V0(SignatureVerificationQuorumSetForSavingV0), - /// Version 0 of the signature verification quorums + /// Version 1 of the signature verification quorums V1(SignatureVerificationQuorumSetForSavingV1), } 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 1c6a07db91..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 @@ -156,10 +156,10 @@ 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: bls_signatures::PublicKey::from_bytes( 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 index c7e9bbaf10..bfb596e451 100644 --- 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 @@ -78,11 +78,10 @@ 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)| QuorumForSavingV1 { hash: Bytes32::from(hash.as_byte_array()), public_key: quorum.public_key, 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 bdd1ecc911..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 @@ -38,9 +38,9 @@ impl UpdateMasternodeListItem for MasternodeListItem { .to_bytes() .to_vec(); let private_key_operator = BlsPrivateKey::::from_be_bytes( - &private_key_operator_bytes.try_into().unwrap(), + &private_key_operator_bytes.try_into().expect("expected the secret key to be 32 bytes"), ) - .unwrap(); + .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; @@ -92,9 +92,9 @@ mod tests { .to_bytes() .to_vec(); let private_key_operator = BlsPrivateKey::::from_be_bytes( - &private_key_operator_bytes.try_into().unwrap(), + &private_key_operator_bytes.try_into().expect("expected the secret key to be 32 bytes"), ) - .unwrap(); + .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, diff --git a/packages/rs-drive-abci/tests/strategy_tests/masternodes.rs b/packages/rs-drive-abci/tests/strategy_tests/masternodes.rs index 89a9697d44..02a647b66c 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/masternodes.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/masternodes.rs @@ -214,9 +214,9 @@ pub fn generate_test_masternodes( .to_bytes() .to_vec(); let private_key_operator = BlsPrivateKey::::from_be_bytes( - &private_key_operator_bytes.try_into().unwrap(), + &private_key_operator_bytes.try_into().expect("expected the secret key to be 32 bytes"), ) - .unwrap(); + .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 { @@ -352,9 +352,9 @@ pub fn generate_test_masternodes( .to_bytes() .to_vec(); let private_key_operator = BlsPrivateKey::::from_be_bytes( - &private_key_operator_bytes.try_into().unwrap(), + &private_key_operator_bytes.try_into().expect("expected the secret key to be 32 bytes"), ) - .unwrap(); + .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, diff --git a/packages/simple-signer/src/signer.rs b/packages/simple-signer/src/signer.rs index 04a9b325d3..d93acb5aee 100644 --- a/packages/simple-signer/src/signer.rs +++ b/packages/simple-signer/src/signer.rs @@ -89,7 +89,7 @@ impl Signer for SimpleSigner { ))?; let signature = pk .sign(SignatureSchemes::Basic, data) - .map_err(|e| ProtocolError::Generic(format!("unable to sign {}", e)))?; + .map_err(|e| ProtocolError::Generic(format!("BLS signing failed {}", e)))?; Ok(signature.as_raw_value().to_compressed().to_vec().into()) } KeyType::EDDSA_25519_HASH160 => { From 6eeec1a14ed40d5aaeb48a42f4f5e10d5a489e96 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 6 Dec 2024 12:44:50 +0100 Subject: [PATCH 27/29] deps: bump dashcore and dashcore-rpc --- Cargo.lock | 131 ++++++++++++++++++------------ packages/rs-dpp/Cargo.toml | 4 +- packages/rs-drive-abci/Cargo.toml | 2 +- packages/rs-sdk/Cargo.toml | 4 +- packages/simple-signer/Cargo.toml | 2 +- 5 files changed, 86 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6a16559de8..d9899552c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -506,7 +506,7 @@ dependencies = [ "arrayvec", "cc", "cfg-if", - "constant_time_eq 0.3.0", + "constant_time_eq 0.3.1", ] [[package]] @@ -949,9 +949,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "constant_time_eq" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] name = "convert_case" @@ -1231,14 +1231,14 @@ dependencies = [ [[package]] name = "dashcore" -version = "0.33.1" -source = "git+https://github.com/dashpay/rust-dashcore?tag=0.33.1#eb700aeff1610188414d0250254d0a6daaa4db46" +version = "0.34.0" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.34.0#4c61ab617ca9f86f84484607014a7e8e0baba960" dependencies = [ "anyhow", "bech32", "bitflags 2.6.0", "blsful", - "dashcore-private 0.1.0 (git+https://github.com/dashpay/rust-dashcore?tag=0.33.1)", + "dashcore-private", "dashcore_hashes", "ed25519-dalek", "hex", @@ -1254,19 +1254,14 @@ dependencies = [ [[package]] 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" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.34.0#4c61ab617ca9f86f84484607014a7e8e0baba960" [[package]] name = "dashcore-rpc" -version = "0.15.9" -source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.9#dcfa6b34da596c52093ed6a1f26f15bcf2196c0d" +version = "0.15.13" +source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.13#88dfef0dc04cbe8f4b0d24e9aabfae8ca126c74a" dependencies = [ - "dashcore-private 0.1.0 (git+https://github.com/dashpay/rust-dashcore?tag=0.32.0)", + "dashcore-private", "dashcore-rpc-json", "env_logger 0.10.2", "hex", @@ -1278,8 +1273,8 @@ dependencies = [ [[package]] name = "dashcore-rpc-json" -version = "0.15.9" -source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.9#dcfa6b34da596c52093ed6a1f26f15bcf2196c0d" +version = "0.15.13" +source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.13#88dfef0dc04cbe8f4b0d24e9aabfae8ca126c74a" dependencies = [ "bincode", "dashcore", @@ -1293,9 +1288,9 @@ dependencies = [ [[package]] name = "dashcore_hashes" version = "0.14.0" -source = "git+https://github.com/dashpay/rust-dashcore?tag=0.33.1#eb700aeff1610188414d0250254d0a6daaa4db46" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.34.0#4c61ab617ca9f86f84484607014a7e8e0baba960" dependencies = [ - "dashcore-private 0.1.0 (git+https://github.com/dashpay/rust-dashcore?tag=0.33.1)", + "dashcore-private", "secp256k1", "serde", ] @@ -1472,7 +1467,7 @@ dependencies = [ "env_logger 0.11.5", "getrandom", "hex", - "indexmap 2.6.0", + "indexmap 2.7.0", "integer-encoding", "itertools 0.13.0", "json-schema-compatibility-validator", @@ -1525,7 +1520,7 @@ dependencies = [ "grovedb-storage", "grovedb-version", "hex", - "indexmap 2.6.0", + "indexmap 2.7.0", "integer-encoding", "intmap", "itertools 0.13.0", @@ -1569,7 +1564,7 @@ dependencies = [ "envy", "file-rotate", "hex", - "indexmap 2.6.0", + "indexmap 2.7.0", "integer-encoding", "itertools 0.13.0", "lazy_static", @@ -1608,7 +1603,7 @@ dependencies = [ "dpp", "drive", "hex", - "indexmap 2.6.0", + "indexmap 2.7.0", "platform-serialization", "platform-serialization-derive", "serde", @@ -1923,6 +1918,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "foreign-types" version = "0.3.2" @@ -2155,7 +2156,7 @@ dependencies = [ "grovedbg-types", "hex", "hex-literal", - "indexmap 2.6.0", + "indexmap 2.7.0", "integer-encoding", "intmap", "itertools 0.12.1", @@ -2212,7 +2213,7 @@ dependencies = [ "grovedb-version", "grovedb-visualize", "hex", - "indexmap 2.6.0", + "indexmap 2.7.0", "integer-encoding", "num_cpus", "rand", @@ -2288,7 +2289,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.6.0", + "indexmap 2.7.0", "slab", "tokio", "tokio-util", @@ -2331,7 +2332,7 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ @@ -2341,9 +2342,14 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] [[package]] name = "hdrhistogram" @@ -2656,12 +2662,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.2", "serde", ] @@ -2909,6 +2915,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "lock_api" version = "0.4.12" @@ -2933,11 +2945,11 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.14.5", + "hashbrown 0.15.2", ] [[package]] @@ -3013,7 +3025,7 @@ dependencies = [ "http-body-util", "hyper", "hyper-util", - "indexmap 2.6.0", + "indexmap 2.7.0", "ipnet", "metrics", "metrics-util", @@ -3517,7 +3529,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.6.0", + "indexmap 2.7.0", ] [[package]] @@ -3595,7 +3607,7 @@ dependencies = [ "bs58", "ciborium 0.2.0", "hex", - "indexmap 2.6.0", + "indexmap 2.7.0", "lazy_static", "platform-serialization", "platform-version", @@ -4203,9 +4215,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1" dependencies = [ "log", "once_cell", @@ -4241,15 +4253,15 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-webpki" -version = "0.102.6" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -4426,7 +4438,7 @@ version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3b863381a05ffefbc82571a2d893edf47b27fb0ebedbf582c39640e51abebef" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "itoa", "memchr", "ryu", @@ -4501,7 +4513,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_derive", "serde_json", @@ -5207,7 +5219,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "toml_datetime", "winnow 0.5.40", ] @@ -5218,7 +5230,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "toml_datetime", "winnow 0.5.40", ] @@ -5229,7 +5241,7 @@ version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", @@ -5291,7 +5303,7 @@ source = "git+https://github.com/QuantumExplorer/tower?branch=fix/indexMap2OnV04 dependencies = [ "futures-core", "futures-util", - "indexmap 2.6.0", + "indexmap 2.7.0", "pin-project", "pin-project-lite", "rand", @@ -6026,6 +6038,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "zerofrom", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -6047,6 +6070,12 @@ dependencies = [ "syn 2.0.75", ] +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" + [[package]] name = "zeroize" version = "1.8.1" @@ -6099,7 +6128,7 @@ dependencies = [ "crossbeam-utils", "displaydoc", "flate2", - "indexmap 2.6.0", + "indexmap 2.7.0", "memchr", "thiserror", "zopfli", diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index 1e9125db78..cac0277ec3 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -28,7 +28,7 @@ dashcore = { git = "https://github.com/dashpay/rust-dashcore", features = [ "rand", "signer", "serde", -], default-features = false, tag = "0.33.1" } +], default-features = false, tag = "0.34.0" } env_logger = { version = "0.11" } getrandom = { version = "0.2", features = ["js"] } hex = { version = "0.4" } @@ -58,7 +58,7 @@ derive_more = { version = "1.0", features = ["from", "display", "try_into"] } nohash-hasher = "0.2.0" rust_decimal = "1.29.1" rust_decimal_macros = "1.29.1" -indexmap = { version = "2.0.2", features = ["serde"] } +indexmap = { version = "2.7.0", features = ["serde"] } strum = { version = "0.26", features = ["derive"] } json-schema-compatibility-validator = { path = '../rs-json-schema-compatibility-validator' } once_cell = "1.19.0" diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 46b498b479..48f60e83ad 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.9" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.13" } dpp = { path = "../rs-dpp", features = ["abci"] } simple-signer = { path = "../simple-signer" } rust_decimal = "1.2.5" diff --git a/packages/rs-sdk/Cargo.toml b/packages/rs-sdk/Cargo.toml index 345a293000..61054444aa 100644 --- a/packages/rs-sdk/Cargo.toml +++ b/packages/rs-sdk/Cargo.toml @@ -35,8 +35,8 @@ 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.9" } -lru = { version = "0.12.3", optional = true } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.13" } +lru = { version = "0.12.5", 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/simple-signer/Cargo.toml b/packages/simple-signer/Cargo.toml index deec00cbe0..fea2aca5bb 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.9" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.13" } dpp = { path = "../rs-dpp", features = ["abci"] } base64 = { version = "0.22.1" } From 5c3f318683c9b4a022acd81a966a31eb67936395 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 6 Dec 2024 14:31:09 +0100 Subject: [PATCH 28/29] chore: uncomment logging --- packages/rs-sdk/src/core/transaction.rs | 91 ++++++++++++------------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/packages/rs-sdk/src/core/transaction.rs b/packages/rs-sdk/src/core/transaction.rs index ae0e09629d..f3d2df46c2 100644 --- a/packages/rs-sdk/src/core/transaction.rs +++ b/packages/rs-sdk/src/core/transaction.rs @@ -69,13 +69,13 @@ impl Sdk { ) -> Result { let transaction_id = transaction.txid(); - // let _span = tracing::debug_span!( - // "wait_for_asset_lock_proof_for_transaction", - // transaction_id = transaction_id.to_string(), - // ) - // .entered(); - // - // tracing::debug!("waiting for messages from stream"); + let _span = tracing::debug_span!( + "wait_for_asset_lock_proof_for_transaction", + transaction_id = transaction_id.to_string(), + ) + .entered(); + + tracing::debug!("waiting for messages from stream"); // Define an inner async block to handle the stream processing. let stream_processing = async { @@ -98,10 +98,10 @@ impl Sdk { instant_send_lock_messages, ), ) => { - // tracing::debug!( - // "received {} instant lock message(s)", - // instant_send_lock_messages.messages.len() - // ); + tracing::trace!( + "received {} instant lock message(s)", + instant_send_lock_messages.messages.len() + ); for instant_lock_bytes in instant_send_lock_messages.messages { let instant_lock = @@ -120,29 +120,28 @@ impl Sdk { output_index: 0, }); - // tracing::debug!( - // ?asset_lock_proof, - // "instant lock is matching to the broadcasted transaction, returning instant asset lock proof" - // ); + tracing::trace!( + ?asset_lock_proof, + "instant lock is matching to the broadcasted transaction, returning instant asset lock proof" + ); return Ok(asset_lock_proof); + } else { + tracing::debug!( + "instant lock is not matching, waiting for the next message" + ); } - // else { - // tracing::debug!( - // "instant lock is not matching, waiting for the next message" - // ); - // } } } Some(transactions_with_proofs_response::Responses::RawMerkleBlock( raw_merkle_block, )) => { - // tracing::debug!("received merkle block"); + tracing::trace!("received merkle block"); let merkle_block = MerkleBlock::consensus_decode(&mut raw_merkle_block.as_slice()) .map_err(|e| { - // tracing::error!("can't decode merkle block: {}", e); + tracing::error!("can't decode merkle block: {}", e); Error::CoreError(e.into()) })?; @@ -154,16 +153,16 @@ impl Sdk { // Continue receiving messages until we find the transaction if !matches.contains(&transaction_id) { - // tracing::debug!( - // "merkle block doesn't contain the transaction, waiting for the next message" - // ); + tracing::debug!( + "merkle block doesn't contain the transaction, waiting for the next message" + ); continue; } - // tracing::debug!( - // "merkle block contains the transaction, obtaining core chain locked height" - // ); + tracing::trace!( + "merkle block contains the transaction, obtaining core chain locked height" + ); // TODO: This a temporary implementation until we have headers stream running in background // so we can always get actual height and chain locks @@ -191,15 +190,15 @@ impl Sdk { break; } - // tracing::trace!("the transaction is on height {} but not chainlocked. try again in 1 sec", height); + tracing::trace!("the transaction is on height {} but not chainlocked. try again in 1 sec", height); sleep(Duration::from_secs(1)).await; } - // tracing::debug!( - // "the transaction is chainlocked on height {}, waiting platform for reaching the same core height", - // core_chain_locked_height - // ); + tracing::trace!( + "the transaction is chainlocked on height {}, waiting platform for reaching the same core height", + core_chain_locked_height + ); // Wait until platform chain is on the block's chain locked height loop { @@ -210,11 +209,11 @@ impl Sdk { break; } - // tracing::trace!( - // "platform chain locked core height {} but we need {}. try again in 1 sec", - // metadata.core_chain_locked_height, - // core_chain_locked_height, - // ); + tracing::trace!( + "platform chain locked core height {} but we need {}. try again in 1 sec", + metadata.core_chain_locked_height, + core_chain_locked_height, + ); sleep(Duration::from_secs(1)).await; } @@ -227,20 +226,20 @@ impl Sdk { }, }); - // tracing::debug!( - // ?asset_lock_proof, - // "merkle block contains the broadcasted transaction, returning chain asset lock proof" - // ); + tracing::trace!( + ?asset_lock_proof, + "merkle block contains the broadcasted transaction, returning chain asset lock proof" + ); return Ok(asset_lock_proof); } Some(transactions_with_proofs_response::Responses::RawTransactions(_)) => { - // tracing::trace!("received transaction(s), ignoring") + tracing::trace!("received transaction(s), ignoring") } None => { - // tracing::trace!( - // "received empty response as a workaround for the bug in tonic, ignoring" - // ) + tracing::trace!( + "received empty response as a workaround for the bug in tonic, ignoring" + ) } } } From c3a8f8037341a634e106fa9509c773ac223e2dd9 Mon Sep 17 00:00:00 2001 From: lklimek <842586+lklimek@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:22:24 +0100 Subject: [PATCH 29/29] refactor(sdk)!: separate dash core client error (#2380) --- packages/rs-dpp/src/bls/native_bls.rs | 1 - packages/rs-drive-proof-verifier/src/error.rs | 4 + packages/rs-sdk/src/core/dash_core_client.rs | 83 +++++++------------ packages/rs-sdk/src/core/error.rs | 56 +++++++++++++ packages/rs-sdk/src/core/mod.rs | 2 + packages/rs-sdk/src/error.rs | 17 +++- packages/rs-sdk/src/mock/provider.rs | 2 +- packages/rs-sdk/src/sync.rs | 1 - packages/rs-sdk/tests/fetch/config.rs | 2 +- packages/rs-sdk/tests/fetch/evonode.rs | 1 - 10 files changed, 111 insertions(+), 58 deletions(-) create mode 100644 packages/rs-sdk/src/core/error.rs diff --git a/packages/rs-dpp/src/bls/native_bls.rs b/packages/rs-dpp/src/bls/native_bls.rs index 492f563511..3e1341bf9a 100644 --- a/packages/rs-dpp/src/bls/native_bls.rs +++ b/packages/rs-dpp/src/bls/native_bls.rs @@ -2,7 +2,6 @@ use crate::bls_signatures::{ Bls12381G2Impl, Pairing, PublicKey, SecretKey, Signature, SignatureSchemes, }; use crate::{BlsModule, ProtocolError, PublicKeyValidationError}; -use std::array::TryFromSliceError; #[derive(Default)] pub struct NativeBlsModule; diff --git a/packages/rs-drive-proof-verifier/src/error.rs b/packages/rs-drive-proof-verifier/src/error.rs index 3fb5825a8c..3da25aacc7 100644 --- a/packages/rs-drive-proof-verifier/src/error.rs +++ b/packages/rs-drive-proof-verifier/src/error.rs @@ -119,6 +119,10 @@ pub enum ContextProviderError { /// Async error, eg. when tokio runtime fails #[error("async error: {0}")] AsyncError(String), + + /// Dash Core error + #[error("Dash Core error: {0}")] + DashCoreError(String), } impl From for Error { diff --git a/packages/rs-sdk/src/core/dash_core_client.rs b/packages/rs-sdk/src/core/dash_core_client.rs index 11c1749cff..73216f294a 100644 --- a/packages/rs-sdk/src/core/dash_core_client.rs +++ b/packages/rs-sdk/src/core/dash_core_client.rs @@ -12,11 +12,12 @@ use dashcore_rpc::{ }; use dpp::dashcore::ProTxHash; use dpp::prelude::CoreBlockHeight; -use drive_proof_verifier::error::ContextProviderError; use std::time::Duration; use std::{fmt::Debug, sync::Mutex}; use zeroize::Zeroizing; +use super::DashCoreError; + /// Core RPC client that can be used to retrieve quorum keys from core. /// /// TODO: This is a temporary implementation, effective until we integrate SPV. @@ -28,13 +29,6 @@ pub struct LowLevelDashCoreClient { core_port: u16, } -/// Client still warming up -pub const CORE_RPC_ERROR_IN_WARMUP: i32 = -28; -/// Dash is not connected -pub const CORE_RPC_CLIENT_NOT_CONNECTED: i32 = -9; -/// Still downloading initial blocks -pub const CORE_RPC_CLIENT_IN_INITIAL_DOWNLOAD: i32 = -10; - macro_rules! retry { ($action:expr) => {{ /// Maximum number of retry attempts @@ -60,30 +54,18 @@ macro_rules! retry { break; } Err(e) => { - match e { - dashcore_rpc::Error::JsonRpc( - // Retry on transport connection error - dashcore_rpc::jsonrpc::error::Error::Transport(_) - | dashcore_rpc::jsonrpc::error::Error::Rpc( - // Retry on Core RPC "not ready" errors - dashcore_rpc::jsonrpc::error::RpcError { - code: - CORE_RPC_ERROR_IN_WARMUP - | CORE_RPC_CLIENT_NOT_CONNECTED - | CORE_RPC_CLIENT_IN_INITIAL_DOWNLOAD, - .. - }, - ), - ) => { - if i == MAX_RETRIES - 1 { - final_result = - Some(Err(ContextProviderError::Generic(e.to_string()))); - } - let delay = fibonacci(i + 2) * FIB_MULTIPLIER; - std::thread::sleep(Duration::from_millis(delay * BASE_TIME_MS)); + use rs_dapi_client::CanRetry; + + let err: DashCoreError = e.into(); + if err.can_retry() { + if i == MAX_RETRIES - 1 { + final_result = Some(Err(err)); } - _ => return Err(ContextProviderError::Generic(e.to_string())), - }; + let delay = fibonacci(i + 2) * FIB_MULTIPLIER; + std::thread::sleep(Duration::from_millis(delay * BASE_TIME_MS)); + } else { + return Err(err); + } } } } @@ -133,8 +115,7 @@ impl LowLevelDashCoreClient { let core = Client::new( &addr, Auth::UserPass(core_user.to_string(), core_password.to_string()), - ) - .map_err(Error::CoreClientError)?; + )?; Ok(Self { core: Mutex::new(core), @@ -162,7 +143,7 @@ impl LowLevelDashCoreClient { pub fn list_unspent( &self, minimum_sum_satoshi: Option, - ) -> Result, ContextProviderError> { + ) -> Result, DashCoreError> { let options = json::ListUnspentQueryOptions { minimum_sum_amount: minimum_sum_satoshi.map(Amount::from_sat), ..Default::default() @@ -176,7 +157,7 @@ impl LowLevelDashCoreClient { /// Return address to which change of transaction can be sent. #[allow(dead_code)] #[deprecated(note = "This function is marked as unused.")] - pub fn get_balance(&self) -> Result { + pub fn get_balance(&self) -> Result { let core = self.core.lock().expect("Core lock poisoned"); retry!(core.get_balance(None, None)) } @@ -186,9 +167,9 @@ impl LowLevelDashCoreClient { &self, quorum_type: u32, quorum_hash: [u8; 32], - ) -> Result<[u8; 48], ContextProviderError> { + ) -> Result<[u8; 48], DashCoreError> { let quorum_hash = QuorumHash::from_slice(&quorum_hash) - .map_err(|e| ContextProviderError::InvalidQuorum(e.to_string()))?; + .map_err(|e| DashCoreError::InvalidQuorum(format!("invalid quorum hash: {}", e)))?; let core = self.core.lock().expect("Core lock poisoned"); @@ -199,29 +180,29 @@ impl LowLevelDashCoreClient { // Extract the quorum public key and attempt to convert it let key = quorum_info.quorum_public_key; let pubkey = as TryInto<[u8; 48]>>::try_into(key).map_err(|_| { - ContextProviderError::InvalidQuorum( - "quorum public key is not 48 bytes long".to_string(), - ) + DashCoreError::InvalidQuorum("quorum public key is not 48 bytes long".to_string()) })?; Ok(pubkey) } /// Retrieve platform activation height from core. - pub fn get_platform_activation_height(&self) -> Result { + pub fn get_platform_activation_height(&self) -> Result { let core = self.core.lock().expect("Core lock poisoned"); let blockchain_info = retry!(core.get_blockchain_info())?; - let fork_info = blockchain_info.softforks.get("mn_rr").ok_or( - ContextProviderError::ActivationForkError("no fork info for mn_rr".to_string()), - )?; - - fork_info - .height - .ok_or(ContextProviderError::ActivationForkError( - "unknown fork height".to_string(), - )) + let fork_info = + blockchain_info + .softforks + .get("mn_rr") + .ok_or(DashCoreError::ActivationForkError( + "no fork info for mn_rr".to_string(), + ))?; + + fork_info.height.ok_or(DashCoreError::ActivationForkError( + "unknown fork height".to_string(), + )) } /// Require list of validators from Core. @@ -232,7 +213,7 @@ impl LowLevelDashCoreClient { &self, height: Option, protx_type: Option, - ) -> Result, ContextProviderError> { + ) -> Result, DashCoreError> { let core = self.core.lock().expect("Core lock poisoned"); let pro_tx_list = retry!(core.get_protx_list(protx_type.clone(), Some(false), height))?; diff --git a/packages/rs-sdk/src/core/error.rs b/packages/rs-sdk/src/core/error.rs new file mode 100644 index 0000000000..ec1b4925f6 --- /dev/null +++ b/packages/rs-sdk/src/core/error.rs @@ -0,0 +1,56 @@ +//! Errors that can occur in the Dash Core. + +use drive_proof_verifier::error::ContextProviderError; +use rs_dapi_client::CanRetry; + +/// Dash Core still warming up +pub const CORE_RPC_ERROR_IN_WARMUP: i32 = -28; +/// Dash Core Client is not connected +pub const CORE_RPC_CLIENT_NOT_CONNECTED: i32 = -9; +/// Dash Core still downloading initial blocks +pub const CORE_RPC_CLIENT_IN_INITIAL_DOWNLOAD: i32 = -10; + +#[derive(Debug, thiserror::Error)] +/// Errors that can occur when communicating with the Dash Core. +pub enum DashCoreError { + /// Error from Dash Core. + #[error("Dash Core RPC error: {0}")] + Rpc(#[from] dashcore_rpc::Error), + + /// Quorum is invalid. + #[error("Invalid quorum: {0}")] + InvalidQuorum(String), + + /// Fork activation error - most likely the fork is not activated yet. + #[error("Fork activation: {0}")] + ActivationForkError(String), +} + +impl From for ContextProviderError { + fn from(error: DashCoreError) -> Self { + match error { + DashCoreError::Rpc(e) => Self::DashCoreError(e.to_string()), + DashCoreError::InvalidQuorum(e) => Self::InvalidQuorum(e), + DashCoreError::ActivationForkError(e) => Self::ActivationForkError(e), + } + } +} + +impl CanRetry for DashCoreError { + fn can_retry(&self) -> bool { + use dashcore_rpc::jsonrpc::error::Error as JsonRpcError; + use dashcore_rpc::Error as RpcError; + match self { + DashCoreError::Rpc(RpcError::JsonRpc(JsonRpcError::Transport(..))) => true, + DashCoreError::Rpc(RpcError::JsonRpc(JsonRpcError::Rpc(e))) => { + matches!( + e.code, + CORE_RPC_ERROR_IN_WARMUP + | CORE_RPC_CLIENT_NOT_CONNECTED + | CORE_RPC_CLIENT_IN_INITIAL_DOWNLOAD, + ) + } + _ => false, + } + } +} diff --git a/packages/rs-sdk/src/core/mod.rs b/packages/rs-sdk/src/core/mod.rs index f642f3b26f..d5c4be9cd5 100644 --- a/packages/rs-sdk/src/core/mod.rs +++ b/packages/rs-sdk/src/core/mod.rs @@ -6,3 +6,5 @@ mod dash_core_client; mod transaction; #[cfg(feature = "mocks")] pub use dash_core_client::LowLevelDashCoreClient; +mod error; +pub use error::DashCoreError; diff --git a/packages/rs-sdk/src/error.rs b/packages/rs-sdk/src/error.rs index 23def69d1a..75e114a800 100644 --- a/packages/rs-sdk/src/error.rs +++ b/packages/rs-sdk/src/error.rs @@ -10,6 +10,8 @@ use rs_dapi_client::{CanRetry, DapiClientError, ExecutionError}; use std::fmt::Debug; use std::time::Duration; +use crate::core::DashCoreError; + /// Error type for the SDK // TODO: Propagate server address and retry information so that the user can retrieve it #[derive(Debug, thiserror::Error)] @@ -44,7 +46,7 @@ pub enum Error { MerkleBlockError(#[from] dpp::dashcore::merkle_tree::MerkleBlockError), /// Core client error, for example, connection error #[error("Core client error: {0}")] - CoreClientError(#[from] dashcore_rpc::Error), + CoreClientError(#[from] DashCoreError), /// Dependency not found, for example data contract for a document not found #[error("Required {0} not found: {1}")] MissingDependency(String, String), @@ -125,9 +127,20 @@ where } } +impl From for Error { + fn from(value: dashcore_rpc::Error) -> Self { + Self::CoreClientError(value.into()) + } +} + impl CanRetry for Error { fn can_retry(&self) -> bool { - matches!(self, Error::StaleNode(..) | Error::TimeoutReached(_, _)) + match self { + Error::StaleNode(..) => true, + Error::TimeoutReached(..) => true, + Error::CoreClientError(e) => e.can_retry(), + _ => false, + } } } diff --git a/packages/rs-sdk/src/mock/provider.rs b/packages/rs-sdk/src/mock/provider.rs index 879c4137eb..ef0db5be92 100644 --- a/packages/rs-sdk/src/mock/provider.rs +++ b/packages/rs-sdk/src/mock/provider.rs @@ -215,7 +215,7 @@ impl ContextProvider for GrpcContextProvider { } fn get_platform_activation_height(&self) -> Result { - self.core.get_platform_activation_height() + Ok(self.core.get_platform_activation_height()?) } } diff --git a/packages/rs-sdk/src/sync.rs b/packages/rs-sdk/src/sync.rs index 5f5d266669..3b267f5a53 100644 --- a/packages/rs-sdk/src/sync.rs +++ b/packages/rs-sdk/src/sync.rs @@ -244,7 +244,6 @@ where mod test { use super::*; use derive_more::Display; - use http::Uri; use rs_dapi_client::ExecutionError; use std::{ future::Future, diff --git a/packages/rs-sdk/tests/fetch/config.rs b/packages/rs-sdk/tests/fetch/config.rs index f55484f5ce..5fc403560d 100644 --- a/packages/rs-sdk/tests/fetch/config.rs +++ b/packages/rs-sdk/tests/fetch/config.rs @@ -10,7 +10,7 @@ use dpp::{ }; use rs_dapi_client::{Address, AddressList}; use serde::Deserialize; -use std::{path::PathBuf, str::FromStr}; +use std::path::PathBuf; use zeroize::Zeroizing; /// Existing document ID diff --git a/packages/rs-sdk/tests/fetch/evonode.rs b/packages/rs-sdk/tests/fetch/evonode.rs index b2521ba864..9a01eabb9d 100644 --- a/packages/rs-sdk/tests/fetch/evonode.rs +++ b/packages/rs-sdk/tests/fetch/evonode.rs @@ -4,7 +4,6 @@ use super::{common::setup_logs, config::Config}; use dash_sdk::platform::{types::evonode::EvoNode, FetchUnproved}; use dpp::dashcore::{hashes::Hash, ProTxHash}; use drive_proof_verifier::types::EvoNodeStatus; -use http::Uri; use rs_dapi_client::Address; use std::time::Duration; /// Given some existing evonode URIs, WHEN we connect to them, THEN we get status.