@@ -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