@@ -651,10 +651,10 @@ pub trait ShieldedApi<U: ShieldedUtils + MaybeSend + MaybeSync>:
651651 async fn is_amount_required (
652652 & mut self ,
653653 client : & ( impl Client + Sync ) ,
654- src : ValueSum < Address , Change > ,
655- dest : ValueSum < Address , Change > ,
654+ src : ValueSum < ( MaspDigitPos , Address ) , Change > ,
655+ dest : ValueSum < ( MaspDigitPos , Address ) , Change > ,
656656 delta : I128Sum ,
657- ) -> Option < ValueSum < Address , Change > > {
657+ ) -> Option < ValueSum < ( MaspDigitPos , Address ) , Change > > {
658658 // If the delta causes any regression, then do not use it
659659 #[ allow( clippy:: neg_cmp_op_on_partial_ord) ]
660660 if !( delta >= I128Sum :: zero ( ) ) {
@@ -664,17 +664,18 @@ pub trait ShieldedApi<U: ShieldedUtils + MaybeSend + MaybeSync>:
664664 let ( decoded_delta, _rem_delta) = self . decode_sum ( client, delta) . await ;
665665 for ( ( _, asset_data) , value) in decoded_delta. components ( ) {
666666 // Check that this component of the delta helps close the gap
667- if * value > 0 && gap. get ( & asset_data. token ) . is_positive ( ) {
667+ if * value > 0
668+ && gap
669+ . get ( & ( asset_data. position , asset_data. token . clone ( ) ) )
670+ . is_positive ( )
671+ {
668672 // Convert the delta into Namada amounts
669673 let mut converted_delta = ValueSum :: zero ( ) ;
670674 for ( ( _, asset_data) , value) in decoded_delta. components ( ) {
671- let amt = Change :: from_masp_denominated (
672- * value,
673- asset_data. position ,
674- )
675- . ok ( ) ?;
676- converted_delta +=
677- ValueSum :: from_pair ( asset_data. token . clone ( ) , amt) ;
675+ converted_delta += ValueSum :: from_pair (
676+ ( asset_data. position , asset_data. token . clone ( ) ) ,
677+ Change :: from ( * value) ,
678+ ) ;
678679 }
679680 return Some ( converted_delta) ;
680681 }
@@ -693,7 +694,7 @@ pub trait ShieldedApi<U: ShieldedUtils + MaybeSend + MaybeSync>:
693694 context : & impl NamadaIo ,
694695 spent_notes : & mut SpentNotesTracker ,
695696 sk : namada_core:: masp:: ExtendedSpendingKey ,
696- target : ValueSum < Address , Change > ,
697+ target : ValueSum < ( MaspDigitPos , Address ) , Change > ,
697698 target_epoch : MaspEpoch ,
698699 ) -> Result <
699700 (
@@ -1206,27 +1207,31 @@ pub trait ShieldedApi<U: ShieldedUtils + MaybeSend + MaybeSync>:
12061207 & mut self ,
12071208 client : & ( impl Client + Sync ) ,
12081209 added_amt : I128Sum ,
1209- mut required_amt : ValueSum < Address , Change > ,
1210+ mut required_amt : ValueSum < ( MaspDigitPos , Address ) , Change > ,
12101211 ) -> Result < I128Sum , TransferErr > {
12111212 // Compute the amount of change due to the sender.
12121213 let ( decoded_amount, mut change) =
12131214 self . decode_sum ( client, added_amt. clone ( ) ) . await ;
12141215 for ( ( asset_type, asset_data) , value) in decoded_amount. components ( ) {
12151216 // Get current component of the required amount
1216- let req = asset_data
1217- . position
1218- . denominate ( & Amount :: from ( required_amt. get ( & asset_data. token ) ) ) ;
1217+ let req = required_amt
1218+ . get ( & ( asset_data. position , asset_data. token . clone ( ) ) ) ;
12191219 // Compute how much this decoded component covers of the requirement
1220- let covered = std:: cmp:: min ( i128:: from ( req) , * value) ;
1220+ let covered = std:: cmp:: min (
1221+ i128:: try_from ( req) . expect ( "Masp digit value overflow" ) ,
1222+ * value,
1223+ ) ;
12211224 // Record how far in excess of the requirement we are. This is
12221225 // change.
12231226 change += ValueSum :: from_pair ( * asset_type, value - covered) ;
12241227 // Denominate the cover and decrease the required amount accordingly
12251228 let covered =
12261229 Change :: from_masp_denominated ( covered, asset_data. position )
12271230 . map_err ( |e| TransferErr :: General ( e. to_string ( ) ) ) ?;
1228- required_amt -=
1229- ValueSum :: from_pair ( asset_data. token . clone ( ) , covered) ;
1231+ required_amt -= ValueSum :: from_pair (
1232+ ( asset_data. position , asset_data. token . clone ( ) ) ,
1233+ covered,
1234+ ) ;
12301235 }
12311236 // Error out if the required amount was not covered by the added amount
12321237 if !required_amt. is_zero ( ) {
@@ -1279,11 +1284,34 @@ pub trait ShieldedApi<U: ShieldedUtils + MaybeSend + MaybeSync>:
12791284
12801285 // If there are shielded inputs
12811286 let added_amt = if let Some ( sk) = spending_key {
1282- // Make the target amount vectorial
1283- let required_amt = ValueSum :: < Address , Change > :: from_pair (
1284- token. clone ( ) ,
1285- ( * amount) . into ( ) ,
1286- ) ;
1287+ // Compute the target amount to spend from the
1288+ // input token address and namada amount. We
1289+ // collect all words from the namada amount
1290+ // whose values are non-zero, and pair them
1291+ // with their corresponding masp digit position.
1292+ let required_amt = amount
1293+ . iter_words ( )
1294+ . enumerate ( )
1295+ . filter_map ( |( masp_digit_pos, value) | {
1296+ if value != 0 {
1297+ Some ( (
1298+ MaspDigitPos :: from ( masp_digit_pos) ,
1299+ Change :: from ( value) ,
1300+ ) )
1301+ } else {
1302+ None
1303+ }
1304+ } )
1305+ . fold (
1306+ ValueSum :: zero ( ) ,
1307+ |mut accum, ( masp_digit_pos, value) | {
1308+ accum += ValueSum :: from_pair (
1309+ ( masp_digit_pos, token. clone ( ) ) ,
1310+ value,
1311+ ) ;
1312+ accum
1313+ } ,
1314+ ) ;
12871315 // Locate unspent notes that can help us meet the transaction
12881316 // amount
12891317 let ( added_amt, unspent_notes, used_convs) = self
0 commit comments