@@ -15,7 +15,7 @@ use crate::{Felt, NoteError};
1515/// [`NoteExecutionHint`] can be encoded into a [`Felt`] with the following layout:
1616///
1717/// ```text
18- /// [26 zero bits | payload (32 bits) | tag (6 bits)]
18+ /// [24 zero bits | payload (32 bits) | tag (8 bits)]
1919/// ```
2020///
2121/// This way, hints such as [NoteExecutionHint::Always], are represented by `Felt::new(1)`.
@@ -27,10 +27,7 @@ pub enum NoteExecutionHint {
2727 /// The note's script can be executed at any time.
2828 Always ,
2929 /// The note's script can be executed after the specified block number.
30- ///
31- /// The block number cannot be [`u32::MAX`] which is enforced through the [`AfterBlockNumber`]
32- /// type.
33- AfterBlock { block_num : AfterBlockNumber } ,
30+ AfterBlock { block_num : BlockNumber } ,
3431 /// The note's script can be executed in the specified slot within the specified round.
3532 ///
3633 /// The slot is defined as follows:
@@ -74,13 +71,8 @@ impl NoteExecutionHint {
7471 }
7572
7673 /// Creates a [NoteExecutionHint::AfterBlock] variant based on the given `block_num`
77- ///
78- /// # Errors
79- ///
80- /// Returns an error if `block_num` is equal to [`u32::MAX`].
81- pub fn after_block ( block_num : BlockNumber ) -> Result < Self , NoteError > {
82- AfterBlockNumber :: new ( block_num)
83- . map ( |block_number| NoteExecutionHint :: AfterBlock { block_num : block_number } )
74+ pub fn after_block ( block_num : BlockNumber ) -> Self {
75+ NoteExecutionHint :: AfterBlock { block_num }
8476 }
8577
8678 /// Creates a [NoteExecutionHint::OnBlockSlot] for the given parameters. See the variants
@@ -103,7 +95,7 @@ impl NoteExecutionHint {
10395 }
10496 Ok ( NoteExecutionHint :: Always )
10597 } ,
106- Self :: AFTER_BLOCK_TAG => NoteExecutionHint :: after_block ( payload . into ( ) ) ,
98+ Self :: AFTER_BLOCK_TAG => Ok ( NoteExecutionHint :: after_block ( BlockNumber :: from ( payload ) ) ) ,
10799 Self :: ON_BLOCK_SLOT_TAG => {
108100 let remainder = ( ( payload >> 24 ) & 0xff ) as u8 ;
109101 if remainder != 0 {
@@ -151,15 +143,7 @@ impl NoteExecutionHint {
151143 }
152144 }
153145
154- /// Encodes the [`NoteExecutionHint`] into a 6-bit tag and a 32-bit payload.
155- ///
156- /// # Guarantees
157- ///
158- /// Since the tag has at most 6 bits, the returned byte is guaranteed to have its two most
159- /// significant bits set to `0`.
160- ///
161- /// The payload is guaranteed to contain at least one `0` bit to make encoding it into
162- /// [`NoteMetadata`](crate::note::NoteMetadata) safely possible.
146+ /// Encodes the [`NoteExecutionHint`] into an 8-bit tag and a 32-bit payload.
163147 pub fn into_parts ( & self ) -> ( u8 , u32 ) {
164148 match self {
165149 NoteExecutionHint :: None => ( Self :: NONE_TAG , 0 ) ,
@@ -187,12 +171,13 @@ impl From<NoteExecutionHint> for Felt {
187171/// Tries to convert a `u64` into a [`NoteExecutionHint`] with the expected layout documented on the
188172/// type.
189173///
190- /// Note: The upper 26 bits are not enforced to be zero.
174+ /// Note: The upper 24 bits are not enforced to be zero.
191175impl TryFrom < u64 > for NoteExecutionHint {
192176 type Error = NoteError ;
193177 fn try_from ( value : u64 ) -> Result < Self , Self :: Error > {
194- let tag = ( value & 0b111111 ) as u8 ;
195- let payload = ( ( value >> 6 ) & 0xffffffff ) as u32 ;
178+ let tag = ( value & 0b1111_1111 ) as u8 ;
179+ // Shift the payload and cut off / ignore the upper 32 bits.
180+ let payload = ( value >> 8 ) as u32 ;
196181
197182 Self :: from_parts ( tag, payload)
198183 }
@@ -202,51 +187,7 @@ impl TryFrom<u64> for NoteExecutionHint {
202187impl From < NoteExecutionHint > for u64 {
203188 fn from ( value : NoteExecutionHint ) -> Self {
204189 let ( tag, payload) = value. into_parts ( ) ;
205- ( ( payload as u64 ) << 6 ) | ( tag as u64 )
206- }
207- }
208-
209- // AFTER BLOCK NUMBER
210- // ================================================================================================
211-
212- /// A wrapper around a block number which enforces that it is not `u32::MAX`.
213- ///
214- /// Used for the [`NoteExecutionHint::AfterBlock`] variant where this constraint is needed.
215- #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
216- pub struct AfterBlockNumber ( BlockNumber ) ;
217-
218- impl AfterBlockNumber {
219- /// Creates a new [`AfterBlockNumber`] from the given `block_number`.
220- ///
221- /// # Errors
222- ///
223- /// Returns an error if:
224- /// - `block_number` is equal to `u32::MAX`.
225- pub fn new ( block_number : BlockNumber ) -> Result < Self , NoteError > {
226- if block_number. as_u32 ( ) == u32:: MAX {
227- Err ( NoteError :: NoteExecutionHintAfterBlockCannotBeU32Max )
228- } else {
229- Ok ( Self ( block_number) )
230- }
231- }
232-
233- /// Returns the block number as a `u32`.
234- pub fn as_u32 ( & self ) -> u32 {
235- self . 0 . as_u32 ( )
236- }
237- }
238-
239- impl From < AfterBlockNumber > for u32 {
240- fn from ( block_number : AfterBlockNumber ) -> Self {
241- block_number. 0 . as_u32 ( )
242- }
243- }
244-
245- impl TryFrom < u32 > for AfterBlockNumber {
246- type Error = NoteError ;
247-
248- fn try_from ( block_number : u32 ) -> Result < Self , Self :: Error > {
249- Self :: new ( block_number. into ( ) )
190+ ( ( payload as u64 ) << 8 ) | ( tag as u64 )
250191 }
251192}
252193
@@ -255,7 +196,6 @@ impl TryFrom<u32> for AfterBlockNumber {
255196
256197#[ cfg( test) ]
257198mod tests {
258- use assert_matches:: assert_matches;
259199
260200 use super :: * ;
261201
@@ -269,7 +209,7 @@ mod tests {
269209 fn test_serialization_round_trip ( ) {
270210 assert_hint_serde ( NoteExecutionHint :: None ) ;
271211 assert_hint_serde ( NoteExecutionHint :: Always ) ;
272- assert_hint_serde ( NoteExecutionHint :: after_block ( 15 . into ( ) ) . unwrap ( ) ) ;
212+ assert_hint_serde ( NoteExecutionHint :: after_block ( 15 . into ( ) ) ) ;
273213 assert_hint_serde ( NoteExecutionHint :: OnBlockSlot {
274214 round_len : 9 ,
275215 slot_len : 12 ,
@@ -279,7 +219,7 @@ mod tests {
279219
280220 #[ test]
281221 fn test_encode_round_trip ( ) {
282- let hint = NoteExecutionHint :: after_block ( 15 . into ( ) ) . unwrap ( ) ;
222+ let hint = NoteExecutionHint :: after_block ( 15 . into ( ) ) ;
283223 let hint_int: u64 = hint. into ( ) ;
284224 let decoded_hint: NoteExecutionHint = hint_int. try_into ( ) . unwrap ( ) ;
285225 assert_eq ! ( hint, decoded_hint) ;
@@ -305,7 +245,7 @@ mod tests {
305245 let always = NoteExecutionHint :: always ( ) ;
306246 assert ! ( always. can_be_consumed( 100 . into( ) ) . unwrap( ) ) ;
307247
308- let after_block = NoteExecutionHint :: after_block ( 12345 . into ( ) ) . unwrap ( ) ;
248+ let after_block = NoteExecutionHint :: after_block ( 12345 . into ( ) ) ;
309249 assert ! ( !after_block. can_be_consumed( 12344 . into( ) ) . unwrap( ) ) ;
310250 assert ! ( after_block. can_be_consumed( 12345 . into( ) ) . unwrap( ) ) ;
311251
@@ -331,12 +271,4 @@ mod tests {
331271
332272 NoteExecutionHint :: from_parts ( 10 , 1 ) . unwrap_err ( ) ;
333273 }
334-
335- #[ test]
336- fn test_after_block_fails_on_u32_max ( ) {
337- assert_matches ! (
338- NoteExecutionHint :: after_block( u32 :: MAX . into( ) ) . unwrap_err( ) ,
339- NoteError :: NoteExecutionHintAfterBlockCannotBeU32Max
340- ) ;
341- }
342274}
0 commit comments