Skip to content

Commit 5513ca0

Browse files
committed
Fix: detect multisig type from input cells in deploy
1 parent 1221235 commit 5513ca0

File tree

1 file changed

+50
-35
lines changed

1 file changed

+50
-35
lines changed

src/subcommands/deploy/tx_builder.rs

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,25 @@ pub fn build_tx<T: ChangeInfo>(
8080
.filter_map(|info| info.build_cell_output(lock_script, first_cell_input))
8181
.unzip();
8282

83+
// Create tx_dep_provider first, so we can use it to inspect input cells
84+
let header_dep_resolver = DefaultHeaderDepResolver::new(ckb_rpc);
85+
let tx_dep_provider = {
86+
let inner = DefaultTransactionDependencyProvider::new(ckb_rpc, 0);
87+
let mut offchain = OffchainTransactionDependencyProvider::default();
88+
if let Some(pending_tx) = pending_tx {
89+
let tx_view = pending_tx.into_view();
90+
let tx_hash: H256 = tx_view.hash().unpack();
91+
offchain.txs.insert(tx_hash.clone(), tx_view.clone());
92+
for (output_idx, (output, output_data)) in tx_view.outputs_with_data_iter().enumerate()
93+
{
94+
offchain
95+
.cells
96+
.insert((tx_hash.clone(), output_idx as u32), (output, output_data));
97+
}
98+
}
99+
TxDepProviderWrapper { inner, offchain }
100+
};
101+
83102
let mut unlockers = HashMap::new();
84103
let signer = DummySigner {
85104
args: vec![from_address.payload().args()],
@@ -92,49 +111,45 @@ pub fn build_tx<T: ChangeInfo>(
92111
);
93112

94113
let mut cell_deps = vec![genesis_info.sighash_dep()];
114+
115+
// Detect multisig script types from input cells and add cell_deps/unlockers
116+
// In upgrade scenarios, we need to check the actual input cell locks, not the deployment config
95117
if let Some(cfg) = multisig_config {
96-
let multisig_script =
97-
MultisigScript::try_from(cfg.lock_code_hash()).unwrap_or_else(|_err| {
98-
panic!(
99-
"Failed to get multisig script from {}",
100-
cfg.lock_code_hash(),
101-
)
102-
});
103-
104-
cell_deps.push(genesis_info.multisig_dep(multisig_script));
105-
106-
let multisig_signer = SecpMultisigScriptSigner::new(Box::new(signer), cfg.clone());
107-
let multisig_unlocker = SecpMultisigUnlocker::new(multisig_signer);
108-
let multisig_script_id = multisig_script.script_id();
109-
unlockers.insert(
110-
multisig_script_id,
111-
Box::new(multisig_unlocker) as Box<dyn ScriptUnlocker>,
112-
);
118+
for input in inputs.iter() {
119+
let out_point = input.previous_output();
120+
let cell_output = tx_dep_provider.get_cell(&out_point)?;
121+
let lock_script_id = ScriptId::from(&cell_output.lock());
122+
123+
// Check if this is a multisig lock and we haven't added it yet
124+
let multisig_script = if lock_script_id == MultisigScript::Legacy.script_id() {
125+
Some(MultisigScript::Legacy)
126+
} else if lock_script_id == MultisigScript::V2.script_id() {
127+
Some(MultisigScript::V2)
128+
} else {
129+
None
130+
};
131+
132+
// Add cell_dep and unlocker if this is a new multisig type
133+
if let Some(multisig_script) = multisig_script {
134+
if !unlockers.contains_key(&lock_script_id) {
135+
cell_deps.push(genesis_info.multisig_dep(multisig_script));
136+
137+
let multisig_signer = SecpMultisigScriptSigner::new(Box::new(signer.clone()), cfg.clone());
138+
let multisig_unlocker = SecpMultisigUnlocker::new(multisig_signer);
139+
unlockers.insert(
140+
lock_script_id,
141+
Box::new(multisig_unlocker) as Box<dyn ScriptUnlocker>,
142+
);
143+
}
144+
}
145+
}
113146
}
114147

115148
let placeholder_witness = packed::WitnessArgs::new_builder()
116149
.lock(Some(Bytes::from(vec![0u8; 65])).pack())
117150
.build();
118151
let balancer = CapacityBalancer::new_simple(from_script, placeholder_witness, fee_rate);
119152

120-
let header_dep_resolver = DefaultHeaderDepResolver::new(ckb_rpc);
121-
let tx_dep_provider = {
122-
let inner = DefaultTransactionDependencyProvider::new(ckb_rpc, 0);
123-
let mut offchain = OffchainTransactionDependencyProvider::default();
124-
if let Some(pending_tx) = pending_tx {
125-
let tx_view = pending_tx.into_view();
126-
let tx_hash: H256 = tx_view.hash().unpack();
127-
offchain.txs.insert(tx_hash.clone(), tx_view.clone());
128-
for (output_idx, (output, output_data)) in tx_view.outputs_with_data_iter().enumerate()
129-
{
130-
offchain
131-
.cells
132-
.insert((tx_hash.clone(), output_idx as u32), (output, output_data));
133-
}
134-
}
135-
TxDepProviderWrapper { inner, offchain }
136-
};
137-
138153
let base_tx = TransactionBuilder::default()
139154
.cell_deps(cell_deps)
140155
.inputs(inputs)

0 commit comments

Comments
 (0)