ckb_sdk/transaction/handler/
multisig.rs1use 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}