Skip to main content

electrum_client/
utils.rs

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