Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 48 additions & 35 deletions src/subcommands/deploy/tx_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,25 @@ pub fn build_tx<T: ChangeInfo>(
.filter_map(|info| info.build_cell_output(lock_script, first_cell_input))
.unzip();

// Create tx_dep_provider first, so we can use it to inspect input cells
let header_dep_resolver = DefaultHeaderDepResolver::new(ckb_rpc);
let tx_dep_provider = {
let inner = DefaultTransactionDependencyProvider::new(ckb_rpc, 0);
let mut offchain = OffchainTransactionDependencyProvider::default();
if let Some(pending_tx) = pending_tx {
let tx_view = pending_tx.into_view();
let tx_hash: H256 = tx_view.hash().unpack();
offchain.txs.insert(tx_hash.clone(), tx_view.clone());
for (output_idx, (output, output_data)) in tx_view.outputs_with_data_iter().enumerate()
{
offchain
.cells
.insert((tx_hash.clone(), output_idx as u32), (output, output_data));
}
}
TxDepProviderWrapper { inner, offchain }
};

let mut unlockers = HashMap::new();
let signer = DummySigner {
args: vec![from_address.payload().args()],
Expand All @@ -92,49 +111,43 @@ pub fn build_tx<T: ChangeInfo>(
);

let mut cell_deps = vec![genesis_info.sighash_dep()];

// Detect multisig script types from input cells and add cell_deps/unlockers
// In upgrade scenarios, we need to check the actual input cell locks, not the deployment config
if let Some(cfg) = multisig_config {
let multisig_script =
MultisigScript::try_from(cfg.lock_code_hash()).unwrap_or_else(|_err| {
panic!(
"Failed to get multisig script from {}",
cfg.lock_code_hash(),
)
});

cell_deps.push(genesis_info.multisig_dep(multisig_script));

let multisig_signer = SecpMultisigScriptSigner::new(Box::new(signer), cfg.clone());
let multisig_unlocker = SecpMultisigUnlocker::new(multisig_signer);
let multisig_script_id = multisig_script.script_id();
unlockers.insert(
multisig_script_id,
Box::new(multisig_unlocker) as Box<dyn ScriptUnlocker>,
);
for input in inputs.iter() {
let out_point = input.previous_output();
let cell_output = tx_dep_provider.get_cell(&out_point)?;
let lock_script_id = ScriptId::from(&cell_output.lock());

// Check if this is a multisig lock and we haven't added it yet
let multisig_script = if lock_script_id == MultisigScript::Legacy.script_id() {
Some(MultisigScript::Legacy)
} else if lock_script_id == MultisigScript::V2.script_id() {
Some(MultisigScript::V2)
} else {
None
};

// Add cell_dep and unlocker if this is a new multisig type
if let Some(multisig_script) = multisig_script {
unlockers.entry(lock_script_id).or_insert_with(|| {
cell_deps.push(genesis_info.multisig_dep(multisig_script));

let multisig_signer =
SecpMultisigScriptSigner::new(Box::new(signer.clone()), cfg.clone());
let multisig_unlocker = SecpMultisigUnlocker::new(multisig_signer);
Box::new(multisig_unlocker) as Box<dyn ScriptUnlocker>
});
}
}
}

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

let header_dep_resolver = DefaultHeaderDepResolver::new(ckb_rpc);
let tx_dep_provider = {
let inner = DefaultTransactionDependencyProvider::new(ckb_rpc, 0);
let mut offchain = OffchainTransactionDependencyProvider::default();
if let Some(pending_tx) = pending_tx {
let tx_view = pending_tx.into_view();
let tx_hash: H256 = tx_view.hash().unpack();
offchain.txs.insert(tx_hash.clone(), tx_view.clone());
for (output_idx, (output, output_data)) in tx_view.outputs_with_data_iter().enumerate()
{
offchain
.cells
.insert((tx_hash.clone(), output_idx as u32), (output, output_data));
}
}
TxDepProviderWrapper { inner, offchain }
};

let base_tx = TransactionBuilder::default()
.cell_deps(cell_deps)
.inputs(inputs)
Expand Down
Loading