Skip to content

Commit

Permalink
refactor: serialize usize with write_usize (#1266)
Browse files Browse the repository at this point in the history
  • Loading branch information
Fumuran authored Mar 9, 2024
1 parent 17e4411 commit 322a70b
Show file tree
Hide file tree
Showing 30 changed files with 176 additions and 128 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,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
44 changes: 33 additions & 11 deletions core/src/stack/inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,34 @@ pub struct StackInputs {
}

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

pub const MAX_LEN: 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_LEN {
return Err(InputError::InputLengthExceeded(Self::MAX_LEN, 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.
pub fn try_from_values<I>(iter: I) -> Result<Self, InputError>
/// 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_ints<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_LEN);
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_LEN {
return Err(DeserializationError::InvalidValue(format!(
"Number of values on the input stack can not be more than {}, but {} was found",
Self::MAX_LEN,
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_LEN: 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_LEN {
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_LEN);
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_LEN {
return Err(DeserializationError::InvalidValue(format!(
"Number of values on the output stack can not be more than {}, but {} was found",
Self::MAX_LEN,
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 miden/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ let program = Assembler::default().compile(&source).unwrap();
let host = DefaultHost::default();

// initialize the stack with values 0 and 1
let stack_inputs = StackInputs::try_from_values([0, 1]).unwrap();
let stack_inputs = StackInputs::try_from_ints([0, 1]).unwrap();

// execute the program
let (outputs, proof) = miden_vm::prove(
Expand Down
2 changes: 1 addition & 1 deletion miden/src/cli/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ impl InputFile {
.map(|v| v.parse::<u64>().map_err(|e| e.to_string()))
.collect::<Result<Vec<_>, _>>()?;

StackInputs::try_from_values(stack_inputs).map_err(|e| e.to_string())
StackInputs::try_from_ints(stack_inputs).map_err(|e| e.to_string())
}
}

Expand Down
2 changes: 1 addition & 1 deletion miden/src/examples/blake3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub fn get_example(n: usize) -> Example<DefaultHost<MemAdviceProvider>> {

Example {
program,
stack_inputs: StackInputs::try_from_values(INITIAL_HASH_VALUE.iter().map(|&v| v as u64))
stack_inputs: StackInputs::try_from_ints(INITIAL_HASH_VALUE.iter().map(|&v| v as u64))
.unwrap(),
host: DefaultHost::default(),
expected_result,
Expand Down
2 changes: 1 addition & 1 deletion miden/src/examples/fibonacci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub fn get_example(n: usize) -> Example<DefaultHost<MemAdviceProvider>> {

Example {
program,
stack_inputs: StackInputs::try_from_values([0, 1]).unwrap(),
stack_inputs: StackInputs::try_from_ints([0, 1]).unwrap(),
host: DefaultHost::default(),
expected_result,
num_outputs: 1,
Expand Down
2 changes: 1 addition & 1 deletion miden/src/tools/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ mod tests {
fn analyze_test_execution_error() {
let source = "begin div end";
let stack_inputs = vec![1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let stack_inputs = StackInputs::try_from_values(stack_inputs).unwrap();
let stack_inputs = StackInputs::try_from_ints(stack_inputs).unwrap();
let host = DefaultHost::default();
let execution_details = super::analyze(source, stack_inputs, host);
let expected_error = "Execution Error: DivideByZero(1)";
Expand Down
6 changes: 3 additions & 3 deletions miden/tests/integration/flow_control/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ fn simple_syscall() {
let test = Test {
source: program_source.to_string(),
kernel: Some(kernel_source.to_string()),
stack_inputs: StackInputs::try_from_values([1, 2]).unwrap(),
stack_inputs: StackInputs::try_from_ints([1, 2]).unwrap(),
advice_inputs: AdviceInputs::default(),
in_debug_mode: false,
libraries: Vec::default(),
Expand Down Expand Up @@ -251,7 +251,7 @@ fn simple_dyn_exec() {
let test = Test {
source: program_source.to_string(),
kernel: None,
stack_inputs: StackInputs::try_from_values([
stack_inputs: StackInputs::try_from_ints([
3,
// put the hash of foo on the stack
16045159387802755434,
Expand Down Expand Up @@ -357,7 +357,7 @@ fn simple_dyncall() {
let test = Test {
source: program_source.to_string(),
kernel: None,
stack_inputs: StackInputs::try_from_values([
stack_inputs: StackInputs::try_from_ints([
3,
// put the hash of foo on the stack
8324248212344458853,
Expand Down
2 changes: 1 addition & 1 deletion miden/tests/integration/operations/io_ops/env_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ fn caller() {
let test = Test {
source: program_source.to_string(),
kernel: Some(kernel_source.to_string()),
stack_inputs: StackInputs::try_from_values([1, 2, 3, 4, 5]).unwrap(),
stack_inputs: StackInputs::try_from_ints([1, 2, 3, 4, 5]).unwrap(),
advice_inputs: AdviceInputs::default(),
in_debug_mode: false,
libraries: Vec::default(),
Expand Down
2 changes: 1 addition & 1 deletion processor/src/chiplets/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ fn build_trace(
operations: Vec<Operation>,
kernel: Kernel,
) -> (ChipletsTrace, usize) {
let stack_inputs = StackInputs::try_from_values(stack_inputs.iter().copied()).unwrap();
let stack_inputs = StackInputs::try_from_ints(stack_inputs.iter().copied()).unwrap();
let host = DefaultHost::default();
let mut process = Process::new(kernel, stack_inputs, host, ExecutionOptions::default());
let program = CodeBlock::new_span(operations);
Expand Down
4 changes: 2 additions & 2 deletions processor/src/decoder/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@ fn set_user_op_helpers_many() {
// ================================================================================================

fn build_trace(stack_inputs: &[u64], program: &CodeBlock) -> (DecoderTrace, usize) {
let stack_inputs = StackInputs::try_from_values(stack_inputs.iter().copied()).unwrap();
let stack_inputs = StackInputs::try_from_ints(stack_inputs.iter().copied()).unwrap();
let host = DefaultHost::default();
let mut process =
Process::new(Kernel::default(), stack_inputs, host, ExecutionOptions::default());
Expand All @@ -1217,7 +1217,7 @@ fn build_dyn_trace(
program: &CodeBlock,
fn_block: CodeBlock,
) -> (DecoderTrace, usize) {
let stack_inputs = StackInputs::try_from_values(stack_inputs.iter().copied()).unwrap();
let stack_inputs = StackInputs::try_from_ints(stack_inputs.iter().copied()).unwrap();
let host = DefaultHost::default();
let mut process =
Process::new(Kernel::default(), stack_inputs, host, ExecutionOptions::default());
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
12 changes: 6 additions & 6 deletions processor/src/operations/crypto_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ mod tests {
1, 1, // data: [ONE, ONE]
1, 0, 0, 0, 0, 0 // padding: ONE followed by the necessary ZEROs
];
let stack = StackInputs::try_from_values(inputs).unwrap();
let stack = StackInputs::try_from_ints(inputs).unwrap();
let mut process = Process::new_dummy_with_decoder_helpers(stack);

let expected: [Felt; STATE_WIDTH] = build_expected_perm(&inputs);
Expand All @@ -212,7 +212,7 @@ mod tests {
let values = rand_vector::<u64>(8);
let mut inputs: Vec<u64> = vec![values.len() as u64, 0, 0, 0];
inputs.extend_from_slice(&values);
let stack = StackInputs::try_from_values(inputs.clone()).unwrap();
let stack = StackInputs::try_from_ints(inputs.clone()).unwrap();
let mut process = Process::new_dummy_with_decoder_helpers(stack);

// add the capacity to prepare the input vector
Expand All @@ -226,7 +226,7 @@ mod tests {
let values: Vec<u64> = vec![2, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0];
inputs.extend_from_slice(&values);

let stack = StackInputs::try_from_values(inputs).unwrap();
let stack = StackInputs::try_from_ints(inputs).unwrap();
let mut process = Process::new_dummy_with_decoder_helpers(stack);
process.execute_op(Operation::HPerm).unwrap();
assert_eq!(expected, &process.stack.trace_state()[12..16]);
Expand Down Expand Up @@ -260,7 +260,7 @@ mod tests {
let index = Felt::new(index);

let advice_inputs = AdviceInputs::default().with_merkle_store(store);
let stack_inputs = StackInputs::try_from_values(stack_inputs).unwrap();
let stack_inputs = StackInputs::try_from_ints(stack_inputs).unwrap();
let mut process =
Process::new_dummy_with_inputs_and_decoder_helpers(stack_inputs, advice_inputs);

Expand Down Expand Up @@ -302,7 +302,7 @@ mod tests {

let store = MerkleStore::from(&tree);
let advice_inputs = AdviceInputs::default().with_merkle_store(store);
let stack_inputs = StackInputs::try_from_values(stack_inputs).unwrap();
let stack_inputs = StackInputs::try_from_ints(stack_inputs).unwrap();
let mut process =
Process::new_dummy_with_inputs_and_decoder_helpers(stack_inputs, advice_inputs);

Expand Down Expand Up @@ -380,7 +380,7 @@ mod tests {
replaced_node[2].as_int(),
replaced_node[3].as_int(),
];
let stack_inputs = StackInputs::try_from_values(stack_inputs).unwrap();
let stack_inputs = StackInputs::try_from_ints(stack_inputs).unwrap();
let mut process =
Process::new_dummy_with_inputs_and_decoder_helpers(stack_inputs, advice_inputs);

Expand Down
Loading

0 comments on commit 322a70b

Please sign in to comment.