Skip to content

Commit

Permalink
f Validate merkle inclusion proofs
Browse files Browse the repository at this point in the history
  • Loading branch information
tnull committed Oct 27, 2023
1 parent 5d6e258 commit f527cec
Showing 1 changed file with 33 additions and 2 deletions.
35 changes: 33 additions & 2 deletions lightning-transaction-sync/src/electrum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ use crate::error::{TxSyncError, InternalError};

use electrum_client::Client as ElectrumClient;
use electrum_client::ElectrumApi;
use electrum_client::GetMerkleRes;

use lightning::util::logger::Logger;
use lightning::{log_error, log_debug, log_trace};
use lightning::chain::WatchedOutput;
use lightning::chain::{Confirm, Filter};

use bitcoin::{BlockHash, BlockHeader, Script, Txid};
use bitcoin::hashes::Hash;
use bitcoin::hashes::sha256d::Hash as Sha256d;

use std::ops::Deref;
use std::sync::Mutex;
Expand Down Expand Up @@ -263,7 +266,10 @@ where
debug_assert_eq!(prob_conf_height, merkle_res.block_height as u32);
match self.client.block_header(prob_conf_height as usize) {
Ok(block_header) => {
// TODO can we check the merkle proof here to be sure?
if !validate_merkle_proof(**txid, block_header.merkle_root.as_hash(), &merkle_res) {
log_error!(self.logger, "Retrieved Merkle block for txid {} doesn't match expectations. This should not happen. Please verify server integrity.", txid);
return Err(InternalError::Failed);
}
confirmed_txs.push(ConfirmedTx { tx: tx.clone(), block_header, block_height: prob_conf_height, pos: merkle_res.pos });
}
Err(e) => {
Expand Down Expand Up @@ -301,7 +307,10 @@ where
debug_assert_eq!(prob_conf_height, merkle_res.block_height as u32);
match self.client.block_header(prob_conf_height as usize) {
Ok(block_header) => {
// TODO can we check the merkle proof here to be sure?
if !validate_merkle_proof(txid, block_header.merkle_root.as_hash(), &merkle_res) {
log_error!(self.logger, "Retrieved Merkle block for txid {} doesn't match expectations. This should not happen. Please verify server integrity.", txid);
return Err(InternalError::Failed);
}
confirmed_txs.push(ConfirmedTx { tx: tx.clone(), block_header, block_height: prob_conf_height, pos: merkle_res.pos });
}
Err(e) => {
Expand Down Expand Up @@ -386,6 +395,28 @@ where

}

fn validate_merkle_proof(txid: Txid, merkle_root: Sha256d, merkle_res: &GetMerkleRes) -> bool {
let mut index = merkle_res.pos;
let mut cur = txid.as_hash();
for bytes in &merkle_res.merkle {
let mut reversed = Vec::with_capacity(32);
reversed.truncate(0);
reversed.extend(bytes.iter().rev());
let next_hash = Sha256d::from_slice(&reversed).unwrap();

let (left, right) = if index % 2 == 0 {
(cur, next_hash)
} else {
(next_hash, cur)
};

let data = [&left[..], &right[..]].concat();
cur = Sha256d::hash(&data);
index /= 2;
}
cur == merkle_root
}

impl<L: Deref> Filter for ElectrumSyncClient<L>
where
L::Target: Logger,
Expand Down

0 comments on commit f527cec

Please sign in to comment.