ckb_sdk/transaction/handler/
sighash.rs

1use ckb_types::{
2    core::DepType,
3    h256,
4    packed::{CellDep, OutPoint, Script, WitnessArgs},
5    prelude::{Builder, Entity, Pack},
6};
7
8use crate::{
9    constants, core::TransactionBuilder, tx_builder::TxBuilderError, unlock::UnlockError,
10    NetworkInfo, NetworkType, ScriptGroup,
11};
12
13use super::{HandlerContext, ScriptHandler};
14
15pub struct Secp256k1Blake160SighashAllScriptHandler {
16    cell_deps: Vec<CellDep>,
17}
18
19pub struct Secp256k1Blake160SighashAllScriptContext;
20
21impl HandlerContext for Secp256k1Blake160SighashAllScriptContext {}
22
23impl Secp256k1Blake160SighashAllScriptHandler {
24    pub fn is_match(&self, script: &Script) -> bool {
25        script.code_hash() == constants::SIGHASH_TYPE_HASH.pack()
26    }
27    #[cfg(not(target_arch = "wasm32"))]
28    pub fn new_with_network(network: &NetworkInfo) -> Result<Self, TxBuilderError> {
29        let mut ret = Self { cell_deps: vec![] };
30        ret.init(network)?;
31        Ok(ret)
32    }
33    pub async fn new_with_network_async(network: &NetworkInfo) -> Result<Self, TxBuilderError> {
34        let mut ret = Self { cell_deps: vec![] };
35        ret.init_async(network).await?;
36        Ok(ret)
37    }
38
39    pub fn new_with_customize(cell_deps: Vec<CellDep>) -> Self {
40        Self { cell_deps }
41    }
42}
43#[cfg_attr(target_arch="wasm32", async_trait::async_trait(?Send))]
44#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
45impl ScriptHandler for Secp256k1Blake160SighashAllScriptHandler {
46    fn build_transaction(
47        &self,
48        tx_builder: &mut TransactionBuilder,
49        script_group: &mut ScriptGroup,
50        context: &dyn HandlerContext,
51    ) -> Result<bool, TxBuilderError> {
52        if !self.is_match(&script_group.script) {
53            return Ok(false);
54        }
55        if let Some(_args) = context
56            .as_any()
57            .downcast_ref::<Secp256k1Blake160SighashAllScriptContext>()
58        {
59            tx_builder.dedup_cell_deps(self.cell_deps.clone());
60            let index = *script_group.input_indices.first().unwrap();
61            let witness = if let Some(witness) = tx_builder.get_witnesses().get(index) {
62                let witness_data = witness.raw_data();
63                if witness_data.is_empty() {
64                    WitnessArgs::new_builder()
65                } else {
66                    WitnessArgs::from_slice(witness_data.as_ref())
67                        .map_err(|_| UnlockError::InvalidWitnessArgs(index))?
68                        .as_builder()
69                }
70            } else {
71                WitnessArgs::new_builder()
72            }
73            .lock(Some(bytes::Bytes::from(vec![0u8; 65])).pack())
74            .build();
75            tx_builder.set_witness(index, witness.as_bytes().pack());
76            Ok(true)
77        } else {
78            Ok(false)
79        }
80    }
81
82    #[cfg(not(target_arch = "wasm32"))]
83    fn init(&mut self, network: &NetworkInfo) -> Result<(), TxBuilderError> {
84        let out_point = if network.network_type == NetworkType::Mainnet {
85            OutPoint::new_builder()
86                .tx_hash(
87                    h256!("0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c")
88                        .pack(),
89                )
90                .index(0u32)
91                .build()
92        } else if network.network_type == NetworkType::Testnet {
93            OutPoint::new_builder()
94                .tx_hash(
95                    h256!("0xf8de3bb47d055cdf460d93a2a6e1b05f7432f9777c8c474abf4eec1d4aee5d37")
96                        .pack(),
97                )
98                .index(0u32)
99                .build()
100        } else if network.network_type == NetworkType::Preview {
101            OutPoint::new_builder()
102                .tx_hash(
103                    h256!("0x0fab65924f2784f17ad7f86d6aef4b04ca1ca237102a68961594acebc5c77816")
104                        .pack(),
105                )
106                .index(0u32)
107                .build()
108        } else {
109            return Err(TxBuilderError::UnsupportedNetworkType(network.network_type));
110        };
111
112        let cell_dep = CellDep::new_builder()
113            .out_point(out_point)
114            .dep_type(DepType::DepGroup)
115            .build();
116        self.cell_deps.push(cell_dep);
117        Ok(())
118    }
119    async fn init_async(&mut self, network: &NetworkInfo) -> Result<(), TxBuilderError> {
120        let out_point = if network.network_type == NetworkType::Mainnet {
121            OutPoint::new_builder()
122                .tx_hash(
123                    h256!("0x71a7ba8fc96349fea0ed3a5c47992e3b4084b031a42264a018e0072e8172e46c")
124                        .pack(),
125                )
126                .index(0u32)
127                .build()
128        } else if network.network_type == NetworkType::Testnet {
129            OutPoint::new_builder()
130                .tx_hash(
131                    h256!("0xf8de3bb47d055cdf460d93a2a6e1b05f7432f9777c8c474abf4eec1d4aee5d37")
132                        .pack(),
133                )
134                .index(0u32)
135                .build()
136        } else if network.network_type == NetworkType::Preview {
137            OutPoint::new_builder()
138                .tx_hash(
139                    h256!("0x0fab65924f2784f17ad7f86d6aef4b04ca1ca237102a68961594acebc5c77816")
140                        .pack(),
141                )
142                .index(0u32)
143                .build()
144        } else {
145            return Err(TxBuilderError::UnsupportedNetworkType(network.network_type));
146        };
147
148        let cell_dep = CellDep::new_builder()
149            .out_point(out_point)
150            .dep_type(DepType::DepGroup)
151            .build();
152        self.cell_deps.push(cell_dep);
153        Ok(())
154    }
155}