electrum_client/
utils.rs

1//! Utilities helping to handle Electrum-related data.
2
3use crate::types::GetMerkleRes;
4use bitcoin::hash_types::TxMerkleNode;
5use bitcoin::hashes::sha256d::Hash as Sha256d;
6use bitcoin::hashes::{Hash, HashEngine};
7use bitcoin::Txid;
8
9/// Verifies a Merkle inclusion proof as retrieved via [`transaction_get_merkle`] for a transaction with the
10/// given `txid` and `merkle_root` as included in the [`BlockHeader`].
11///
12/// Returns `true` if the transaction is included in the corresponding block, and `false`
13/// otherwise.
14///
15/// [`transaction_get_merkle`]: crate::ElectrumApi::transaction_get_merkle
16/// [`BlockHeader`]: bitcoin::BlockHeader
17pub fn validate_merkle_proof(
18    txid: &Txid,
19    merkle_root: &TxMerkleNode,
20    merkle_res: &GetMerkleRes,
21) -> bool {
22    let mut index = merkle_res.pos;
23    let mut cur = txid.to_raw_hash();
24    for mut bytes in merkle_res.merkle.iter().cloned() {
25        bytes.reverse();
26        let next_hash = Sha256d::from_byte_array(bytes);
27
28        cur = Sha256d::from_engine({
29            let mut engine = Sha256d::engine();
30            if index % 2 == 0 {
31                engine.input(cur.as_ref());
32                engine.input(next_hash.as_ref());
33            } else {
34                engine.input(next_hash.as_ref());
35                engine.input(cur.as_ref());
36            };
37            engine
38        });
39        index /= 2;
40    }
41
42    cur == merkle_root.to_raw_hash()
43}