subcoin_service/
transaction_adapter.rs

1use bitcoin::Transaction;
2use sp_core::{Decode, Encode};
3use sp_runtime::traits::Block as BlockT;
4use subcoin_primitives::BitcoinTransactionAdapter;
5
6/// Responsible for doing the conversion between Bitcoin transaction and Substrate extrinsic.
7///
8/// ## NOTE
9///
10/// To convert the bitcoin transactions to substrate extrinsics, the recommended
11/// practice in Substrate is to leverage a runtime api for forkless upgrade such that
12/// the client (node binary) does not have to be upgraded when the Pallet/Runtime call
13/// is changed within the runtime. However, we don't need this convenience as the
14/// pallet-bitcoin is designed to be super stable with one and only one call. Hence we
15/// choose to pull in the pallet-bitcoin dependency directly for saving the cost of
16/// calling a runtime api.
17///
18/// Using a trait also allows not to introduce the subcoin_runtime and pallet_bitcoin
19/// deps when the adapter is needed in other crates, making the compilation faster.
20pub struct TransactionAdapter;
21
22impl<Block: BlockT> BitcoinTransactionAdapter<Block> for TransactionAdapter {
23    fn extrinsic_to_bitcoin_transaction(extrinsic: &Block::Extrinsic) -> Transaction {
24        let unchecked_extrinsic: subcoin_runtime::UncheckedExtrinsic =
25            Decode::decode(&mut extrinsic.encode().as_slice()).unwrap();
26
27        match unchecked_extrinsic.function {
28            subcoin_runtime::RuntimeCall::Bitcoin(pallet_bitcoin::Call::<
29                subcoin_runtime::Runtime,
30            >::transact {
31                btc_tx,
32            }) => btc_tx.into(),
33            _ => unreachable!("Transactions only exist in pallet-bitcoin; qed"),
34        }
35    }
36
37    fn bitcoin_transaction_into_extrinsic(btc_tx: bitcoin::Transaction) -> Block::Extrinsic {
38        Decode::decode(
39            &mut subcoin_runtime::UncheckedExtrinsic::new_bare(
40                pallet_bitcoin::Call::<subcoin_runtime::Runtime>::transact {
41                    btc_tx: btc_tx.into(),
42                }
43                .into(),
44            )
45            .encode()
46            .as_slice(),
47        )
48        .expect("Extrinsic constructed internally must not fail; qed")
49    }
50}