Skip to content

Commit

Permalink
refactor: serialize usize with write_usize
Browse files Browse the repository at this point in the history
  • Loading branch information
Fumuran committed Mar 6, 2024
1 parent 3b0d975 commit 024c631
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 35 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#### VM Internals
- Removed unused `find_lone_leaf()` function from the Advice Provider (#1262).
- Changed fields type of the `StackOutputs` struct from `Vec<u64>` to `Vec<Felt>` (#1268).
- [BREAKING] Changed fields type of the `StackOutputs` struct from `Vec<u64>` to `Vec<Felt>` (#1268).

## 0.8.0 (02-26-2024)

Expand Down
15 changes: 11 additions & 4 deletions core/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,27 @@ use core::fmt;

#[derive(Clone, Debug)]
pub enum InputError {
NotFieldElement(u64, String),
DuplicateAdviceRoot([u8; 32]),
InputLengthExceeded(usize, usize),
NotFieldElement(u64, String),
}

impl fmt::Display for InputError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use InputError::*;
match self {
NotFieldElement(num, description) => {
write!(f, "{num} is not a valid field element: {description}")
}
DuplicateAdviceRoot(key) => {
write!(f, "{key:02x?} is a duplicate of the current merkle set")
}
InputLengthExceeded(limit, provided) => {
write!(
f,
"Number of input values can not exceed {limit}, but {provided} was provided"
)
}
NotFieldElement(num, description) => {
write!(f, "{num} is not a valid field element: {description}")
}
}
}
}
Expand Down
10 changes: 8 additions & 2 deletions core/src/program/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,20 @@ impl Kernel {
impl Serializable for Kernel {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
debug_assert!(self.0.len() <= MAX_KERNEL_PROCEDURES);
target.write_u16(self.0.len() as u16);
target.write_usize(self.0.len());
target.write_many(&self.0)
}
}

impl Deserializable for Kernel {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
let len = source.read_u16()?.into();
let len = source.read_usize()?;
if len > MAX_KERNEL_PROCEDURES {
return Err(DeserializationError::InvalidValue(format!(
"Number of kernel procedures can not be more than {}, but {} was provided",
MAX_KERNEL_PROCEDURES, len
)));
}
let kernel = source.read_many::<Digest>(len)?;
Ok(Self(kernel))
}
Expand Down
42 changes: 32 additions & 10 deletions core/src/stack/inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,33 @@ pub struct StackInputs {
}

impl StackInputs {
// CONSTANTS
// --------------------------------------------------------------------------------------------

pub const MAX_STACK_INPUTS_SIZE: usize = u16::MAX as usize;

// CONSTRUCTORS
// --------------------------------------------------------------------------------------------

/// Returns [StackInputs] from a list of values, reversing them into a stack.
pub fn new(mut values: Vec<Felt>) -> Self {
///
/// # Errors
/// Returns an error if the number of input values exceeds the allowed maximum.
pub fn new(mut values: Vec<Felt>) -> Result<Self, InputError> {
if values.len() > Self::MAX_STACK_INPUTS_SIZE {
return Err(InputError::InputLengthExceeded(Self::MAX_STACK_INPUTS_SIZE, values.len()));
}
values.reverse();
Self { values }

Ok(Self { values })
}

/// Attempts to create stack inputs from an iterator of numbers, failing if they do not
/// represent a valid field element.
/// Attempts to create stack inputs from an iterator of integers.
///
/// # Errors
/// Returns an error if:
/// - The values do not represent a valid field element.
/// - Number of values in the iterator exceeds the allowed maximum number of input values.
pub fn try_from_values<I>(iter: I) -> Result<Self, InputError>
where
I: IntoIterator<Item = u64>,
Expand All @@ -36,7 +52,7 @@ impl StackInputs {
.map(|v| Felt::try_from(v).map_err(|e| InputError::NotFieldElement(v, e)))
.collect::<Result<Vec<_>, _>>()?;

Ok(Self::new(values))
Self::new(values)
}

// PUBLIC ACCESSORS
Expand Down Expand Up @@ -81,17 +97,23 @@ impl Serializable for StackInputs {
// we must define a common serialization format as we might diverge from the implementation
// here and the one provided by default from winterfell.

debug_assert!(self.values.len() <= u32::MAX as usize);
target.write_u32(self.values.len() as u32);
debug_assert!(self.values.len() <= Self::MAX_STACK_INPUTS_SIZE);
target.write_usize(self.values.len());
target.write_many(&self.values);
}
}

impl Deserializable for StackInputs {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
let count = source.read_u32()?;

let values = source.read_many::<Felt>(count as usize)?;
let count = source.read_usize()?;
if count > Self::MAX_STACK_INPUTS_SIZE {
return Err(DeserializationError::InvalidValue(format!(
"Number of values on the input stack can not be more than {}, but {} was found",
Self::MAX_STACK_INPUTS_SIZE,
count
)));
}
let values = source.read_many::<Felt>(count)?;
Ok(StackInputs { values })
}
}
43 changes: 29 additions & 14 deletions core/src/stack/outputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@ pub struct StackOutputs {
overflow_addrs: Vec<Felt>,
}

pub const MAX_STACK_OUTPUTS_SIZE: usize = u16::MAX as usize;

impl StackOutputs {
// CONSTANTS
// --------------------------------------------------------------------------------------------

pub const MAX_STACK_OUTPUTS_SIZE: usize = u16::MAX as usize;

// CONSTRUCTORS
// --------------------------------------------------------------------------------------------

Expand All @@ -44,16 +47,14 @@ impl StackOutputs {
/// `overflow_addrs` does not contain exactly `stack.len() + 1 - STACK_TOP_SIZE` elements.
pub fn new(mut stack: Vec<Felt>, overflow_addrs: Vec<Felt>) -> Result<Self, OutputError> {
// validate stack length
if stack.len() > MAX_STACK_OUTPUTS_SIZE {
if stack.len() > Self::MAX_STACK_OUTPUTS_SIZE {
return Err(OutputError::OutputSizeTooBig(stack.len()));
}

// get overflow_addrs length
let expected_overflow_addrs_len = get_overflow_addrs_len(stack.len());

// validate overflow_addrs length
let expected_overflow_addrs_len = if stack.len() > STACK_TOP_SIZE {
stack.len() + 1 - STACK_TOP_SIZE
} else {
0
};
if overflow_addrs.len() != expected_overflow_addrs_len {
return Err(OutputError::InvalidOverflowAddressLength(
overflow_addrs.len(),
Expand Down Expand Up @@ -200,27 +201,41 @@ impl ToElements<Felt> for StackOutputs {
}
}

/// Returs the number of overflow addresses based on the lenght of the stack.
fn get_overflow_addrs_len(stack_len: usize) -> usize {
if stack_len > STACK_TOP_SIZE {
stack_len + 1 - STACK_TOP_SIZE
} else {
0
}
}

// SERIALIZATION
// ================================================================================================

impl Serializable for StackOutputs {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
debug_assert!(self.stack.len() <= u32::MAX as usize);
target.write_u32(self.stack.len() as u32);
debug_assert!(self.stack.len() <= Self::MAX_STACK_OUTPUTS_SIZE);
target.write_usize(self.stack.len());
target.write_many(&self.stack);

debug_assert!(self.overflow_addrs.len() <= u32::MAX as usize);
target.write_u32(self.overflow_addrs.len() as u32);
target.write_many(&self.overflow_addrs);
}
}

impl Deserializable for StackOutputs {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
let count = source.read_u32()?.try_into().expect("u32 must fit in a usize");
let count = source.read_usize()?;
if count > Self::MAX_STACK_OUTPUTS_SIZE {
return Err(DeserializationError::InvalidValue(format!(
"Number of values on the output stack can not be more than {}, but {} was found",
Self::MAX_STACK_OUTPUTS_SIZE,
count
)));
}
let stack = source.read_many::<Felt>(count)?;

let count = source.read_u32()?.try_into().expect("u32 must fit in a usize");
let count = get_overflow_addrs_len(stack.len());
let overflow_addrs = source.read_many::<Felt>(count)?;

Ok(Self {
Expand Down
2 changes: 1 addition & 1 deletion processor/src/operations/comb_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ mod tests {
inputs.reverse();

// --- setup the operand stack ------------------------------------------------------------
let stack_inputs = StackInputs::new(inputs.to_vec());
let stack_inputs = StackInputs::new(inputs.to_vec()).expect("inputs lenght too long");
let mut process = Process::new_dummy_with_decoder_helpers(stack_inputs);

// --- setup memory -----------------------------------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions processor/src/operations/ext2_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ mod tests {
// initialize the stack with a few values
let [a0, a1, b0, b1] = [rand_value(); 4];

let stack = StackInputs::new(vec![a0, a1, b0, b1]);
let stack = StackInputs::new(vec![a0, a1, b0, b1]).expect("inputs lenght too long");
let mut process = Process::new_dummy(stack);

// multiply the top two values
Expand All @@ -64,7 +64,7 @@ mod tests {
assert_eq!(expected, process.stack.trace_state());

// calling ext2mul with a stack of minimum depth is ok
let stack = StackInputs::new(vec![]);
let stack = StackInputs::new(vec![]).expect("inputs lenght too long");
let mut process = Process::new_dummy(stack);
assert!(process.execute_op(Operation::Ext2Mul).is_ok());
}
Expand Down
2 changes: 1 addition & 1 deletion processor/src/operations/fri_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ mod tests {
];

// --- execute FRIE2F4 operation --------------------------------------
let stack_inputs = StackInputs::new(inputs.to_vec());
let stack_inputs = StackInputs::new(inputs.to_vec()).expect("inputs lenght too long");
let mut process = Process::new_dummy_with_decoder_helpers(stack_inputs);
process.execute_op(Operation::FriE2F4).unwrap();

Expand Down

0 comments on commit 024c631

Please sign in to comment.