Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replace Result<T, Box<dyn Error>> with anyhow::Result<T> #134

Merged
merged 5 commits into from
Nov 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 88 additions & 111 deletions triton-vm/src/bfield_codec.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,13 @@
use std::{error::Error, fmt::Display};

use anyhow::{bail, Result};
use itertools::Itertools;
use num_traits::{One, Zero};
use twenty_first::{
shared_math::{
b_field_element::BFieldElement, rescue_prime_digest::Digest,
rescue_prime_regular::DIGEST_LENGTH, x_field_element::XFieldElement,
},
util_types::{algebraic_hasher::Hashable, merkle_tree::PartialAuthenticationPath},
};

#[derive(Debug, Clone)]
pub struct BFieldCodecError {
pub message: String,
}

impl BFieldCodecError {
pub fn new(message: &str) -> Self {
Self {
message: message.to_string(),
}
}

pub fn boxed(message: &str) -> Box<dyn Error> {
Box::new(Self::new(message))
}
}

impl Display for BFieldCodecError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "{}", self.message)
}
}

impl Error for BFieldCodecError {}
use twenty_first::shared_math::b_field_element::BFieldElement;
use twenty_first::shared_math::rescue_prime_digest::Digest;
use twenty_first::shared_math::rescue_prime_regular::DIGEST_LENGTH;
use twenty_first::shared_math::x_field_element::{XFieldElement, EXTENSION_DEGREE};
use twenty_first::util_types::algebraic_hasher::Hashable;
use twenty_first::util_types::merkle_tree::PartialAuthenticationPath;

/// BFieldCodec
///
Expand All @@ -43,18 +17,16 @@ impl Error for BFieldCodecError {}
/// length-prepending. It does not record type information; this is
/// the responsibility of the decoder.
pub trait BFieldCodec {
fn decode(string: &[BFieldElement]) -> Result<Box<Self>, Box<dyn Error>>;
fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>>;
fn encode(&self) -> Vec<BFieldElement>;
}

impl BFieldCodec for BFieldElement {
fn decode(str: &[BFieldElement]) -> Result<Box<Self>, Box<dyn Error>> {
if str.len() != 1 {
return Err(BFieldCodecError::boxed(
"trying to decode more or less than one BFieldElements as one BFieldElement",
));
fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>> {
if sequence.len() != 1 {
bail!("trying to decode more or less than one BFieldElements as one BFieldElement");
}
let element_zero = str[0];
let element_zero = sequence[0];
Ok(Box::new(element_zero))
}

Expand All @@ -64,16 +36,17 @@ impl BFieldCodec for BFieldElement {
}

impl BFieldCodec for XFieldElement {
fn decode(str: &[BFieldElement]) -> Result<Box<Self>, Box<dyn Error>> {
if str.len() != 3 {
Err(BFieldCodecError::boxed(
"trying to decode slice of not 3 BFieldElements into XFieldElement",
))
} else {
Ok(Box::new(XFieldElement {
coefficients: str.try_into().unwrap(),
}))
// FIXME: Use `XFieldElement::try_into()`.
fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>> {
if sequence.len() != EXTENSION_DEGREE {
bail!(
"trying to decode slice of not EXTENSION_DEGREE BFieldElements into XFieldElement"
);
}

Ok(Box::new(XFieldElement {
coefficients: sequence.try_into().unwrap(),
}))
}

fn encode(&self) -> Vec<BFieldElement> {
Expand All @@ -82,14 +55,13 @@ impl BFieldCodec for XFieldElement {
}

impl BFieldCodec for Digest {
fn decode(str: &[BFieldElement]) -> Result<Box<Self>, Box<dyn Error>> {
if str.len() != DIGEST_LENGTH {
Err(BFieldCodecError::boxed(
"trying to decode slice of not DIGEST_LENGTH BFieldElements into Digest",
))
} else {
Ok(Box::new(Digest::new(str.try_into().unwrap())))
// FIXME: Use `Digest::try_from()`
fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>> {
if sequence.len() != DIGEST_LENGTH {
bail!("trying to decode slice of not DIGEST_LENGTH BFieldElements into Digest");
}

Ok(Box::new(Digest::new(sequence.try_into().unwrap())))
}

fn encode(&self) -> Vec<BFieldElement> {
Expand All @@ -98,45 +70,41 @@ impl BFieldCodec for Digest {
}

impl<T: BFieldCodec, S: BFieldCodec> BFieldCodec for (T, S) {
fn decode(str: &[BFieldElement]) -> Result<Box<Self>, Box<dyn Error>> {
fn decode(str: &[BFieldElement]) -> Result<Box<Self>> {
// decode T
let maybe_element_zero = str.get(0);
if matches!(maybe_element_zero, None) {
return Err(BFieldCodecError::boxed(
"trying to decode empty slice as tuple",
));
bail!("trying to decode empty slice as tuple",);
}

let len_t = maybe_element_zero.unwrap().value() as usize;
if str.len() < 1 + len_t {
return Err(BFieldCodecError::boxed(
"prepended length of tuple element does not match with remaining string length",
));
bail!("prepended length of tuple element does not match with remaining string length");
}
let maybe_t = T::decode(&str[1..(1 + len_t)]);

// decode S
let maybe_next_element = str.get(1 + len_t);
if matches!(maybe_next_element, None) {
return Err(BFieldCodecError::boxed(
"trying to decode singleton as tuple",
));
bail!("trying to decode singleton as tuple");
}

let len_s = maybe_next_element.unwrap().value() as usize;
if str.len() != 1 + len_t + 1 + len_s {
return Err(BFieldCodecError::boxed(
bail!(
"prepended length of second tuple element does not match with remaining string length",
));
);
}
let maybe_s = S::decode(&str[(1 + len_t + 1)..]);

if let Ok(t) = maybe_t {
if let Ok(s) = maybe_s {
Ok(Box::new((*t, *s)))
} else {
Err(BFieldCodecError::boxed("could not decode s"))
bail!("could not decode s")
}
} else {
Err(BFieldCodecError::boxed("could not decode t"))
bail!("could not decode t")
}
}

Expand All @@ -157,29 +125,25 @@ impl<T: BFieldCodec, S: BFieldCodec> BFieldCodec for (T, S) {
}

impl BFieldCodec for PartialAuthenticationPath<Digest> {
fn decode(str: &[BFieldElement]) -> Result<Box<Self>, Box<dyn Error>> {
if str.is_empty() {
return Err(BFieldCodecError::boxed(
"cannot decode empty string into PartialAuthenticationPath",
));
fn decode(sequence: &[BFieldElement]) -> Result<Box<Self>> {
if sequence.is_empty() {
bail!("cannot decode empty string into PartialAuthenticationPath");
}
let mut vect: Vec<Option<Digest>> = vec![];
let mut index = 0;
while index < str.len() {
let len = str[index].value();
if str.len() < index + 1 + len as usize {
return Err(BFieldCodecError::boxed(
"cannot decode vec of optional digests because of improper length prepending",
));
while index < sequence.len() {
let len = sequence[index].value();
if sequence.len() < index + 1 + len as usize {
bail!(
"cannot decode vec of optional digests because of improper length prepending"
);
}
let substr = &str[(index + 1)..(index + 1 + len as usize)];
let substr = &sequence[(index + 1)..(index + 1 + len as usize)];
let decoded = Option::<Digest>::decode(substr);
if let Ok(optional_digest) = decoded {
vect.push(*optional_digest);
} else {
return Err(BFieldCodecError::boxed(
"cannot decode optional digest in vec",
));
bail!("cannot decode optional digest in vec");
}

index += 1 + len as usize;
Expand All @@ -201,13 +165,12 @@ impl BFieldCodec for PartialAuthenticationPath<Digest> {
}

impl<T: BFieldCodec> BFieldCodec for Option<T> {
fn decode(str: &[BFieldElement]) -> Result<Box<Self>, Box<dyn Error>> {
fn decode(str: &[BFieldElement]) -> Result<Box<Self>> {
let maybe_element_zero = str.get(0);
if matches!(maybe_element_zero, None) {
return Err(BFieldCodecError::boxed(
"trying to decode empty slice into option of elements",
));
bail!("trying to decode empty slice into option of elements");
}

if maybe_element_zero.unwrap().is_zero() {
Ok(Box::new(None))
} else {
Expand Down Expand Up @@ -235,7 +198,7 @@ impl<T: BFieldCodec> BFieldCodec for Option<T> {
}

impl BFieldCodec for Vec<BFieldElement> {
fn decode(str: &[BFieldElement]) -> Result<Box<Self>, Box<dyn Error>> {
fn decode(str: &[BFieldElement]) -> Result<Box<Self>> {
Ok(Box::new(str.to_vec()))
}

Expand All @@ -245,13 +208,16 @@ impl BFieldCodec for Vec<BFieldElement> {
}

impl BFieldCodec for Vec<XFieldElement> {
fn decode(str: &[BFieldElement]) -> Result<Box<Self>, Box<dyn Error>> {
if str.len() % 3 != 0 {
return Err(BFieldCodecError::boxed("cannot decode string of BFieldElements into XFieldElements when string length is not a multiple of 3"));
fn decode(str: &[BFieldElement]) -> Result<Box<Self>> {
if str.len() % EXTENSION_DEGREE != 0 {
bail!(
"cannot decode string of BFieldElements into XFieldElements \
when string length is not a multiple of EXTENSION_DEGREE",
);
}
let mut vector = vec![];
for chunk in str.chunks(3) {
let coefficients: [BFieldElement; 3] = chunk.try_into().unwrap();
for chunk in str.chunks(EXTENSION_DEGREE) {
let coefficients: [BFieldElement; EXTENSION_DEGREE] = chunk.try_into().unwrap();
vector.push(XFieldElement::new(coefficients));
}
Ok(Box::new(vector))
Expand All @@ -263,9 +229,12 @@ impl BFieldCodec for Vec<XFieldElement> {
}

impl BFieldCodec for Vec<Digest> {
fn decode(str: &[BFieldElement]) -> Result<Box<Self>, Box<dyn Error>> {
fn decode(str: &[BFieldElement]) -> Result<Box<Self>> {
if str.len() % DIGEST_LENGTH != 0 {
return Err(BFieldCodecError::boxed("cannot decode string of BFieldElements into Digests when string length is not a multiple of DIGEST_LENGTH"));
bail!(
"cannot decode string of BFieldElements into Digests \
when string length is not a multiple of DIGEST_LENGTH",
);
}
let mut vector: Vec<Digest> = vec![];
for chunk in str.chunks(DIGEST_LENGTH) {
Expand All @@ -284,7 +253,7 @@ impl<T> BFieldCodec for Vec<Vec<T>>
where
Vec<T>: BFieldCodec,
{
fn decode(str: &[BFieldElement]) -> Result<Box<Self>, Box<dyn Error>> {
fn decode(str: &[BFieldElement]) -> Result<Box<Self>> {
let mut index = 0;
let mut outer_vec: Vec<Vec<T>> = vec![];
while index < str.len() {
Expand All @@ -294,9 +263,7 @@ where
if let Some(inner_vec) = str.get(index..(index + len)) {
outer_vec.push(*Vec::<T>::decode(inner_vec)?);
} else {
return Err(BFieldCodecError::boxed(
"cannot decode string BFieldElements into Vec<Vec<T>>; length mismatch",
));
bail!("cannot decode string BFieldElements into Vec<Vec<T>>; length mismatch");
}
index += len;
}
Expand All @@ -315,7 +282,7 @@ where
}

impl BFieldCodec for Vec<PartialAuthenticationPath<Digest>> {
fn decode(str: &[BFieldElement]) -> Result<Box<Self>, Box<dyn Error>> {
fn decode(str: &[BFieldElement]) -> Result<Box<Self>> {
let mut index = 0;
let mut vector = vec![];

Expand All @@ -325,7 +292,10 @@ impl BFieldCodec for Vec<PartialAuthenticationPath<Digest>> {
index += 1;

if len_remaining < 2 || index + len_remaining > str.len() {
return Err(BFieldCodecError::boxed("cannot decode string of BFieldElements as Vec of PartialAuthenticationPaths due to length mismatch (1)"));
bail!(
"cannot decode string of BFieldElements as Vec of PartialAuthenticationPaths \
due to length mismatch (1)",
);
}

let vec_len = str[index].value() as usize;
Expand All @@ -335,8 +305,9 @@ impl BFieldCodec for Vec<PartialAuthenticationPath<Digest>> {
// if the vector length and mask indicates some digests are following
// and we are already at the end of the buffer
if vec_len != 0 && mask != 0 && index == str.len() {
return Err(BFieldCodecError::boxed(
&format!("Cannot decode string of BFieldElements as Vec of PartialAuthenticationPaths due to length mismatch (2).\n\
bail!(
"Cannot decode string of BFieldElements as Vec of PartialAuthenticationPaths \
due to length mismatch (2).\n\
vec_len: {}\n\
mask: {}\n\
index: {}\n\
Expand All @@ -346,12 +317,15 @@ impl BFieldCodec for Vec<PartialAuthenticationPath<Digest>> {
mask,
index,
str.len(),
str[0])
));
str[0]
);
}

if (len_remaining - 2) % DIGEST_LENGTH != 0 {
return Err(BFieldCodecError::boxed("cannot decode string of BFieldElements as Vec of PartialAuthenticationPaths due to length mismatch (3)"));
bail!(
"cannot decode string of BFieldElements as Vec of PartialAuthenticationPaths \
due to length mismatch (3)",
);
}

let mut pap = vec![];
Expand All @@ -363,7 +337,10 @@ impl BFieldCodec for Vec<PartialAuthenticationPath<Digest>> {
pap.push(Some(*Digest::decode(chunk)?));
index += DIGEST_LENGTH;
} else {
return Err(BFieldCodecError::boxed("cannot decode string of BFieldElements as Vec of PartialAuthenticationPaths due to length mismatch (4)"));
bail!(
"cannot decode string of BFieldElements as Vec of \
PartialAuthenticationPaths due to length mismatch (4)",
);
}
}

Expand Down Expand Up @@ -595,7 +572,7 @@ mod bfield_codec_tests {
}

if let Ok(_sth) = XFieldElement::decode(&str) {
if str.len() != 3 {
if str.len() != EXTENSION_DEGREE {
panic!();
}
}
Expand All @@ -610,7 +587,7 @@ mod bfield_codec_tests {
// (should work)
// }

if str.len() % 3 != 0 {
if str.len() % EXTENSION_DEGREE != 0 {
if let Ok(sth) = Vec::<XFieldElement>::decode(&str) {
panic!("{:?}", sth);
}
Expand Down
7 changes: 4 additions & 3 deletions triton-vm/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use anyhow::Result;
use std::error::Error;
use std::fmt::{Display, Formatter};
use twenty_first::shared_math::b_field_element::BFieldElement;
Expand Down Expand Up @@ -74,10 +75,10 @@ impl Display for InstructionError {

impl Error for InstructionError {}

pub fn vm_err<T>(runtime_error: InstructionError) -> Result<T, Box<dyn Error>> {
pub fn vm_err<T>(runtime_error: InstructionError) -> Result<T> {
Err(vm_fail(runtime_error))
}

pub fn vm_fail(runtime_error: InstructionError) -> Box<dyn Error> {
Box::new(runtime_error)
pub fn vm_fail(runtime_error: InstructionError) -> anyhow::Error {
anyhow::Error::new(runtime_error)
}
Loading