From 3ef2782468f0ed479037935ab0270d48605821e1 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Thu, 13 Apr 2023 13:28:04 +0200 Subject: [PATCH 01/15] fix(rs-drive-abci): withdrawal: don't compare empty signature --- packages/rs-drive-abci/src/abci/withdrawal.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/rs-drive-abci/src/abci/withdrawal.rs b/packages/rs-drive-abci/src/abci/withdrawal.rs index 6a7a8f7c49..a62ed4ab42 100644 --- a/packages/rs-drive-abci/src/abci/withdrawal.rs +++ b/packages/rs-drive-abci/src/abci/withdrawal.rs @@ -135,9 +135,21 @@ impl<'a> From<&Vec> for WithdrawalTxs<'a> { impl<'a> PartialEq for WithdrawalTxs<'a> { /// Two sets of withdrawal transactions are equal if all their inner raw transactions are equal. - /// Note we don't compare `drive_operations`. + /// Notes: + /// 1. We don't compare `drive_operations`, as this is internal utility fields + /// 2. For a transaction, we don't compare signatures if at least one of them is empty fn eq(&self, other: &Self) -> bool { - self.inner.eq(&other.inner) + if self.inner.len() != other.inner.len() { + return false; + } + + std::iter::zip(&self.inner,& other.inner).all(|(left, right)| { + left.r#type == right.r#type + && left.extension == right.extension + && (left.signature.len() == 0 + || right.signature.len() == 0 + || left.signature == right.signature) + }) } } From cbe70fc44c847de25fa32d1962a3ed48c9e5a59a Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 14 Apr 2023 13:36:41 +0200 Subject: [PATCH 02/15] feat(rs-drive-abci): validate commit signature --- packages/rs-drive-abci/.env.example | 1 + packages/rs-drive-abci/Cargo.toml | 4 +- packages/rs-drive-abci/src/abci/commit.rs | 29 +++++ packages/rs-drive-abci/src/abci/config.rs | 4 + packages/rs-drive-abci/src/abci/handlers.rs | 9 +- packages/rs-drive-abci/src/abci/mimic.rs | 10 +- packages/rs-drive-abci/src/abci/mod.rs | 1 + .../src/abci/signature_verifier.rs | 48 ++++--- packages/rs-drive-abci/src/abci/withdrawal.rs | 33 +++-- packages/rs-drive-abci/src/config.rs | 1 + .../src/execution/commit_validation.rs | 47 ------- .../rs-drive-abci/src/execution/engine.rs | 117 ++++++++---------- packages/rs-drive-abci/src/execution/mod.rs | 2 - 13 files changed, 142 insertions(+), 164 deletions(-) create mode 100644 packages/rs-drive-abci/src/abci/commit.rs delete mode 100644 packages/rs-drive-abci/src/execution/commit_validation.rs diff --git a/packages/rs-drive-abci/.env.example b/packages/rs-drive-abci/.env.example index 29c9705c2e..61f1c1b637 100644 --- a/packages/rs-drive-abci/.env.example +++ b/packages/rs-drive-abci/.env.example @@ -62,3 +62,4 @@ TENDERDASH_P2P_PORT=26656 QUORUM_SIZE=5 QUORUM_TYPE=llmq_25_67 +CHAIN_ID=devnet diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 1a452460fa..d7c37bfd0d 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -51,8 +51,8 @@ tracing-subscriber = { version = "0.3.16", default-features = false, features = "ansi", ], optional = true } atty = { version = "0.2.14", optional = true } -tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", branch = "master", optional = true } -# tenderdash-abci = { path = "/home/lklimek/git/lklimek/tenderdash-abci-rs/abci", optional = true } +tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", branch = "feat/sign-bytes", optional = true } +# tenderdash-abci = { path = "../../../rs-tenderdash-abci/abci", optional = true } anyhow = { version = "1.0.70" } lazy_static = "1.4.0" itertools = { version = "0.10.5" } diff --git a/packages/rs-drive-abci/src/abci/commit.rs b/packages/rs-drive-abci/src/abci/commit.rs new file mode 100644 index 0000000000..c68461289e --- /dev/null +++ b/packages/rs-drive-abci/src/abci/commit.rs @@ -0,0 +1,29 @@ +//! Tenderdash commit logic +use tenderdash_abci::proto::{self, abci::CommitInfo, signatures::SignBytes, types::BlockId}; + +/// Represents commit for a block +pub struct Commit { + inner: proto::types::Commit, +} + +impl Commit { + /// Create new Commit struct based on commit info and block id received from Tenderdash + pub fn new(ci: CommitInfo, block_id: BlockId, height: i64) -> Self { + Self { + inner: proto::types::Commit { + block_id: Some(block_id), + height, + round: ci.round, + quorum_hash: ci.quorum_hash, + threshold_block_signature: ci.block_signature, + threshold_vote_extensions: ci.threshold_vote_extensions, + }, + } + } +} + +impl SignBytes for Commit { + fn sign_bytes(&self, chain_id: &str, height: i64, round: i32) -> Result, proto::Error> { + self.inner.sign_bytes(chain_id, height, round) + } +} diff --git a/packages/rs-drive-abci/src/abci/config.rs b/packages/rs-drive-abci/src/abci/config.rs index 29d166509d..6ad7c53524 100644 --- a/packages/rs-drive-abci/src/abci/config.rs +++ b/packages/rs-drive-abci/src/abci/config.rs @@ -33,6 +33,10 @@ pub struct AbciConfig { /// Height of core at genesis #[serde(default = "AbciConfig::default_genesis_core_height")] pub genesis_core_height: u32, + + /// Chain ID of the network to use + #[serde(default)] + pub chain_id: String, } impl AbciConfig { diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 900414ba1e..528452f2f6 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -34,7 +34,6 @@ use crate::abci::server::AbciApplication; use crate::rpc::core::CoreRPCLike; -use dpp::ProtocolError; use drive::fee::credits::SignedCredits; use tenderdash_abci::proto::abci::response_verify_vote_extension::VerifyStatus; use tenderdash_abci::proto::abci::tx_record::TxAction; @@ -107,7 +106,6 @@ where } //todo: we need to set the block hash - let BlockExecutionOutcome { app_hash, tx_results, @@ -177,7 +175,7 @@ where let transaction = transaction_guard.as_ref().unwrap(); // We can take the core chain lock update here because it won't be used anywhere else - if let Some(c) = request.core_chain_lock_update.take() { + if let Some(_c) = request.core_chain_lock_update.take() { //todo: if there is a core chain lock update we need to validate it } @@ -238,12 +236,11 @@ where let got: WithdrawalTxs = request.vote_extensions.into(); let expected = WithdrawalTxs::load(Some(transaction), &self.platform.drive)?; - if let Err(err) = self.platform.check_withdrawals(&got, &expected, None) { + if got.ne(&expected) { tracing::error!( method = "verify_vote_extension", ?got, ?expected, - ?err, "vote extension mismatch" ); Ok(proto::ResponseVerifyVoteExtension { @@ -297,7 +294,7 @@ where } fn check_tx(&self, request: RequestCheckTx) -> Result { - let RequestCheckTx { tx, r#type } = request; + let RequestCheckTx { tx, r#type: _ } = request; let validation_result = self.platform.check_tx(tx)?; // If there are no execution errors the code will be 0 diff --git a/packages/rs-drive-abci/src/abci/mimic.rs b/packages/rs-drive-abci/src/abci/mimic.rs index cae3ec1265..07fb91bdf2 100644 --- a/packages/rs-drive-abci/src/abci/mimic.rs +++ b/packages/rs-drive-abci/src/abci/mimic.rs @@ -19,7 +19,7 @@ impl<'a, C: CoreRPCLike> AbciApplication<'a, C> { proposer_pro_tx_hash: [u8; 32], quorum_hash: [u8; 32], proposed_version: ProtocolVersion, - total_hpmns: u32, + _total_hpmns: u32, block_info: BlockInfo, expect_validation_errors: bool, state_transitions: Vec, @@ -33,7 +33,7 @@ impl<'a, C: CoreRPCLike> AbciApplication<'a, C> { time_ms, height, core_height, - epoch, + epoch: _, } = block_info; let request_prepare_proposal = RequestPrepareProposal { @@ -67,9 +67,9 @@ impl<'a, C: CoreRPCLike> AbciApplication<'a, C> { tx_records, app_hash, tx_results, - consensus_param_updates, - core_chain_lock_update, - validator_set_update, + consensus_param_updates: _, + core_chain_lock_update: _, + validator_set_update: _, } = response_prepare_proposal; if expect_validation_errors == false { diff --git a/packages/rs-drive-abci/src/abci/mod.rs b/packages/rs-drive-abci/src/abci/mod.rs index 7b6e8e98dc..c5206a306a 100644 --- a/packages/rs-drive-abci/src/abci/mod.rs +++ b/packages/rs-drive-abci/src/abci/mod.rs @@ -15,6 +15,7 @@ pub mod mimic; #[cfg(any(feature = "server", test))] mod server; +pub mod commit; pub mod signature_verifier; pub mod withdrawal; diff --git a/packages/rs-drive-abci/src/abci/signature_verifier.rs b/packages/rs-drive-abci/src/abci/signature_verifier.rs index 53759b2966..07d60ed9a7 100644 --- a/packages/rs-drive-abci/src/abci/signature_verifier.rs +++ b/packages/rs-drive-abci/src/abci/signature_verifier.rs @@ -1,7 +1,7 @@ //! Signature verification use dpp::bls_signatures::Serialize; -use tenderdash_abci::proto::types::VoteExtension; +use tenderdash_abci::proto::signatures::SignBytes; /// Errors occured during signature verification #[derive(Debug, thiserror::Error)] @@ -9,6 +9,10 @@ pub enum SignatureError { /// Error occurred during bls signature verification #[error("bls error set: {0}")] BLSError(#[from] dpp::bls_signatures::Error), + + /// Error creating canonical form of signed data + #[error("error creating canonical form of signed data: {0}")] + CanonicalError(tenderdash_abci::proto::Error), } /// SignatureVerifier can be used to verify a BLS signature. pub trait SignatureVerifier { @@ -21,40 +25,32 @@ pub trait SignatureVerifier { /// * Err(e) on error fn verify_signature( &self, - quorum_public_key: dpp::bls_signatures::PublicKey, + signature: &Vec, + chain_id: &str, + height: i64, + round: i32, + quorum_public_key: &dpp::bls_signatures::PublicKey, ) -> Result; } -impl SignatureVerifier for Vec { - fn verify_signature( - &self, - quorum_public_key: dpp::bls_signatures::PublicKey, - ) -> Result { - for tx in self { - if !tx.verify_signature(quorum_public_key)? { - return Ok(false); - } - } - - Ok(true) - } -} - -impl SignatureVerifier for VoteExtension { +impl SignatureVerifier for T { fn verify_signature( &self, - _quorum_public_key: dpp::bls_signatures::PublicKey, + signature: &Vec, + chain_id: &str, + height: i64, + round: i32, + quorum_public_key: &dpp::bls_signatures::PublicKey, ) -> Result { - let signature = &self.signature; - // 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(signature.as_slice()) { + let signature = match dpp::bls_signatures::Signature::from_bytes(signature.as_slice()) { Ok(signature) => signature, Err(e) => return Err(SignatureError::from(e)), }; - // TODO: implement correct signature verification for VoteExtension. It uses CanonicalVoteExtension. - // For now, we just return `true` - // Ok(quorum_public_key.verify(signature, &self.extension)) - Ok(true) + + let hash = self + .sha256(chain_id, height, round) + .map_err(SignatureError::CanonicalError)?; + Ok(quorum_public_key.verify(signature, hash)) } } diff --git a/packages/rs-drive-abci/src/abci/withdrawal.rs b/packages/rs-drive-abci/src/abci/withdrawal.rs index a62ed4ab42..fff36a6eec 100644 --- a/packages/rs-drive-abci/src/abci/withdrawal.rs +++ b/packages/rs-drive-abci/src/abci/withdrawal.rs @@ -92,6 +92,24 @@ impl<'a> WithdrawalTxs<'a> { }) .collect::>() } + + /// Verify signatures of all withdrawal TXs + pub fn verify_signatures( + &self, + chain_id: &str, + height: i64, + round: i32, + quorum_public_key: bls_signatures::PublicKey, + ) -> Result { + // self.inner.all(|s| s.verify_signature()) + for s in &self.inner { + if !s.verify_signature(&s.signature, chain_id, height, round, &quorum_public_key)? { + return Ok(false); + } + } + + Ok(true) + } } impl<'a> Display for WithdrawalTxs<'a> { @@ -135,7 +153,9 @@ impl<'a> From<&Vec> for WithdrawalTxs<'a> { impl<'a> PartialEq for WithdrawalTxs<'a> { /// Two sets of withdrawal transactions are equal if all their inner raw transactions are equal. - /// Notes: + /// + /// ## Notes + /// /// 1. We don't compare `drive_operations`, as this is internal utility fields /// 2. For a transaction, we don't compare signatures if at least one of them is empty fn eq(&self, other: &Self) -> bool { @@ -143,7 +163,7 @@ impl<'a> PartialEq for WithdrawalTxs<'a> { return false; } - std::iter::zip(&self.inner,& other.inner).all(|(left, right)| { + std::iter::zip(&self.inner, &other.inner).all(|(left, right)| { left.r#type == right.r#type && left.extension == right.extension && (left.signature.len() == 0 @@ -152,12 +172,3 @@ impl<'a> PartialEq for WithdrawalTxs<'a> { }) } } - -impl<'a> SignatureVerifier for WithdrawalTxs<'a> { - fn verify_signature( - &self, - quorum_public_key: bls_signatures::PublicKey, - ) -> Result { - self.inner.verify_signature(quorum_public_key) - } -} diff --git a/packages/rs-drive-abci/src/config.rs b/packages/rs-drive-abci/src/config.rs index daa31bc471..031c44ab48 100644 --- a/packages/rs-drive-abci/src/config.rs +++ b/packages/rs-drive-abci/src/config.rs @@ -199,6 +199,7 @@ impl Default for PlatformConfig { keys: Keys::new_random_keys_with_seed(18012014), //Dash genesis day genesis_height: 1, genesis_core_height: 0, + chain_id: "chain_id".to_string(), }, core: Default::default(), db_path: PathBuf::from("/var/lib/dash-platform/data"), diff --git a/packages/rs-drive-abci/src/execution/commit_validation.rs b/packages/rs-drive-abci/src/execution/commit_validation.rs deleted file mode 100644 index 21c2ba9087..0000000000 --- a/packages/rs-drive-abci/src/execution/commit_validation.rs +++ /dev/null @@ -1,47 +0,0 @@ -use crate::abci::AbciError; -use crate::error::Error; -use crate::platform::Platform; -use crate::rpc::core::CoreRPCLike; -use dpp::bls_signatures; -use dpp::bls_signatures::Serialize; -use dpp::validation::SimpleValidationResult; -use tenderdash_abci::proto::abci::CommitInfo; -use tenderdash_abci::proto::types::BlockId; - -impl Platform -where - C: CoreRPCLike, -{ - /// Validates a commit received in finalize block - /// An explanation can be found here - /// https://github.com/dashpay/tenderdash/blob/v0.12-dev/spec/consensus/signing.md#block-signature-verification-on-light-client - /// - /// Verification algorithm can be described as follows: - /// - /// Build StateID message and encode it using Protobuf encoding. - /// Calculate checksum (SHA256) of encoded StateID. - /// Retrieve or calculate SHA256 checksum of CanonicalBlockID - /// Build CanonicalVote message and encode it using Protobuf. - /// Calculate SHA256 checksum of encoded CanonicalVote. - /// Verify that block signature matches calculated checksum. - pub(crate) fn validate_commit( - &self, - commit: CommitInfo, - block_id: BlockId, - quorum_public_key: bls_signatures::PublicKey, - ) -> Result, Error> { - let signature = commit.block_signature; - // 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.as_slice()) { - Ok(signature) => signature, - Err(e) => { - return Ok(SimpleValidationResult::new_with_error( - AbciError::SignatureError(e.into()), - )) - } - }; - // todo: public_key.verify(signature, ) - - Ok(SimpleValidationResult::default()) - } -} diff --git a/packages/rs-drive-abci/src/execution/engine.rs b/packages/rs-drive-abci/src/execution/engine.rs index 67b344ef72..f090076e25 100644 --- a/packages/rs-drive-abci/src/execution/engine.rs +++ b/packages/rs-drive-abci/src/execution/engine.rs @@ -1,3 +1,4 @@ +use crate::abci::commit::Commit; use dashcore_rpc::json::QuorumHash; use dpp::bls_signatures; use dpp::bls_signatures::Serialize; @@ -368,31 +369,6 @@ where Ok(()) } - /// check if received withdrawal transactions are correct and match our withdrawal txs - pub fn check_withdrawals( - &self, - received_withdrawals: &WithdrawalTxs, - our_withdrawals: &WithdrawalTxs, - quorum_public_key: Option, - ) -> Result<(), AbciError> { - if received_withdrawals.ne(&our_withdrawals) { - return Err(AbciError::VoteExtensionMismatchReceived { - got: received_withdrawals.to_string(), - expected: our_withdrawals.to_string(), - }); - } - - // Now, verify signature - if let Some(public_key) = quorum_public_key { - match received_withdrawals.verify_signature(public_key) { - Ok(true) => return Ok(()), - Ok(false) => return Err(AbciError::VoteExtensionsSignatureInvalid), - Err(e) => return Err(e.into()), - } - } - - Ok(()) - } // Retrieve quorum public key fn get_quorum_key(&self, quorum_hash: Vec) -> Result { let public_key = self @@ -433,7 +409,7 @@ where // Let's decompose the request let RequestFinalizeBlock { - commit, + commit: commit_info, misbehavior, hash, height, @@ -443,7 +419,21 @@ where } = request_finalize_block; //todo: block and header should not be optional - let block_header = block.unwrap().header.unwrap(); + let block = block.ok_or(Error::Abci(AbciError::WrongFinalizeBlockReceived( + "empty block".into(), + )))?; + let block_header = + block + .header + .ok_or(Error::Abci(AbciError::WrongFinalizeBlockReceived( + "missing block header".into(), + )))?; + let block_id = block_id.ok_or(Error::Abci(AbciError::WrongFinalizeBlockReceived( + "missing block id".into(), + )))?; + let commit_info = commit_info.ok_or(Error::Abci(AbciError::WrongFinalizeBlockReceived( + "missing commit".into(), + )))?; let Ok(proposer_protx_hash) = block_header.proposer_pro_tx_hash.try_into() else { validation_result.add_error(AbciError::WrongFinalizeBlockReceived(format!( @@ -472,47 +462,44 @@ where return Ok(validation_result.into()); } - // Next we need to verify that the signature returned from the quorum is valid - let commit = if let Some(commit) = commit { - commit - } else { - validation_result.add_error(AbciError::WrongFinalizeBlockReceived(format!( - "received a block for h: {} r: {} without a commit", - height, round - ))); - return Ok(validation_result.into()); - }; - - let quorum_public_key = self.get_quorum_key(commit.quorum_hash.clone())?; + let quorum_public_key = self.get_quorum_key(commit_info.quorum_hash.clone())?; + + // Verify commit + let commit = Commit::new(commit_info.clone(), block_id.clone(), height); + commit + .verify_signature( + &commit_info.block_signature, + &block_header.chain_id, + height, + round, + &quorum_public_key, + ) + .map_err(AbciError::from)?; - //todo: verify commit - // if let Some(block_id) = block_id { - // let result = self.validate_commit(commit.clone(), block_id, quorum_public_key)?; - // if !result.is_valid() { - // return Ok(validation_result.into()); - // } - // } else { - // validation_result.add_error(AbciError::WrongFinalizeBlockReceived(format!( - // "received a block for h: {} r: {} without a block id", - // height, round - // ))); - // return Ok(validation_result.into()); - // } - - // Verify vote extensions - let received_withdrawals = WithdrawalTxs::from(&commit.threshold_vote_extensions); + // Verify vote extensions; right now, we only support withdrawal txs + let received_withdrawals = WithdrawalTxs::from(&commit_info.threshold_vote_extensions); let our_withdrawals = WithdrawalTxs::load(Some(transaction), &self.drive) .map_err(|e| AbciError::WithdrawalTransactionsDBLoadError(e.to_string()))?; - //todo: reenable check - // - // if let Err(e) = self.check_withdrawals( - // &received_withdrawals, - // &our_withdrawals, - // Some(quorum_public_key), - // ) { - // validation_result.add_error(e); - // return Ok(validation_result.into()); - // } + + if received_withdrawals.ne(&our_withdrawals) { + return Err(AbciError::VoteExtensionMismatchReceived { + got: received_withdrawals.to_string(), + expected: our_withdrawals.to_string(), + } + .into()); + } + + // Now, verify signatures if present + match received_withdrawals.verify_signatures( + &self.config.abci.chain_id, + height, + round, + quorum_public_key, + ) { + Ok(true) => (), + Ok(false) => return Err(AbciError::VoteExtensionsSignatureInvalid.into()), + Err(e) => return Err(AbciError::from(e).into()), + }; // Next let's check that the hash received is the same as the hash we expect diff --git a/packages/rs-drive-abci/src/execution/mod.rs b/packages/rs-drive-abci/src/execution/mod.rs index dc796bb6bb..9d42e0444f 100644 --- a/packages/rs-drive-abci/src/execution/mod.rs +++ b/packages/rs-drive-abci/src/execution/mod.rs @@ -1,7 +1,5 @@ /// The block proposal pub mod block_proposal; -/// Commit validation -pub mod commit_validation; // /// Data triggers // pub mod data_trigger; /// Engine module From 2da23cf4c21c25a889e847a52fef9be64dac4b79 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Fri, 14 Apr 2023 16:44:34 +0200 Subject: [PATCH 03/15] chore(rs-drive-abci): get rid of some warnings --- .../src/asset_lock/fetch_tx_out.rs | 4 ++-- .../src/execution/block_proposal.rs | 20 +++++++++---------- .../rs-drive-abci/src/execution/engine.rs | 6 +++--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/rs-drive-abci/src/asset_lock/fetch_tx_out.rs b/packages/rs-drive-abci/src/asset_lock/fetch_tx_out.rs index 1da24471f9..6e42e49c1c 100644 --- a/packages/rs-drive-abci/src/asset_lock/fetch_tx_out.rs +++ b/packages/rs-drive-abci/src/asset_lock/fetch_tx_out.rs @@ -47,7 +47,7 @@ impl FetchAssetLockProofTxOut for AssetLockProof { let transaction_data = match core.get_transaction_extended_info(&transaction_hash) { Ok(transaction) => transaction, - Err(e) => { + Err(_e) => { //todo: deal with IO errors return Ok(ValidationResult::new_with_error( ConsensusError::IdentityAssetLockTransactionIsNotFoundError( @@ -80,7 +80,7 @@ impl FetchAssetLockProofTxOut for AssetLockProof { let transaction_data = match core.get_transaction_extended_info(&transaction_hash) { Ok(transaction) => transaction, - Err(e) => { + Err(_e) => { return Ok(ValidationResult::new_with_error( ConsensusError::IdentityAssetLockTransactionIsNotFoundError( IdentityAssetLockTransactionIsNotFoundError::new( diff --git a/packages/rs-drive-abci/src/execution/block_proposal.rs b/packages/rs-drive-abci/src/execution/block_proposal.rs index b697926255..10fd17901b 100644 --- a/packages/rs-drive-abci/src/execution/block_proposal.rs +++ b/packages/rs-drive-abci/src/execution/block_proposal.rs @@ -31,18 +31,18 @@ impl<'a> TryFrom<&'a RequestPrepareProposal> for BlockProposal<'a> { fn try_from(value: &'a RequestPrepareProposal) -> Result { let RequestPrepareProposal { - max_tx_bytes, + max_tx_bytes: _, txs, - local_last_commit, - misbehavior, + local_last_commit: _, + misbehavior: _, height, time, - next_validators_hash, + next_validators_hash: _, round, core_chain_locked_height, proposer_pro_tx_hash, proposed_app_version, - version, + version: _, quorum_hash, } = value; let block_time_ms = time @@ -85,18 +85,18 @@ impl<'a> TryFrom<&'a RequestProcessProposal> for BlockProposal<'a> { fn try_from(value: &'a RequestProcessProposal) -> Result { let RequestProcessProposal { txs, - proposed_last_commit, - misbehavior, + proposed_last_commit: _, + misbehavior: _, hash, height, round, time, - next_validators_hash, + next_validators_hash: _, core_chain_locked_height, - core_chain_lock_update, + core_chain_lock_update: _, proposer_pro_tx_hash, proposed_app_version, - version, + version: _, quorum_hash, } = value; let block_time_ms = time diff --git a/packages/rs-drive-abci/src/execution/engine.rs b/packages/rs-drive-abci/src/execution/engine.rs index f090076e25..33eafcb674 100644 --- a/packages/rs-drive-abci/src/execution/engine.rs +++ b/packages/rs-drive-abci/src/execution/engine.rs @@ -255,9 +255,9 @@ where // destructure the block proposal let BlockProposal { - block_hash, + block_hash:_, height, - round, + round:_, core_chain_locked_height, proposed_app_version, proposer_pro_tx_hash, @@ -308,7 +308,7 @@ where &transaction, )?; - let unsigned_withdrawal_transaction_bytes = self + let _unsigned_withdrawal_transaction_bytes = self .fetch_and_prepare_unsigned_withdrawal_transactions( validator_set_quorum_hash, &block_execution_context, From 9b87be58c87117fc67a050fa8220b136cb9897b5 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 17 Apr 2023 13:10:50 +0200 Subject: [PATCH 04/15] feat(rs-drive-abci): commit validation - WIP --- Cargo.lock | 175 ++++++----------- Cargo.toml | 5 +- packages/rs-dpp/Cargo.toml | 61 +++--- packages/rs-drive-abci/Cargo.toml | 8 +- packages/rs-drive-abci/src/abci/commit.rs | 185 +++++++++++++++++- packages/rs-drive-abci/src/abci/error.rs | 11 +- packages/rs-drive-abci/src/abci/mod.rs | 1 - .../src/abci/signature_verifier.rs | 56 ------ packages/rs-drive-abci/src/abci/withdrawal.rs | 14 +- .../src/asset_lock/fetch_tx_out.rs | 4 +- packages/rs-drive-abci/src/error/execution.rs | 2 +- .../rs-drive-abci/src/execution/engine.rs | 24 +-- packages/rs-drive-abci/src/platform/mod.rs | 4 +- packages/rs-drive-abci/src/rpc/core.rs | 2 +- .../tests/strategy_tests/main.rs | 8 +- 15 files changed, 323 insertions(+), 237 deletions(-) delete mode 100644 packages/rs-drive-abci/src/abci/signature_verifier.rs diff --git a/Cargo.lock b/Cargo.lock index bbd9d7321f..9a5ce6bb3b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,42 +60,51 @@ dependencies = [ [[package]] name = "anstream" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f" +checksum = "9e579a7752471abc2a8268df8b20005e3eadd975f585398f17efcfd8d4927371" dependencies = [ "anstyle", "anstyle-parse", + "anstyle-query", "anstyle-wincon", - "concolor-override", - "concolor-query", + "colorchoice", "is-terminal", "utf8parse", ] [[package]] name = "anstyle" -version = "0.3.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2" +checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" [[package]] name = "anstyle-parse" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116" +checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" dependencies = [ "utf8parse", ] +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "anstyle-wincon" -version = "0.2.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa" +checksum = "4bcd8291a340dd8ac70e18878bc4501dd7b4ff970cfa21c207d36ece51ea88fd" dependencies = [ "anstyle", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -153,7 +162,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.14", + "syn 2.0.15", ] [[package]] @@ -608,9 +617,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.2.1" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046ae530c528f252094e4a77886ee1374437744b2bff1497aa898bbddbbb29b3" +checksum = "9b802d85aaf3a1cdb02b224ba472ebdea62014fccfcb269b95a4d76443b5ee5a" dependencies = [ "clap_builder", "clap_derive", @@ -619,9 +628,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.2.1" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f" +checksum = "14a1a858f532119338887a4b8e1af9c60de8249cd7bafd68036a489e261e37b6" dependencies = [ "anstream", "anstyle", @@ -639,7 +648,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.14", + "syn 2.0.15", ] [[package]] @@ -658,6 +667,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "colored" version = "1.9.3" @@ -669,21 +684,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "concolor-override" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f" - -[[package]] -name = "concolor-query" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf" -dependencies = [ - "windows-sys 0.45.0", -] - [[package]] name = "concurrent-queue" version = "2.2.0" @@ -693,16 +693,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - [[package]] name = "constant_time_eq" version = "0.2.5" @@ -903,7 +893,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.14", + "syn 2.0.15", ] [[package]] @@ -920,7 +910,7 @@ checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.14", + "syn 2.0.15", ] [[package]] @@ -961,7 +951,7 @@ dependencies = [ [[package]] name = "dashcore" version = "0.29.1" -source = "git+https://github.com/dashpay/rust-dashcore?rev=51548a4a1b9eca7430f5f3caf94d9784886ff2e9#51548a4a1b9eca7430f5f3caf94d9784886ff2e9" +source = "git+https://github.com/dashpay/rust-dashcore?branch=feat/addons#c9bfcb53b77c03d533dfcbb515760ece5beb0aa9" dependencies = [ "anyhow", "bech32", @@ -975,7 +965,7 @@ dependencies = [ [[package]] name = "dashcore-rpc" version = "0.15.0" -source = "git+https://github.com/dashpay/rust-dashcore-rpc?branch=feat/quorumListImprovement#df45a5eb0998bac0d219c8a48208137d64f00a77" +source = "git+https://github.com/dashpay/rust-dashcore-rpc?branch=feat/quorumListImprovement#03b1c43b33670644971e1557ce97dc17bf55e868" dependencies = [ "dashcore-rpc-json", "env_logger 0.10.0", @@ -988,7 +978,7 @@ dependencies = [ [[package]] name = "dashcore-rpc-json" version = "0.15.0" -source = "git+https://github.com/dashpay/rust-dashcore-rpc?branch=feat/quorumListImprovement#df45a5eb0998bac0d219c8a48208137d64f00a77" +source = "git+https://github.com/dashpay/rust-dashcore-rpc?branch=feat/quorumListImprovement#03b1c43b33670644971e1557ce97dc17bf55e868" dependencies = [ "dashcore", "hex", @@ -1171,7 +1161,7 @@ dependencies = [ "bytes", "chrono", "ciborium", - "clap 4.2.1", + "clap 4.2.2", "dashcore", "dashcore-rpc", "dotenvy", @@ -1533,7 +1523,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.14", + "syn 2.0.15", ] [[package]] @@ -1964,6 +1954,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "lhash" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6df04c84bd3f83849dd23c51be4cbb22a02d80ebdea22741558fe30127d837ae" + [[package]] name = "libc" version = "0.2.141" @@ -2744,9 +2740,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ "bytes", "prost-derive", @@ -2754,9 +2750,9 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c828f93f5ca4826f97fedcbd3f9a536c16b12cff3dbbb4a007f932bbad95b12" +checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" dependencies = [ "bytes", "heck 0.4.1", @@ -2776,9 +2772,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", "itertools", @@ -2789,9 +2785,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "379119666929a1afd7a043aa6cf96fa67a6dce9af60c88095a4686dbce4c9c88" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" dependencies = [ "prost", ] @@ -3052,9 +3048,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustc-hash" @@ -3218,16 +3214,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde-wasm-bindgen" -version = "0.5.0" -source = "git+https://github.com/QuantumExplorer/serde-wasm-bindgen?branch=feat/not_human_readable#121d1f7fbf62cb97f74b91626a1b23851098cc82" -dependencies = [ - "js-sys", - "serde", - "wasm-bindgen", -] - [[package]] name = "serde_bytes" version = "0.11.9" @@ -3255,14 +3241,14 @@ checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" dependencies = [ "proc-macro2", "quote", - "syn 2.0.14", + "syn 2.0.15", ] [[package]] name = "serde_json" -version = "1.0.95" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ "indexmap", "itoa", @@ -3278,7 +3264,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.14", + "syn 2.0.15", ] [[package]] @@ -3516,9 +3502,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.14" +version = "2.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcf316d5356ed6847742d036f8a39c3b8435cac10bd528a4bd461928a6ab34d5" +checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" dependencies = [ "proc-macro2", "quote", @@ -3576,7 +3562,6 @@ dependencies = [ [[package]] name = "tenderdash-abci" version = "0.12.0-dev.1" -source = "git+https://github.com/dashpay/rs-tenderdash-abci?branch=master#d61717a0c6ae129f6f64da6189d1e59e176ed42c" dependencies = [ "bytes", "prost", @@ -3591,12 +3576,12 @@ dependencies = [ [[package]] name = "tenderdash-proto" version = "0.12.0-dev.1" -source = "git+https://github.com/dashpay/rs-tenderdash-abci?branch=master#d61717a0c6ae129f6f64da6189d1e59e176ed42c" dependencies = [ "bytes", "chrono", "derive_more", "flex-error", + "lhash", "num-derive", "num-traits", "prost", @@ -3609,7 +3594,6 @@ dependencies = [ [[package]] name = "tenderdash-proto-compiler" version = "0.1.0" -source = "git+https://github.com/dashpay/rs-tenderdash-abci?branch=master#d61717a0c6ae129f6f64da6189d1e59e176ed42c" dependencies = [ "fs_extra", "prost-build", @@ -3683,7 +3667,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.14", + "syn 2.0.15", ] [[package]] @@ -3786,7 +3770,7 @@ checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.14", + "syn 2.0.15", ] [[package]] @@ -4072,18 +4056,6 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" version = "0.2.84" @@ -4113,25 +4085,6 @@ version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" -[[package]] -name = "wasm-dpp" -version = "0.1.0" -dependencies = [ - "anyhow", - "async-trait", - "console_error_panic_hook", - "dpp", - "itertools", - "js-sys", - "serde", - "serde-wasm-bindgen", - "serde_json", - "thiserror", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "web-sys" version = "0.3.61" diff --git a/Cargo.toml b/Cargo.toml index 0af5b8688a..5ba6ae4bff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ members = [ "packages/rs-dpp", - "packages/wasm-dpp", + # "packages/wasm-dpp", "packages/rs-drive", "packages/rs-platform-value", "packages/rs-drive-abci", @@ -12,5 +12,6 @@ members = [ "packages/masternode-reward-shares-contract", "packages/feature-flags-contract", "packages/dpns-contract", - "packages/data-contracts" + "packages/data-contracts", ] +exclude = ["packages/wasm-dpp"] diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index 0aca92d18d..3d6e8f4374 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -5,46 +5,57 @@ edition = "2018" authors = ["Anton Suprunchuk "] [dependencies] -anyhow = { version = "1.0.70"} -async-trait = { version = "0.1"} +anyhow = { version = "1.0.70" } +async-trait = { version = "0.1" } base64 = "0.20.0" bls-signatures = { version = "0.13.0" } bs58 = "0.4.0" -byteorder = { version="1.4"} -chrono = { version="0.4.20", default-features=false, features=["wasmbind", "clock"]} -ciborium = { git="https://github.com/qrayven/ciborium", branch="feat-ser-null-as-undefined"} -dashcore = { git="https://github.com/dashpay/rust-dashcore", features=["std", "secp-recovery", "rand", "signer", "use-serde"], default-features = false, rev = "51548a4a1b9eca7430f5f3caf94d9784886ff2e9" } -env_logger = { version="0.9"} -futures = { version ="0.3"} -getrandom= { version="0.2", features=["js"]} -hex = { version = "0.4"} -integer-encoding = { version="3.0.4"} -itertools = { version ="0.10"} +byteorder = { version = "1.4" } +chrono = { version = "0.4.20", default-features = false, features = [ + "wasmbind", + "clock", +] } +ciborium = { git = "https://github.com/qrayven/ciborium", branch = "feat-ser-null-as-undefined" } +dashcore = { git = "https://github.com/dashpay/rust-dashcore", features = [ + "std", + "secp-recovery", + "rand", + "signer", + "use-serde", +], default-features = false, branch = "feat/addons" } +env_logger = { version = "0.9" } +futures = { version = "0.3" } +getrandom = { version = "0.2", features = ["js"] } +hex = { version = "0.4" } +integer-encoding = { version = "3.0.4" } +itertools = { version = "0.10" } json-patch = "0.2.6" jsonptr = "0.1.5" -jsonschema = { git="https://github.com/fominok/jsonschema-rs", branch="feat-unevaluated-properties", default-features=false, features=["draft202012"] } -lazy_static = { version ="1.4"} -log = { version="0.4"} +jsonschema = { git = "https://github.com/fominok/jsonschema-rs", branch = "feat-unevaluated-properties", default-features = false, features = [ + "draft202012", +] } +lazy_static = { version = "1.4" } +log = { version = "0.4" } num_enum = "0.5.7" -bincode = { version="2.0.0-rc.3", features=["serde"] } +bincode = { version = "2.0.0-rc.3", features = ["serde"] } rand = { version = "0.8.4", features = ["small_rng"] } -regex = { version="1.5"} -serde = { version="1.0.152", features=["derive"]} +regex = { version = "1.5" } +serde = { version = "1.0.152", features = ["derive"] } serde-big-array = "0.4.1" serde_cbor = "0.11.2" -serde_json = { version="1.0", features=["preserve_order"]} +serde_json = { version = "1.0", features = ["preserve_order"] } serde_repr = { version = "0.1.7" } -sha2 = { version="0.10"} -thiserror = { version = "1.0"} -mockall = { version="0.11.3", optional=true} +sha2 = { version = "0.10" } +thiserror = { version = "1.0" } +mockall = { version = "0.11.3", optional = true } data-contracts = { path = "../data-contracts" } platform-value = { path = "../rs-platform-value" } derive_more = "0.99.17" [dev-dependencies] -test-case = { version ="2.0"} -tokio = { version ="1.17", features=["full"]} -pretty_assertions = { version="1.3.0"} +test-case = { version = "2.0" } +tokio = { version = "1.17", features = ["full"] } +pretty_assertions = { version = "1.3.0" } [features] default = ["fixtures-and-mocks"] diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index d7c37bfd0d..44154b2471 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -32,7 +32,7 @@ dashcore = { git = "https://github.com/dashpay/rust-dashcore", features = [ "rand", "signer", "use-serde", -], default-features = false, rev = "51548a4a1b9eca7430f5f3caf94d9784886ff2e9" } +], default-features = false, branch = "feat/addons" } dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", branch = "feat/quorumListImprovement" } dpp = { path = "../rs-dpp", features = ["fixtures-and-mocks"] } rust_decimal = "1.2.5" @@ -51,12 +51,14 @@ tracing-subscriber = { version = "0.3.16", default-features = false, features = "ansi", ], optional = true } atty = { version = "0.2.14", optional = true } -tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", branch = "feat/sign-bytes", optional = true } -# tenderdash-abci = { path = "../../../rs-tenderdash-abci/abci", optional = true } +# tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", branch = "feat/sign-bytes", optional = true } +tenderdash-abci = { path = "../../../rs-tenderdash-abci/abci", optional = true } anyhow = { version = "1.0.70" } lazy_static = "1.4.0" itertools = { version = "0.10.5" } +[dev-dependencies] + [features] default = ["server"] server = ["tenderdash-abci", "clap", "dotenvy", "tracing-subscriber", "atty"] diff --git a/packages/rs-drive-abci/src/abci/commit.rs b/packages/rs-drive-abci/src/abci/commit.rs index c68461289e..6061e937c5 100644 --- a/packages/rs-drive-abci/src/abci/commit.rs +++ b/packages/rs-drive-abci/src/abci/commit.rs @@ -1,15 +1,30 @@ //! Tenderdash commit logic -use tenderdash_abci::proto::{self, abci::CommitInfo, signatures::SignBytes, types::BlockId}; +use dashcore_rpc::dashcore_rpc_json::QuorumType; +use dpp::bls_signatures::Serialize; +use tenderdash_abci::proto::{self, abci::CommitInfo, signatures::SignDigest, types::BlockId}; + +use super::AbciError; /// Represents commit for a block pub struct Commit { inner: proto::types::Commit, + chain_id: String, + quorum_type: QuorumType, } impl Commit { /// Create new Commit struct based on commit info and block id received from Tenderdash - pub fn new(ci: CommitInfo, block_id: BlockId, height: i64) -> Self { + pub fn new( + ci: CommitInfo, + block_id: BlockId, + height: i64, + quorum_type: QuorumType, + chain_id: &str, + ) -> Self { Self { + chain_id: String::from(chain_id), + quorum_type: quorum_type, + inner: proto::types::Commit { block_id: Some(block_id), height, @@ -20,10 +35,170 @@ impl Commit { }, } } + + /// Verify all signatures using provided public key. + /// + /// ## Return value + /// + /// * Ok(true) when all signatures are correct + /// * Ok(false) when at least one signature is invalid + /// * Err(e) on error + pub fn verify_signature( + &self, + signature: &Vec, + public_key: &dpp::bls_signatures::PublicKey, + ) -> Result { + // 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(signature.as_slice()) { + Ok(signature) => signature, + Err(e) => return Err(AbciError::from(e)), + }; + let hash = self + .inner + .sign_digest( + &self.chain_id, + self.quorum_type as u8, + self.inner.quorum_hash, + self.inner.height, + self.inner.round, + ) + .map_err(AbciError::TenderdashProto)?; + + Ok(public_key.verify(signature, hash)) + } } +// impl SignBytes for Commit { +// fn sign_bytes(&self, chain_id: &str, height: i64, round: i32) -> Result, proto::Error> { +// self.inner.sign_bytes(chain_id, height, round) +// } +// } + +#[cfg(test)] +mod test { + use super::{request_id, Commit}; + use crate::abci::signature_verifier::Signable; + use dashcore_rpc::{ + dashcore::hashes::sha256, dashcore::hashes::Hash, dashcore_rpc_json::QuorumType, + }; + use dpp::bls_signatures::Serialize; + use tenderdash_abci::proto::{ + abci::CommitInfo, + signatures::SignBytes, + types::{BlockId, PartSetHeader, StateId}, + }; + + #[test] + fn test_request_id() { + let expected = + hex::decode("28277743e77872951df01bda93a344feca2435e113b8824ce636eada665aadd5") + .unwrap(); + let got = request_id(super::VOTE_REQUEST_ID_PREFIX, 12, 34); + assert_eq!(expected, got); + } + /* + vote: Vote{ + Type: types.PrecommitType, + Height: 1001, + ValidatorProTxHash: tmbytes.MustHexDecode("9CC13F685BC3EA0FCA99B87F42ABCC934C6305AA47F62A32266A2B9D55306B7B"), + }, + quorumHash: tmbytes.MustHexDecode("6A12D9CF7091D69072E254B297AEF15997093E480FDE295E09A7DE73B31CEEDD"), + want: newSignItem( + "C8F2E1FE35DE03AC94F76191F59CAD1BA1F7A3C63742B7125990D996315001CC", + "DA25B746781DDF47B5D736F30B1D9D0CC86981EEC67CBE255265C4361DEF8C2E", + "02000000E9030000000000000000000000000000E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B"+ + "7852B855E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855646173682D706C6174666F726D", + ), + wantHash: tmbytes.MustHexDecode("0CA3D5F42BDFED0C4FDE7E6DE0F046CC76CDA6CEE734D65E8B2EE0E375D4C57D"), + + */ + #[test] + fn test_build_sign_hash() { + let quorum_hash = + hex::decode("6A12D9CF7091D69072E254B297AEF15997093E480FDE295E09A7DE73B31CEEDD") + .unwrap(); + let request_id = request_id(super::VOTE_REQUEST_ID_PREFIX, 1001, 0); + + let sign_bytes_hash = + hex::decode("0CA3D5F42BDFED0C4FDE7E6DE0F046CC76CDA6CEE734D65E8B2EE0E375D4C57D") + .unwrap(); + + let expect_sign_id = + hex::decode("DA25B746781DDF47B5D736F30B1D9D0CC86981EEC67CBE255265C4361DEF8C2E") + .unwrap(); + + let sign_id = super::build_sign_hash( + QuorumType::LlmqTest, + &quorum_hash, + &request_id, + &sign_bytes_hash, + ); + assert_eq!(expect_sign_id, sign_id); // 194,4 + } + + /// Verify that commit signature is correct + #[test] + fn test_commit_verify() { + const HEIGHT: i64 = 12345; + const ROUND: i32 = 2; + const CHAIN_ID: &str = "test_chain_id"; + + let ci = CommitInfo { + round: ROUND, + quorum_hash: vec![0u8; 32], + ..Default::default() + }; + let app_hash = [1u8, 2, 3, 4].repeat(8); + + let state_id = StateId { + height: HEIGHT as u64, + app_hash, + app_version: 1, + core_chain_locked_height: 3, + time: Some(tenderdash_abci::proto::google::protobuf::Timestamp { + seconds: 0, + nanos: 0, + }), + }; + + let block_id = BlockId { + hash: sha256::Hash::hash("blockID_hash".as_bytes()).to_vec(), + part_set_header: Some(PartSetHeader { + total: 1000000, + hash: sha256::Hash::hash("blockID_part_set_header_hash".as_bytes()).to_vec(), + }), + state_id: state_id + .sha256(CHAIN_ID, HEIGHT as i64, ROUND as i32) + .unwrap(), + }; + let pubkey = hex::decode( + "b7b76cbef11f48952b4c9778b0cd1e27948c6438c0480e69ce78\ + dc4748611f4463389450a6898f91b08f1de666934324", + ) + .unwrap(); + + let pubkey = dpp::bls_signatures::PublicKey::from_bytes(pubkey.as_slice()).unwrap(); + let signature = hex::decode("95e4a532ccb549cd4feca372b61dd2a5dedea2bb5c33ac22d70e310f\ + 7e38126b21029c29e6af6d00462b7c6f5e47047414dbfb2e1008fa0969a246bc38b61e96edddea9c35a01670b0ae45f0\ + 8a2626b251bb2a8e937547e65994f2c72d2e8f4e").unwrap(); + + let commit = Commit::new(ci, block_id, HEIGHT, QuorumType::LlmqTest, CHAIN_ID); + + let expect_sign_bytes = hex::decode("0200000039300000000000000200000000000000\ + 35117edfe49351da1e81d1b0f2edfa0b984a7508958870337126efb352f1210711ae5fef92053e8998c37cb4\ + 915968cadfbd2af4fa176b77ade0dadc74028fc5746573745f636861696e5f6964").unwrap(); + let expect_sign_id = + hex::decode("6f3cb0168cfaf3d9806be8a9eaa85d6ac10e2d32ce02e6a965a66f6c598b06cf") + .unwrap(); + assert_eq!( + expect_sign_bytes, + commit.sign_bytes(CHAIN_ID, HEIGHT, ROUND).unwrap() + ); + assert_eq!(expect_sign_id, commit.sign_id().unwrap()); + assert!(commit.verify_signature(&signature, &pubkey).unwrap()); -impl SignBytes for Commit { - fn sign_bytes(&self, chain_id: &str, height: i64, round: i32) -> Result, proto::Error> { - self.inner.sign_bytes(chain_id, height, round) + // mutate data and ensure it is invalid + let mut commit = commit; + commit.chain_id = "invalid".to_string(); + assert!(!commit.verify_signature(&signature, &pubkey).unwrap()); } } diff --git a/packages/rs-drive-abci/src/abci/error.rs b/packages/rs-drive-abci/src/abci/error.rs index 0f18f4a25e..e13c2b5d9c 100644 --- a/packages/rs-drive-abci/src/abci/error.rs +++ b/packages/rs-drive-abci/src/abci/error.rs @@ -1,4 +1,3 @@ -use super::signature_verifier::SignatureError; use crate::validator_set::ValidatorSetError; /// Error returned within ABCI server @@ -39,9 +38,13 @@ pub enum AbciError { #[error("tenderdash: {0}")] Tenderdash(#[from] tenderdash_abci::Error), - /// Error occurred during signature verification - #[error("signature error: {0}")] - SignatureError(#[from] SignatureError), + /// Error occurred during protobuf data manipulation + #[error("tenderdash protobuf: {0}")] + TenderdashProto(tenderdash_abci::proto::Error), + + /// Error during BLS cryptographic processing + #[error("bls crypto processing: {0}")] + BlsError(#[from] dpp::bls_signatures::Error), /// Error occurred during validator set creation #[error("validator set: {0}")] diff --git a/packages/rs-drive-abci/src/abci/mod.rs b/packages/rs-drive-abci/src/abci/mod.rs index c5206a306a..35705362f5 100644 --- a/packages/rs-drive-abci/src/abci/mod.rs +++ b/packages/rs-drive-abci/src/abci/mod.rs @@ -16,7 +16,6 @@ pub mod mimic; mod server; pub mod commit; -pub mod signature_verifier; pub mod withdrawal; pub use error::AbciError; diff --git a/packages/rs-drive-abci/src/abci/signature_verifier.rs b/packages/rs-drive-abci/src/abci/signature_verifier.rs deleted file mode 100644 index 07d60ed9a7..0000000000 --- a/packages/rs-drive-abci/src/abci/signature_verifier.rs +++ /dev/null @@ -1,56 +0,0 @@ -//! Signature verification - -use dpp::bls_signatures::Serialize; -use tenderdash_abci::proto::signatures::SignBytes; - -/// Errors occured during signature verification -#[derive(Debug, thiserror::Error)] -pub enum SignatureError { - /// Error occurred during bls signature verification - #[error("bls error set: {0}")] - BLSError(#[from] dpp::bls_signatures::Error), - - /// Error creating canonical form of signed data - #[error("error creating canonical form of signed data: {0}")] - CanonicalError(tenderdash_abci::proto::Error), -} -/// SignatureVerifier can be used to verify a BLS signature. -pub trait SignatureVerifier { - /// Verify all signatures using provided public key. - /// - /// ## Return value - /// - /// * Ok(true) when all signatures are correct - /// * Ok(false) when at least one signature is invalid - /// * Err(e) on error - fn verify_signature( - &self, - signature: &Vec, - chain_id: &str, - height: i64, - round: i32, - quorum_public_key: &dpp::bls_signatures::PublicKey, - ) -> Result; -} - -impl SignatureVerifier for T { - fn verify_signature( - &self, - signature: &Vec, - chain_id: &str, - height: i64, - round: i32, - quorum_public_key: &dpp::bls_signatures::PublicKey, - ) -> Result { - // 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(signature.as_slice()) { - Ok(signature) => signature, - Err(e) => return Err(SignatureError::from(e)), - }; - - let hash = self - .sha256(chain_id, height, round) - .map_err(SignatureError::CanonicalError)?; - Ok(quorum_public_key.verify(signature, hash)) - } -} diff --git a/packages/rs-drive-abci/src/abci/withdrawal.rs b/packages/rs-drive-abci/src/abci/withdrawal.rs index fff36a6eec..537cc19819 100644 --- a/packages/rs-drive-abci/src/abci/withdrawal.rs +++ b/packages/rs-drive-abci/src/abci/withdrawal.rs @@ -12,10 +12,7 @@ use tenderdash_abci::proto::{ types::{VoteExtension, VoteExtensionType}, }; -use super::{ - signature_verifier::{SignatureError, SignatureVerifier}, - AbciError, -}; +use super::AbciError; const MAX_WITHDRAWAL_TXS: u16 = 16; @@ -100,12 +97,13 @@ impl<'a> WithdrawalTxs<'a> { height: i64, round: i32, quorum_public_key: bls_signatures::PublicKey, - ) -> Result { + ) -> Result { // self.inner.all(|s| s.verify_signature()) for s in &self.inner { - if !s.verify_signature(&s.signature, chain_id, height, round, &quorum_public_key)? { - return Ok(false); - } + // TODO: fix + // if !s.verify_signature(&s.signature, &quorum_public_key)? { + // return Ok(false); + // } } Ok(true) diff --git a/packages/rs-drive-abci/src/asset_lock/fetch_tx_out.rs b/packages/rs-drive-abci/src/asset_lock/fetch_tx_out.rs index 6e42e49c1c..5400ece500 100644 --- a/packages/rs-drive-abci/src/asset_lock/fetch_tx_out.rs +++ b/packages/rs-drive-abci/src/asset_lock/fetch_tx_out.rs @@ -1,14 +1,14 @@ use crate::error::execution::ExecutionError; use crate::error::Error; use crate::rpc::core::CoreRPCLike; -use dashcore::hashes::Hash; -use dashcore::{OutPoint, TxOut}; use dpp::consensus::basic::identity::{ IdentityAssetLockTransactionIsNotFoundError, IdentityAssetLockTransactionOutputNotFoundError, InvalidAssetLockProofCoreChainHeightError, InvalidIdentityAssetLockProofChainLockValidationError, }; use dpp::consensus::ConsensusError; +use dpp::dashcore::hashes::Hash; +use dpp::dashcore::{OutPoint, TxOut}; use dpp::identity::state_transition::asset_lock_proof::AssetLockProof; use dpp::validation::ValidationResult; diff --git a/packages/rs-drive-abci/src/error/execution.rs b/packages/rs-drive-abci/src/error/execution.rs index 5e5534e119..61ee240626 100644 --- a/packages/rs-drive-abci/src/error/execution.rs +++ b/packages/rs-drive-abci/src/error/execution.rs @@ -1,5 +1,5 @@ use crate::error::data_trigger::DataTriggerError; -use dashcore::consensus::encode::Error as DashCoreConsensusEncodeError; +use dpp::dashcore::consensus::encode::Error as DashCoreConsensusEncodeError; use drive::error::Error as DriveError; /// Execution errors diff --git a/packages/rs-drive-abci/src/execution/engine.rs b/packages/rs-drive-abci/src/execution/engine.rs index 33eafcb674..accca8b832 100644 --- a/packages/rs-drive-abci/src/execution/engine.rs +++ b/packages/rs-drive-abci/src/execution/engine.rs @@ -16,7 +16,6 @@ use drive::grovedb::{Transaction, TransactionArg}; use tenderdash_abci::proto::abci::{ExecTxResult, RequestFinalizeBlock}; use tenderdash_abci::proto::serializers::timestamp::ToMilis; -use crate::abci::signature_verifier::{SignatureError, SignatureVerifier}; use crate::abci::withdrawal::WithdrawalTxs; use crate::abci::AbciError; use crate::block::{BlockExecutionContext, BlockStateInfo}; @@ -255,9 +254,9 @@ where // destructure the block proposal let BlockProposal { - block_hash:_, + block_hash: _, height, - round:_, + round: _, core_chain_locked_height, proposed_app_version, proposer_pro_tx_hash, @@ -381,7 +380,7 @@ where .quorum_public_key; bls_signatures::PublicKey::from_bytes(public_key.as_slice()) - .map_err(|e| AbciError::from(SignatureError::from(e)).into()) + .map_err(|e| AbciError::from(e).into()) } /// Finalize the block, this first involves validating it, then if valid /// it is committed to the state @@ -465,15 +464,16 @@ where let quorum_public_key = self.get_quorum_key(commit_info.quorum_hash.clone())?; // Verify commit - let commit = Commit::new(commit_info.clone(), block_id.clone(), height); + let quorum_type = self.config.quorum_type; + let commit = Commit::new( + commit_info.clone(), + block_id.clone(), + height, + quorum_type, + &block_header.chain_id, + ); commit - .verify_signature( - &commit_info.block_signature, - &block_header.chain_id, - height, - round, - &quorum_public_key, - ) + .verify_signature(&commit_info.block_signature, &quorum_public_key) .map_err(AbciError::from)?; // Verify vote extensions; right now, we only support withdrawal txs diff --git a/packages/rs-drive-abci/src/platform/mod.rs b/packages/rs-drive-abci/src/platform/mod.rs index 1fbed4d0bd..3bd9e49f95 100644 --- a/packages/rs-drive-abci/src/platform/mod.rs +++ b/packages/rs-drive-abci/src/platform/mod.rs @@ -43,8 +43,8 @@ use std::path::Path; use std::sync::RwLock; use crate::rpc::core::MockCoreRPCLike; -use dashcore::hashes::hex::FromHex; -use dashcore::BlockHash; +use dpp::dashcore::hashes::hex::FromHex; +use dpp::dashcore::BlockHash; use serde_json::json; mod state_repository; diff --git a/packages/rs-drive-abci/src/rpc/core.rs b/packages/rs-drive-abci/src/rpc/core.rs index e391eb96de..54e6e37678 100644 --- a/packages/rs-drive-abci/src/rpc/core.rs +++ b/packages/rs-drive-abci/src/rpc/core.rs @@ -1,4 +1,3 @@ -use dashcore::{Block, BlockHash, Transaction, Txid}; use dashcore_rpc::dashcore_rpc_json::{ ExtendedQuorumDetails, GetBestChainLockResult, MasternodeListDiff, ProTxHash, ProTxInfo, QuorumHash, QuorumInfoResult, QuorumListResult, QuorumType, @@ -6,6 +5,7 @@ use dashcore_rpc::dashcore_rpc_json::{ use dashcore_rpc::json::GetTransactionResult; use dashcore_rpc::Error; use dashcore_rpc::{Auth, Client, RpcApi}; +use dpp::dashcore::{Block, BlockHash, Transaction, Txid}; use mockall::{automock, predicate::*}; use serde_json::Value; use std::collections::HashMap; diff --git a/packages/rs-drive-abci/tests/strategy_tests/main.rs b/packages/rs-drive-abci/tests/strategy_tests/main.rs index fd78a237c7..189f9763a5 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/main.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/main.rs @@ -31,11 +31,11 @@ //! use anyhow::anyhow; -use dashcore::secp256k1::SecretKey; -use dashcore::{signer, Network, PrivateKey}; use dashcore_rpc::dashcore_rpc_json::{ ExtendedQuorumDetails, QuorumHash as QuorumHashObject, QuorumInfoResult, QuorumType, }; +use dpp::dashcore::secp256k1::SecretKey; +use dpp::dashcore::{signer, Network, PrivateKey}; use dpp::data_contract::state_transition::data_contract_create_transition::DataContractCreateTransition; use dpp::document::document_transition::document_base_transition::DocumentBaseTransition; use dpp::document::document_transition::{ @@ -1245,9 +1245,9 @@ pub(crate) fn continue_chain_for_strategy( mod tests { use super::*; use crate::DocumentAction::DocumentActionReplace; - use dashcore::hashes::Hash; - use dashcore::BlockHash; use dashcore_rpc::dashcore_rpc_json::{ExtendedQuorumDetails, QuorumHash}; + use dpp::dashcore::hashes::Hash; + use dpp::dashcore::BlockHash; use drive::dpp::data_contract::extra::common::json_document_to_cbor; use drive::dpp::data_contract::DriveContractExt; use drive_abci::rpc::core::QuorumListExtendedInfo; From ec645e4981849c7f217a12a03d4071825607e41b Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 17 Apr 2023 14:31:21 +0200 Subject: [PATCH 05/15] test(rs-drive-abci): cleanup tests --- packages/rs-drive-abci/src/abci/commit.rs | 25 +------------------ .../rs-drive-abci/src/execution/quorum.rs | 1 - 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/packages/rs-drive-abci/src/abci/commit.rs b/packages/rs-drive-abci/src/abci/commit.rs index 57c483072e..1e6313779e 100644 --- a/packages/rs-drive-abci/src/abci/commit.rs +++ b/packages/rs-drive-abci/src/abci/commit.rs @@ -111,30 +111,7 @@ mod test { wantHash: tmbytes.MustHexDecode("0CA3D5F42BDFED0C4FDE7E6DE0F046CC76CDA6CEE734D65E8B2EE0E375D4C57D"), */ - #[test] - fn test_build_sign_hash() { - let quorum_hash = - hex::decode("6A12D9CF7091D69072E254B297AEF15997093E480FDE295E09A7DE73B31CEEDD") - .unwrap(); - let request_id = request_id(super::VOTE_REQUEST_ID_PREFIX, 1001, 0); - - let sign_bytes_hash = - hex::decode("0CA3D5F42BDFED0C4FDE7E6DE0F046CC76CDA6CEE734D65E8B2EE0E375D4C57D") - .unwrap(); - - let expect_sign_id = - hex::decode("DA25B746781DDF47B5D736F30B1D9D0CC86981EEC67CBE255265C4361DEF8C2E") - .unwrap(); - - let sign_id = super::build_sign_hash( - QuorumType::LlmqTest, - &quorum_hash, - &request_id, - &sign_bytes_hash, - ); - assert_eq!(expect_sign_id, sign_id); // 194,4 - } - + /// Verify that commit signature is correct #[test] fn test_commit_verify() { diff --git a/packages/rs-drive-abci/src/execution/quorum.rs b/packages/rs-drive-abci/src/execution/quorum.rs index 91937b4bd1..e89da356cf 100644 --- a/packages/rs-drive-abci/src/execution/quorum.rs +++ b/packages/rs-drive-abci/src/execution/quorum.rs @@ -3,7 +3,6 @@ use crate::error::execution::ExecutionError; use crate::error::Error; use bls_signatures::PublicKey as BlsPublicKey; use dashcore::{ProTxHash, QuorumHash}; -use dashcore_rpc::dashcore_rpc_json::MasternodeListItem; use dashcore_rpc::json::QuorumInfoResult; use std::collections::BTreeMap; From 4542c0f418f9eb855cd6808df2ff7d93efe94e9b Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 17 Apr 2023 15:10:37 +0200 Subject: [PATCH 06/15] chore(rs-drive-abci): fix after merge --- Cargo.lock | 3 + packages/rs-drive-abci/Cargo.toml | 13 ++- packages/rs-drive-abci/src/abci/handlers.rs | 71 ++++++++------- .../rs-drive-abci/src/execution/engine.rs | 88 ++++++++++--------- 4 files changed, 97 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2c62ab6df7..1395c85fb5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3421,6 +3421,7 @@ dependencies = [ [[package]] name = "tenderdash-abci" version = "0.12.0-dev.1" +source = "git+https://github.com/dashpay/rs-tenderdash-abci?branch=feat/sign-bytes#ae1a80905e487207ef3d196d32b9d5f3ff99630e" dependencies = [ "bytes", "prost", @@ -3435,6 +3436,7 @@ dependencies = [ [[package]] name = "tenderdash-proto" version = "0.12.0-dev.1" +source = "git+https://github.com/dashpay/rs-tenderdash-abci?branch=feat/sign-bytes#ae1a80905e487207ef3d196d32b9d5f3ff99630e" dependencies = [ "bytes", "chrono", @@ -3453,6 +3455,7 @@ dependencies = [ [[package]] name = "tenderdash-proto-compiler" version = "0.1.0" +source = "git+https://github.com/dashpay/rs-tenderdash-abci?branch=feat/sign-bytes#ae1a80905e487207ef3d196d32b9d5f3ff99630e" dependencies = [ "fs_extra", "prost-build", diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 0f36567eff..99d28b19bb 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -50,8 +50,8 @@ tracing-subscriber = { version = "0.3.16", default-features = false, features = "ansi", ], optional = true } atty = { version = "0.2.14", optional = true } -# tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", branch = "feat/sign-bytes", optional = true } -tenderdash-abci = { path = "../../../rs-tenderdash-abci/abci", optional = true } +tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", branch = "feat/sign-bytes", optional = true } +# tenderdash-abci = { path = "../../../rs-tenderdash-abci/abci", optional = true } anyhow = { version = "1.0.70" } lazy_static = "1.4.0" itertools = { version = "0.10.5" } @@ -60,7 +60,14 @@ itertools = { version = "0.10.5" } [features] default = ["server"] -server = ["tenderdash-abci", "clap", "dotenvy", "tracing-subscriber", "atty", "mockall"] +server = [ + "tenderdash-abci", + "clap", + "dotenvy", + "tracing-subscriber", + "atty", + "mockall", +] [[bin]] name = "drive-abci" diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 2b20d05355..64d82f3c13 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -217,7 +217,9 @@ where request: proto::RequestExtendVote, ) -> Result { let proto::RequestExtendVote { - hash: block_hash, height, round + hash: block_hash, + height, + round, } = request; let guarded_block_execution_context = self.platform.block_execution_context.read().unwrap(); let block_execution_context = @@ -230,20 +232,21 @@ where let block_state_info = &block_execution_context.block_state_info; if !block_state_info.matches_current_block(height as u64, round as u32, block_hash)? { - return Err(Error::from(AbciError::RequestForWrongBlockReceived( - format!( - "received request for height: {} rount: {}, expected height: {} round: {}", - height, round, block_state_info.height, block_state_info.round - ), - )).into()); + return Err(Error::from(AbciError::RequestForWrongBlockReceived(format!( + "received request for height: {} rount: {}, expected height: {} round: {}", + height, round, block_state_info.height, block_state_info.round + ))) + .into()); } else { // we only want to sign the hash of the transaction - let extensions = block_execution_context.withdrawal_transactions.keys().map(|tx_id| { - ExtendVoteExtension { + let extensions = block_execution_context + .withdrawal_transactions + .keys() + .map(|tx_id| ExtendVoteExtension { r#type: VoteExtensionType::ThresholdRecover as i32, extension: tx_id.to_vec(), - } - }).collect(); + }) + .collect(); Ok(proto::ResponseExtendVote { vote_extensions: extensions, }) @@ -256,8 +259,11 @@ where request: proto::RequestVerifyVoteExtension, ) -> Result { let proto::RequestVerifyVoteExtension { - hash: block_hash, validator_pro_tx_hash, height, - round, vote_extensions + hash: block_hash, + validator_pro_tx_hash, + height, + round, + vote_extensions, } = request; let guarded_block_execution_context = self.platform.block_execution_context.read().unwrap(); @@ -271,21 +277,23 @@ where let block_state_info = &block_execution_context.block_state_info; if !block_state_info.matches_current_block(height as u64, round as u32, block_hash)? { - return Err(Error::from(AbciError::RequestForWrongBlockReceived( - format!( - "received request for height: {} rount: {}, expected height: {} round: {}", - height, round, block_state_info.height, block_state_info.round - ), - )).into()); + return Err(Error::from(AbciError::RequestForWrongBlockReceived(format!( + "received request for height: {} rount: {}, expected height: {} round: {}", + height, round, block_state_info.height, block_state_info.round + ))) + .into()); } let got: WithdrawalTxs = vote_extensions.into(); - let expected = block_execution_context.withdrawal_transactions.keys().map(|tx_id| { - ExtendVoteExtension { + let expected = block_execution_context + .withdrawal_transactions + .keys() + .map(|tx_id| ExtendVoteExtension { r#type: VoteExtensionType::ThresholdRecover as i32, extension: tx_id.to_vec(), - } - }).collect::>().into(); + }) + .collect::>() + .into(); // let state = self.platform.state.read().unwrap(); // @@ -307,7 +315,7 @@ where let validation_result = self.platform - .check_withdrawals(&got, &expected, None); + .check_withdrawals(&got, &expected, None, height as u64, round as u32); if validation_result.is_valid() { Ok(proto::ResponseVerifyVoteExtension { @@ -315,17 +323,16 @@ where }) } else { tracing::error!( - method = "verify_vote_extension", - ?got, - ?expected, - ?validation_result.errors, - "vote extension mismatch" - ); + method = "verify_vote_extension", + ?got, + ?expected, + ?validation_result.errors, + "vote extension mismatch" + ); Ok(proto::ResponseVerifyVoteExtension { status: VerifyStatus::Reject.into(), }) } - } fn finalize_block( @@ -954,4 +961,4 @@ where // } // } // } -// } \ No newline at end of file +// } diff --git a/packages/rs-drive-abci/src/execution/engine.rs b/packages/rs-drive-abci/src/execution/engine.rs index 81235fb3fa..9c7a668166 100644 --- a/packages/rs-drive-abci/src/execution/engine.rs +++ b/packages/rs-drive-abci/src/execution/engine.rs @@ -1,4 +1,3 @@ -use std::collections::BTreeMap; use bls_signatures; use dashcore::hashes::Hash; use dashcore::{QuorumHash, Txid}; @@ -13,11 +12,11 @@ use drive::drive::block_info::BlockInfo; use drive::error::Error::GroveDB; use drive::fee::result::FeeResult; use drive::grovedb::{Transaction, TransactionArg}; -use tenderdash_abci::proto::abci::{ExecTxResult, RequestFinalizeBlock}; +use std::collections::BTreeMap; +use tenderdash_abci::proto::abci::ExecTxResult; use tenderdash_abci::proto::serializers::timestamp::ToMilis; -use tenderdash_abci::proto::types::Block; -use crate::abci::signature_verifier::SignatureVerifier; +use crate::abci::commit::Commit; use crate::abci::withdrawal::WithdrawalTxs; use crate::abci::AbciError; use crate::abci::AbciError::BlsError; @@ -322,9 +321,15 @@ where )?; // Set the withdrawal transactions - block_execution_context.withdrawal_transactions = unsigned_withdrawal_transaction_bytes.into_iter().map(|withdrawal_transaction| { - (Txid::hash(withdrawal_transaction.as_slice()), withdrawal_transaction) - }).collect(); + block_execution_context.withdrawal_transactions = unsigned_withdrawal_transaction_bytes + .into_iter() + .map(|withdrawal_transaction| { + ( + Txid::hash(withdrawal_transaction.as_slice()), + withdrawal_transaction, + ) + }) + .collect(); let (block_fees, tx_results) = self.process_raw_state_transitions(&raw_state_transitions, &block_info, transaction)?; @@ -395,6 +400,8 @@ where received_withdrawals: &WithdrawalTxs, our_withdrawals: &WithdrawalTxs, verify_with_validator_public_key: Option<&bls_signatures::PublicKey>, + height: u64, + round: u32, ) -> SimpleValidationResult { if received_withdrawals.ne(&our_withdrawals) { return SimpleValidationResult::new_with_error( @@ -407,30 +414,24 @@ where // we only verify if verify_with_validator_public_key exists if let Some(validator_public_key) = verify_with_validator_public_key { - let validation_result = received_withdrawals.verify_signature(validator_public_key); + let validation_result = received_withdrawals.verify_signatures( + &self.config.abci.chain_id, + height, + round, + validator_public_key, + ); // There are two types of errors, // The first is that the signature was invalid and that is shown with the result bool as false // The second is that the signature is malformed, and that gives a BLSError // However for this case we want to treat both as errors - - if validation_result.is_valid() { - let value = validation_result.into_data().expect("expected data"); - if value == true { - SimpleValidationResult::default() - } else { - SimpleValidationResult::new_with_error(AbciError::VoteExtensionsSignatureInvalid) - } - } else { - SimpleValidationResult::new_with_error( - validation_result - .errors - .into_iter() - .next() - .expect("expected an error") - .into(), - ) + match validation_result { + Ok(true) => SimpleValidationResult::default(), + Ok(false) => SimpleValidationResult::new_with_error( + AbciError::VoteExtensionsSignatureInvalid, + ), + Err(e) => SimpleValidationResult::new_with_error(e), } } else { SimpleValidationResult::default() @@ -473,12 +474,13 @@ where let BlockExecutionContext { block_state_info, epoch_info, - hpmn_count, withdrawal_transactions, + hpmn_count, + withdrawal_transactions, } = &block_execution_context; // Let's decompose the request let FinalizeBlockCleanedRequest { - commit, + commit: commit_info, misbehavior, hash, height, @@ -515,28 +517,28 @@ where } let mut state = self.state.write().unwrap(); - if state.current_validator_set_quorum_hash.as_inner() != &commit.quorum_hash { + if state.current_validator_set_quorum_hash.as_inner() != &commit_info.quorum_hash { validation_result.add_error(AbciError::WrongFinalizeBlockReceived(format!( "received a block for h: {} r: {} with validator set quorum hash {} expected current validator set quorum hash is {}", - height, round, hex::encode(commit.quorum_hash), hex::encode(state.current_validator_set_quorum_hash) + height, round, hex::encode(commit_info.quorum_hash), hex::encode(state.current_validator_set_quorum_hash) ))); } - let quorum_public_key = self.get_quorum_key(commit.quorum_hash)?; + let quorum_public_key = self.get_quorum_key(commit_info.quorum_hash)?; - //todo: verify commit - // if let Some(block_id) = block_id { - // let result = self.validate_commit(commit.clone(), block_id, quorum_public_key)?; - // if !result.is_valid() { - // return Ok(validation_result.into()); - // } - // } else { - // validation_result.add_error(AbciError::WrongFinalizeBlockReceived(format!( - // "received a block for h: {} r: {} without a block id", - // height, round - // ))); - // return Ok(validation_result.into()); - // } + // Verify commit + + let quorum_type = self.config.quorum_type; + let commit = Commit::new( + commit_info.clone(), + block_id.clone(), + height, + quorum_type, + &block_header.chain_id, + ); + commit + .verify_signature(&commit_info.block_signature.to_vec(), &quorum_public_key) + .map_err(AbciError::from)?; // Verify vote extensions // let received_withdrawals = WithdrawalTxs::from(&commit.threshold_vote_extensions); From d0c02b9a1f099c94232eae25f516c5564190bcab Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 17 Apr 2023 15:31:11 +0200 Subject: [PATCH 07/15] chore(rs-drive-abci): self-review --- Cargo.lock | 51 +++++++++++++++++++++ Cargo.toml | 3 +- packages/rs-drive-abci/src/abci/commit.rs | 38 ++------------- packages/rs-drive-abci/src/abci/error.rs | 2 +- packages/rs-drive-abci/src/abci/handlers.rs | 4 +- 5 files changed, 58 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1395c85fb5..a4745dd765 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -683,6 +683,16 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + [[package]] name = "constant_time_eq" version = "0.2.5" @@ -3116,6 +3126,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.5.0" +source = "git+https://github.com/QuantumExplorer/serde-wasm-bindgen?branch=feat/not_human_readable#121d1f7fbf62cb97f74b91626a1b23851098cc82" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_bytes" version = "0.11.9" @@ -3912,6 +3932,18 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.84" @@ -3941,6 +3973,25 @@ version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +[[package]] +name = "wasm-dpp" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "console_error_panic_hook", + "dpp", + "itertools", + "js-sys", + "serde", + "serde-wasm-bindgen", + "serde_json", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-sys" version = "0.3.61" diff --git a/Cargo.toml b/Cargo.toml index 5ba6ae4bff..1e84b12d92 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ members = [ "packages/rs-dpp", - # "packages/wasm-dpp", + "packages/wasm-dpp", "packages/rs-drive", "packages/rs-platform-value", "packages/rs-drive-abci", @@ -14,4 +14,3 @@ members = [ "packages/dpns-contract", "packages/data-contracts", ] -exclude = ["packages/wasm-dpp"] diff --git a/packages/rs-drive-abci/src/abci/commit.rs b/packages/rs-drive-abci/src/abci/commit.rs index bce91f503f..c962ef2dbf 100644 --- a/packages/rs-drive-abci/src/abci/commit.rs +++ b/packages/rs-drive-abci/src/abci/commit.rs @@ -1,11 +1,11 @@ -//! Tenderdash commit logic +//! Processing of commits generated by Tenderdash use crate::execution::finalize_block_cleaned_request::{CleanedBlockId, CleanedCommitInfo}; use dashcore_rpc::dashcore_rpc_json::QuorumType; use tenderdash_abci::proto::{self, signatures::SignDigest}; use super::AbciError; -/// Represents commit for a block +/// Represents block commit pub struct Commit { inner: proto::types::Commit, chain_id: String, @@ -67,11 +67,6 @@ impl Commit { Ok(public_key.verify(&signature, &hash)) } } -// impl SignBytes for Commit { -// fn sign_bytes(&self, chain_id: &str, height: i64, round: i32) -> Result, proto::Error> { -// self.inner.sign_bytes(chain_id, height, round) -// } -// } #[cfg(test)] mod test { @@ -79,39 +74,12 @@ mod test { use dashcore_rpc::{ dashcore::hashes::sha256, dashcore::hashes::Hash, dashcore_rpc_json::QuorumType, }; - use dpp::bls_signatures::Serialize; use tenderdash_abci::proto::{ abci::CommitInfo, - signatures::SignBytes, types::{BlockId, PartSetHeader, StateId}, }; - #[test] - fn test_request_id() { - let expected = - hex::decode("28277743e77872951df01bda93a344feca2435e113b8824ce636eada665aadd5") - .unwrap(); - let got = request_id(super::VOTE_REQUEST_ID_PREFIX, 12, 34); - assert_eq!(expected, got); - } - /* - vote: Vote{ - Type: types.PrecommitType, - Height: 1001, - ValidatorProTxHash: tmbytes.MustHexDecode("9CC13F685BC3EA0FCA99B87F42ABCC934C6305AA47F62A32266A2B9D55306B7B"), - }, - quorumHash: tmbytes.MustHexDecode("6A12D9CF7091D69072E254B297AEF15997093E480FDE295E09A7DE73B31CEEDD"), - want: newSignItem( - "C8F2E1FE35DE03AC94F76191F59CAD1BA1F7A3C63742B7125990D996315001CC", - "DA25B746781DDF47B5D736F30B1D9D0CC86981EEC67CBE255265C4361DEF8C2E", - "02000000E9030000000000000000000000000000E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B"+ - "7852B855E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855646173682D706C6174666F726D", - ), - wantHash: tmbytes.MustHexDecode("0CA3D5F42BDFED0C4FDE7E6DE0F046CC76CDA6CEE734D65E8B2EE0E375D4C57D"), - - */ - - /// Verify that commit signature is correct + /// Given a commit info and a signature, check that the signature is verified correctly #[test] fn test_commit_verify() { const HEIGHT: i64 = 12345; diff --git a/packages/rs-drive-abci/src/abci/error.rs b/packages/rs-drive-abci/src/abci/error.rs index 33246f71a2..0a249a6df0 100644 --- a/packages/rs-drive-abci/src/abci/error.rs +++ b/packages/rs-drive-abci/src/abci/error.rs @@ -40,7 +40,7 @@ pub enum AbciError { Tenderdash(#[from] tenderdash_abci::Error), /// Error occurred during protobuf data manipulation - #[error("tenderdash protobuf: {0}")] + #[error("tenderdash data: {0}")] TenderdashProto(tenderdash_abci::proto::Error), /// Error occurred during signature verification or deserializing a BLS primitive diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index 64d82f3c13..e24c8de1e7 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -233,7 +233,7 @@ where if !block_state_info.matches_current_block(height as u64, round as u32, block_hash)? { return Err(Error::from(AbciError::RequestForWrongBlockReceived(format!( - "received request for height: {} rount: {}, expected height: {} round: {}", + "received request for height: {} round: {}, expected height: {} round: {}", height, round, block_state_info.height, block_state_info.round ))) .into()); @@ -278,7 +278,7 @@ where if !block_state_info.matches_current_block(height as u64, round as u32, block_hash)? { return Err(Error::from(AbciError::RequestForWrongBlockReceived(format!( - "received request for height: {} rount: {}, expected height: {} round: {}", + "received request for height: {} round: {}, expected height: {} round: {}", height, round, block_state_info.height, block_state_info.round ))) .into()); From d57736c0ead5ab12bd55c88c1168f9384cd68a5c Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 17 Apr 2023 16:54:14 +0200 Subject: [PATCH 08/15] test(rs-drive-abci): fix commit tests --- packages/rs-drive-abci/src/abci/commit.rs | 45 ++++++++++++++++++----- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/packages/rs-drive-abci/src/abci/commit.rs b/packages/rs-drive-abci/src/abci/commit.rs index c962ef2dbf..d3910aa1b5 100644 --- a/packages/rs-drive-abci/src/abci/commit.rs +++ b/packages/rs-drive-abci/src/abci/commit.rs @@ -70,12 +70,15 @@ impl Commit { #[cfg(test)] mod test { + use crate::execution::finalize_block_cleaned_request::CleanedCommitInfo; + use super::Commit; + use bls_signatures::PublicKey; use dashcore_rpc::{ dashcore::hashes::sha256, dashcore::hashes::Hash, dashcore_rpc_json::QuorumType, }; use tenderdash_abci::proto::{ - abci::CommitInfo, + signatures::{SignBytes, SignDigest}, types::{BlockId, PartSetHeader, StateId}, }; @@ -83,13 +86,16 @@ mod test { #[test] fn test_commit_verify() { const HEIGHT: i64 = 12345; - const ROUND: i32 = 2; + const ROUND: u32 = 2; const CHAIN_ID: &str = "test_chain_id"; - let ci = CommitInfo { + const QUORUM_HASH: [u8; 32] = [0u8; 32]; + + let ci = CleanedCommitInfo { round: ROUND, - quorum_hash: vec![0u8; 32], - ..Default::default() + quorum_hash: QUORUM_HASH, + block_signature: [0u8; 96], + threshold_vote_extensions: Vec::new(), }; let app_hash = [1u8, 2, 3, 4].repeat(8); @@ -120,12 +126,18 @@ mod test { ) .unwrap(); - let pubkey = dpp::bls_signatures::PublicKey::from_bytes(pubkey.as_slice()).unwrap(); + let pubkey = PublicKey::from_bytes(pubkey.as_slice()).unwrap(); let signature = hex::decode("95e4a532ccb549cd4feca372b61dd2a5dedea2bb5c33ac22d70e310f\ 7e38126b21029c29e6af6d00462b7c6f5e47047414dbfb2e1008fa0969a246bc38b61e96edddea9c35a01670b0ae45f0\ 8a2626b251bb2a8e937547e65994f2c72d2e8f4e").unwrap(); - let commit = Commit::new(ci, block_id, HEIGHT, QuorumType::LlmqTest, CHAIN_ID); + let commit = Commit::new( + ci, + block_id.try_into().unwrap(), + HEIGHT as u64, + QuorumType::LlmqTest, + CHAIN_ID, + ); let expect_sign_bytes = hex::decode("0200000039300000000000000200000000000000\ 35117edfe49351da1e81d1b0f2edfa0b984a7508958870337126efb352f1210711ae5fef92053e8998c37cb4\ @@ -135,9 +147,24 @@ mod test { .unwrap(); assert_eq!( expect_sign_bytes, - commit.sign_bytes(CHAIN_ID, HEIGHT, ROUND).unwrap() + commit + .inner + .sign_bytes(CHAIN_ID, HEIGHT, ROUND as i32) + .unwrap() + ); + assert_eq!( + expect_sign_id, + commit + .inner + .sign_digest( + CHAIN_ID, + QuorumType::LlmqTest as u8, + &QUORUM_HASH, + HEIGHT, + ROUND as i32 + ) + .unwrap() ); - assert_eq!(expect_sign_id, commit.sign_id().unwrap()); assert!(commit.verify_signature(&signature, &pubkey).unwrap()); // mutate data and ensure it is invalid From c85074a6711d3806653574851316ce621ca8107e Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 17 Apr 2023 17:07:08 +0200 Subject: [PATCH 09/15] feat(rs-drive-abci): withdrawal tx signature verification --- Cargo.lock | 61 ++----------------- packages/rs-drive-abci/src/abci/commit.rs | 7 +-- packages/rs-drive-abci/src/abci/handlers.rs | 11 +++- packages/rs-drive-abci/src/abci/withdrawal.rs | 55 ++++++++++++++--- .../rs-drive-abci/src/execution/engine.rs | 6 +- 5 files changed, 68 insertions(+), 72 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4745dd765..df1bfa34e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -683,16 +683,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - [[package]] name = "constant_time_eq" version = "0.2.5" @@ -955,7 +945,7 @@ dependencies = [ [[package]] name = "dashcore-rpc" version = "0.15.0" -source = "git+https://github.com/dashpay/rust-dashcore-rpc?branch=feat/quorumListImprovement#4362e2f90677fac3a53cb5b5a9f3e52a9b1665b2" +source = "git+https://github.com/dashpay/rust-dashcore-rpc?branch=feat/quorumListImprovement#03b1c43b33670644971e1557ce97dc17bf55e868" dependencies = [ "dashcore-rpc-json", "env_logger 0.10.0", @@ -968,7 +958,7 @@ dependencies = [ [[package]] name = "dashcore-rpc-json" version = "0.15.0" -source = "git+https://github.com/dashpay/rust-dashcore-rpc?branch=feat/quorumListImprovement#4362e2f90677fac3a53cb5b5a9f3e52a9b1665b2" +source = "git+https://github.com/dashpay/rust-dashcore-rpc?branch=feat/quorumListImprovement#03b1c43b33670644971e1557ce97dc17bf55e868" dependencies = [ "dashcore", "hex", @@ -3126,16 +3116,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde-wasm-bindgen" -version = "0.5.0" -source = "git+https://github.com/QuantumExplorer/serde-wasm-bindgen?branch=feat/not_human_readable#121d1f7fbf62cb97f74b91626a1b23851098cc82" -dependencies = [ - "js-sys", - "serde", - "wasm-bindgen", -] - [[package]] name = "serde_bytes" version = "0.11.9" @@ -3441,7 +3421,7 @@ dependencies = [ [[package]] name = "tenderdash-abci" version = "0.12.0-dev.1" -source = "git+https://github.com/dashpay/rs-tenderdash-abci?branch=feat/sign-bytes#ae1a80905e487207ef3d196d32b9d5f3ff99630e" +source = "git+https://github.com/dashpay/rs-tenderdash-abci?branch=feat/sign-bytes#ad697e3b17bcc65fdf952731d90e756426030949" dependencies = [ "bytes", "prost", @@ -3456,7 +3436,7 @@ dependencies = [ [[package]] name = "tenderdash-proto" version = "0.12.0-dev.1" -source = "git+https://github.com/dashpay/rs-tenderdash-abci?branch=feat/sign-bytes#ae1a80905e487207ef3d196d32b9d5f3ff99630e" +source = "git+https://github.com/dashpay/rs-tenderdash-abci?branch=feat/sign-bytes#ad697e3b17bcc65fdf952731d90e756426030949" dependencies = [ "bytes", "chrono", @@ -3475,7 +3455,7 @@ dependencies = [ [[package]] name = "tenderdash-proto-compiler" version = "0.1.0" -source = "git+https://github.com/dashpay/rs-tenderdash-abci?branch=feat/sign-bytes#ae1a80905e487207ef3d196d32b9d5f3ff99630e" +source = "git+https://github.com/dashpay/rs-tenderdash-abci?branch=feat/sign-bytes#ad697e3b17bcc65fdf952731d90e756426030949" dependencies = [ "fs_extra", "prost-build", @@ -3932,18 +3912,6 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" version = "0.2.84" @@ -3973,25 +3941,6 @@ version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" -[[package]] -name = "wasm-dpp" -version = "0.1.0" -dependencies = [ - "anyhow", - "async-trait", - "console_error_panic_hook", - "dpp", - "itertools", - "js-sys", - "serde", - "serde-wasm-bindgen", - "serde_json", - "thiserror", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "web-sys" version = "0.3.61" diff --git a/packages/rs-drive-abci/src/abci/commit.rs b/packages/rs-drive-abci/src/abci/commit.rs index d3910aa1b5..2393f73bb1 100644 --- a/packages/rs-drive-abci/src/abci/commit.rs +++ b/packages/rs-drive-abci/src/abci/commit.rs @@ -49,10 +49,9 @@ impl Commit { public_key: &bls_signatures::PublicKey, ) -> Result { // 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.as_slice()) { - Ok(signature) => signature, - Err(e) => return Err(AbciError::from(e)), - }; + let signature = + bls_signatures::Signature::from_bytes(&signature).map_err(AbciError::from)?; + let hash = self .inner .sign_digest( diff --git a/packages/rs-drive-abci/src/abci/handlers.rs b/packages/rs-drive-abci/src/abci/handlers.rs index e24c8de1e7..fd330ef033 100644 --- a/packages/rs-drive-abci/src/abci/handlers.rs +++ b/packages/rs-drive-abci/src/abci/handlers.rs @@ -313,9 +313,14 @@ where // }); // }; - let validation_result = - self.platform - .check_withdrawals(&got, &expected, None, height as u64, round as u32); + let validation_result = self.platform.check_withdrawals( + &got, + &expected, + height as u64, + round as u32, + None, + None, + ); if validation_result.is_valid() { Ok(proto::ResponseVerifyVoteExtension { diff --git a/packages/rs-drive-abci/src/abci/withdrawal.rs b/packages/rs-drive-abci/src/abci/withdrawal.rs index 05c921921e..f9d74e186d 100644 --- a/packages/rs-drive-abci/src/abci/withdrawal.rs +++ b/packages/rs-drive-abci/src/abci/withdrawal.rs @@ -1,7 +1,7 @@ //! Withdrawal transactions definitions and processing -use bls_signatures::{self, BlsError}; -use dpp::validation::ValidationResult; +use bls_signatures; +use dashcore_rpc::dashcore_rpc_json::QuorumType; use drive::{ drive::{batch::DriveOperation, block_info::BlockInfo, Drive}, fee::result::FeeResult, @@ -10,6 +10,7 @@ use drive::{ use std::fmt::Display; use tenderdash_abci::proto::{ abci::ExtendVoteExtension, + signatures::SignDigest, types::{VoteExtension, VoteExtensionType}, }; @@ -105,16 +106,27 @@ impl<'a> WithdrawalTxs<'a> { pub fn verify_signatures( &self, chain_id: &str, + quorum_type: QuorumType, + quorum_hash: &[u8], height: u64, round: u32, - quorum_public_key: &bls_signatures::PublicKey, + public_key: &bls_signatures::PublicKey, ) -> Result { - // self.inner.all(|s| s.verify_signature()) for s in &self.inner { - // TODO: fix - // if !s.verify_signature(&s.signature, &quorum_public_key)? { - // return Ok(false); - // } + let hash = s + .sign_digest( + chain_id, + quorum_type as u8, + quorum_hash, + height as i64, + round as i32, + ) + .map_err(AbciError::TenderdashProto)?; + let signature = + bls_signatures::Signature::from_bytes(&s.signature).map_err(AbciError::from)?; + if !public_key.verify(&signature, &hash) { + return Ok(false); + } } Ok(true) @@ -181,3 +193,30 @@ impl<'a> PartialEq for WithdrawalTxs<'a> { }) } } +#[cfg(test)] +mod test { + use tenderdash_abci::proto::types::{VoteExtension, VoteExtensionType}; + + #[test] + fn verify_signature() { + let mut wt = super::WithdrawalTxs { + inner: Vec::new(), + drive_operations: Vec::new(), + }; + let pubkey = hex::decode("5075624b6579424c5331323338317b3832383043423636393446313831444234383643353944464130433644313244314334434132363738393334304145424144303534304646453245444541433338374143454543393739343534433243464245373546443843463034443536447d").unwrap(); + let pubkey = bls_signatures::PublicKey::from_bytes(&pubkey).unwrap(); + + let signature = hex::decode("A1022D9503CCAFC94FF76FA2E58E10A0474E6EB46305009274FAFCE57E28C7DE57602277777D07855567FAEF6A2F27590258858A875707F4DA32936DDD556BA28455AB04D9301E5F6F0762AC5B9FC036A302EE26116B1F89B74E1457C2D7383A").unwrap(); + // check if signature is correct + bls_signatures::Signature::from_bytes(&signature).unwrap(); + wt.inner.push(VoteExtension { + extension: [ + 82u8, 79, 29, 3, 209, 216, 30, 148, 160, 153, 4, 39, 54, 212, 11, 217, 104, 27, + 134, 115, 33, 68, 63, 245, 138, 69, 104, 226, 116, 219, 216, 59, + ] + .into(), + signature, + r#type: VoteExtensionType::ThresholdRecover.into(), + }) + } +} diff --git a/packages/rs-drive-abci/src/execution/engine.rs b/packages/rs-drive-abci/src/execution/engine.rs index 3f1179102b..4e2f98050a 100644 --- a/packages/rs-drive-abci/src/execution/engine.rs +++ b/packages/rs-drive-abci/src/execution/engine.rs @@ -397,9 +397,10 @@ where &self, received_withdrawals: &WithdrawalTxs, our_withdrawals: &WithdrawalTxs, - verify_with_validator_public_key: Option<&bls_signatures::PublicKey>, height: u64, round: u32, + verify_with_validator_public_key: Option<&bls_signatures::PublicKey>, + quorum_hash: Option<&[u8]>, ) -> SimpleValidationResult { if received_withdrawals.ne(&our_withdrawals) { return SimpleValidationResult::new_with_error( @@ -412,8 +413,11 @@ where // we only verify if verify_with_validator_public_key exists if let Some(validator_public_key) = verify_with_validator_public_key { + let quorum_hash = quorum_hash.expect("quorum hash is required to verify signature"); let validation_result = received_withdrawals.verify_signatures( &self.config.abci.chain_id, + self.config.quorum_type, + quorum_hash, height, round, validator_public_key, From 8d8dfcfc83df2b55d1c7939b1025fa5f9ae340e4 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 17 Apr 2023 17:14:22 +0200 Subject: [PATCH 10/15] chore(rs-drive-abci): fix some imports --- packages/rs-drive-abci/tests/strategy_tests/main.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/rs-drive-abci/tests/strategy_tests/main.rs b/packages/rs-drive-abci/tests/strategy_tests/main.rs index 417d53ae1d..957cf0eba3 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/main.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/main.rs @@ -40,8 +40,6 @@ use dashcore_rpc::dashcore_rpc_json::{ DMNState, ExtendedQuorumDetails, MasternodeListDiffWithMasternodes, MasternodeListItem, MasternodeType, QuorumInfoResult, QuorumType, }; -use dpp::dashcore::secp256k1::SecretKey; -use dpp::dashcore::{signer, Network, PrivateKey}; use dpp::data_contract::state_transition::data_contract_create_transition::DataContractCreateTransition; use dpp::document::document_transition::document_base_transition::DocumentBaseTransition; use dpp::document::document_transition::{ From 1cbc1dc2f0c4b4720d305cb4d2fa3cc62e5ccafa Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 17 Apr 2023 17:27:24 +0200 Subject: [PATCH 11/15] test(rs-drive-abci): withdrawals/vote extensions tests --- packages/rs-drive-abci/src/abci/withdrawal.rs | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/packages/rs-drive-abci/src/abci/withdrawal.rs b/packages/rs-drive-abci/src/abci/withdrawal.rs index f9d74e186d..6928544134 100644 --- a/packages/rs-drive-abci/src/abci/withdrawal.rs +++ b/packages/rs-drive-abci/src/abci/withdrawal.rs @@ -195,15 +195,24 @@ impl<'a> PartialEq for WithdrawalTxs<'a> { } #[cfg(test)] mod test { + use dashcore_rpc::dashcore_rpc_json::QuorumType; use tenderdash_abci::proto::types::{VoteExtension, VoteExtensionType}; #[test] fn verify_signature() { + const HEIGHT: u64 = 100; + const ROUND: u32 = 0; + const CHAIN_ID: &str = "test-chain"; + + let quorum_hash = + hex::decode("D6711FA18C7DA6D3FF8615D3CD3C14500EE91DA5FA942425B8E2B79A30FD8E6C") + .unwrap(); + let mut wt = super::WithdrawalTxs { inner: Vec::new(), drive_operations: Vec::new(), }; - let pubkey = hex::decode("5075624b6579424c5331323338317b3832383043423636393446313831444234383643353944464130433644313244314334434132363738393334304145424144303534304646453245444541433338374143454543393739343534433243464245373546443843463034443536447d").unwrap(); + let pubkey = hex::decode("8280cb6694f181db486c59dfa0c6d12d1c4ca26789340aebad0540ffe2edeac387aceec979454c2cfbe75fd8cf04d56d").unwrap(); let pubkey = bls_signatures::PublicKey::from_bytes(&pubkey).unwrap(); let signature = hex::decode("A1022D9503CCAFC94FF76FA2E58E10A0474E6EB46305009274FAFCE57E28C7DE57602277777D07855567FAEF6A2F27590258858A875707F4DA32936DDD556BA28455AB04D9301E5F6F0762AC5B9FC036A302EE26116B1F89B74E1457C2D7383A").unwrap(); @@ -217,6 +226,32 @@ mod test { .into(), signature, r#type: VoteExtensionType::ThresholdRecover.into(), - }) + }); + + assert!(wt + .verify_signatures( + CHAIN_ID, + QuorumType::LlmqTest, + &quorum_hash, + HEIGHT, + ROUND, + &pubkey + ) + .unwrap()); + + // Now break the data + wt.inner[0].extension[3] = 0; + assert_eq!( + false, + wt.verify_signatures( + CHAIN_ID, + QuorumType::LlmqTest, + &quorum_hash, + HEIGHT, + ROUND, + &pubkey + ) + .unwrap() + ); } } From 4e374507062751f8ca878672499629d662212ac9 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 17 Apr 2023 17:38:27 +0200 Subject: [PATCH 12/15] fix(rs-drive-abci): config quorum type doesn't work --- packages/rs-drive-abci/src/config.rs | 21 ++++++++++++++++--- .../rs-drive-abci/src/execution/engine.rs | 9 ++++---- .../rs-drive-abci/src/execution/helpers.rs | 4 ++-- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/packages/rs-drive-abci/src/config.rs b/packages/rs-drive-abci/src/config.rs index 031c44ab48..82a7f10861 100644 --- a/packages/rs-drive-abci/src/config.rs +++ b/packages/rs-drive-abci/src/config.rs @@ -150,7 +150,7 @@ pub struct PlatformConfig { pub verify_sum_trees: bool, /// The default quorum type - pub quorum_type: QuorumType, + pub quorum_type: String, /// The default quorum size pub quorum_size: u16, @@ -171,6 +171,21 @@ impl PlatformConfig { fn default_verify_sum_trees() -> bool { true } + + /// Return type of quorum + pub fn quorum_type(&self) -> QuorumType { + let found = if let Ok(t) = self.quorum_type.trim().parse::() { + QuorumType::from(t) + } else { + QuorumType::from(self.quorum_type.as_str()) + }; + + if found == QuorumType::UNKNOWN { + panic!("config: unsupported QUORUM_TYPE: {}", self.quorum_type); + } + + found + } } /// create new object using values from environment variables pub trait FromEnv { @@ -189,7 +204,7 @@ impl Default for PlatformConfig { fn default() -> Self { Self { verify_sum_trees: true, - quorum_type: QuorumType::Llmq100_67, + quorum_type: "llmq_100_67".to_string(), quorum_size: 100, block_spacing_ms: 5000, validator_set_quorum_rotation_block_count: 15, @@ -224,6 +239,6 @@ mod tests { let config = super::PlatformConfig::from_env().unwrap(); assert_eq!(config.verify_sum_trees, true); - assert_ne!(config.quorum_type, QuorumType::UNKNOWN); + assert_ne!(config.quorum_type(), QuorumType::UNKNOWN); } } diff --git a/packages/rs-drive-abci/src/execution/engine.rs b/packages/rs-drive-abci/src/execution/engine.rs index 4e2f98050a..dfdc899a5a 100644 --- a/packages/rs-drive-abci/src/execution/engine.rs +++ b/packages/rs-drive-abci/src/execution/engine.rs @@ -13,13 +13,12 @@ use drive::error::Error::GroveDB; use drive::fee::result::FeeResult; use drive::grovedb::{Transaction, TransactionArg}; use std::collections::BTreeMap; -use tenderdash_abci::proto::abci::{ExecTxResult, RequestFinalizeBlock}; +use tenderdash_abci::proto::abci::{ExecTxResult}; use tenderdash_abci::proto::serializers::timestamp::ToMilis; use crate::abci::commit::Commit; use crate::abci::withdrawal::WithdrawalTxs; use crate::abci::AbciError; -use crate::abci::AbciError::BlsError; use crate::block::{BlockExecutionContext, BlockStateInfo}; use crate::error::execution::ExecutionError; use crate::error::Error; @@ -416,7 +415,7 @@ where let quorum_hash = quorum_hash.expect("quorum hash is required to verify signature"); let validation_result = received_withdrawals.verify_signatures( &self.config.abci.chain_id, - self.config.quorum_type, + self.config.quorum_type(), quorum_hash, height, round, @@ -445,7 +444,7 @@ where let public_key = self .core_rpc .get_quorum_info( - self.config.quorum_type, + self.config.quorum_type(), &QuorumHash::from_inner(quorum_hash), Some(false), )? @@ -530,7 +529,7 @@ where // Verify commit - let quorum_type = self.config.quorum_type; + let quorum_type = self.config.quorum_type(); let commit = Commit::new( commit_info.clone(), block_id.clone(), diff --git a/packages/rs-drive-abci/src/execution/helpers.rs b/packages/rs-drive-abci/src/execution/helpers.rs index 9750b27547..75a264873f 100644 --- a/packages/rs-drive-abci/src/execution/helpers.rs +++ b/packages/rs-drive-abci/src/execution/helpers.rs @@ -74,7 +74,7 @@ where .get_quorum_listextended(Some(core_block_height))?; let quorum_info = quorum_list .quorums_by_type - .get(&self.config.quorum_type) + .get(&self.config.quorum_type()) .ok_or(Error::Execution(ExecutionError::DashCoreBadResponseError( format!( "expected quorums of type {}, but did not receive any from Dash Core", @@ -93,7 +93,7 @@ where .map(|(key, _)| { let quorum_info_result = self.core_rpc - .get_quorum_info(self.config.quorum_type, key, None)?; + .get_quorum_info(self.config.quorum_type(), key, None)?; let quorum: Quorum = quorum_info_result.try_into()?; Ok((key.clone(), quorum)) }) From ff502f286b91068cf442233add6f9f1495927c3e Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Mon, 17 Apr 2023 17:41:12 +0200 Subject: [PATCH 13/15] fix(rs-drive-abci): missing BLOCK_SPACING_MS in .env.example --- packages/rs-drive-abci/.env.example | 1 + packages/rs-drive-abci/src/config.rs | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/rs-drive-abci/.env.example b/packages/rs-drive-abci/.env.example index 61f1c1b637..265175ac1d 100644 --- a/packages/rs-drive-abci/.env.example +++ b/packages/rs-drive-abci/.env.example @@ -63,3 +63,4 @@ TENDERDASH_P2P_PORT=26656 QUORUM_SIZE=5 QUORUM_TYPE=llmq_25_67 CHAIN_ID=devnet +BLOCK_SPACING_MS=3000 diff --git a/packages/rs-drive-abci/src/config.rs b/packages/rs-drive-abci/src/config.rs index 82a7f10861..2369b0ea7e 100644 --- a/packages/rs-drive-abci/src/config.rs +++ b/packages/rs-drive-abci/src/config.rs @@ -224,11 +224,9 @@ impl Default for PlatformConfig { #[cfg(test)] mod tests { - use std::env; - - use dashcore_rpc::dashcore_rpc_json::QuorumType; - use super::FromEnv; + use dashcore_rpc::dashcore_rpc_json::QuorumType; + use std::env; #[test] fn test_config_from_env() { From d9ea05474b564b31d58096499178896f54181ccd Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Tue, 18 Apr 2023 11:23:26 +0200 Subject: [PATCH 14/15] refactor(rs-drive-abci): withdrawal verify signature returns SimpleValidationResult --- Cargo.lock | 6 +-- packages/rs-drive-abci/Cargo.toml | 2 +- packages/rs-drive-abci/src/abci/withdrawal.rs | 48 +++++++++++++------ .../rs-drive-abci/src/execution/engine.rs | 24 +++++----- 4 files changed, 50 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index df1bfa34e5..6168ec28df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3421,7 +3421,7 @@ dependencies = [ [[package]] name = "tenderdash-abci" version = "0.12.0-dev.1" -source = "git+https://github.com/dashpay/rs-tenderdash-abci?branch=feat/sign-bytes#ad697e3b17bcc65fdf952731d90e756426030949" +source = "git+https://github.com/dashpay/rs-tenderdash-abci#e66a7d6683c0843f11e980f8f057ea78feccef49" dependencies = [ "bytes", "prost", @@ -3436,7 +3436,7 @@ dependencies = [ [[package]] name = "tenderdash-proto" version = "0.12.0-dev.1" -source = "git+https://github.com/dashpay/rs-tenderdash-abci?branch=feat/sign-bytes#ad697e3b17bcc65fdf952731d90e756426030949" +source = "git+https://github.com/dashpay/rs-tenderdash-abci#e66a7d6683c0843f11e980f8f057ea78feccef49" dependencies = [ "bytes", "chrono", @@ -3455,7 +3455,7 @@ dependencies = [ [[package]] name = "tenderdash-proto-compiler" version = "0.1.0" -source = "git+https://github.com/dashpay/rs-tenderdash-abci?branch=feat/sign-bytes#ad697e3b17bcc65fdf952731d90e756426030949" +source = "git+https://github.com/dashpay/rs-tenderdash-abci#e66a7d6683c0843f11e980f8f057ea78feccef49" dependencies = [ "fs_extra", "prost-build", diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 99d28b19bb..2229d7a9d9 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -50,7 +50,7 @@ tracing-subscriber = { version = "0.3.16", default-features = false, features = "ansi", ], optional = true } atty = { version = "0.2.14", optional = true } -tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", branch = "feat/sign-bytes", optional = true } +tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", optional = true } # tenderdash-abci = { path = "../../../rs-tenderdash-abci/abci", optional = true } anyhow = { version = "1.0.70" } lazy_static = "1.4.0" diff --git a/packages/rs-drive-abci/src/abci/withdrawal.rs b/packages/rs-drive-abci/src/abci/withdrawal.rs index 6928544134..2ac5aa3414 100644 --- a/packages/rs-drive-abci/src/abci/withdrawal.rs +++ b/packages/rs-drive-abci/src/abci/withdrawal.rs @@ -2,6 +2,7 @@ use bls_signatures; use dashcore_rpc::dashcore_rpc_json::QuorumType; +use dpp::validation::SimpleValidationResult; use drive::{ drive::{batch::DriveOperation, block_info::BlockInfo, Drive}, fee::result::FeeResult, @@ -103,6 +104,18 @@ impl<'a> WithdrawalTxs<'a> { } /// Verify signatures of all withdrawal TXs + /// + /// ## Return value + /// + /// There are the following types of errors during verification: + /// + /// 1. The signature was invalid, most likely due to change in the data; in this case, + /// [AbciError::VoteExtensionsSignatureInvalid] is returned. + /// 2. Signature or public key is malformed - in this case, [AbciError::BlsError] is returned + /// 3. Provided data is invalid - [AbciError::TenderdashProto] is returned + /// + /// As all these conditions, in normal circumstances, should cause processing to be terminated, they are all + /// treated as errors. pub fn verify_signatures( &self, chain_id: &str, @@ -111,25 +124,32 @@ impl<'a> WithdrawalTxs<'a> { height: u64, round: u32, public_key: &bls_signatures::PublicKey, - ) -> Result { + ) -> SimpleValidationResult { for s in &self.inner { - let hash = s - .sign_digest( - chain_id, - quorum_type as u8, - quorum_hash, - height as i64, - round as i32, - ) - .map_err(AbciError::TenderdashProto)?; - let signature = - bls_signatures::Signature::from_bytes(&s.signature).map_err(AbciError::from)?; + let hash = match s.sign_digest( + chain_id, + quorum_type as u8, + quorum_hash, + height as i64, + round as i32, + ) { + Ok(h) => h, + Err(e) => { + return SimpleValidationResult::new_with_error(AbciError::TenderdashProto(e)) + } + }; + + let signature = match bls_signatures::Signature::from_bytes(&s.signature) { + Ok(s) => s, + Err(e) => return SimpleValidationResult::new_with_error(AbciError::BlsError(e)), + }; + if !public_key.verify(&signature, &hash) { - return Ok(false); + return SimpleValidationResult::new_with_error(AbciError::VoteExtensionsSignatureInvalid); } } - Ok(true) + SimpleValidationResult::default() } } diff --git a/packages/rs-drive-abci/src/execution/engine.rs b/packages/rs-drive-abci/src/execution/engine.rs index dfdc899a5a..e65032f28f 100644 --- a/packages/rs-drive-abci/src/execution/engine.rs +++ b/packages/rs-drive-abci/src/execution/engine.rs @@ -13,7 +13,7 @@ use drive::error::Error::GroveDB; use drive::fee::result::FeeResult; use drive::grovedb::{Transaction, TransactionArg}; use std::collections::BTreeMap; -use tenderdash_abci::proto::abci::{ExecTxResult}; +use tenderdash_abci::proto::abci::ExecTxResult; use tenderdash_abci::proto::serializers::timestamp::ToMilis; use crate::abci::commit::Commit; @@ -422,17 +422,17 @@ where validator_public_key, ); - // There are two types of errors, - // The first is that the signature was invalid and that is shown with the result bool as false - // The second is that the signature is malformed, and that gives a BLSError - - // However for this case we want to treat both as errors - match validation_result { - Ok(true) => SimpleValidationResult::default(), - Ok(false) => SimpleValidationResult::new_with_error( - AbciError::VoteExtensionsSignatureInvalid, - ), - Err(e) => SimpleValidationResult::new_with_error(e), + if validation_result.is_valid() { + SimpleValidationResult::default() + } else { + SimpleValidationResult::new_with_error( + validation_result + .errors + .into_iter() + .next() + .expect("expected an error") + .into(), + ) } } else { SimpleValidationResult::default() From 9cdb803f19f89ecfa20ce5f346eb4433d434de78 Mon Sep 17 00:00:00 2001 From: Lukasz Klimek <842586+lklimek@users.noreply.github.com> Date: Tue, 18 Apr 2023 11:47:08 +0200 Subject: [PATCH 15/15] test(rs-drive-abci): fix withdrawal tests --- packages/rs-drive-abci/src/abci/withdrawal.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/rs-drive-abci/src/abci/withdrawal.rs b/packages/rs-drive-abci/src/abci/withdrawal.rs index 2ac5aa3414..e4f4c3d01e 100644 --- a/packages/rs-drive-abci/src/abci/withdrawal.rs +++ b/packages/rs-drive-abci/src/abci/withdrawal.rs @@ -145,7 +145,9 @@ impl<'a> WithdrawalTxs<'a> { }; if !public_key.verify(&signature, &hash) { - return SimpleValidationResult::new_with_error(AbciError::VoteExtensionsSignatureInvalid); + return SimpleValidationResult::new_with_error( + AbciError::VoteExtensionsSignatureInvalid, + ); } } @@ -248,8 +250,9 @@ mod test { r#type: VoteExtensionType::ThresholdRecover.into(), }); - assert!(wt - .verify_signatures( + assert_eq!( + true, + wt.verify_signatures( CHAIN_ID, QuorumType::LlmqTest, &quorum_hash, @@ -257,7 +260,8 @@ mod test { ROUND, &pubkey ) - .unwrap()); + .is_valid() + ); // Now break the data wt.inner[0].extension[3] = 0; @@ -271,7 +275,7 @@ mod test { ROUND, &pubkey ) - .unwrap() + .is_valid() ); } }