@@ -143,20 +143,18 @@ impl BorshSerialize for AllowedConversion {
143143}
144144
145145impl BorshDeserialize for AllowedConversion {
146- /// This deserialization is unsafe because it does not do the expensive
147- /// computation of checking whether the asset generator corresponds to the
148- /// deserialized amount.
149146 fn deserialize_reader < R : io:: Read > ( reader : & mut R ) -> io:: Result < Self > {
150- let assets = I128Sum :: read ( reader) ?;
151- let gen_bytes =
152- <<jubjub:: ExtendedPoint as GroupEncoding >:: Repr as BorshDeserialize >:: deserialize_reader ( reader) ?;
153- let generator = Option :: from ( jubjub:: ExtendedPoint :: from_bytes ( & gen_bytes) )
154- . ok_or_else ( || io:: Error :: from ( io:: ErrorKind :: InvalidData ) ) ?;
155- let allowed_conversion: AllowedConversion = assets. clone ( ) . into ( ) ;
156- if allowed_conversion. generator != generator {
157- return Err ( io:: Error :: from ( io:: ErrorKind :: InvalidData ) ) ;
147+ // Use the unchecked reader to ensure that same format is supported
148+ let unchecked_conv = UncheckedAllowedConversion :: deserialize_reader ( reader) ?. 0 ;
149+ // Recompute the generator using only the value sum
150+ let safe_conv: AllowedConversion = unchecked_conv. assets . clone ( ) . into ( ) ;
151+ // Check that the computed generator is identical to what was read
152+ if safe_conv. generator == unchecked_conv. generator {
153+ Ok ( safe_conv)
154+ } else {
155+ // The generators do not match, so the bytes cannot be from Self::serialize
156+ Err ( io:: Error :: from ( io:: ErrorKind :: InvalidData ) )
158157 }
159- Ok ( AllowedConversion { assets, generator } )
160158 }
161159}
162160
@@ -213,6 +211,25 @@ impl Sum for AllowedConversion {
213211 }
214212}
215213
214+ /// A seprate type to allow unchecked deserializations of AllowedConversions
215+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
216+ pub struct UncheckedAllowedConversion ( pub AllowedConversion ) ;
217+
218+ impl BorshDeserialize for UncheckedAllowedConversion {
219+ /// This deserialization is unchecked because it does not do the expensive
220+ /// computation of checking whether the asset generator corresponds to the
221+ /// deserialized amount.
222+ fn deserialize_reader < R : io:: Read > ( reader : & mut R ) -> io:: Result < Self > {
223+ let assets = I128Sum :: read ( reader) ?;
224+ let gen_bytes =
225+ <<jubjub:: ExtendedPoint as GroupEncoding >:: Repr as BorshDeserialize >:: deserialize_reader ( reader) ?;
226+ let generator = Option :: from ( jubjub:: ExtendedPoint :: from_bytes ( & gen_bytes) )
227+ . ok_or_else ( || io:: Error :: from ( io:: ErrorKind :: InvalidData ) ) ?;
228+ // Assume that the generator just read corresponds to the value sum
229+ Ok ( Self ( AllowedConversion { assets, generator } ) )
230+ }
231+ }
232+
216233#[ cfg( test) ]
217234mod tests {
218235 use crate :: asset_type:: AssetType ;
0 commit comments