Skip to content

Commit 811e0cf

Browse files
feat: simplified masternode list messages (#50)
* feat: simplified masternode list * expose * more work on sml * more work on sml * more work on sml * fixed message deserialization * refactor: changed service address to SocketAddr * test: assert message type * docs: fixed example * docs: add documentation for message fields * test: fix magic assert * test: fixing tests in progress * tests passing --------- Co-authored-by: Quantum Explorer <quantum@dash.org>
1 parent 521a76b commit 811e0cf

File tree

17 files changed

+486
-51
lines changed

17 files changed

+486
-51
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dash/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ serde_derive = "1.0.103"
7474
secp256k1 = { features = [ "recovery", "rand", "hashes" ], version="0.30.0" }
7575
bip39 = "2.0.0"
7676
bincode_test = {package = "bincode", version= "1.3.3" }
77+
assert_matches = "1.5.0"
7778

7879
[[example]]
7980
name = "bip32"

dash/examples/handshake.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use dashcore::consensus::{Decodable, encode};
99
use dashcore::network::{address, constants, message, message_network};
1010
use dashcore::secp256k1;
1111
use dashcore::secp256k1::rand::Rng;
12+
use secp256k1::rand;
1213

1314
fn main() {
1415
// This example establishes a connection to a Bitcoin node, sends the intial
@@ -97,6 +98,9 @@ fn build_version_message(address: SocketAddr) -> message::NetworkMessage {
9798
// "The last block received by the emitting node"
9899
let start_height: i32 = 0;
99100

101+
// Generate challenge for masternode authentication
102+
let mn_auth_challenge = rand::random();
103+
100104
// Construct the message
101105
message::NetworkMessage::Version(message_network::VersionMessage::new(
102106
services,
@@ -106,5 +110,6 @@ fn build_version_message(address: SocketAddr) -> message::NetworkMessage {
106110
nonce,
107111
user_agent,
108112
start_height,
113+
mn_auth_challenge,
109114
))
110115
}

dash/src/consensus/encode.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,25 @@ use internals::write_err;
4141

4242
use crate::bip152::{PrefilledTransaction, ShortId};
4343
use crate::blockdata::transaction::Transaction;
44-
use crate::hash_types::{BlockHash, FilterHash, FilterHeader, TxMerkleNode};
44+
use crate::bls_sig_utils::BLSSignature;
45+
use crate::hash_types::{
46+
BlockHash, FilterHash, FilterHeader, MerkleRootMasternodeList, TxMerkleNode,
47+
};
4548
use crate::io::{self, Cursor, Read};
49+
use crate::network::message_sml::DeletedQuorum;
4650
#[cfg(feature = "std")]
4751
use crate::network::{
4852
address::{AddrV2Message, Address},
4953
message_blockdata::Inventory,
5054
};
5155
use crate::prelude::*;
56+
use crate::sml::entry::MasternodeListEntry;
5257
use crate::taproot::TapLeafHash;
5358
use crate::transaction::special_transaction::TransactionType;
59+
use crate::transaction::special_transaction::quorum_commitment::QuorumFinalizationCommitment;
5460
use crate::transaction::txin::TxIn;
5561
use crate::transaction::txout::TxOut;
56-
use crate::{OutPoint, ScriptBuf, address};
62+
use crate::{OutPoint, ProTxHash, ScriptBuf, address};
5763

5864
/// Encoding error.
5965
#[derive(Debug)]
@@ -104,11 +110,13 @@ pub enum Error {
104110
Hex(hashes::hex::Error),
105111
/// Address error
106112
Address(address::Error),
113+
/// Invalid enum value
114+
InvalidEnumValue { max: u16, received: u16, msg: String },
107115
}
108116

109117
impl fmt::Display for Error {
110118
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
111-
match *self {
119+
match self {
112120
Error::Io(ref e) => write_err!(f, "IO error"; e),
113121
Error::OversizedVectorAllocation { requested: ref r, max: ref m } => {
114122
write!(f, "allocation of oversized vector: requested {}, maximum {}", r, m)
@@ -135,6 +143,9 @@ impl fmt::Display for Error {
135143
}
136144
Error::Hex(ref e) => write!(f, "hex error {}", e),
137145
Error::Address(ref e) => write!(f, "address error {}", e),
146+
Error::InvalidEnumValue { max, received, msg } => {
147+
write!(f, "invalid enum value, max: {} received: {} ({})", max, received, msg)
148+
}
138149
}
139150
}
140151
}
@@ -155,8 +166,9 @@ impl std::error::Error for Error {
155166
| Error::WrongSpecialTransactionPayloadConversion { .. }
156167
| Error::NonStandardScriptPayout(..)
157168
| Error::InvalidVectorSize { .. }
158-
| Error::Hex(_) => None,
159-
Error::Address(_) => None,
169+
| Error::Hex(_)
170+
| Error::Address(_)
171+
| InvalidEnumValue { .. } => None,
160172
}
161173
}
162174
}
@@ -673,6 +685,12 @@ impl_vec!(VarInt);
673685
impl_vec!(ShortId);
674686
impl_vec!(OutPoint);
675687
impl_vec!(PrefilledTransaction);
688+
impl_vec!(QuorumFinalizationCommitment);
689+
impl_vec!(DeletedQuorum);
690+
impl_vec!(BLSSignature);
691+
impl_vec!(ProTxHash);
692+
impl_vec!(MerkleRootMasternodeList);
693+
impl_vec!(MasternodeListEntry);
676694

677695
#[cfg(feature = "std")]
678696
impl_vec!(Inventory);

dash/src/consensus/serde.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use serde::de::{SeqAccess, Unexpected, Visitor};
1414
use serde::ser::SerializeSeq;
1515
use serde::{Deserializer, Serializer};
1616

17-
use super::encode::Error as ConsensusError;
17+
use super::encode::{Error as ConsensusError, Error};
1818
use super::{Decodable, Encodable};
1919
use crate::alloc::string::ToString;
2020
use crate::io;
@@ -411,6 +411,10 @@ fn consensus_error_into_serde<E: serde::de::Error>(error: ConsensusError) -> E {
411411
),
412412
ConsensusError::Hex(error) => E::custom(error),
413413
ConsensusError::Address(error) => E::custom(error),
414+
ConsensusError::InvalidEnumValue { max, received, msg } => E::invalid_value(
415+
Unexpected::Unsigned(received.into()),
416+
&DisplayExpected(format_args!("expected enum value ≤ {}: {}", max, msg)),
417+
),
414418
}
415419
}
416420

@@ -455,8 +459,9 @@ impl<E: fmt::Debug, I: Iterator<Item = Result<u8, E>>> IterReader<E, I> {
455459
match (result, self.error) {
456460
(Ok(_), None) if self.iterator.next().is_some() => Err(DecodeError::TooManyBytes),
457461
(Ok(value), None) => Ok(value),
458-
(Ok(_), Some(error)) =>
459-
panic!("{} silently ate the error: {:?}", core::any::type_name::<T>(), error),
462+
(Ok(_), Some(error)) => {
463+
panic!("{} silently ate the error: {:?}", core::any::type_name::<T>(), error)
464+
}
460465
(Err(ConsensusError::Io(io_error)), Some(de_error))
461466
if io_error.kind() == io::ErrorKind::Other && io_error.source().is_none() =>
462467
Err(DecodeError::Other(de_error)),

dash/src/crypto/sighash.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -273,10 +273,12 @@ impl fmt::Display for Error {
273273
f,
274274
"A single prevout has been provided but all prevouts are needed without `ANYONECANPAY`"
275275
),
276-
WrongAnnex =>
277-
write!(f, "Annex must be at least one byte long and the first bytes must be `0x50`"),
278-
InvalidSighashType(hash_ty) =>
279-
write!(f, "Invalid taproot signature hash type : {} ", hash_ty),
276+
WrongAnnex => {
277+
write!(f, "Annex must be at least one byte long and the first bytes must be `0x50`")
278+
}
279+
InvalidSighashType(hash_ty) => {
280+
write!(f, "Invalid taproot signature hash type : {} ", hash_ty)
281+
}
280282
}
281283
}
282284
}

dash/src/hash_types.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,6 @@ mod newtypes {
9999
/// A dash witness transaction ID.
100100
pub struct Wtxid(sha256d::Hash);
101101

102-
103-
104-
105102
/// A hash of a public key.
106103
pub struct PubkeyHash(hash160::Hash);
107104
/// A hash of Dash Script bytecode.
@@ -145,6 +142,8 @@ mod newtypes {
145142
/// ProTxHash is a pro-tx hash
146143
#[hash_newtype(forward)]
147144
pub struct ProTxHash(sha256d::Hash);
145+
pub struct ConfirmedHash(sha256d::Hash);
146+
pub struct Sha256dHash(sha256d::Hash);
148147
}
149148

150149
impl_hashencode!(Txid);
@@ -169,6 +168,10 @@ mod newtypes {
169168
impl_hashencode!(PubkeyHash);
170169
impl_hashencode!(CycleHash);
171170

171+
impl_hashencode!(ConfirmedHash);
172+
impl_hashencode!(ProTxHash);
173+
impl_hashencode!(Sha256dHash);
174+
172175
impl_asref_push_bytes!(PubkeyHash, ScriptHash, WPubkeyHash, WScriptHash);
173176

174177
impl Txid {
@@ -195,6 +198,30 @@ mod newtypes {
195198
}
196199
}
197200

201+
impl ConfirmedHash {
202+
/// Create a ConfirmedHash from a string
203+
pub fn from_hex(s: &str) -> Result<ConfirmedHash, Error> {
204+
Ok(Self(sha256d::Hash::from_str(s)?))
205+
}
206+
207+
/// Convert a ConfirmedHash to a string
208+
pub fn to_hex(&self) -> String {
209+
self.0.to_string()
210+
}
211+
}
212+
213+
impl Sha256dHash {
214+
/// Create a Sha256dHash from a string
215+
pub fn from_hex(s: &str) -> Result<Sha256dHash, Error> {
216+
Ok(Self(sha256d::Hash::from_str(s)?))
217+
}
218+
219+
/// Convert a ConfirmedHash to a string
220+
pub fn to_hex(&self) -> String {
221+
self.0.to_string()
222+
}
223+
}
224+
198225
impl InputsHash {
199226
/// Create an InputsHash from a string
200227
pub fn from_hex(s: &str) -> Result<InputsHash, Error> {

dash/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ pub mod pow;
119119
pub mod psbt;
120120
pub mod sign_message;
121121
pub mod signer;
122+
pub mod sml;
122123
pub mod string;
123124
pub mod taproot;
124125
pub mod util;

dash/src/network/message.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use crate::merkle_tree::MerkleBlock;
3030
use crate::network::address::{AddrV2Message, Address};
3131
use crate::network::{
3232
message_blockdata, message_bloom, message_compact_blocks, message_filter, message_network,
33+
message_sml,
3334
};
3435
use crate::prelude::*;
3536

@@ -236,7 +237,10 @@ pub enum NetworkMessage {
236237
AddrV2(Vec<AddrV2Message>),
237238
/// `sendaddrv2`
238239
SendAddrV2,
239-
240+
/// `getmnlistd`
241+
GetMnListD(message_sml::GetMnListDiff),
242+
/// `mnlistdiff`
243+
MnListDiff(message_sml::MnListDiff),
240244
/// Any other message.
241245
Unknown {
242246
/// The command of this message.
@@ -290,6 +294,8 @@ impl NetworkMessage {
290294
NetworkMessage::WtxidRelay => "wtxidrelay",
291295
NetworkMessage::AddrV2(_) => "addrv2",
292296
NetworkMessage::SendAddrV2 => "sendaddrv2",
297+
NetworkMessage::GetMnListD(_) => "getmnlistd",
298+
NetworkMessage::MnListDiff(_) => "mnlistdiff",
293299
NetworkMessage::Unknown { .. } => "unknown",
294300
}
295301
}
@@ -373,6 +379,8 @@ impl Encodable for RawNetworkMessage {
373379
| NetworkMessage::FilterClear
374380
| NetworkMessage::SendAddrV2 => vec![],
375381
NetworkMessage::Unknown { payload: ref data, .. } => serialize(data),
382+
NetworkMessage::GetMnListD(ref dat) => serialize(dat),
383+
NetworkMessage::MnListDiff(ref dat) => serialize(dat),
376384
})
377385
.consensus_encode(w)?;
378386
Ok(len)
@@ -498,6 +506,12 @@ impl Decodable for RawNetworkMessage {
498506
"addrv2" =>
499507
NetworkMessage::AddrV2(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
500508
"sendaddrv2" => NetworkMessage::SendAddrV2,
509+
"getmnlistd" => NetworkMessage::GetMnListD(
510+
Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
511+
),
512+
"mnlistdiff" => NetworkMessage::MnListDiff(
513+
Decodable::consensus_decode_from_finite_reader(&mut mem_d)?,
514+
),
501515
_ => NetworkMessage::Unknown { command: cmd, payload: mem_d.into_inner() },
502516
};
503517
Ok(RawNetworkMessage { magic, payload })
@@ -756,10 +770,8 @@ mod test {
756770
0x10, 0x2f, 0x53, 0x61, 0x74, 0x6f, 0x73, 0x68,
757771
0x69, 0x3a, 0x30, 0x2e, 0x31, 0x37, 0x2e, 0x31,
758772
0x2f, 0x93, 0x8c, 0x08, 0x00, 0x01
759-
]);
773+
]).expect("deserialize version message");
760774

761-
assert!(msg.is_ok());
762-
let msg = msg.unwrap();
763775
assert_eq!(msg.magic, 0xd9b4bef9);
764776
if let NetworkMessage::Version(version_msg) = msg.payload {
765777
assert_eq!(version_msg.version, 70015);
@@ -801,10 +813,9 @@ mod test {
801813
0x69, 0x3a, 0x30, 0x2e, 0x31, 0x37, 0x2e, 0x31,
802814
0x2f, 0x93, 0x8c, 0x08, 0x00, 0x01, 0x00, 0x00
803815
];
804-
let msg = deserialize_partial::<RawNetworkMessage>(&data);
805-
assert!(msg.is_ok());
816+
let (msg, consumed) =
817+
deserialize_partial::<RawNetworkMessage>(&data).expect("deserialize partial message");
806818

807-
let (msg, consumed) = msg.unwrap();
808819
assert_eq!(consumed, data.to_vec().len() - 2);
809820
assert_eq!(msg.magic, 0xd9b4bef9);
810821
if let NetworkMessage::Version(version_msg) = msg.payload {

0 commit comments

Comments
 (0)