Skip to content

Use deterministic ordering of HashMaps when encoding a ChannelMonitor #1911

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
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
16 changes: 12 additions & 4 deletions lightning/src/chain/channelmonitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1005,13 +1005,17 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
}

writer.write_all(&(self.counterparty_commitment_txn_on_chain.len() as u64).to_be_bytes())?;
for (ref txid, commitment_number) in self.counterparty_commitment_txn_on_chain.iter() {
let mut sorted_counterparty_commitment_txn_on_chain: Vec<(&Txid, &u64)> = self.counterparty_commitment_txn_on_chain.iter().collect();
sorted_counterparty_commitment_txn_on_chain.sort_by(|&a, &b| b.0.cmp(a.0));
for (ref txid, commitment_number) in sorted_counterparty_commitment_txn_on_chain {
writer.write_all(&txid[..])?;
writer.write_all(&byte_utils::be48_to_array(*commitment_number))?;
}

writer.write_all(&(self.counterparty_hash_commitment_number.len() as u64).to_be_bytes())?;
for (ref payment_hash, commitment_number) in self.counterparty_hash_commitment_number.iter() {
let mut sorted_counterparty_hash_commitment_number: Vec<(&PaymentHash, &u64)> = self.counterparty_hash_commitment_number.iter().collect();
sorted_counterparty_hash_commitment_number.sort_by(|&a, &b| b.0.cmp(a.0));
for (ref payment_hash, commitment_number) in sorted_counterparty_hash_commitment_number {
writer.write_all(&payment_hash.0[..])?;
writer.write_all(&byte_utils::be48_to_array(*commitment_number))?;
}
Expand All @@ -1029,7 +1033,9 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
writer.write_all(&byte_utils::be48_to_array(self.current_holder_commitment_number))?;

writer.write_all(&(self.payment_preimages.len() as u64).to_be_bytes())?;
for payment_preimage in self.payment_preimages.values() {
let mut sorted_preimages: Vec<&PaymentPreimage> = self.payment_preimages.values().collect();
sorted_preimages.sort();
for payment_preimage in sorted_preimages {
writer.write_all(&payment_preimage.0[..])?;
}

Expand Down Expand Up @@ -1063,7 +1069,9 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
}

(self.outputs_to_watch.len() as u64).write(writer)?;
for (txid, idx_scripts) in self.outputs_to_watch.iter() {
let mut sorted_outputs_to_watch: Vec<(&Txid, &Vec<(u32, Script)>)> = self.outputs_to_watch.iter().collect();
sorted_outputs_to_watch.sort_by(|&a, &b| b.0.cmp(a.0));
for (txid, idx_scripts) in sorted_outputs_to_watch {
txid.write(writer)?;
(idx_scripts.len() as u64).write(writer)?;
for (idx, script) in idx_scripts.iter() {
Expand Down
14 changes: 10 additions & 4 deletions lightning/src/chain/onchaintx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ pub struct OnchainTxHandler<ChannelSigner: Sign> {
// Key is outpoint than monitor parsing has detected we have keys/scripts to claim
// Value is (pending claim request identifier, confirmation_block), identifier
// is txid of the initial claiming transaction and is immutable until outpoint is
// post-anti-reorg-delay solved, confirmaiton_block is used to erase entry if
// post-anti-reorg-delay solved, confirmation_block is used to erase entry if
// block with output gets disconnected.
#[cfg(test)] // Used in functional_test to verify sanitization
pub claimable_outpoints: HashMap<BitcoinOutPoint, (PackageID, u32)>,
Expand Down Expand Up @@ -291,20 +291,26 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
writer.write_all(&key_data.0[..])?;

writer.write_all(&(self.pending_claim_requests.len() as u64).to_be_bytes())?;
for (ref ancestor_claim_txid, request) in self.pending_claim_requests.iter() {
let mut sorted_pending_claim_requests: Vec<(&PackageID, &PackageTemplate)> = self.pending_claim_requests.iter().collect();
sorted_pending_claim_requests.sort_by(|&a, &b| b.0.cmp(a.0));
for (ref ancestor_claim_txid, request) in sorted_pending_claim_requests {
ancestor_claim_txid.write(writer)?;
request.write(writer)?;
}

writer.write_all(&(self.claimable_outpoints.len() as u64).to_be_bytes())?;
for (ref outp, ref claim_and_height) in self.claimable_outpoints.iter() {
let mut sorted_claimable_outpoints: Vec<(&BitcoinOutPoint, &(PackageID, u32))> = self.claimable_outpoints.iter().collect();
sorted_claimable_outpoints.sort_by(|&a, &b| b.0.cmp(a.0));
for (ref outp, ref claim_and_height) in sorted_claimable_outpoints {
outp.write(writer)?;
claim_and_height.0.write(writer)?;
claim_and_height.1.write(writer)?;
}

writer.write_all(&(self.locktimed_packages.len() as u64).to_be_bytes())?;
for (ref locktime, ref packages) in self.locktimed_packages.iter() {
let mut sorted_locktimed_packages: Vec<(&u32, &Vec<PackageTemplate>)> = self.locktimed_packages.iter().collect();
sorted_locktimed_packages.sort_by(|&a, &b| b.0.cmp(a.0));
for (ref locktime, ref packages) in sorted_locktimed_packages {
locktime.write(writer)?;
writer.write_all(&(packages.len() as u64).to_be_bytes())?;
for ref package in packages.iter() {
Expand Down
4 changes: 2 additions & 2 deletions lightning/src/ln/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,11 @@ pub use self::peer_channel_encryptor::LN_MAX_MSG_LEN;

/// payment_hash type, use to cross-lock hop
/// (C-not exported) as we just use [u8; 32] directly
#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
#[derive(Hash, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Debug)]
pub struct PaymentHash(pub [u8; 32]);
/// payment_preimage type, use to route payment between hop
/// (C-not exported) as we just use [u8; 32] directly
#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
#[derive(Hash, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Debug)]
pub struct PaymentPreimage(pub [u8; 32]);
/// payment_secret type, use to authenticate sender to the receiver and tie MPP HTLCs together
/// (C-not exported) as we just use [u8; 32] directly
Expand Down