diff --git a/dash/Cargo.toml b/dash/Cargo.toml index 7de35a51a..50abe21e8 100644 --- a/dash/Cargo.toml +++ b/dash/Cargo.toml @@ -33,6 +33,7 @@ eddsa = ["ed25519-dalek"] quorum_validation = ["bls", "bls-signatures"] message_verification = ["bls"] bincode = [ "dep:bincode", "dashcore_hashes/bincode" ] +apple = [ "ferment", "ferment-macro", "bls-signatures/legacy", "bls-signatures/bip32", "bls-signatures/apple", "bls-signatures/use_serde" ] # At least one of std, no-std must be enabled. # @@ -62,14 +63,15 @@ hex_lit = "0.1.1" anyhow = { version= "1.0" } hex = { version= "0.4" } bincode = { version= "=2.0.0-rc.3", optional = true } +bincode_derive = { version= "=2.0.0-rc.3", optional = true } bitflags = "2.9.0" blsful = { version = "3.0.0-pre8", optional = true } ed25519-dalek = { version = "2.1", features = ["rand_core"], optional = true } blake3 = "1.8.1" thiserror = "2" -# version 1.3.5 is 0bb5c5b03249c463debb5cef5f7e52ee66f3aaab -bls-signatures = { git = "https://github.com/dashpay/bls-signatures", rev = "0bb5c5b03249c463debb5cef5f7e52ee66f3aaab", optional = true } - +bls-signatures = { git = "https://github.com/dashpay/bls-signatures", rev = "b840e447227dbe6e9a302c97acdf45b95c4d3b21", optional = true } +ferment = { version = "0.2", package = "ferment", optional = true } +ferment-macro = { version = "0.2", package = "ferment-macro", optional = true } [dev-dependencies] serde_json = "1.0.140" serde_test = "1.0.177" diff --git a/dash/src/bip158.rs b/dash/src/bip158.rs index 7377f4735..cf21cf091 100644 --- a/dash/src/bip158.rs +++ b/dash/src/bip158.rs @@ -601,7 +601,7 @@ mod test { use serde_json::Value; use super::*; - use crate::ScriptBuf; + use crate::blockdata::script::ScriptBuf; use crate::consensus::encode::deserialize; use crate::hash_types::BlockHash; use crate::internal_macros::hex; diff --git a/dash/src/blockdata/script/mod.rs b/dash/src/blockdata/script/mod.rs index e01c8c91d..4c508b22f 100644 --- a/dash/src/blockdata/script/mod.rs +++ b/dash/src/blockdata/script/mod.rs @@ -69,7 +69,7 @@ use crate::{OutPoint, io}; mod borrowed; mod builder; mod instruction; -mod owned; +pub mod owned; mod push_bytes; #[cfg(test)] mod tests; @@ -77,7 +77,7 @@ mod tests; pub use self::borrowed::*; pub use self::builder::*; pub use self::instruction::*; -pub use self::owned::*; +pub use self::owned::ScriptBuf; pub use self::push_bytes::*; /// Encodes an integer in script(minimal CScriptNum) format. diff --git a/dash/src/blockdata/script/owned.rs b/dash/src/blockdata/script/owned.rs index f7276ccf4..54aea2ab5 100644 --- a/dash/src/blockdata/script/owned.rs +++ b/dash/src/blockdata/script/owned.rs @@ -29,6 +29,7 @@ use crate::taproot::TapNodeHash; /// [deref coercions]: https://doc.rust-lang.org/std/ops/trait.Deref.html#more-on-deref-coercion #[derive(Default, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)] #[cfg_attr(feature = "bincode", derive(Encode, Decode))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct ScriptBuf(pub Vec); impl ScriptBuf { diff --git a/dash/src/blockdata/transaction/mod.rs b/dash/src/blockdata/transaction/mod.rs index 4cf3e42f3..dc11e68f6 100644 --- a/dash/src/blockdata/transaction/mod.rs +++ b/dash/src/blockdata/transaction/mod.rs @@ -41,7 +41,7 @@ use hashes::{Hash, sha256d}; use crate::blockdata::constants::WITNESS_SCALE_FACTOR; #[cfg(feature = "bitcoinconsensus")] use crate::blockdata::script; -use crate::blockdata::script::Script; +use crate::blockdata::script::{Script, ScriptBuf}; use crate::blockdata::transaction::hash_type::EcdsaSighashType; use crate::blockdata::transaction::special_transaction::{TransactionPayload, TransactionType}; use crate::blockdata::transaction::txin::TxIn; @@ -52,8 +52,8 @@ use crate::consensus::{Decodable, Encodable, encode}; use crate::hash_types::{InputsHash, Txid, Wtxid}; use crate::prelude::*; use crate::sighash::LegacySighash; -pub use crate::transaction::outpoint::*; -use crate::{ScriptBuf, Weight, io}; +pub use self::outpoint::OutPoint; +use crate::{Weight, io}; /// Used for signature hash for invalid use of SIGHASH_SINGLE. const UINT256_ONE: [u8; 32] = [ @@ -165,6 +165,7 @@ impl EncodeSigningDataResult { #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct Transaction { /// The protocol version, is currently expected to be 1 or 2 (BIP 68). pub version: u16, @@ -178,29 +179,8 @@ pub struct Transaction { pub special_transaction_payload: Option, } +#[cfg_attr(feature = "apple", ferment_macro::export)] impl Transaction { - /// Computes a "normalized TXID" which does not include any signatures. - /// This gives a way to identify a transaction that is "the same" as - /// another in the sense of having same inputs and outputs. - pub fn ntxid(&self) -> sha256d::Hash { - let cloned_tx = Transaction { - version: self.version, - lock_time: self.lock_time, - input: self - .input - .iter() - .map(|txin| TxIn { - script_sig: ScriptBuf::new(), - witness: Witness::default(), - ..*txin - }) - .collect(), - output: self.output.clone(), - special_transaction_payload: self.special_transaction_payload.clone(), - }; - cloned_tx.txid().into() - } - /// Computes the txid. For non-segwit transactions this will be identical /// to the output of `wtxid()`, but for segwit transactions, /// this will give the correct txid (not including witnesses) while `wtxid` @@ -228,6 +208,36 @@ impl Transaction { TransactionType::from_optional_payload(&self.special_transaction_payload) } + /// Is this a coin base transaction? + pub fn is_coin_base(&self) -> bool { + self.input.len() == 1 && self.input[0].previous_output.is_null() + } + +} + +impl Transaction { + /// Computes a "normalized TXID" which does not include any signatures. + /// This gives a way to identify a transaction that is "the same" as + /// another in the sense of having same inputs and outputs. + pub fn ntxid(&self) -> sha256d::Hash { + let cloned_tx = Transaction { + version: self.version, + lock_time: self.lock_time, + input: self + .input + .iter() + .map(|txin| TxIn { + script_sig: ScriptBuf::new(), + witness: Witness::default(), + ..*txin + }) + .collect(), + output: self.output.clone(), + special_transaction_payload: self.special_transaction_payload.clone(), + }; + cloned_tx.txid().into() + } + /// Computes SegWit-version of the transaction id (wtxid). For transaction with the witness /// data this hash includes witness, for pre-witness transaction it is equal to the normal /// value returned by txid() function. @@ -556,11 +566,6 @@ impl Transaction { Ok(()) } - /// Is this a coin base transaction? - pub fn is_coin_base(&self) -> bool { - self.input.len() == 1 && self.input[0].previous_output.is_null() - } - /// Returns `true` if the transaction itself opted in to be BIP-125-replaceable (RBF). This /// **does not** cover the case where a transaction becomes replaceable due to ancestors being /// RBF. diff --git a/dash/src/blockdata/transaction/outpoint.rs b/dash/src/blockdata/transaction/outpoint.rs index 3c3e5b54e..e0be0278d 100644 --- a/dash/src/blockdata/transaction/outpoint.rs +++ b/dash/src/blockdata/transaction/outpoint.rs @@ -35,6 +35,7 @@ use crate::io; /// A reference to a transaction output. #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] #[cfg_attr(feature = "bincode", derive(Encode, Decode))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct OutPoint { /// The referenced transaction's txid. pub txid: Txid, @@ -68,6 +69,7 @@ impl From for [u8; 36] { } } +#[cfg_attr(feature = "apple", ferment_macro::export)] impl OutPoint { /// Creates a new [`OutPoint`]. #[inline] diff --git a/dash/src/blockdata/transaction/special_transaction/asset_lock.rs b/dash/src/blockdata/transaction/special_transaction/asset_lock.rs index 3bce7f420..578a0821f 100644 --- a/dash/src/blockdata/transaction/special_transaction/asset_lock.rs +++ b/dash/src/blockdata/transaction/special_transaction/asset_lock.rs @@ -27,7 +27,7 @@ use bincode::{Decode, Encode}; use crate::consensus::{Decodable, Encodable, encode}; use crate::prelude::*; -use crate::transaction::txout::TxOut; +use crate::blockdata::transaction::txout::TxOut; use crate::{VarInt, io}; /// An Asset Lock payload. This is contained as the payload of an asset lock special transaction. @@ -41,11 +41,13 @@ use crate::{VarInt, io}; #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct AssetLockPayload { pub version: u8, pub credit_outputs: Vec, } +#[cfg_attr(feature = "apple", ferment_macro::export)] impl AssetLockPayload { /// The size of the payload in bytes. pub fn size(&self) -> usize { diff --git a/dash/src/blockdata/transaction/special_transaction/asset_unlock/qualified_asset_unlock.rs b/dash/src/blockdata/transaction/special_transaction/asset_unlock/qualified_asset_unlock.rs index cad0ae1d2..f7d631f63 100644 --- a/dash/src/blockdata/transaction/special_transaction/asset_unlock/qualified_asset_unlock.rs +++ b/dash/src/blockdata/transaction/special_transaction/asset_unlock/qualified_asset_unlock.rs @@ -51,6 +51,7 @@ pub const ASSET_UNLOCK_TX_SIZE: usize = 190; #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct AssetUnlockPayload { /// The base information about the asset unlock. This base information is the information that /// should be put into a queue. diff --git a/dash/src/blockdata/transaction/special_transaction/asset_unlock/request_info.rs b/dash/src/blockdata/transaction/special_transaction/asset_unlock/request_info.rs index 852692b1f..4e4ac8f56 100644 --- a/dash/src/blockdata/transaction/special_transaction/asset_unlock/request_info.rs +++ b/dash/src/blockdata/transaction/special_transaction/asset_unlock/request_info.rs @@ -35,6 +35,7 @@ use crate::prelude::*; #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct AssetUnlockRequestInfo { /// The core request height of the transaction. This should match a period where the quorum_hash /// is still active diff --git a/dash/src/blockdata/transaction/special_transaction/asset_unlock/unqualified_asset_unlock.rs b/dash/src/blockdata/transaction/special_transaction/asset_unlock/unqualified_asset_unlock.rs index 05c15e6ba..da3712393 100644 --- a/dash/src/blockdata/transaction/special_transaction/asset_unlock/unqualified_asset_unlock.rs +++ b/dash/src/blockdata/transaction/special_transaction/asset_unlock/unqualified_asset_unlock.rs @@ -25,13 +25,15 @@ #[cfg(feature = "bincode")] use bincode::{Decode, Encode}; +use crate::blockdata::script::ScriptBuf; use crate::blockdata::transaction::special_transaction::TransactionType; use crate::blockdata::transaction::special_transaction::TransactionType::AssetUnlock; +use crate::blockdata::transaction::txin::TxIn; +use crate::blockdata::transaction::txout::TxOut; use crate::consensus::{Decodable, Encodable, encode}; use crate::hash_types::{PubkeyHash, ScriptHash}; use crate::prelude::*; -use crate::transaction::TxOut; -use crate::{ScriptBuf, TxIn, VarInt, io}; +use crate::{VarInt, io}; /// An Asset Unlock Base payload. This is the base payload of the Asset Unlock. In order to make /// it a full payload the request info should be added. @@ -39,6 +41,7 @@ use crate::{ScriptBuf, TxIn, VarInt, io}; #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct AssetUnlockBasePayload { /// The payload protocol version, is currently expected to be 0. pub version: u8, diff --git a/dash/src/blockdata/transaction/special_transaction/coinbase.rs b/dash/src/blockdata/transaction/special_transaction/coinbase.rs index 604eef96f..6a7790aae 100644 --- a/dash/src/blockdata/transaction/special_transaction/coinbase.rs +++ b/dash/src/blockdata/transaction/special_transaction/coinbase.rs @@ -35,6 +35,7 @@ use crate::io::{Error, ErrorKind}; #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct CoinbasePayload { pub version: u16, pub height: u32, @@ -45,6 +46,7 @@ pub struct CoinbasePayload { pub asset_locked_amount: Option, } +#[cfg_attr(feature = "apple", ferment_macro::export)] impl CoinbasePayload { /// The size of the payload in bytes. /// version(2) + height(4) + merkle_root_masternode_list(32) + merkle_root_quorums(32) diff --git a/dash/src/blockdata/transaction/special_transaction/mod.rs b/dash/src/blockdata/transaction/special_transaction/mod.rs index d2921da13..f71aa6392 100644 --- a/dash/src/blockdata/transaction/special_transaction/mod.rs +++ b/dash/src/blockdata/transaction/special_transaction/mod.rs @@ -64,6 +64,7 @@ pub mod quorum_commitment; #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub enum TransactionPayload { /// A wrapper for a Masternode Registration payload ProviderRegistrationPayloadType(ProviderRegistrationPayload), @@ -98,6 +99,7 @@ impl Encodable for TransactionPayload { } } +#[cfg_attr(feature = "apple", ferment_macro::export)] impl TransactionPayload { /// Gets the Transaction Type for a Special Transaction Payload pub fn get_type(&self) -> TransactionType { @@ -128,6 +130,9 @@ impl TransactionPayload { } } +} +impl TransactionPayload { + /// Convenience method that assumes the payload to be a provider registration payload to get it /// easier. /// Errors if it is not a provider registration payload. @@ -254,6 +259,7 @@ impl TransactionPayload { /// #[derive(Clone, Copy, PartialEq, Eq)] #[repr(u16)] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub enum TransactionType { /// A Classic transaction Classic = 0, diff --git a/dash/src/blockdata/transaction/special_transaction/provider_registration.rs b/dash/src/blockdata/transaction/special_transaction/provider_registration.rs index fd892dc54..7dd8d3b0a 100644 --- a/dash/src/blockdata/transaction/special_transaction/provider_registration.rs +++ b/dash/src/blockdata/transaction/special_transaction/provider_registration.rs @@ -42,17 +42,20 @@ use hashes::Hash; use internals::hex::Case::Lower; use crate::address::Payload; +use crate::blockdata::script::ScriptBuf; +use crate::blockdata::transaction::OutPoint; use crate::blockdata::transaction::special_transaction::SpecialTransactionBasePayloadEncodable; use crate::bls_sig_utils::BLSPublicKey; use crate::consensus::{Decodable, Encodable, encode}; use crate::hash_types::{InputsHash, PubkeyHash, SpecialTransactionPayloadHash}; use crate::prelude::*; -use crate::{Address, Network, OutPoint, ScriptBuf, VarInt, io}; +use crate::{Address, Network, VarInt, io}; #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Copy)] #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub enum ProviderMasternodeType { Regular = 0, HighPerformance = 1, @@ -97,6 +100,7 @@ impl Decodable for ProviderMasternodeType { #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct ProviderRegistrationPayload { pub version: u16, pub masternode_type: ProviderMasternodeType, @@ -114,7 +118,23 @@ pub struct ProviderRegistrationPayload { pub platform_p2p_port: Option, pub platform_http_port: Option, } - +#[cfg_attr(feature = "apple", ferment_macro::export)] +impl ProviderRegistrationPayload { + /// The size of the payload in bytes. + /// version(2) + provider_type(2) + provider_mode(2) + collateral_outpoint(32 + 4) + ip_address(16) + + /// port(2) + owner_key_hash(20) + operator_public_key(48) + voting_key_hash(20) + operator_reward(2) + + /// script_payout(VarInt(script_payout_len).len() + script_payout_len) + + /// inputs_hash(32) + + /// payload_sig(VarInt(payload_sig_len).len() + payload_sig_len) + pub fn size(&self) -> usize { + let mut size = 2 + 2 + 2 + 32 + 4 + 16 + 2 + 20 + 48 + 20 + 2 + 32; // 182 bytes + let script_payout_len = self.script_payout.0.len(); + let signature_len = self.signature.len(); + size += VarInt(script_payout_len as u64).len() + script_payout_len; + size += VarInt(signature_len as u64).len() + signature_len; + size + } +} impl ProviderRegistrationPayload { /// A convenience method to get the address from payout script pub fn payout_address(&self, network: Network) -> Result { @@ -149,21 +169,6 @@ impl ProviderRegistrationPayload { base_payload_hash.as_byte_array().to_hex_string(Lower) )) } - - /// The size of the payload in bytes. - /// version(2) + provider_type(2) + provider_mode(2) + collateral_outpoint(32 + 4) + ip_address(16) + - /// port(2) + owner_key_hash(20) + operator_public_key(48) + voting_key_hash(20) + operator_reward(2) + - /// script_payout(VarInt(script_payout_len).len() + script_payout_len) + - /// inputs_hash(32) + - /// payload_sig(VarInt(payload_sig_len).len() + payload_sig_len) - pub fn size(&self) -> usize { - let mut size = 2 + 2 + 2 + 32 + 4 + 16 + 2 + 20 + 48 + 20 + 2 + 32; // 182 bytes - let script_payout_len = self.script_payout.0.len(); - let signature_len = self.signature.len(); - size += VarInt(script_payout_len as u64).len() + script_payout_len; - size += VarInt(signature_len as u64).len() + signature_len; - size - } } impl SpecialTransactionBasePayloadEncodable for ProviderRegistrationPayload { diff --git a/dash/src/blockdata/transaction/special_transaction/provider_update_registrar.rs b/dash/src/blockdata/transaction/special_transaction/provider_update_registrar.rs index fe2084c7d..54648572d 100644 --- a/dash/src/blockdata/transaction/special_transaction/provider_update_registrar.rs +++ b/dash/src/blockdata/transaction/special_transaction/provider_update_registrar.rs @@ -32,13 +32,13 @@ #[cfg(feature = "bincode")] use bincode::{Decode, Encode}; use hashes::Hash; - +use crate::blockdata::script::ScriptBuf; use crate::blockdata::transaction::special_transaction::SpecialTransactionBasePayloadEncodable; use crate::bls_sig_utils::BLSPublicKey; use crate::consensus::{Decodable, Encodable, encode}; use crate::hash_types::{InputsHash, PubkeyHash, SpecialTransactionPayloadHash, Txid}; use crate::prelude::*; -use crate::{ScriptBuf, VarInt, io}; +use crate::{VarInt, io}; /// A Provider Update Registrar Payload used in a Provider Update Registrar Special Transaction. /// This is used to update the base aspects a Masternode on the network. @@ -47,6 +47,7 @@ use crate::{ScriptBuf, VarInt, io}; #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct ProviderUpdateRegistrarPayload { pub version: u16, pub pro_tx_hash: Txid, @@ -58,6 +59,7 @@ pub struct ProviderUpdateRegistrarPayload { pub payload_sig: Vec, // TODO: Need to figure out, is this signature BLS Signature (length 96) } +#[cfg_attr(feature = "apple", ferment_macro::export)] impl ProviderUpdateRegistrarPayload { /// The size of the payload in bytes. pub fn size(&self) -> usize { diff --git a/dash/src/blockdata/transaction/special_transaction/provider_update_revocation.rs b/dash/src/blockdata/transaction/special_transaction/provider_update_revocation.rs index 5e9fe3b4e..f8e7deb95 100644 --- a/dash/src/blockdata/transaction/special_transaction/provider_update_revocation.rs +++ b/dash/src/blockdata/transaction/special_transaction/provider_update_revocation.rs @@ -53,6 +53,7 @@ use crate::io; #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct ProviderUpdateRevocationPayload { pub version: u16, pub pro_tx_hash: Txid, @@ -61,6 +62,7 @@ pub struct ProviderUpdateRevocationPayload { pub payload_sig: BLSSignature, } +#[cfg_attr(feature = "apple", ferment_macro::export)] impl ProviderUpdateRevocationPayload { /// The size of the payload in bytes. pub fn size(&self) -> usize { diff --git a/dash/src/blockdata/transaction/special_transaction/provider_update_service.rs b/dash/src/blockdata/transaction/special_transaction/provider_update_service.rs index 0dbd644b3..d0bb57ec2 100644 --- a/dash/src/blockdata/transaction/special_transaction/provider_update_service.rs +++ b/dash/src/blockdata/transaction/special_transaction/provider_update_service.rs @@ -37,12 +37,12 @@ #[cfg(feature = "bincode")] use bincode::{Decode, Encode}; use hashes::Hash; - +use crate::blockdata::script::ScriptBuf; use crate::blockdata::transaction::special_transaction::SpecialTransactionBasePayloadEncodable; use crate::bls_sig_utils::BLSSignature; use crate::consensus::{Decodable, Encodable, encode}; use crate::hash_types::{InputsHash, SpecialTransactionPayloadHash, Txid}; -use crate::{ScriptBuf, VarInt, io}; +use crate::{VarInt, io}; /// A Provider Update Service Payload used in a Provider Update Service Special Transaction. /// This is used to update the operational aspects a Masternode on the network. @@ -52,6 +52,7 @@ use crate::{ScriptBuf, VarInt, io}; #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct ProviderUpdateServicePayload { pub version: u16, pub pro_tx_hash: Txid, @@ -62,6 +63,7 @@ pub struct ProviderUpdateServicePayload { pub payload_sig: BLSSignature, } +#[cfg_attr(feature = "apple", ferment_macro::export)] impl ProviderUpdateServicePayload { /// The size of the payload in bytes. pub fn size(&self) -> usize { diff --git a/dash/src/blockdata/transaction/special_transaction/quorum_commitment.rs b/dash/src/blockdata/transaction/special_transaction/quorum_commitment.rs index c9cc5f26b..82ae73f13 100644 --- a/dash/src/blockdata/transaction/special_transaction/quorum_commitment.rs +++ b/dash/src/blockdata/transaction/special_transaction/quorum_commitment.rs @@ -39,6 +39,7 @@ use crate::sml::quorum_validation_error::QuorumValidationError; #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] #[cfg_attr(feature = "bincode", derive(Encode, Decode))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct QuorumEntry { pub version: u16, pub llmq_type: LLMQType, @@ -51,7 +52,7 @@ pub struct QuorumEntry { pub threshold_sig: BLSSignature, pub all_commitment_aggregated_signature: BLSSignature, } - +#[cfg_attr(feature = "apple", ferment_macro::export)] impl QuorumEntry { /// The size of the payload in bytes. pub fn size(&self) -> usize { @@ -66,6 +67,9 @@ impl QuorumEntry { size } +} +impl QuorumEntry { + pub fn validate_structure(&self) -> Result<(), QuorumValidationError> { let quorum_threshold = self.llmq_type.threshold() as u64; @@ -183,12 +187,14 @@ impl Decodable for QuorumEntry { #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct QuorumCommitmentPayload { - version: u16, - height: u32, - finalization_commitment: QuorumEntry, + pub version: u16, + pub height: u32, + pub finalization_commitment: QuorumEntry, } +#[cfg_attr(feature = "apple", ferment_macro::export)] impl QuorumCommitmentPayload { /// The size of the payload in bytes. pub fn size(&self) -> usize { diff --git a/dash/src/blockdata/transaction/txin.rs b/dash/src/blockdata/transaction/txin.rs index 7debc835a..5a68cef01 100644 --- a/dash/src/blockdata/transaction/txin.rs +++ b/dash/src/blockdata/transaction/txin.rs @@ -24,15 +24,17 @@ use bincode::{Decode, Encode}; use crate::blockdata::script::ScriptBuf; -use crate::consensus::{Decodable, Encodable, encode}; -use crate::transaction::outpoint::OutPoint; -use crate::{Witness, io}; +use crate::blockdata::transaction::outpoint::OutPoint; +use crate::blockdata::witness::Witness; +use crate::consensus::{encode, Decodable, Encodable}; +use crate::io; /// A transaction input, which defines old coins to be consumed #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] #[cfg_attr(feature = "bincode", derive(Encode, Decode))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct TxIn { /// The reference to the previous output that is being used an an input. pub previous_output: OutPoint, diff --git a/dash/src/blockdata/transaction/txout.rs b/dash/src/blockdata/transaction/txout.rs index 6fdf4c185..926ceae3f 100644 --- a/dash/src/blockdata/transaction/txout.rs +++ b/dash/src/blockdata/transaction/txout.rs @@ -24,13 +24,16 @@ use bincode::{Decode, Encode}; use crate::internal_macros::impl_consensus_encoding; -use crate::{Address, PubkeyHash, ScriptBuf, ScriptHash, VarInt}; +use crate::{Address, VarInt}; +use crate::blockdata::script::ScriptBuf; +use crate::hash_types::{PubkeyHash, ScriptHash}; /// A transaction output, which defines new coins to be created from old ones. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] #[cfg_attr(feature = "bincode", derive(Encode, Decode))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct TxOut { /// The value of the output, in satoshis. pub value: u64, diff --git a/dash/src/blockdata/witness.rs b/dash/src/blockdata/witness.rs index 9023dac76..5cfd23a7c 100644 --- a/dash/src/blockdata/witness.rs +++ b/dash/src/blockdata/witness.rs @@ -32,20 +32,21 @@ use crate::{Script, VarInt}; /// [segwit upgrade]: #[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] #[cfg_attr(feature = "bincode", derive(Encode, Decode))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct Witness { /// Contains the witness `Vec>` serialization without the initial varint indicating the /// number of elements (which is stored in `witness_elements`). - content: Vec, + pub content: Vec, /// The number of elements in the witness. /// /// Stored separately (instead of as a VarInt in the initial part of content) so that methods /// like [`Witness::push`] don't have to shift the entire array. - witness_elements: usize, + pub witness_elements: usize, /// This is the valid index pointing to the beginning of the index area. This area is 4 * /// stack_size bytes at the end of the content vector which stores the indices of each item. - indices_start: usize, + pub indices_start: usize, } /// An iterator returning individual witness elements. diff --git a/dash/src/bls_sig_utils.rs b/dash/src/bls_sig_utils.rs index 376689396..bc44d3237 100644 --- a/dash/src/bls_sig_utils.rs +++ b/dash/src/bls_sig_utils.rs @@ -34,7 +34,8 @@ use crate::sml::quorum_validation_error::QuorumValidationError; #[rustversion::attr(since(1.48), derive(PartialEq, Eq, Ord, PartialOrd, Hash))] #[derive(Clone, Copy, Debug)] #[cfg_attr(feature = "bincode", derive(Encode, Decode))] -pub struct BLSPublicKey([u8; 48]); +#[cfg_attr(feature = "apple", ferment_macro::export)] +pub struct BLSPublicKey(pub [u8; 48]); impl BLSPublicKey { pub fn is_zeroed(&self) -> bool { @@ -96,7 +97,8 @@ impl fmt::Display for BLSPublicKey { #[rustversion::attr(since(1.48), derive(PartialEq, Eq, Ord, PartialOrd, Hash))] #[derive(Clone, Copy)] #[cfg_attr(feature = "bincode", derive(Encode, Decode))] -pub struct BLSSignature([u8; 96]); +#[cfg_attr(feature = "apple", ferment_macro::export)] +pub struct BLSSignature(pub [u8; 96]); impl BLSSignature { pub fn is_zeroed(&self) -> bool { diff --git a/dash/src/consensus/encode.rs b/dash/src/consensus/encode.rs index e61c7f956..b322e6b5a 100644 --- a/dash/src/consensus/encode.rs +++ b/dash/src/consensus/encode.rs @@ -46,6 +46,7 @@ use crate::hash_types::{ BlockHash, FilterHash, FilterHeader, MerkleRootMasternodeList, TxMerkleNode, }; use crate::io::{self, Cursor, Read}; +use crate::hash_types::ProTxHash; use crate::network::message_qrinfo::QuorumSnapshot; use crate::network::message_sml::{DeletedQuorum, MnListDiff, QuorumCLSigObject}; #[cfg(feature = "std")] @@ -56,11 +57,13 @@ use crate::network::{ use crate::prelude::*; use crate::sml::masternode_list_entry::MasternodeListEntry; use crate::taproot::TapLeafHash; -use crate::transaction::special_transaction::TransactionType; -use crate::transaction::special_transaction::quorum_commitment::QuorumEntry; -use crate::transaction::txin::TxIn; -use crate::transaction::txout::TxOut; -use crate::{OutPoint, ProTxHash, ScriptBuf, address}; +use crate::blockdata::script::ScriptBuf; +use crate::blockdata::transaction::OutPoint; +use crate::blockdata::transaction::special_transaction::TransactionType; +use crate::blockdata::transaction::special_transaction::quorum_commitment::QuorumEntry; +use crate::blockdata::transaction::txin::TxIn; +use crate::blockdata::transaction::txout::TxOut; +use crate::address; /// Encoding error. #[derive(Debug)] diff --git a/dash/src/crypto/sighash.rs b/dash/src/crypto/sighash.rs index 26824537e..9f1d3070a 100644 --- a/dash/src/crypto/sighash.rs +++ b/dash/src/crypto/sighash.rs @@ -24,7 +24,7 @@ use crate::consensus::{Encodable, encode}; use crate::error::impl_std_error; use crate::io; use crate::prelude::*; -use crate::script::{Script, ScriptBuf}; +use crate::blockdata::script::{Script, ScriptBuf}; use crate::taproot::{LeafVersion, TAPROOT_ANNEX_PREFIX, TapLeafHash}; /// Used for signature hash for invalid use of SIGHASH_SINGLE. diff --git a/dash/src/ephemerealdata/chain_lock.rs b/dash/src/ephemerealdata/chain_lock.rs index 84cb28cb0..e8011ede0 100644 --- a/dash/src/ephemerealdata/chain_lock.rs +++ b/dash/src/ephemerealdata/chain_lock.rs @@ -25,6 +25,7 @@ const CL_REQUEST_ID_PREFIX: &str = "clsig"; /// reduces mining uncertainty and mitigate 51% attack. /// This data structure represents a p2p message containing a data to verify such a lock. #[derive(Debug, Clone, Eq, PartialEq)] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct ChainLock { /// Block height pub block_height: u32, diff --git a/dash/src/ephemerealdata/instant_lock.rs b/dash/src/ephemerealdata/instant_lock.rs index 21b1f61ff..bea9f2e9e 100644 --- a/dash/src/ephemerealdata/instant_lock.rs +++ b/dash/src/ephemerealdata/instant_lock.rs @@ -2,20 +2,21 @@ //! confirm transaction within 1 or 2 seconds. This data structure //! represents a p2p message containing a data to verify such a lock. -#[cfg(all(not(feature = "std"), not(test)))] -use alloc::vec::Vec; +// #[cfg(all(not(feature = "std"), not(test)))] +// use alloc::vec::Vec; use core::fmt::{Debug, Formatter}; -#[cfg(any(feature = "std", test))] -pub use std::vec::Vec; +// #[cfg(any(feature = "std", test))] +// pub use std::vec::Vec; use hashes::{Hash, HashEngine}; +use crate::blockdata::transaction::outpoint::OutPoint; use crate::bls_sig_utils::BLSSignature; -use crate::consensus::Encodable; -use crate::hash_types::{CycleHash, QuorumSigningRequestId, QuorumSigningSignId}; +use crate::consensus::{Encodable, encode::VarInt}; +use crate::hash_types::{CycleHash, QuorumHash, QuorumSigningRequestId, QuorumSigningSignId, Txid}; use crate::internal_macros::impl_consensus_encoding; use crate::sml::llmq_type::LLMQType; -use crate::{OutPoint, QuorumHash, Txid, VarInt, io}; +use crate::io; const IS_LOCK_REQUEST_ID_PREFIX: &str = "islock"; @@ -23,6 +24,7 @@ const IS_LOCK_REQUEST_ID_PREFIX: &str = "islock"; /// Instant send lock is a mechanism used by the Dash network to /// confirm transaction within 1 or 2 seconds. This data structure /// represents a p2p message containing a data to verify such a lock. +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct InstantLock { /// Instant lock version pub version: u8, diff --git a/dash/src/hash_types.rs b/dash/src/hash_types.rs index 76b204919..a2ae5cc9e 100644 --- a/dash/src/hash_types.rs +++ b/dash/src/hash_types.rs @@ -77,7 +77,7 @@ mod newtypes { use crate::alloc::string::ToString; use crate::prelude::String; - use crate::transaction::special_transaction::quorum_commitment::QuorumEntry; + use crate::blockdata::transaction::special_transaction::quorum_commitment::QuorumEntry; #[cfg(feature = "core-block-hash-use-x11")] hash_newtype! { diff --git a/dash/src/lib.rs b/dash/src/lib.rs index 2c88532b6..4367af90c 100644 --- a/dash/src/lib.rs +++ b/dash/src/lib.rs @@ -109,7 +109,7 @@ pub mod consensus; // Private until we either make this a crate or flatten it - still to be decided. pub mod bls_sig_utils; pub(crate) mod crypto; -mod dip9; +pub mod dip9; pub mod ephemerealdata; pub mod error; pub mod hash_types; @@ -193,7 +193,7 @@ mod io_extras { } #[rustfmt::skip] -mod prelude { +pub mod prelude { #[cfg(all(not(feature = "std"), not(test)))] pub use alloc::{string::{String, ToString}, vec::Vec, boxed::Box, borrow::{Borrow, Cow, ToOwned}, slice, rc}; @@ -217,6 +217,7 @@ mod prelude { pub use internals::hex::display::DisplayHex; + #[cfg_attr(feature = "apple", ferment_macro::export)] pub type CoreBlockHeight = u32; } diff --git a/dash/src/network/message_qrinfo.rs b/dash/src/network/message_qrinfo.rs index 0b741b990..c3b843c3b 100644 --- a/dash/src/network/message_qrinfo.rs +++ b/dash/src/network/message_qrinfo.rs @@ -4,12 +4,12 @@ use std::{fmt, io}; #[cfg(feature = "bincode")] use bincode::{Decode, Encode}; -use crate::BlockHash; +use crate::blockdata::transaction::special_transaction::quorum_commitment::QuorumEntry; use crate::consensus::encode::{read_compact_size, read_fixed_bitset, write_fixed_bitset}; use crate::consensus::{Decodable, Encodable, encode}; use crate::internal_macros::impl_consensus_encoding; use crate::network::message_sml::MnListDiff; -use crate::transaction::special_transaction::quorum_commitment::QuorumEntry; +use crate::hash_types::BlockHash; /// The `getqrinfo` message requests a `qrinfo` message that provides the information /// required to verify quorum details for quorums formed using the quorum rotation process. @@ -154,6 +154,7 @@ impl Decodable for QRInfo { #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct QuorumSnapshot { pub skip_list_mode: MNSkipListMode, pub active_quorum_members: Vec, // Bitset, length = (active_quorum_members_count + 7) / 8 @@ -217,6 +218,7 @@ impl Decodable for QuorumSnapshot { #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub enum MNSkipListMode { /// Mode 0: No skipping – the skip list is empty. NoSkipping = 0, diff --git a/dash/src/network/message_sml.rs b/dash/src/network/message_sml.rs index 89570e8ea..22818f6f0 100644 --- a/dash/src/network/message_sml.rs +++ b/dash/src/network/message_sml.rs @@ -6,7 +6,7 @@ use crate::hash_types::MerkleRootMasternodeList; use crate::internal_macros::impl_consensus_encoding; use crate::sml::llmq_type::LLMQType; use crate::sml::masternode_list_entry::MasternodeListEntry; -use crate::transaction::special_transaction::quorum_commitment::QuorumEntry; +use crate::blockdata::transaction::special_transaction::quorum_commitment::QuorumEntry; use crate::{BlockHash, ProTxHash, QuorumHash, Transaction}; /// The `getmnlistd` message requests a `mnlistdiff` message that provides either: diff --git a/dash/src/sml/error.rs b/dash/src/sml/error.rs index f3b33bacf..2de643967 100644 --- a/dash/src/sml/error.rs +++ b/dash/src/sml/error.rs @@ -8,6 +8,7 @@ use crate::BlockHash; #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub enum SmlError { /// Error indicating that the base block is not the genesis block. #[error("Base block is not the genesis block: {0}")] diff --git a/dash/src/sml/llmq_entry_verification.rs b/dash/src/sml/llmq_entry_verification.rs index efaaeb38a..d96bba192 100644 --- a/dash/src/sml/llmq_entry_verification.rs +++ b/dash/src/sml/llmq_entry_verification.rs @@ -44,6 +44,7 @@ impl Display for LLMQEntryVerificationSkipStatus { #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub enum LLMQEntryVerificationStatus { #[default] Unknown, diff --git a/dash/src/sml/llmq_type/mod.rs b/dash/src/sml/llmq_type/mod.rs index 942587ef0..2c0fa1dbd 100644 --- a/dash/src/sml/llmq_type/mod.rs +++ b/dash/src/sml/llmq_type/mod.rs @@ -281,6 +281,7 @@ pub const LLMQ_DEV_PLATFORM: LLMQParams = LLMQParams { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] #[cfg_attr(feature = "bincode", derive(Encode, Decode))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub enum LLMQType { LlmqtypeUnknown = 0, // other kind of Llmqtype50_60 = 1, // 50 members, 30 (60%) threshold, 24 / day @@ -444,6 +445,7 @@ pub fn dkg_rotation_params(network: Network) -> DKGParams { } } +#[cfg_attr(feature = "apple", ferment_macro::export)] impl LLMQType { pub fn index(&self) -> u8 { u8::from(self.clone()) diff --git a/dash/src/sml/masternode_list/merkle_roots.rs b/dash/src/sml/masternode_list/merkle_roots.rs index f4b322923..a4c3940e4 100644 --- a/dash/src/sml/masternode_list/merkle_roots.rs +++ b/dash/src/sml/masternode_list/merkle_roots.rs @@ -161,7 +161,7 @@ impl MasternodeList { pro_tx_hashes.sort_by(|&s1, &s2| s1.reverse().cmp(&s2.reverse())); pro_tx_hashes .into_iter() - .map(|hash| self.masternodes[hash].entry_hash) + .map(|hash| self.masternodes[hash].entry_hash.to_raw_hash()) .collect::>() }) } diff --git a/dash/src/sml/masternode_list/mod.rs b/dash/src/sml/masternode_list/mod.rs index c0c80c4fb..de2204b23 100644 --- a/dash/src/sml/masternode_list/mod.rs +++ b/dash/src/sml/masternode_list/mod.rs @@ -15,16 +15,17 @@ use std::collections::BTreeMap; use bincode::{Decode, Encode}; pub use builder::MasternodeListBuilder; -use crate::hash_types::{MerkleRootMasternodeList, MerkleRootQuorums}; +use crate::bls_sig_utils::BLSPublicKey; +use crate::hash_types::{BlockHash, MerkleRootMasternodeList, MerkleRootQuorums, ProTxHash, QuorumHash}; use crate::sml::llmq_type::LLMQType; use crate::sml::masternode_list_entry::qualified_masternode_list_entry::QualifiedMasternodeListEntry; use crate::sml::quorum_entry::qualified_quorum_entry::QualifiedQuorumEntry; -use crate::{BlockHash, ProTxHash, QuorumHash}; #[derive(Clone, Eq, PartialEq)] #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct MasternodeList { pub block_hash: BlockHash, pub known_height: u32, @@ -49,4 +50,12 @@ impl MasternodeList { ) -> MasternodeListBuilder { MasternodeListBuilder::new(masternodes, quorums, block_hash, block_height) } + + pub fn find_quorum_public_key(&self, quorum_type: &LLMQType, quorum_hash: &QuorumHash) -> Option { + self.quorums.get(quorum_type) + .and_then(|quorums_of_type| + quorums_of_type.get(quorum_hash) + .map(|quorum| quorum.quorum_entry.quorum_public_key)) + } + } diff --git a/dash/src/sml/masternode_list_engine/mod.rs b/dash/src/sml/masternode_list_engine/mod.rs index fd1ac4290..cced46fd3 100644 --- a/dash/src/sml/masternode_list_engine/mod.rs +++ b/dash/src/sml/masternode_list_engine/mod.rs @@ -1,6 +1,6 @@ mod helpers; #[cfg(feature = "message_verification")] -mod message_request_verification; +pub mod message_request_verification; mod non_rotated_quorum_construction; mod rotated_quorum_construction; #[cfg(feature = "quorum_validation")] @@ -21,7 +21,7 @@ use crate::sml::quorum_entry::qualified_quorum_entry::{ QualifiedQuorumEntry, VerifyingChainLockSignaturesType, }; use crate::sml::quorum_validation_error::{ClientDataRetrievalError, QuorumValidationError}; -use crate::transaction::special_transaction::quorum_commitment::QuorumEntry; +use crate::blockdata::transaction::special_transaction::quorum_commitment::QuorumEntry; use crate::{BlockHash, Network, QuorumHash}; #[cfg(feature = "bincode")] use bincode::{Decode, Encode}; @@ -43,6 +43,11 @@ impl MasternodeListEngineBTreeMapBlockContainer { self.block_heights.insert(block_hash, height); self.block_hashes.insert(height, block_hash); } + + pub fn clear(&mut self) { + self.block_hashes.clear(); + self.block_heights.clear(); + } } #[derive(Clone, Eq, PartialEq)] @@ -116,6 +121,12 @@ impl MasternodeListEngineBlockContainer { MasternodeListEngineBlockContainer::BTreeMapContainer(map) => map.block_hashes.len(), } } + + pub fn clear(&mut self) { + match self { + MasternodeListEngineBlockContainer::BTreeMapContainer(map) => map.clear(), + } + } } #[derive(Clone, Eq, PartialEq)] @@ -180,6 +191,14 @@ impl MasternodeListEngine { }) } + pub fn clear(&mut self) { + self.block_container.clear(); + self.masternode_lists.clear(); + self.known_snapshots.clear(); + self.rotated_quorums_per_cycle.clear(); + self.quorum_statuses.clear(); + } + pub fn latest_masternode_list(&self) -> Option<&MasternodeList> { self.masternode_lists.last_key_value().map(|(_, list)| list) } @@ -683,17 +702,17 @@ impl MasternodeListEngine { verify_quorums: bool, previous_chain_lock_sigs: Option<[BLSSignature; 3]>, ) -> Result, SmlError> { + let base_block_hash = masternode_list_diff.base_block_hash; + let block_hash = masternode_list_diff.block_hash; if let Some(known_genesis_block_hash) = self .network .known_genesis_block_hash() .or_else(|| self.block_container.get_hash(&0).cloned()) { - if masternode_list_diff.base_block_hash == known_genesis_block_hash - || masternode_list_diff.base_block_hash.as_byte_array() == &[0; 32] + if base_block_hash == known_genesis_block_hash + || base_block_hash.as_byte_array() == &[0; 32] { // we are going from the start - let block_hash = masternode_list_diff.block_hash; - let masternode_list = masternode_list_diff.try_into_with_block_hash_lookup( |block_hash| diff_end_height.or(self.block_container.get_height(block_hash)), self.network, @@ -953,6 +972,11 @@ impl MasternodeListEngine { Ok(()) } + + pub fn find_quorum_public_key(&self, quorum_type: &LLMQType, quorum_hash: &QuorumHash) -> Option { + self.masternode_lists.values() + .find_map(|masternode_list| masternode_list.find_quorum_public_key(quorum_type, quorum_hash)) + } } #[cfg(test)] diff --git a/dash/src/sml/masternode_list_entry/hash.rs b/dash/src/sml/masternode_list_entry/hash.rs index 51f5932cf..c6befde01 100644 --- a/dash/src/sml/masternode_list_entry/hash.rs +++ b/dash/src/sml/masternode_list_entry/hash.rs @@ -1,13 +1,13 @@ use hashes::{Hash, sha256d}; use crate::consensus::Encodable; +use crate::hash_types::Sha256dHash; use crate::sml::masternode_list_entry::MasternodeListEntry; impl MasternodeListEntry { - pub fn calculate_entry_hash(&self) -> sha256d::Hash { + pub fn calculate_entry_hash(&self) -> Sha256dHash { let mut writer = Vec::new(); - self.consensus_encode(&mut writer).expect("encoding failed"); - sha256d::Hash::hash(&writer) + Sha256dHash::from_raw_hash(sha256d::Hash::hash(&writer)) } } diff --git a/dash/src/sml/masternode_list_entry/mod.rs b/dash/src/sml/masternode_list_entry/mod.rs index 578d91558..9e7d84e8a 100644 --- a/dash/src/sml/masternode_list_entry/mod.rs +++ b/dash/src/sml/masternode_list_entry/mod.rs @@ -9,14 +9,14 @@ use std::net::SocketAddr; use crate::bls_sig_utils::BLSPublicKey; use crate::consensus::encode::Error; use crate::consensus::{Decodable, Encodable}; -use crate::hash_types::ConfirmedHash; +use crate::hash_types::{ConfirmedHash, ProTxHash, PubkeyHash}; use crate::internal_macros::impl_consensus_encoding; -use crate::{ProTxHash, PubkeyHash}; #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Debug)] #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub enum EntryMasternodeType { Regular, HighPerformance { @@ -72,18 +72,29 @@ impl Decodable for EntryMasternodeType { } #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Debug)] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct OperatorPublicKey { // TODO: We are using two different public keys here pub data: BLSPublicKey, pub version: u16, } +impl OperatorPublicKey { + pub fn is_basic(&self) -> bool { + self.version >= 2 + } + pub fn is_legacy(&self) -> bool { + self.version < 2 + } +} + impl_consensus_encoding!(OperatorPublicKey, data, version); #[derive(Clone, Eq, PartialEq, Debug)] #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct MasternodeListEntry { pub version: u16, pub pro_reg_tx_hash: ProTxHash, diff --git a/dash/src/sml/masternode_list_entry/qualified_masternode_list_entry.rs b/dash/src/sml/masternode_list_entry/qualified_masternode_list_entry.rs index 595d4c9ee..cff3e613d 100644 --- a/dash/src/sml/masternode_list_entry/qualified_masternode_list_entry.rs +++ b/dash/src/sml/masternode_list_entry/qualified_masternode_list_entry.rs @@ -2,9 +2,8 @@ use std::cmp::Ordering; #[cfg(feature = "bincode")] use bincode::{Decode, Encode}; -use hashes::{Hash, sha256d}; - -use crate::hash_types::ConfirmedHashHashedWithProRegTx; +use hashes::Hash; +use crate::hash_types::{ConfirmedHashHashedWithProRegTx, Sha256dHash}; use crate::sml::masternode_list_entry::MasternodeListEntry; /// A structured representation of a masternode list entry with a cached entry hash and a confirmed @@ -14,11 +13,12 @@ use crate::sml::masternode_list_entry::MasternodeListEntry; #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct QualifiedMasternodeListEntry { /// The underlying masternode list entry pub masternode_list_entry: MasternodeListEntry, /// The computed entry hash - pub entry_hash: sha256d::Hash, + pub entry_hash: Sha256dHash, /// The confirmed hash hashed with the pro_reg_tx if the confirmed hash is set pub confirmed_hash_hashed_with_pro_reg_tx: Option, } diff --git a/dash/src/sml/mod.rs b/dash/src/sml/mod.rs index 2374fa944..3f0d25442 100644 --- a/dash/src/sml/mod.rs +++ b/dash/src/sml/mod.rs @@ -5,7 +5,7 @@ pub mod llmq_type; pub mod masternode_list; pub mod masternode_list_engine; pub mod masternode_list_entry; -mod message_verification_error; +pub mod message_verification_error; mod order_option; pub mod quorum_entry; pub mod quorum_validation_error; diff --git a/dash/src/sml/quorum_entry/hash.rs b/dash/src/sml/quorum_entry/hash.rs index fd346c96d..d4ff1fb84 100644 --- a/dash/src/sml/quorum_entry/hash.rs +++ b/dash/src/sml/quorum_entry/hash.rs @@ -3,7 +3,7 @@ use hashes::Hash; use crate::consensus::Encodable; use crate::consensus::encode::{write_compact_size, write_fixed_bitset}; use crate::hash_types::{QuorumCommitmentHash, QuorumEntryHash}; -use crate::transaction::special_transaction::quorum_commitment::QuorumEntry; +use crate::blockdata::transaction::special_transaction::quorum_commitment::QuorumEntry; impl QuorumEntry { /// Calculates the hash of the entire quorum entry. diff --git a/dash/src/sml/quorum_entry/qualified_quorum_entry.rs b/dash/src/sml/quorum_entry/qualified_quorum_entry.rs index c98b48b6a..f362c1ad8 100644 --- a/dash/src/sml/quorum_entry/qualified_quorum_entry.rs +++ b/dash/src/sml/quorum_entry/qualified_quorum_entry.rs @@ -4,7 +4,7 @@ use crate::sml::llmq_entry_verification::{ LLMQEntryVerificationSkipStatus, LLMQEntryVerificationStatus, }; use crate::sml::quorum_validation_error::QuorumValidationError; -use crate::transaction::special_transaction::quorum_commitment::QuorumEntry; +use crate::blockdata::transaction::special_transaction::quorum_commitment::QuorumEntry; #[cfg(feature = "bincode")] use bincode::{Decode, Encode}; @@ -12,6 +12,7 @@ use bincode::{Decode, Encode}; #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] #[cfg_attr(feature = "bincode", derive(Encode, Decode))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub enum VerifyingChainLockSignaturesType { Rotating([BLSSignature; 4]), NonRotating(BLSSignature), @@ -25,6 +26,7 @@ pub enum VerifyingChainLockSignaturesType { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] #[cfg_attr(feature = "bincode", derive(Encode, Decode))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub struct QualifiedQuorumEntry { /// The underlying quorum entry pub quorum_entry: QuorumEntry, diff --git a/dash/src/sml/quorum_validation_error.rs b/dash/src/sml/quorum_validation_error.rs index 3ced05614..2934bab7e 100644 --- a/dash/src/sml/quorum_validation_error.rs +++ b/dash/src/sml/quorum_validation_error.rs @@ -11,6 +11,7 @@ use crate::{BlockHash, QuorumHash}; #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub enum ClientDataRetrievalError { #[error("Required block not present: {0}")] RequiredBlockNotPresent(BlockHash), @@ -23,6 +24,7 @@ pub enum ClientDataRetrievalError { #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "apple", ferment_macro::export)] pub enum QuorumValidationError { #[error("Required block not present: {0} ({1})")] RequiredBlockNotPresent(BlockHash, String), diff --git a/dash/src/taproot.rs b/dash/src/taproot.rs index d182f0564..c8e4005c3 100644 --- a/dash/src/taproot.rs +++ b/dash/src/taproot.rs @@ -14,12 +14,13 @@ use hashes::{Hash, HashEngine, sha256t_hash_newtype}; use internals::write_err; use secp256k1::{self, Scalar, Secp256k1}; +use crate::blockdata::script::{Script, ScriptBuf}; use crate::consensus::Encodable; use crate::crypto::key::{TapTweak, TweakedPublicKey, UntweakedPublicKey, XOnlyPublicKey}; // Re-export these so downstream only has to use one `taproot` module. pub use crate::crypto::taproot::{Error, Signature}; use crate::prelude::*; -use crate::{Script, ScriptBuf, io}; +use crate::io; // Taproot test vectors from BIP-341 state the hashes without any reversing sha256t_hash_newtype! { diff --git a/hashes/Cargo.toml b/hashes/Cargo.toml index 07023b674..5eeea45b5 100644 --- a/hashes/Cargo.toml +++ b/hashes/Cargo.toml @@ -39,6 +39,7 @@ secp256k1 = { default-features = false, features = ["hashes"], version= "0.30.0" rs-x11-hash = { version = "0.1.8", optional = true } bincode = { version= "=2.0.0-rc.3", optional = true } +bincode_derive = { version= "=2.0.0-rc.3", optional = true } [dev-dependencies] serde_test = "1.0" diff --git a/hashes/src/internal_macros.rs b/hashes/src/internal_macros.rs index f2f59379e..dba1d9b49 100644 --- a/hashes/src/internal_macros.rs +++ b/hashes/src/internal_macros.rs @@ -241,7 +241,7 @@ macro_rules! hash_type { pub struct Hash( #[cfg_attr(feature = "schemars", schemars(schema_with = $schemars))] [u8; $bits / 8], ); - + impl Hash { fn internal_new(arr: [u8; $bits / 8]) -> Self { Hash(arr) diff --git a/rpc-json/Cargo.toml b/rpc-json/Cargo.toml index e725412b5..325eefe2d 100644 --- a/rpc-json/Cargo.toml +++ b/rpc-json/Cargo.toml @@ -28,3 +28,4 @@ hex = { version="0.4", features=["serde"]} dashcore = { path = "../dash", features=["std", "secp-recovery", "rand-std", "signer", "serde"], default-features = false } bincode = { version = "=2.0.0-rc.3", features = ["serde"] } +bincode_derive = { version= "=2.0.0-rc.3", optional = true }