diff --git a/jets-bench/benches/elements/input.rs b/jets-bench/benches/elements/input.rs new file mode 100644 index 00000000..e69de29b diff --git a/jets-bench/benches/elements/main.rs b/jets-bench/benches/elements/main.rs index ca7e6a41..d7509786 100644 --- a/jets-bench/benches/elements/main.rs +++ b/jets-bench/benches/elements/main.rs @@ -755,30 +755,30 @@ fn bench(c: &mut Criterion) { let ctx8 = SimplicityCtx8::with_len(511).value(); let genesis_pegin = genesis_pegin(); let outpoint = elements::OutPoint::sample().value(); - Value::prod(ctx8, Value::prod(genesis_pegin, outpoint)) + Value::product(ctx8, Value::product(genesis_pegin, outpoint)) } fn asset_amount_hash() -> Arc { let ctx8 = SimplicityCtx8::with_len(511).value(); let asset = confidential::Asset::sample().value(); let amount = confidential::Value::sample().value(); - Value::prod(ctx8, Value::prod(asset, amount)) + Value::product(ctx8, Value::product(asset, amount)) } fn nonce_hash() -> Arc { let ctx8 = SimplicityCtx8::with_len(511).value(); let nonce = confidential::Nonce::sample().value(); - Value::prod(ctx8, nonce) + Value::product(ctx8, nonce) } fn annex_hash() -> Arc { let ctx8 = SimplicityCtx8::with_len(511).value(); let annex = if rand::random() { - Value::sum_r(Value::u256_from_slice(&rand::random::<[u8; 32]>())) + Value::right(Value::u256(&rand::random::<[u8; 32]>())) } else { - Value::sum_l(Value::unit()) + Value::left(Value::unit()) }; - Value::prod(ctx8, annex) + Value::product(ctx8, annex) } let arr: [(Elements, Arc Arc>); 4] = [ (Elements::OutpointHash, Arc::new(&outpoint_hash)), diff --git a/jets-bench/src/data_structures.rs b/jets-bench/src/data_structures.rs index e51a35b5..4e299ef4 100644 --- a/jets-bench/src/data_structures.rs +++ b/jets-bench/src/data_structures.rs @@ -67,12 +67,12 @@ pub fn var_len_buf_from_slice(v: &[u8], mut n: usize) -> Result, Erro let v = if v.len() >= (1 << (n + 1)) { let ty = &types[n]; let val = iter.read_value(&ty.final_data().unwrap())?; - Value::sum_r(val) + Value::right(val) } else { - Value::sum_l(Value::unit()) + Value::left(Value::unit()) }; res = match res { - Some(prod) => Some(Value::prod(prod, v)), + Some(prod) => Some(Value::product(prod, v)), None => Some(v), }; n -= 1; @@ -164,21 +164,20 @@ impl SimplicityEncode for SimplicityCtx8 { let buf = var_len_buf_from_slice(&self.buffer[..buf_len], 8).unwrap(); let len = Value::u64(self.length as u64); // convert to 32 byte array - let arr = self - .h - .iter() - .flat_map(|x| x.to_be_bytes()) - .collect::>(); - let mid_state = Value::u256_from_slice(&arr); - Value::prod(buf, Value::prod(len, mid_state)) + let mut arr = [0u8; 32]; + for (i, byte) in self.h.iter().flat_map(|x| x.to_be_bytes()).enumerate() { + arr[i] = byte; + } + let mid_state = Value::u256(&arr); + Value::product(buf, Value::product(len, mid_state)) } } impl SimplicityEncode for elements::OutPoint { fn value(&self) -> Arc { - let txid = Value::u256_from_slice(&self.txid[..]); + let txid = Value::u256(self.txid.as_byte_array()); let vout = Value::u32(self.vout); - Value::prod(txid, vout) + Value::product(txid, vout) } } @@ -186,13 +185,15 @@ impl SimplicityEncode for elements::confidential::Asset { fn value(&self) -> Arc { match self { elements::confidential::Asset::Explicit(a) => { - Value::sum_r(Value::u256_from_slice(&a.into_inner()[..])) + Value::right(Value::u256(&a.into_inner().0)) } elements::confidential::Asset::Confidential(gen) => { - let odd_gen = gen.serialize()[0] & 1 == 1; - let x_pt = Value::u256_from_slice(&gen.serialize()[1..]); + let ser = gen.serialize(); + let odd_gen = ser[0] & 1 == 1; + let x_bytes: &[u8; 32] = (&ser[1..33]).try_into().unwrap(); + let x_pt = Value::u256(x_bytes); let y_pt = Value::u1(odd_gen as u8); - Value::sum_l(Value::prod(y_pt, x_pt)) + Value::left(Value::product(y_pt, x_pt)) } elements::confidential::Asset::Null => panic!("Tried to encode Null asset"), } @@ -202,12 +203,13 @@ impl SimplicityEncode for elements::confidential::Asset { impl SimplicityEncode for elements::confidential::Value { fn value(&self) -> Arc { match self { - elements::confidential::Value::Explicit(v) => Value::sum_r(Value::u64(*v)), + elements::confidential::Value::Explicit(v) => Value::right(Value::u64(*v)), elements::confidential::Value::Confidential(v) => { let ser = v.serialize(); - let x_pt = Value::u256_from_slice(&ser[1..]); + let x_bytes: &[u8; 32] = (&ser[1..33]).try_into().unwrap(); + let x_pt = Value::u256(x_bytes); let y_pt = Value::u1((ser[0] & 1 == 1) as u8); - Value::sum_l(Value::prod(y_pt, x_pt)) + Value::left(Value::product(y_pt, x_pt)) } elements::confidential::Value::Null => panic!("Tried to encode Null value"), } @@ -218,22 +220,23 @@ impl SimplicityEncode for elements::confidential::Nonce { fn value(&self) -> Arc { match self { elements::confidential::Nonce::Explicit(n) => { - Value::sum_r(Value::sum_r(Value::u256_from_slice(&n[..]))) + Value::right(Value::right(Value::u256(n))) } elements::confidential::Nonce::Confidential(n) => { let ser = n.serialize(); - let x_pt = Value::u256_from_slice(&ser[1..]); + let x_bytes: &[u8; 32] = (&ser[1..33]).try_into().unwrap(); + let x_pt = Value::u256(&x_bytes); let y_pt = Value::u1((ser[0] & 1 == 1) as u8); - Value::sum_r(Value::sum_l(Value::prod(y_pt, x_pt))) + Value::right(Value::left(Value::product(y_pt, x_pt))) } - elements::confidential::Nonce::Null => Value::sum_l(Value::unit()), + elements::confidential::Nonce::Null => Value::left(Value::unit()), } } } impl SimplicityEncode for SimplicityFe { fn value(&self) -> Arc { - Value::u256_from_slice(self.as_inner()) + Value::u256(self.as_inner()) } } @@ -249,9 +252,11 @@ impl SimplicityEncode for SimplicityGe { ser } }; - let x_pt = Value::u256_from_slice(&ser[1..33]); - let y_pt = Value::u256_from_slice(&ser[33..]); - Value::prod(x_pt, y_pt) + let x_bytes: &[u8; 32] = (&ser[1..33]).try_into().unwrap(); + let y_bytes: &[u8; 32] = (&ser[33..65]).try_into().unwrap(); + let x_pt = Value::u256(x_bytes); + let y_pt = Value::u256(y_bytes); + Value::product(x_pt, y_pt) } } @@ -259,22 +264,23 @@ impl SimplicityEncode for SimplicityGej { fn value(&self) -> Arc { let ge = self.ge.value(); let z = self.z.value(); - Value::prod(ge, z) + Value::product(ge, z) } } impl SimplicityEncode for SimplicityScalar { fn value(&self) -> Arc { - Value::u256_from_slice(&self.0[..]) + Value::u256(&self.0) } } impl SimplicityEncode for SimplicityPoint { fn value(&self) -> Arc { let ser = self.0.serialize(); // compressed + let x_bytes: &[u8; 32] = (&ser[1..33]).try_into().unwrap(); let y_pt = Value::u1((ser[0] & 1 == 1) as u8); - let x_pt = Value::u256_from_slice(&ser[1..]); - Value::prod(y_pt, x_pt) + let x_pt = Value::u256(x_bytes); + Value::product(y_pt, x_pt) } } @@ -403,9 +409,9 @@ impl BenchSample for SimplicityPoint { // Sample genesis pegin with 50% probability pub fn genesis_pegin() -> Arc { if rand::random() { - Value::sum_l(Value::unit()) + Value::left(Value::unit()) } else { let genesis_hash = rand::random::<[u8; 32]>(); - Value::sum_r(Value::u256_from_slice(&genesis_hash[..])) + Value::right(Value::u256(&genesis_hash)) } } diff --git a/jets-bench/src/input.rs b/jets-bench/src/input.rs index 0c43076d..2a04a325 100644 --- a/jets-bench/src/input.rs +++ b/jets-bench/src/input.rs @@ -42,16 +42,16 @@ pub fn random_value(ty: &types::Final, rng: &mut ThreadRng) -> Arc { }, StackItem::LeftSum => { let left = value_stack.pop().unwrap(); - value_stack.push(Value::sum_l(left)); + value_stack.push(Value::left(left)); } StackItem::RightSum => { let right = value_stack.pop().unwrap(); - value_stack.push(Value::sum_r(right)); + value_stack.push(Value::right(right)); } StackItem::Product => { let right = value_stack.pop().unwrap(); let left = value_stack.pop().unwrap(); - value_stack.push(Value::prod(left, right)); + value_stack.push(Value::product(left, right)); } } } diff --git a/src/bit_encoding/bititer.rs b/src/bit_encoding/bititer.rs index b012df1b..27c529fa 100644 --- a/src/bit_encoding/bititer.rs +++ b/src/bit_encoding/bititer.rs @@ -252,16 +252,16 @@ impl> BitIter { }, State::DoSumL => { let val = result_stack.pop().unwrap(); - result_stack.push(Value::sum_l(val)); + result_stack.push(Value::left(val)); } State::DoSumR => { let val = result_stack.pop().unwrap(); - result_stack.push(Value::sum_r(val)); + result_stack.push(Value::right(val)); } State::DoProduct => { let val_r = result_stack.pop().unwrap(); let val_l = result_stack.pop().unwrap(); - result_stack.push(Value::prod(val_l, val_r)); + result_stack.push(Value::product(val_l, val_r)); } } } diff --git a/src/bit_encoding/decode.rs b/src/bit_encoding/decode.rs index 65c937ec..d6042daf 100644 --- a/src/bit_encoding/decode.rs +++ b/src/bit_encoding/decode.rs @@ -347,7 +347,7 @@ pub fn decode_power_of_2>( let right = stack.pop().unwrap(); let left = stack.pop().unwrap(); stack.push(StackElem { - value: Value::prod(left.value, right.value), + value: Value::product(left.value, right.value), width: left.width * 2, }); } diff --git a/src/bit_encoding/encode.rs b/src/bit_encoding/encode.rs index 1f3b0f2a..daeec0b8 100644 --- a/src/bit_encoding/encode.rs +++ b/src/bit_encoding/encode.rs @@ -291,15 +291,15 @@ pub fn encode_value(value: &Value, w: &mut BitWriter) -> io::Re match value { Value::Unit => {} - Value::SumL(left) => { + Value::Left(left) => { w.write_bit(false)?; encode_value(left, w)?; } - Value::SumR(right) => { + Value::Right(right) => { w.write_bit(true)?; encode_value(right, w)?; } - Value::Prod(left, right) => { + Value::Product(left, right) => { encode_value(left, w)?; encode_value(right, w)?; } diff --git a/src/bit_machine/mod.rs b/src/bit_machine/mod.rs index 9d13c7c0..4edf10b4 100644 --- a/src/bit_machine/mod.rs +++ b/src/bit_machine/mod.rs @@ -175,9 +175,9 @@ impl BitMachine { for val in val.pre_order_iter::() { match val { Value::Unit => {} - Value::SumL(..) => self.write_bit(false), - Value::SumR(..) => self.write_bit(true), - Value::Prod(..) => {} + Value::Left(..) => self.write_bit(false), + Value::Right(..) => self.write_bit(true), + Value::Product(..) => {} } } } diff --git a/src/human_encoding/serialize.rs b/src/human_encoding/serialize.rs index 7e87b387..653208e2 100644 --- a/src/human_encoding/serialize.rs +++ b/src/human_encoding/serialize.rs @@ -21,8 +21,8 @@ impl<'a> fmt::Display for DisplayWord<'a> { f.write_str("0b")?; for comb in self.0.pre_order_iter::() { match comb { - Value::SumL(..) => f.write_str("0")?, - Value::SumR(..) => f.write_str("1")?, + Value::Left(..) => f.write_str("0")?, + Value::Right(..) => f.write_str("1")?, _ => {} } } diff --git a/src/jet/mod.rs b/src/jet/mod.rs index 32cd28b0..705ce8aa 100644 --- a/src/jet/mod.rs +++ b/src/jet/mod.rs @@ -111,7 +111,7 @@ mod tests { .unwrap(); assert_eq!( BitMachine::test_exec(two_words, &()).expect("executing"), - Value::prod( + Value::product( Value::u1(0), // carry bit Value::u32(2 + 16), // result ), @@ -128,7 +128,7 @@ mod tests { .unwrap(); assert_eq!( BitMachine::test_exec(two_words, &()).expect("executing"), - Value::prod(Value::u32(2), Value::u16(16)), + Value::product(Value::u32(2), Value::u16(16)), ); } } diff --git a/src/merkle/cmr.rs b/src/merkle/cmr.rs index 9093ac18..7e088f5a 100644 --- a/src/merkle/cmr.rs +++ b/src/merkle/cmr.rs @@ -422,7 +422,7 @@ mod tests { #[test] fn fixed_const_word_cmr() { // Checked against C implementation - let bit0 = Value::sum_l(Value::unit()); + let bit0 = Value::left(Value::unit()); #[rustfmt::skip] assert_eq!( Cmr::const_word(&bit0), diff --git a/src/node/mod.rs b/src/node/mod.rs index ed26544a..056347e6 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -190,15 +190,15 @@ pub trait CoreConstructible: Sized { for data in value.post_order_iter::() { match data.node { Value::Unit => stack.push(Self::unit(inference_context)), - Value::SumL(..) => { + Value::Left(..) => { let child = stack.pop().unwrap(); stack.push(Self::injl(&child)); } - Value::SumR(..) => { + Value::Right(..) => { let child = stack.pop().unwrap(); stack.push(Self::injr(&child)); } - Value::Prod(..) => { + Value::Product(..) => { let right = stack.pop().unwrap(); let left = stack.pop().unwrap(); stack.push( diff --git a/src/policy/satisfy.rs b/src/policy/satisfy.rs index 94d43be2..dcd0f912 100644 --- a/src/policy/satisfy.rs +++ b/src/policy/satisfy.rs @@ -105,7 +105,7 @@ impl Policy { Policy::Key(ref key) => { let sig_wit = satisfier .lookup_tap_leaf_script_sig(key, &TapLeafHash::all_zeros()) - .map(|sig| Value::u512_from_slice(sig.sig.as_ref())); + .map(|sig| Value::u512(sig.sig.as_ref())); super::serialize::key(inference_context, key, sig_wit) } Policy::After(n) => { @@ -128,7 +128,7 @@ impl Policy { Policy::Sha256(ref hash) => { let preimage_wit = satisfier .lookup_sha256(hash) - .map(|preimage| Value::u256_from_slice(preimage.as_ref())); + .map(|preimage| Value::u256(&preimage)); super::serialize::sha256::(inference_context, hash, preimage_wit) } Policy::And { diff --git a/src/policy/serialize.rs b/src/policy/serialize.rs index 2c586657..10c3db13 100644 --- a/src/policy/serialize.rs +++ b/src/policy/serialize.rs @@ -54,7 +54,7 @@ where Pk: ToXOnlyPubkey, N: CoreConstructible + JetConstructible + WitnessConstructible, { - let key_value = Value::u256_from_slice(&key.to_x_only_pubkey().serialize()); + let key_value = Value::u256(&key.to_x_only_pubkey().serialize()); let const_key = N::const_word(inference_context, key_value); let sighash_all = N::jet(inference_context, Elements::SigAllHash); let pair_key_msg = N::pair(&const_key, &sighash_all).expect("consistent types"); @@ -118,7 +118,7 @@ where Pk: ToXOnlyPubkey, N: CoreConstructible + JetConstructible + WitnessConstructible, { - let hash_value = Value::u256_from_slice(Pk::to_sha256(hash).as_ref()); + let hash_value = Value::u256(Pk::to_sha256(hash).as_ref()); let const_hash = N::const_word(inference_context, hash_value); let witness256 = N::witness(inference_context, witness); let computed_hash = compute_sha256(&witness256); @@ -320,7 +320,7 @@ mod tests { assert!(execute_successful( &commit, - vec![Value::u512_from_slice(signature.as_ref())], + vec![Value::u512(signature.as_ref())], &env )); } @@ -376,10 +376,10 @@ mod tests { let image = sha256::Hash::hash(&preimage); let (commit, env) = compile(Policy::Sha256(image)); - let valid_witness = vec![Value::u256_from_slice(&preimage)]; + let valid_witness = vec![Value::u256(&preimage)]; assert!(execute_successful(&commit, valid_witness, &env)); - let invalid_witness = vec![Value::u256_from_slice(&[0; 32])]; + let invalid_witness = vec![Value::u256(&[0; 32])]; assert!(!execute_successful(&commit, invalid_witness, &env)); } @@ -395,22 +395,13 @@ mod tests { right: Arc::new(Policy::Sha256(image1)), }); - let valid_witness = vec![ - Value::u256_from_slice(&preimage0), - Value::u256_from_slice(&preimage1), - ]; + let valid_witness = vec![Value::u256(&preimage0), Value::u256(&preimage1)]; assert!(execute_successful(&commit, valid_witness, &env)); - let invalid_witness = vec![ - Value::u256_from_slice(&preimage0), - Value::u256_from_slice(&[0; 32]), - ]; + let invalid_witness = vec![Value::u256(&preimage0), Value::u256(&[0; 32])]; assert!(!execute_successful(&commit, invalid_witness, &env)); - let invalid_witness = vec![ - Value::u256_from_slice(&[0; 32]), - Value::u256_from_slice(&preimage1), - ]; + let invalid_witness = vec![Value::u256(&[0; 32]), Value::u256(&preimage1)]; assert!(!execute_successful(&commit, invalid_witness, &env)); } @@ -424,10 +415,10 @@ mod tests { right: Arc::new(Policy::Trivial), }); - let valid_witness = vec![Value::u256_from_slice(&preimage0)]; + let valid_witness = vec![Value::u256(&preimage0)]; assert!(execute_successful(&commit, valid_witness, &env)); - let invalid_witness = vec![Value::u256_from_slice(&[0; 32])]; + let invalid_witness = vec![Value::u256(&[0; 32])]; assert!(!execute_successful(&commit, invalid_witness, &env)); } @@ -443,30 +434,14 @@ mod tests { right: Arc::new(Policy::Sha256(image1)), }); - let valid_witness = vec![ - Value::u1(0), - Value::u256_from_slice(&preimage0), - Value::u256_from_slice(&[0; 32]), - ]; + let valid_witness = vec![Value::u1(0), Value::u256(&preimage0), Value::u256(&[0; 32])]; assert!(execute_successful(&commit, valid_witness, &env)); - let valid_witness = vec![ - Value::u1(1), - Value::u256_from_slice(&[0; 32]), - Value::u256_from_slice(&preimage1), - ]; + let valid_witness = vec![Value::u1(1), Value::u256(&[0; 32]), Value::u256(&preimage1)]; assert!(execute_successful(&commit, valid_witness, &env)); - let invalid_witness = vec![ - Value::u1(0), - Value::u256_from_slice(&[0; 32]), - Value::u256_from_slice(&preimage1), - ]; + let invalid_witness = vec![Value::u1(0), Value::u256(&[0; 32]), Value::u256(&preimage1)]; assert!(!execute_successful(&commit, invalid_witness, &env)); - let invalid_witness = vec![ - Value::u1(1), - Value::u256_from_slice(&preimage0), - Value::u256_from_slice(&[0; 32]), - ]; + let invalid_witness = vec![Value::u1(1), Value::u256(&preimage0), Value::u256(&[0; 32])]; assert!(!execute_successful(&commit, invalid_witness, &env)); } @@ -490,61 +465,61 @@ mod tests { let valid_witness = vec![ Value::u1(1), - Value::u256_from_slice(&preimage0), + Value::u256(&preimage0), Value::u1(1), - Value::u256_from_slice(&preimage1), + Value::u256(&preimage1), Value::u1(0), - Value::u256_from_slice(&[0; 32]), + Value::u256(&[0; 32]), ]; assert!(execute_successful(&commit, valid_witness, &env)); let valid_witness = vec![ Value::u1(1), - Value::u256_from_slice(&preimage0), + Value::u256(&preimage0), Value::u1(0), - Value::u256_from_slice(&[0; 32]), + Value::u256(&[0; 32]), Value::u1(1), - Value::u256_from_slice(&preimage2), + Value::u256(&preimage2), ]; assert!(execute_successful(&commit, valid_witness, &env)); let valid_witness = vec![ Value::u1(0), - Value::u256_from_slice(&[0; 32]), + Value::u256(&[0; 32]), Value::u1(1), - Value::u256_from_slice(&preimage1), + Value::u256(&preimage1), Value::u1(1), - Value::u256_from_slice(&preimage2), + Value::u256(&preimage2), ]; assert!(execute_successful(&commit, valid_witness, &env)); let invalid_witness = vec![ Value::u1(1), - Value::u256_from_slice(&preimage0), + Value::u256(&preimage0), Value::u1(1), - Value::u256_from_slice(&preimage1), + Value::u256(&preimage1), Value::u1(1), - Value::u256_from_slice(&preimage2), + Value::u256(&preimage2), ]; assert!(!execute_successful(&commit, invalid_witness, &env)); let invalid_witness = vec![ Value::u1(1), - Value::u256_from_slice(&preimage1), + Value::u256(&preimage1), Value::u1(1), - Value::u256_from_slice(&preimage0), + Value::u256(&preimage0), Value::u1(0), - Value::u256_from_slice(&[0; 32]), + Value::u256(&[0; 32]), ]; assert!(!execute_successful(&commit, invalid_witness, &env)); let invalid_witness = vec![ Value::u1(1), - Value::u256_from_slice(&preimage0), + Value::u256(&preimage0), Value::u1(0), - Value::u256_from_slice(&[0; 32]), + Value::u256(&[0; 32]), Value::u1(0), - Value::u256_from_slice(&[0; 32]), + Value::u256(&[0; 32]), ]; assert!(!execute_successful(&commit, invalid_witness, &env)); } diff --git a/src/value.rs b/src/value.rs index 4e2ca079..8b95dfa5 100644 --- a/src/value.rs +++ b/src/value.rs @@ -9,42 +9,34 @@ use crate::dag::{Dag, DagLike, NoSharing}; use crate::types::Final; use std::collections::VecDeque; -use std::convert::TryInto; use std::fmt; use std::hash::Hash; use std::sync::Arc; -/// Value of some type. -/// -/// The _unit value_ is the only value of the _unit type_. -/// This is the basis for everything we are doing. -/// Because there is only a single unit value, there is no information contained in it. -/// Instead, we wrap unit values in sum and product values to encode information. -/// -/// A _sum value_ wraps another value. -/// The _left sum value_ `L(a)` wraps a value `a` from the _left type_ `A`. -/// The _right sum value_ `R(b)` wraps a value `b` from the _right type_ `B`. -/// The type of the sum value is the _sum type_ `A + B` of the left type and the right type. -/// -/// We represent the false bit as a left value that wraps a unit value. -/// The true bit is represented as a right value that wraps a unit value. -/// -/// A _product value_ `(a, b)` wraps two values: -/// a value `a` from the _left type_ `A` and a value `b` from the _right type_ `B`. -/// The type of the product value is the _product type_ `A × B` of the left type and the right type. -/// -/// We represent bit strings (tuples of bits) as trees of nested product values -/// that have bit values (sum values wrapping the unit value) at their leaves. +/// A Simplicity value. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Value { - /// Unit value + /// The unit value. + /// + /// The unit value is the only value of the unit type `1`. + /// It must be wrapped in left and right values to encode information. Unit, - /// Sum value that wraps a left value - SumL(Arc), - /// Sum value that wraps a right value - SumR(Arc), - /// Product value that wraps a left and a right value - Prod(Arc, Arc), + /// A left value. + /// + /// A left value wraps a value of type `A` and its type is the sum `A + B` for some `B`. + /// A `false` bit encodes that a left value is wrapped. + Left(Arc), + /// A right value. + /// + /// A right value wraps a value of type `B` and its type is the sum `A + B` for some `A`. + /// A `true` bit encodes that a right value is wrapped. + Right(Arc), + /// A product value. + /// + /// A product value wraps a left value of type `A` and a right value of type `B`, + /// and its type is the product `A × B`. + /// A product value combines the information of its inner values. + Product(Arc, Arc), } impl<'a> DagLike for &'a Value { @@ -57,8 +49,8 @@ impl<'a> DagLike for &'a Value { fn as_dag_node(&self) -> Dag { match self { Value::Unit => Dag::Nullary, - Value::SumL(child) | Value::SumR(child) => Dag::Unary(child), - Value::Prod(left, right) => Dag::Binary(left, right), + Value::Left(child) | Value::Right(child) => Dag::Unary(child), + Value::Product(left, right) => Dag::Binary(left, right), } } } @@ -69,25 +61,25 @@ impl Value { Arc::new(Self::Unit) } - /// Create a sum value that wraps a left value. - pub fn sum_l(left: Arc) -> Arc { - Arc::new(Value::SumL(left)) + /// Create a left value that wraps the given `inner` value. + pub fn left(inner: Arc) -> Arc { + Arc::new(Value::Left(inner)) } - /// Create a sum value that wraps a right value. - pub fn sum_r(right: Arc) -> Arc { - Arc::new(Value::SumR(right)) + /// Create a right value that wraps the given `inner` value. + pub fn right(inner: Arc) -> Arc { + Arc::new(Value::Right(inner)) } - /// Create a product value that wraps a left and a right value. - pub fn prod(left: Arc, right: Arc) -> Arc { - Arc::new(Value::Prod(left, right)) + /// Create a product value that wraps the given `left` and `right` values. + pub fn product(left: Arc, right: Arc) -> Arc { + Arc::new(Value::Product(left, right)) } /// The length, in bits, of the value when encoded in the Bit Machine pub fn len(&self) -> usize { self.pre_order_iter::() - .filter(|inner| matches!(inner, Value::SumL(_) | Value::SumR(_))) + .filter(|inner| matches!(inner, Value::Left(_) | Value::Right(_))) .count() } @@ -105,7 +97,7 @@ impl Value { /// Access the inner value of a left sum value. pub fn as_left(&self) -> Option<&Self> { match self { - Value::SumL(inner) => Some(inner.as_ref()), + Value::Left(inner) => Some(inner.as_ref()), _ => None, } } @@ -113,7 +105,7 @@ impl Value { /// Access the inner value of a right sum value. pub fn as_right(&self) -> Option<&Self> { match self { - Value::SumR(inner) => Some(inner.as_ref()), + Value::Right(inner) => Some(inner.as_ref()), _ => None, } } @@ -121,7 +113,7 @@ impl Value { /// Access the inner values of a product value. pub fn as_product(&self) -> Option<(&Self, &Self)> { match self { - Value::Prod(left, right) => Some((left.as_ref(), right.as_ref())), + Value::Product(left, right) => Some((left.as_ref(), right.as_ref())), _ => None, } } @@ -129,8 +121,8 @@ impl Value { /// Encode a single bit as a value. Will panic if the input is out of range pub fn u1(n: u8) -> Arc { match n { - 0 => Value::sum_l(Value::unit()), - 1 => Value::sum_r(Value::unit()), + 0 => Value::left(Value::unit()), + 1 => Value::right(Value::unit()), x => panic!("{} out of range for Value::u1", x), } } @@ -140,7 +132,7 @@ impl Value { let b0 = (n & 2) / 2; let b1 = n & 1; assert!(n <= 3, "{} out of range for Value::u2", n); - Value::prod(Value::u1(b0), Value::u1(b1)) + Value::product(Value::u1(b0), Value::u1(b1)) } /// Encode a four-bit number as a value. Will panic if the input is out of range @@ -148,77 +140,59 @@ impl Value { let w0 = (n & 12) / 4; let w1 = n & 3; assert!(n <= 15, "{} out of range for Value::u2", n); - Value::prod(Value::u2(w0), Value::u2(w1)) + Value::product(Value::u2(w0), Value::u2(w1)) } /// Encode an eight-bit number as a value pub fn u8(n: u8) -> Arc { let w0 = n >> 4; let w1 = n & 0xf; - Value::prod(Value::u4(w0), Value::u4(w1)) + Value::product(Value::u4(w0), Value::u4(w1)) } /// Encode a 16-bit number as a value pub fn u16(n: u16) -> Arc { let w0 = (n >> 8) as u8; let w1 = (n & 0xff) as u8; - Value::prod(Value::u8(w0), Value::u8(w1)) + Value::product(Value::u8(w0), Value::u8(w1)) } /// Encode a 32-bit number as a value pub fn u32(n: u32) -> Arc { let w0 = (n >> 16) as u16; let w1 = (n & 0xffff) as u16; - Value::prod(Value::u16(w0), Value::u16(w1)) + Value::product(Value::u16(w0), Value::u16(w1)) } /// Encode a 64-bit number as a value pub fn u64(n: u64) -> Arc { let w0 = (n >> 32) as u32; let w1 = (n & 0xffff_ffff) as u32; - Value::prod(Value::u32(w0), Value::u32(w1)) + Value::product(Value::u32(w0), Value::u32(w1)) } /// Encode a 128-bit number as a value pub fn u128(n: u128) -> Arc { let w0 = (n >> 64) as u64; let w1 = n as u64; // Cast safety: picking last 64 bits - Value::prod(Value::u64(w0), Value::u64(w1)) + Value::product(Value::u64(w0), Value::u64(w1)) } - /// Encode a 32-byte number as a value - /// - /// Useful for encoding public keys and hashes - pub fn u256_from_slice(v: &[u8]) -> Arc { - assert_eq!(32, v.len(), "Expect 32-byte slice"); - - Value::prod( - Value::prod( - Value::u64(u64::from_be_bytes(v[0..8].try_into().unwrap())), - Value::u64(u64::from_be_bytes(v[8..16].try_into().unwrap())), - ), - Value::prod( - Value::u64(u64::from_be_bytes(v[16..24].try_into().unwrap())), - Value::u64(u64::from_be_bytes(v[24..32].try_into().unwrap())), - ), - ) + /// Create a value from 32 bytes. + pub fn u256(bytes: &[u8; 32]) -> Arc { + Value::power_of_two(bytes) } - /// Encode a 64-byte number as a value - /// - /// Useful for encoding signatures - pub fn u512_from_slice(v: &[u8]) -> Arc { - assert_eq!(64, v.len(), "Expect 64-byte slice"); - - Value::prod( - Value::u256_from_slice(&v[0..32]), - Value::u256_from_slice(&v[32..64]), - ) + /// Create a value from 64 bytes. + pub fn u512(bytes: &[u8; 64]) -> Arc { + Value::power_of_two(bytes) } - /// Encode a byte slice as a value. + /// Create a value from a byte slice. /// - /// The length of the slice must be a power of two. + /// ## Panics + /// + /// The length of the slice is not a power of two. pub fn power_of_two(v: &[u8]) -> Arc { assert!( v.len().is_power_of_two(), @@ -230,7 +204,7 @@ impl Value { let mut alt_values = VecDeque::with_capacity(values.len() / 2); while let (Some(left), Some(right)) = (values.pop_front(), values.pop_front()) { - alt_values.push_back(Value::prod(left, right)); + alt_values.push_back(Value::product(left, right)); } values = alt_values; @@ -247,9 +221,9 @@ impl Value { for val in self.pre_order_iter::() { match val { Value::Unit => {} - Value::SumL(..) => f(false), - Value::SumR(..) => f(true), - Value::Prod(..) => {} + Value::Left(..) => f(false), + Value::Right(..) => f(true), + Value::Product(..) => {} } } } @@ -343,22 +317,22 @@ impl fmt::Display for Value { match data.node { Value::Unit => { if data.n_children_yielded == 0 - && !matches!(data.parent, Some(Value::SumL(_)) | Some(Value::SumR(_))) + && !matches!(data.parent, Some(Value::Left(_)) | Some(Value::Right(_))) { f.write_str("ε")?; } } - Value::SumL(..) => { + Value::Left(..) => { if data.n_children_yielded == 0 { f.write_str("0")?; } } - Value::SumR(..) => { + Value::Right(..) => { if data.n_children_yielded == 0 { f.write_str("1")?; } } - Value::Prod(..) => match data.n_children_yielded { + Value::Product(..) => match data.n_children_yielded { 0 => f.write_str("(")?, 1 => f.write_str(",")?, 2 => f.write_str(")")?, @@ -388,11 +362,14 @@ mod tests { fn is_of_type() { let value_typename = [ (Value::unit(), TypeName(b"1")), - (Value::sum_l(Value::unit()), TypeName(b"+11")), - (Value::sum_r(Value::unit()), TypeName(b"+11")), - (Value::sum_l(Value::unit()), TypeName(b"+1h")), - (Value::sum_r(Value::unit()), TypeName(b"+h1")), - (Value::prod(Value::unit(), Value::unit()), TypeName(b"*11")), + (Value::left(Value::unit()), TypeName(b"+11")), + (Value::right(Value::unit()), TypeName(b"+11")), + (Value::left(Value::unit()), TypeName(b"+1h")), + (Value::right(Value::unit()), TypeName(b"+h1")), + ( + Value::product(Value::unit(), Value::unit()), + TypeName(b"*11"), + ), (Value::u8(u8::MAX), TypeName(b"c")), (Value::u64(u64::MAX), TypeName(b"l")), ];