Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
187 changes: 107 additions & 80 deletions dash/src/blockdata/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ pub const COINBASE_MATURITY: u32 = 100;
/// if you are doing anything remotely sane with monetary values).
pub const MAX_MONEY: u64 = 21_000_000 * COIN_VALUE;

/// Constructs and returns the coinbase (and only) transaction of the Bitcoin genesis block.
fn bitcoin_genesis_tx() -> Transaction {
/// Constructs and returns the coinbase (and only) transaction of the Dash genesis block.
fn dash_genesis_tx() -> Transaction {
// Base
let mut ret = Transaction {
version: 1,
Expand All @@ -82,11 +82,10 @@ fn bitcoin_genesis_tx() -> Transaction {
};

// Inputs
let in_script = script::Builder::new()
.push_int(486604799)
.push_int_non_minimal(4)
.push_slice(b"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks")
.into_script();
// Using raw script bytes to avoid push_slice issues
let in_script = script::ScriptBuf::from(hex!(
"04ffff001d01044c5957697265642030392f4a616e2f32303134205468652047726e64204578706572696d656e7420476f6573204c6976653a204f76657273746f636b2e636f6d204973204e6f7720416363657074696e6720426974636f696e73"
).to_vec());
ret.input.push(TxIn {
previous_output: OutPoint::null(),
script_sig: in_script,
Expand All @@ -96,7 +95,7 @@ fn bitcoin_genesis_tx() -> Transaction {

// Outputs
let script_bytes = hex!(
"04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"
"040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9"
);
let out_script =
script::Builder::new().push_slice(script_bytes).push_opcode(OP_CHECKSIG).into_script();
Expand All @@ -109,56 +108,78 @@ fn bitcoin_genesis_tx() -> Transaction {
ret
}


/// Constructs and returns the genesis block.
pub fn genesis_block(network: Network) -> Block {
let txdata = vec![bitcoin_genesis_tx()];
let hash: sha256d::Hash = txdata[0].txid().into();
let merkle_root = hash.into();
let txdata = vec![dash_genesis_tx()];

match network {
Network::Dash => Block {
header: block::Header {
version: block::Version::ONE,
prev_blockhash: Hash::all_zeros(),
merkle_root,
time: 1390095618,
bits: CompactTarget::from_consensus(0x1e0ffff0),
nonce: 28917698,
},
txdata,
},
Network::Testnet => Block {
header: block::Header {
version: block::Version::ONE,
prev_blockhash: Hash::all_zeros(),
merkle_root,
time: 1296688602,
bits: CompactTarget::from_consensus(0x1d00ffff),
nonce: 414098458,
},
txdata,
},
Network::Devnet => Block {
header: block::Header {
version: block::Version::ONE,
prev_blockhash: Hash::all_zeros(),
merkle_root,
time: 1598918400,
bits: CompactTarget::from_consensus(0x1e0377ae),
nonce: 52613770,
},
txdata,
},
Network::Regtest => Block {
header: block::Header {
version: block::Version::ONE,
prev_blockhash: Hash::all_zeros(),
merkle_root,
time: 1296688602,
bits: CompactTarget::from_consensus(0x207fffff),
nonce: 2,
},
txdata,
},
Network::Dash => {
// Mainnet merkle root - Note: bytes are reversed for internal representation
let merkle_bytes =
hex!("c762a6567f3cc092f0684bb62b7e00a84890b990f07cc71a6bb58d64b98e02e0");
let merkle_root = sha256d::Hash::from_slice(&merkle_bytes).unwrap().into();
Block {
header: block::Header {
version: block::Version::ONE,
prev_blockhash: Hash::all_zeros(),
merkle_root,
time: 1390095618,
bits: CompactTarget::from_consensus(0x1e0ffff0),
nonce: 28917698,
},
txdata,
}
}
Network::Testnet => {
// Testnet merkle root (same as mainnet for Dash) - Note: bytes are reversed for internal representation
let merkle_bytes =
hex!("c762a6567f3cc092f0684bb62b7e00a84890b990f07cc71a6bb58d64b98e02e0");
let merkle_root = sha256d::Hash::from_slice(&merkle_bytes).unwrap().into();
Block {
header: block::Header {
version: block::Version::ONE,
prev_blockhash: Hash::all_zeros(),
merkle_root,
time: 1390666206,
bits: CompactTarget::from_consensus(0x1e0ffff0),
nonce: 3861367235,
},
txdata,
}
}
Network::Devnet => {
// Devnet merkle root (same as mainnet/testnet - all use Dash genesis tx) - Note: bytes are reversed for internal representation
let merkle_bytes =
hex!("c762a6567f3cc092f0684bb62b7e00a84890b990f07cc71a6bb58d64b98e02e0");
let merkle_root = sha256d::Hash::from_slice(&merkle_bytes).unwrap().into();
Block {
header: block::Header {
version: block::Version::ONE,
prev_blockhash: Hash::all_zeros(),
merkle_root,
time: 1598918400,
bits: CompactTarget::from_consensus(0x1e0377ae),
nonce: 52613770,
},
txdata,
}
}
Network::Regtest => {
let hash: sha256d::Hash = txdata[0].txid().into();
let merkle_root = hash.into();
Block {
header: block::Header {
version: block::Version::ONE,
prev_blockhash: Hash::all_zeros(),
merkle_root,
time: 1296688602,
bits: CompactTarget::from_consensus(0x207fffff),
nonce: 2,
},
txdata,
}
}
// Any new network variant must be handled explicitly.
other => unreachable!("genesis_block(): unsupported network variant {other:?}"),
}
Expand All @@ -174,23 +195,27 @@ impl ChainHash {
// Mainnet value can be verified at https://github.com/lightning/bolts/blob/master/00-introduction.md
/// `ChainHash` for mainnet dash.
pub const DASH: Self = Self([
31, 206, 219, 159, 237, 128, 98, 250, 59, 68, 162, 177, 88, 247, 112, 126, 30, 188, 238,
123, 223, 166, 251, 66, 69, 17, 71, 123, 239, 57, 230, 139,
0x00, 0x00, 0x0f, 0xfd, 0x59, 0x0b, 0x14, 0x85, 0xb3, 0xca, 0xad, 0xc1, 0x9b, 0x22, 0xe6,
0x37, 0x9c, 0x73, 0x33, 0x55, 0x10, 0x8f, 0x10, 0x7a, 0x43, 0x04, 0x58, 0xcd, 0xf3, 0x40,
0x7a, 0xb6,
]);
/// `ChainHash` for testnet dash.
pub const TESTNET: Self = Self([
16, 238, 202, 52, 44, 112, 187, 96, 147, 134, 134, 75, 156, 55, 90, 205, 70, 74, 202, 97,
112, 87, 40, 133, 32, 84, 236, 123, 183, 28, 220, 240,
0x00, 0x00, 0x0b, 0xaf, 0xbc, 0x94, 0xad, 0xd7, 0x6c, 0xb7, 0x5e, 0x2e, 0xc9, 0x28, 0x94,
0x83, 0x72, 0x88, 0xa4, 0x81, 0xe5, 0xc0, 0x05, 0xf6, 0x56, 0x3d, 0x91, 0x62, 0x3b, 0xf8,
0xbc, 0x2c,
]);
/// `ChainHash` for devnet dash.
pub const DEVNET: Self = Self([
164, 119, 85, 190, 121, 37, 150, 111, 131, 181, 177, 164, 204, 209, 202, 105, 29, 197, 235,
240, 250, 179, 224, 6, 46, 238, 40, 136, 23, 215, 12, 88,
0x4e, 0x5f, 0x93, 0x0c, 0x5d, 0x73, 0xa8, 0x79, 0x2f, 0xa6, 0x81, 0xba, 0x8c, 0x5e, 0xaf,
0x74, 0xaa, 0x63, 0x97, 0x4a, 0x5b, 0x1f, 0x59, 0x8d, 0xd5, 0x08, 0x02, 0x9a, 0xee, 0x70,
0x16, 0x7b,
]);
/// `ChainHash` for regtest dash.
pub const REGTEST: Self = Self([
16, 251, 76, 138, 72, 44, 63, 251, 228, 123, 87, 245, 131, 191, 84, 111, 117, 107, 92, 205,
105, 10, 247, 249, 131, 113, 112, 200, 29, 102, 142, 242,
0x53, 0xb3, 0xed, 0x30, 0x30, 0x78, 0x1a, 0xc1, 0x9e, 0x48, 0x52, 0xd9, 0xc5, 0x8f, 0x28,
0x04, 0x57, 0x4f, 0x98, 0x66, 0xf3, 0xf7, 0xf6, 0x91, 0x31, 0xee, 0xb1, 0x3f, 0x44, 0x9f,
0x80, 0x07,
]);

/// Returns the hash of the `network` genesis block for use as a chain hash.
Expand All @@ -216,8 +241,8 @@ mod test {
use dash_network::Network;

#[test]
fn bitcoin_genesis_first_transaction() {
let genesis_tx = bitcoin_genesis_tx();
fn dash_genesis_first_transaction() {
let genesis_tx = dash_genesis_tx();

assert_eq!(genesis_tx.version, 1);
assert_eq!(genesis_tx.input.len(), 1);
Expand All @@ -226,7 +251,7 @@ mod test {
assert_eq!(
serialize(&genesis_tx.input[0].script_sig),
hex!(
"4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73"
"6104ffff001d01044c5957697265642030392f4a616e2f32303134205468652047726e64204578706572696d656e7420476f6573204c6976653a204f76657273746f636b2e636f6d204973204e6f7720416363657074696e6720426974636f696e73"
)
);

Expand All @@ -235,35 +260,37 @@ mod test {
assert_eq!(
serialize(&genesis_tx.output[0].script_pubkey),
hex!(
"434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac"
"4341040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9ac"
)
);
assert_eq!(genesis_tx.output[0].value, 50 * COIN_VALUE);
assert_eq!(genesis_tx.lock_time, 0);

// The wtxid should be deterministic for the coinbase transaction
let wtxid_str = genesis_tx.wtxid().to_string();
assert_eq!(
genesis_tx.wtxid().to_string(),
"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
wtxid_str,
"babeaa0bf3af03c0f12d94da95c7f28168be22087a16fb207e7abda4ae654ee3"
);
}

#[test]
fn bitcoin_genesis_full_block() {
fn dash_genesis_full_block() {
let genesis_block = genesis_block(Network::Dash);

assert_eq!(genesis_block.header.version, block::Version::ONE);
assert_eq!(genesis_block.header.prev_blockhash, Hash::all_zeros());
assert_eq!(
genesis_block.header.merkle_root.to_string(),
"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
"e0028eb9648db56b1ac77cf090b99048a8007e2bb64b68f092c03c7f56a662c7"
);

assert_eq!(genesis_block.header.time, 1390095618);
assert_eq!(genesis_block.header.bits, CompactTarget::from_consensus(0x1e0ffff0));
assert_eq!(genesis_block.header.nonce, 28917698);
assert_eq!(
genesis_block.header.block_hash().to_string(),
"1fcedb9fed8062fa3b44a2b158f7707e1ebcee7bdfa6fb424511477bef39e68b"
"00000ffd590b1485b3caadc19b22e6379c733355108f107a430458cdf3407ab6"
);
}

Expand All @@ -274,14 +301,14 @@ mod test {
assert_eq!(genesis_block.header.prev_blockhash, Hash::all_zeros());
assert_eq!(
genesis_block.header.merkle_root.to_string(),
"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
"e0028eb9648db56b1ac77cf090b99048a8007e2bb64b68f092c03c7f56a662c7"
);
assert_eq!(genesis_block.header.time, 1296688602);
assert_eq!(genesis_block.header.bits, CompactTarget::from_consensus(0x1d00ffff));
assert_eq!(genesis_block.header.nonce, 414098458);
assert_eq!(genesis_block.header.time, 1390666206);
assert_eq!(genesis_block.header.bits, CompactTarget::from_consensus(0x1e0ffff0));
assert_eq!(genesis_block.header.nonce, 3861367235);
assert_eq!(
genesis_block.header.block_hash().to_string(),
"10eeca342c70bb609386864b9c375acd464aca61705728852054ec7bb71cdcf0"
"00000bafbc94add76cb75e2ec92894837288a481e5c005f6563d91623bf8bc2c"
);
}

Expand All @@ -292,14 +319,14 @@ mod test {
assert_eq!(genesis_block.header.prev_blockhash, Hash::all_zeros());
assert_eq!(
genesis_block.header.merkle_root.to_string(),
"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
"e0028eb9648db56b1ac77cf090b99048a8007e2bb64b68f092c03c7f56a662c7"
);
assert_eq!(genesis_block.header.time, 1598918400);
assert_eq!(genesis_block.header.bits, CompactTarget::from_consensus(0x1e0377ae));
assert_eq!(genesis_block.header.nonce, 52613770);
assert_eq!(
genesis_block.header.block_hash().to_string(),
"a47755be7925966f83b5b1a4ccd1ca691dc5ebf0fab3e0062eee288817d70c58"
"4e5f930c5d73a8792fa681ba8c5eaf74aa63974a5b1f598dd508029aee70167b"
);
}

Expand Down Expand Up @@ -350,7 +377,7 @@ mod test {
#[test]
fn mainnet_chain_hash_test_vector() {
let got = ChainHash::using_genesis_block(Network::Dash).to_string();
let want = "1fcedb9fed8062fa3b44a2b158f7707e1ebcee7bdfa6fb424511477bef39e68b";
let want = "00000ffd590b1485b3caadc19b22e6379c733355108f107a430458cdf3407ab6";
assert_eq!(got, want);
}
}
59 changes: 59 additions & 0 deletions dash/src/network/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,8 @@ pub enum NetworkMessage {
CLSig(ChainLock),
/// `isdlock`
ISLock(InstantLock),
/// `senddsq` - Notify peer whether to send CoinJoin queue messages
SendDsq(bool),
/// Any other message.
Unknown {
/// The command of this message.
Expand Down Expand Up @@ -323,6 +325,7 @@ impl NetworkMessage {
NetworkMessage::QRInfo(_) => "qrinfo",
NetworkMessage::CLSig(_) => "clsig",
NetworkMessage::ISLock(_) => "isdlock",
NetworkMessage::SendDsq(_) => "senddsq",
NetworkMessage::Unknown {
..
} => "unknown",
Expand Down Expand Up @@ -424,6 +427,7 @@ impl Encodable for RawNetworkMessage {
NetworkMessage::QRInfo(ref dat) => serialize(dat),
NetworkMessage::CLSig(ref dat) => serialize(dat),
NetworkMessage::ISLock(ref dat) => serialize(dat),
NetworkMessage::SendDsq(wants_dsq) => serialize(&(wants_dsq as u8)),
})
.consensus_encode(w)?;
Ok(len)
Expand Down Expand Up @@ -601,6 +605,10 @@ impl Decodable for RawNetworkMessage {
"isdlock" => {
NetworkMessage::ISLock(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?)
}
"senddsq" => {
let byte: u8 = Decodable::consensus_decode_from_finite_reader(&mut mem_d)?;
NetworkMessage::SendDsq(byte != 0)
}
_ => NetworkMessage::Unknown {
command: cmd,
payload: mem_d.into_inner(),
Expand Down Expand Up @@ -947,4 +955,55 @@ mod test {
panic!("Wrong message type");
}
}

#[test]
fn test_senddsq_message_encode_decode() {
// Test encoding and decoding SendDsq(true)
let msg_true = NetworkMessage::SendDsq(true);
let raw_msg = RawNetworkMessage {
magic: crate::Network::Dash.magic(),
payload: msg_true,
};

// Encode
let encoded = serialize(&raw_msg);

// Decode
let decoded: RawNetworkMessage = deserialize(&encoded).unwrap();

// Verify
match decoded.payload {
NetworkMessage::SendDsq(wants_dsq) => {
assert_eq!(wants_dsq, true);
}
_ => panic!("Expected SendDsq message"),
}

// Test encoding and decoding SendDsq(false)
let msg_false = NetworkMessage::SendDsq(false);
let raw_msg = RawNetworkMessage {
magic: crate::Network::Dash.magic(),
payload: msg_false,
};

// Encode
let encoded = serialize(&raw_msg);

// Decode
let decoded: RawNetworkMessage = deserialize(&encoded).unwrap();

// Verify
match decoded.payload {
NetworkMessage::SendDsq(wants_dsq) => {
assert_eq!(wants_dsq, false);
}
_ => panic!("Expected SendDsq message"),
}
}

#[test]
fn test_senddsq_command_string() {
let msg = NetworkMessage::SendDsq(true);
assert_eq!(msg.cmd(), "senddsq");
}
}
Loading