@@ -21,7 +21,6 @@ use namada_core::ibc::apps::transfer::types::msgs::transfer::MsgTransfer as IbcM
2121use namada_core:: ibc:: apps:: transfer:: types:: packet:: PacketData ;
2222use namada_core:: masp:: { addr_taddr, encode_asset_type, ibc_taddr, MaspEpoch } ;
2323use namada_core:: storage:: Key ;
24- use namada_gas:: GasMetering ;
2524use namada_governance:: storage:: is_proposal_accepted;
2625use namada_ibc:: core:: channel:: types:: commitment:: {
2726 compute_packet_commitment, PacketCommitment ,
@@ -43,6 +42,7 @@ use namada_sdk::masp::TAddrData;
4342use namada_state:: { ConversionState , OptionExt , ResultExt , StateRead } ;
4443use namada_token:: read_denom;
4544use namada_token:: validation:: verify_shielded_tx;
45+ use namada_tx:: action:: Read ;
4646use namada_tx:: BatchedTxRef ;
4747use namada_vp_env:: VpEnv ;
4848use thiserror:: Error ;
@@ -703,7 +703,7 @@ where
703703 )
704704 . map_err ( native_vp:: Error :: new) ?,
705705 ) ;
706- // And then record thee final state
706+ // And then record the final state
707707 let post_entry = result. post . get ( & addr_hash) . cloned ( ) . unwrap_or ( zero) ;
708708 result. post . insert (
709709 addr_hash,
@@ -750,6 +750,7 @@ where
750750 & self ,
751751 tx_data : & BatchedTxRef < ' _ > ,
752752 keys_changed : & BTreeSet < Key > ,
753+ verifiers : & BTreeSet < Address > ,
753754 ) -> Result < ( ) > {
754755 let masp_epoch_multiplier =
755756 namada_parameters:: read_masp_epoch_multiplier_parameter (
@@ -764,6 +765,7 @@ where
764765 } ) ?;
765766 let conversion_state = self . ctx . state . in_mem ( ) . get_conversion_state ( ) ;
766767 let ibc_msg = self . ctx . get_ibc_message ( tx_data) . ok ( ) ;
768+ let actions = self . ctx . read_actions ( ) ?;
767769 let shielded_tx =
768770 if let Some ( IbcMessage :: Envelope ( ref envelope) ) = ibc_msg {
769771 extract_masp_tx_from_envelope ( envelope) . ok_or_else ( || {
@@ -774,7 +776,7 @@ where
774776 } else {
775777 // Get the Transaction object from the actions
776778 let masp_section_ref =
777- namada_tx:: action:: get_masp_section_ref ( & self . ctx ) ?
779+ namada_tx:: action:: get_masp_section_ref ( & actions )
778780 . ok_or_else ( || {
779781 native_vp:: Error :: new_const (
780782 "Missing MASP section reference in action" ,
@@ -824,7 +826,7 @@ where
824826 ) ?;
825827
826828 // The set of addresses that are required to authorize this transaction
827- let mut signers = BTreeSet :: new ( ) ;
829+ let mut authorizers = BTreeSet :: new ( ) ;
828830
829831 // Checks on the sapling bundle
830832 // 1. The spend descriptions' anchors are valid
@@ -846,7 +848,7 @@ where
846848 & mut changed_bals_minus_txn,
847849 masp_epoch,
848850 conversion_state,
849- & mut signers ,
851+ & mut authorizers ,
850852 ) ?;
851853
852854 // Ensure that every account for which balance has gone down as a result
@@ -869,14 +871,27 @@ where
869871 ( minus_txn_pre, minus_txn_post) != ( pre. clone ( ) , post)
870872 {
871873 // This address will need to provide further authorization
872- signers . insert ( addr) ;
874+ authorizers . insert ( addr) ;
873875 }
874876 }
875877
878+ let mut actions_authorizers: HashSet < & Address > = actions
879+ . iter ( )
880+ . filter_map ( |action| {
881+ if let namada_tx:: action:: Action :: Masp (
882+ namada_tx:: action:: MaspAction :: MaspAuthorizer ( addr) ,
883+ ) = action
884+ {
885+ Some ( addr)
886+ } else {
887+ None
888+ }
889+ } )
890+ . collect ( ) ;
876891 // Ensure that this transaction is authorized by all involved parties
877- for signer in signers {
892+ for authorizer in authorizers {
878893 if let Some ( TAddrData :: Addr ( IBC ) ) =
879- changed_bals_minus_txn. decoder . get ( & signer )
894+ changed_bals_minus_txn. decoder . get ( & authorizer )
880895 {
881896 // If the IBC address is a signatory, then it means that either
882897 // Tx - Transaction(s) causes a decrease in the IBC balance or
@@ -906,39 +921,53 @@ where
906921 }
907922 }
908923 } else if let Some ( TAddrData :: Addr ( signer) ) =
909- changed_bals_minus_txn. decoder . get ( & signer )
924+ changed_bals_minus_txn. decoder . get ( & authorizer )
910925 {
911- // Otherwise the signer must be decodable so that we can
912- // manually check the signatures
913- let public_keys_index_map =
914- crate :: account:: public_keys_index_map (
915- & self . ctx . pre ( ) ,
916- signer,
917- ) ?;
918- let threshold =
919- crate :: account:: threshold ( & self . ctx . pre ( ) , signer) ?
920- . unwrap_or ( 1 ) ;
921- let mut gas_meter = self . ctx . gas_meter . borrow_mut ( ) ;
922- tx_data
923- . tx
924- . verify_signatures (
925- & [ tx_data. tx . raw_header_hash ( ) ] ,
926- public_keys_index_map,
927- & Some ( signer. clone ( ) ) ,
928- threshold,
929- || gas_meter. consume ( crate :: gas:: VERIFY_TX_SIG_GAS ) ,
930- )
931- . map_err ( native_vp:: Error :: new) ?;
926+ // Otherwise the owner's vp must have been triggered and the
927+ // relative action must have been written
928+ if !verifiers. contains ( signer) {
929+ let error = native_vp:: Error :: new_alloc ( format ! (
930+ "The required vp of address {signer} was not triggered"
931+ ) )
932+ . into ( ) ;
933+ tracing:: debug!( "{error}" ) ;
934+ return Err ( error) ;
935+ }
936+
937+ // The action is required becuse the target vp might have been
938+ // triggered for other reasons but we need to signal it that it
939+ // is required to validate a discrepancy in its balance change
940+ // because of a masp transaction, which might require a
941+ // different validation than a normal balance change
942+ if !actions_authorizers. swap_remove ( signer) {
943+ let error = native_vp:: Error :: new_alloc ( format ! (
944+ "The required masp authorizer action for address \
945+ {signer} is missing"
946+ ) )
947+ . into ( ) ;
948+ tracing:: debug!( "{error}" ) ;
949+ return Err ( error) ;
950+ }
932951 } else {
933- // We are not able to decode the signer , so just fail
952+ // We are not able to decode the authorizer , so just fail
934953 let error = native_vp:: Error :: new_const (
935- "Unable to decode a transaction signer " ,
954+ "Unable to decode a transaction authorizer " ,
936955 )
937956 . into ( ) ;
938957 tracing:: debug!( "{error}" ) ;
939958 return Err ( error) ;
940959 }
941960 }
961+ // The transaction shall not push masp authorizer actions that are not
962+ // needed cause this might lead vps to run a wrong validation logic
963+ if !actions_authorizers. is_empty ( ) {
964+ let error = native_vp:: Error :: new_const (
965+ "Found masp authorizer actions that are not required" ,
966+ )
967+ . into ( ) ;
968+ tracing:: debug!( "{error}" ) ;
969+ return Err ( error) ;
970+ }
942971
943972 // Verify the proofs
944973 verify_shielded_tx ( & shielded_tx, |gas| self . ctx . charge_gas ( gas) )
@@ -963,18 +992,17 @@ fn unepoched_tokens(
963992 Ok ( ( ) )
964993}
965994
966- // Handle transparent input
967995fn validate_transparent_input < A : Authorization > (
968996 vin : & TxIn < A > ,
969997 changed_balances : & mut ChangedBalances ,
970998 transparent_tx_pool : & mut I128Sum ,
971999 epoch : MaspEpoch ,
9721000 conversion_state : & ConversionState ,
973- signers : & mut BTreeSet < TransparentAddress > ,
1001+ authorizers : & mut BTreeSet < TransparentAddress > ,
9741002) -> Result < ( ) > {
9751003 // A decrease in the balance of an account needs to be
9761004 // authorized by the account of this transparent input
977- signers . insert ( vin. address ) ;
1005+ authorizers . insert ( vin. address ) ;
9781006 // Non-masp sources add to the transparent tx pool
9791007 * transparent_tx_pool = transparent_tx_pool
9801008 . checked_add (
@@ -1050,7 +1078,6 @@ fn validate_transparent_input<A: Authorization>(
10501078 Ok ( ( ) )
10511079}
10521080
1053- // Handle transparent output
10541081fn validate_transparent_output (
10551082 out : & TxOut ,
10561083 changed_balances : & mut ChangedBalances ,
@@ -1122,7 +1149,7 @@ fn validate_transparent_bundle(
11221149 changed_balances : & mut ChangedBalances ,
11231150 epoch : MaspEpoch ,
11241151 conversion_state : & ConversionState ,
1125- signers : & mut BTreeSet < TransparentAddress > ,
1152+ authorizers : & mut BTreeSet < TransparentAddress > ,
11261153) -> Result < ( ) > {
11271154 // The Sapling value balance adds to the transparent tx pool
11281155 let mut transparent_tx_pool = shielded_tx. sapling_value_balance ( ) ;
@@ -1135,7 +1162,7 @@ fn validate_transparent_bundle(
11351162 & mut transparent_tx_pool,
11361163 epoch,
11371164 conversion_state,
1138- signers ,
1165+ authorizers ,
11391166 ) ?;
11401167 }
11411168
@@ -1259,7 +1286,7 @@ where
12591286 & self ,
12601287 tx_data : & BatchedTxRef < ' _ > ,
12611288 keys_changed : & BTreeSet < Key > ,
1262- _verifiers : & BTreeSet < Address > ,
1289+ verifiers : & BTreeSet < Address > ,
12631290 ) -> Result < ( ) > {
12641291 let masp_keys_changed: Vec < & Key > =
12651292 keys_changed. iter ( ) . filter ( |key| is_masp_key ( key) ) . collect ( ) ;
@@ -1289,7 +1316,7 @@ where
12891316 self . is_valid_parameter_change ( tx_data)
12901317 } else if masp_transfer_changes {
12911318 // The MASP transfer keys can only be changed by a valid Transaction
1292- self . is_valid_masp_transfer ( tx_data, keys_changed)
1319+ self . is_valid_masp_transfer ( tx_data, keys_changed, verifiers )
12931320 } else {
12941321 // Changing no MASP keys at all is also fine
12951322 Ok ( ( ) )
0 commit comments