ckb_sdk/transaction/handler/
multisig.rs

1use ckb_types::{
2    core::DepType,
3    packed::{CellDep, OutPoint, Script},
4    prelude::{Builder, Entity, Pack},
5};
6
7use crate::{
8    constants::MultisigScript, core::TransactionBuilder, tx_builder::TxBuilderError,
9    unlock::MultisigConfig, NetworkInfo, ScriptGroup,
10};
11
12use super::{HandlerContext, ScriptHandler};
13use anyhow::anyhow;
14
15pub struct Secp256k1Blake160MultisigAllScriptContext {
16    multisig_config: MultisigConfig,
17}
18impl HandlerContext for Secp256k1Blake160MultisigAllScriptContext {}
19impl Secp256k1Blake160MultisigAllScriptContext {
20    pub fn new(config: MultisigConfig) -> Self {
21        Self {
22            multisig_config: config,
23        }
24    }
25}
26
27pub struct Secp256k1Blake160MultisigAllScriptHandler {
28    multisig_script: MultisigScript,
29    cell_deps: Vec<CellDep>,
30}
31
32impl Secp256k1Blake160MultisigAllScriptHandler {
33    pub fn is_match(&self, script: &Script) -> bool {
34        let multisig_script_id = self.multisig_script.script_id();
35        script.code_hash() == multisig_script_id.code_hash.pack()
36            && script.hash_type() == multisig_script_id.hash_type.into()
37    }
38
39    #[cfg(not(target_arch = "wasm32"))]
40    pub fn new(
41        network: &NetworkInfo,
42        multisig_script: MultisigScript,
43    ) -> Result<Self, TxBuilderError> {
44        let mut ret = Self {
45            multisig_script,
46            cell_deps: vec![],
47        };
48        ret.init(network)?;
49        Ok(ret)
50    }
51
52    pub async fn new_async(
53        network: &NetworkInfo,
54        multisig_script: MultisigScript,
55    ) -> Result<Self, TxBuilderError> {
56        let mut ret = Self {
57            multisig_script,
58            cell_deps: vec![],
59        };
60        ret.init_async(network).await?;
61        Ok(ret)
62    }
63
64    pub fn new_with_customize(multisig_script: MultisigScript, cell_deps: Vec<CellDep>) -> Self {
65        Self {
66            multisig_script,
67            cell_deps,
68        }
69    }
70}
71#[cfg_attr(target_arch="wasm32", async_trait::async_trait(?Send))]
72#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
73impl ScriptHandler for Secp256k1Blake160MultisigAllScriptHandler {
74    fn build_transaction(
75        &self,
76        tx_builder: &mut TransactionBuilder,
77        script_group: &mut ScriptGroup,
78        context: &dyn HandlerContext,
79    ) -> Result<bool, TxBuilderError> {
80        if !self.is_match(&script_group.script) {
81            return Ok(false);
82        }
83        if let Some(args) = context
84            .as_any()
85            .downcast_ref::<Secp256k1Blake160MultisigAllScriptContext>()
86        {
87            tx_builder.dedup_cell_deps(self.cell_deps.clone());
88            let index = script_group.input_indices.first().unwrap();
89            let witness = args.multisig_config.placeholder_witness();
90            tx_builder.set_witness(*index, witness.as_bytes().pack());
91            Ok(true)
92        } else {
93            Ok(false)
94        }
95    }
96
97    #[cfg(not(target_arch = "wasm32"))]
98    #[allow(clippy::if_same_then_else)]
99    fn init(&mut self, network: &NetworkInfo) -> Result<(), TxBuilderError> {
100        let dep_group = self
101            .multisig_script
102            .dep_group(network.to_owned(), None)
103            .ok_or(TxBuilderError::Other(anyhow!(
104                "not found multisig dep on network: {:?}",
105                network
106            )))?;
107        let out_point = OutPoint::new_builder()
108            .tx_hash(dep_group.0.pack())
109            .index(dep_group.1)
110            .build();
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 dep_group = self
121            .multisig_script
122            .dep_group_async(network.to_owned(), None)
123            .await
124            .ok_or(TxBuilderError::Other(anyhow!(
125                "not found multisig dep on network: {:?}",
126                network
127            )))?;
128        let out_point = OutPoint::new_builder()
129            .tx_hash(dep_group.0.pack())
130            .index(dep_group.1)
131            .build();
132
133        let cell_dep = CellDep::new_builder()
134            .out_point(out_point)
135            .dep_type(DepType::DepGroup)
136            .build();
137        self.cell_deps.push(cell_dep);
138        Ok(())
139    }
140}