diff --git a/crates/uplc/src/builtins.rs b/crates/uplc/src/builtins.rs index 4464b312..8ac00744 100644 --- a/crates/uplc/src/builtins.rs +++ b/crates/uplc/src/builtins.rs @@ -394,7 +394,7 @@ impl FromStr for DefaultFunction { "rotateByteString" => Ok(RotateByteString), "countSetBits" => Ok(CountSetBits), "findFirstSetBit" => Ok(FindFirstSetBit), - "ripemd160" => Ok(Ripemd_160), + "ripemd_160" => Ok(Ripemd_160), "expModInteger" => Ok(ExpModInteger), // "caseList" => Ok(CaseList), // "caseData" => Ok(CaseData), @@ -494,7 +494,7 @@ impl Display for DefaultFunction { RotateByteString => write!(f, "rotateByteString"), CountSetBits => write!(f, "countSetBits"), FindFirstSetBit => write!(f, "findFirstSetBit"), - Ripemd_160 => write!(f, "ripemd160"), + Ripemd_160 => write!(f, "ripemd_160"), ExpModInteger => write!(f, "expModInteger"), // CaseList => write!(f, "caseList"), // CaseData => write!(f, "caseData"), @@ -593,7 +593,7 @@ impl DefaultFunction { RotateByteString => "rotate_bytearray", CountSetBits => "count_set_bits", FindFirstSetBit => "find_first_set_bit", - Ripemd_160 => "ripemd160", + Ripemd_160 => "ripemd_160", ExpModInteger => "exp_mod_integer", // CaseList => "case_list", // CaseData => "case_data", diff --git a/crates/uplc/src/machine/cost_model.rs b/crates/uplc/src/machine/cost_model.rs index 22e2e016..ebb4cf88 100644 --- a/crates/uplc/src/machine/cost_model.rs +++ b/crates/uplc/src/machine/cost_model.rs @@ -2,7 +2,7 @@ use super::{value::integer_log2, Error, Value}; use crate::builtins::DefaultFunction; use num_traits::Signed; use pallas_primitives::conway::Language; -use std::collections::HashMap; +use std::{collections::HashMap, i64}; macro_rules! hashmap { // map-like @@ -2641,7 +2641,10 @@ impl BuiltinCosts { DefaultFunction::ShiftByteString => { let literal = args[1].unwrap_integer()?; - let arg1: i64 = u64::try_from(literal.abs()).unwrap().try_into().unwrap(); + let arg1: i64 = u64::try_from(literal.abs()) + .unwrap() + .try_into() + .unwrap_or(i64::MAX); ExBudget { mem: self.shift_byte_string.mem.cost(args[0].to_ex_mem(), arg1), @@ -2651,7 +2654,10 @@ impl BuiltinCosts { DefaultFunction::RotateByteString => { let literal = args[1].unwrap_integer()?; - let arg1: i64 = u64::try_from(literal.abs()).unwrap().try_into().unwrap(); + let arg1: i64 = u64::try_from(literal.abs()) + .unwrap() + .try_into() + .unwrap_or(i64::MAX); ExBudget { mem: self.rotate_byte_string.mem.cost(args[0].to_ex_mem(), arg1), diff --git a/crates/uplc/src/machine/error.rs b/crates/uplc/src/machine/error.rs index 98278453..5c132bb5 100644 --- a/crates/uplc/src/machine/error.rs +++ b/crates/uplc/src/machine/error.rs @@ -75,6 +75,8 @@ pub enum Error { MachineNeverReachedDone, #[error("integerToByteString encountered negative size\n{:>13} {0}", "Size")] IntegerToByteStringNegativeSize(BigInt), + #[error("replicateByte encountered negative size\n{:>13} {0}", "Size")] + ReplicateByteNegativeSize(BigInt), #[error("integerToByteString encountered negative input\n{:>13} {0}", "Input")] IntegerToByteStringNegativeInput(BigInt), #[error( @@ -83,6 +85,12 @@ pub enum Error { "Maximum" )] IntegerToByteStringSizeTooBig(BigInt, i64), + #[error( + "bytes size beyond limit when replicate byte\n{:>13} {0}\n{:>13} {1}", + "Size", + "Maximum" + )] + ReplicateByteSizeTooBig(BigInt, i64), #[error( "bytes size below limit when converting from integer\n{:>13} {0}\n{:>13} {1}", "Size", diff --git a/crates/uplc/src/machine/runtime.rs b/crates/uplc/src/machine/runtime.rs index 12f6c86c..6de90f48 100644 --- a/crates/uplc/src/machine/runtime.rs +++ b/crates/uplc/src/machine/runtime.rs @@ -9,7 +9,7 @@ use crate::{ machine::value::integer_log2, plutus_data_to_bytes, }; -use bitvec::{order::Lsb0, vec::BitVec}; +use bitvec::{order::Msb0, vec::BitVec}; use itertools::Itertools; use num_bigint::BigInt; use num_integer::Integer; @@ -1629,7 +1629,7 @@ impl DefaultFunction { let flipped_index = bytes.len() - 1 - usize::try_from(byte_index).unwrap(); - let bit_mask: u8 = 1 >> bit_offset; + let bit_mask: u8 = 1 << bit_offset; if *set_bit { bytes[flipped_index] |= bit_mask; @@ -1654,7 +1654,7 @@ impl DefaultFunction { let value = if size == 0 { Value::byte_string(vec![]) } else { - Value::byte_string([byte].repeat(size - 1)) + Value::byte_string([byte].repeat(size)) }; Ok(value) @@ -1673,7 +1673,7 @@ impl DefaultFunction { let is_shl = shift >= &0.into(); - let mut bv = BitVec::::from_vec(bytes.clone()); + let mut bv = BitVec::::from_vec(bytes.clone()); if is_shl { bv.shift_left(usize::try_from(shift.abs()).unwrap()); @@ -1689,11 +1689,15 @@ impl DefaultFunction { let byte_length = bytes.len(); - let shift = shift % byte_length; + if bytes.is_empty() { + return Ok(Value::byte_string(bytes.clone())); + } - let mut bv = BitVec::::from_vec(bytes.clone()); + let shift = shift.mod_floor(&(byte_length * 8).into()); - bv.rotate_right(usize::try_from(shift).unwrap()); + let mut bv = BitVec::::from_vec(bytes.clone()); + + bv.rotate_left(usize::try_from(shift).unwrap()); Ok(Value::byte_string(bv.into_vec())) } @@ -1713,21 +1717,21 @@ impl DefaultFunction { .find_map(|(byte_index, value)| { let value = value.reverse_bits(); - let first_bit: Option = if value > 128 { + let first_bit: Option = if value >= 128 { Some(0) - } else if value > 64 { + } else if value >= 64 { Some(1) - } else if value > 32 { + } else if value >= 32 { Some(2) - } else if value > 16 { + } else if value >= 16 { Some(3) - } else if value > 8 { + } else if value >= 8 { Some(4) - } else if value > 4 { + } else if value >= 4 { Some(5) - } else if value > 2 { + } else if value >= 2 { Some(6) - } else if value > 1 { + } else if value >= 1 { Some(7) } else { None diff --git a/crates/uplc/src/machine/value.rs b/crates/uplc/src/machine/value.rs index d4df0f94..a868e9fe 100644 --- a/crates/uplc/src/machine/value.rs +++ b/crates/uplc/src/machine/value.rs @@ -232,7 +232,7 @@ impl Value { DefaultFunction::IntegerToByteString => { Error::IntegerToByteStringNegativeSize(size.clone()) } - DefaultFunction::ReplicateByte => todo!(), + DefaultFunction::ReplicateByte => Error::ReplicateByteNegativeSize(size.clone()), _ => unreachable!(), }; return Err(error); @@ -244,7 +244,10 @@ impl Value { size.clone(), runtime::INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH, ), - DefaultFunction::ReplicateByte => todo!(), + DefaultFunction::ReplicateByte => Error::ReplicateByteSizeTooBig( + size.clone(), + runtime::INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH, + ), _ => unreachable!(), }; return Err(error);