12345678910111213141516171819use core::{any::type_name, ops::Range};2021use sp_core::{H160, H256, U256};22use sp_std::{borrow::ToOwned, convert::TryInto, vec, vec::Vec};2324use super::{EvmResult, Gasometer};2526272829#[derive(Clone, Copy, Debug, Eq, PartialEq)]30pub struct Address(pub H160);3132impl From<H160> for Address {33 fn from(a: H160) -> Address {34 Address(a)35 }36}3738impl From<Address> for H160 {39 fn from(a: Address) -> H160 {40 a.041 }42}4344454647#[derive(Clone, Debug, Eq, PartialEq)]48pub struct Bytes(pub Vec<u8>);4950impl From<&[u8]> for Bytes {51 fn from(a: &[u8]) -> Self {52 Self(a.to_owned())53 }54}5556impl From<&str> for Bytes {57 fn from(a: &str) -> Self {58 a.as_bytes().into()59 }60}6162impl Into<Vec<u8>> for Bytes {63 fn into(self) -> Vec<u8> {64 self.065 }66}67686970#[derive(Clone, Copy, Debug)]71pub struct EvmDataReader<'a> {72 input: &'a [u8],73 cursor: usize,74}7576impl<'a> EvmDataReader<'a> {77 78 pub fn new(input: &'a [u8]) -> Self {79 Self { input, cursor: 0 }80 }8182 83 pub fn new_with_selector<T>(gasometer: &Gasometer, input: &'a [u8]) -> EvmResult<(Self, T)>84 where85 T: num_enum::TryFromPrimitive<Primitive = u32>,86 {87 if input.len() < 4 {88 return Err(gasometer.revert("tried to parse selector out of bounds"));89 }9091 let mut buffer = [0u8; 4];92 buffer.copy_from_slice(&input[0..4]);93 let selector = T::try_from_primitive(u32::from_be_bytes(buffer)).map_err(|_| {94 log::trace!(95 target: "precompile-utils",96 "Failed to match function selector for {}",97 type_name::<T>()98 );99 gasometer.revert("unknown selector")100 })?;101102 Ok((Self::new(&input[4..]), selector))103 }104105 106 pub fn expect_arguments(&self, gasometer: &Gasometer, args: usize) -> EvmResult {107 if self.input.len() >= self.cursor + args * 32 {108 Ok(())109 } else {110 Err(gasometer.revert("input doesn't match expected length"))111 }112 }113114 115 116 117 pub fn read<T: EvmData>(&mut self, gasometer: &Gasometer) -> EvmResult<T> {118 T::read(self, gasometer)119 }120121 122 pub fn read_pointer(&mut self, gasometer: &Gasometer) -> EvmResult<Self> {123 let offset: usize = self124 .read::<U256>(gasometer)125 .map_err(|_| gasometer.revert("tried to parse array offset out of bounds"))?126 .try_into()127 .map_err(|_| gasometer.revert("array offset is too large"))?;128129 if offset >= self.input.len() {130 return Err(gasometer.revert("pointer points out of bounds"));131 }132133 Ok(Self {134 input: &self.input[offset..],135 cursor: 0,136 })137 }138139 140 141 142 fn move_cursor(&mut self, gasometer: &Gasometer, len: usize) -> EvmResult<Range<usize>> {143 let start = self.cursor;144 let end = self145 .cursor146 .checked_add(len)147 .ok_or_else(|| gasometer.revert("data reading cursor overflow"))?;148149 self.cursor = end;150151 Ok(start..end)152 }153}154155156157158159160161#[derive(Clone, Debug)]162pub struct EvmDataWriter {163 pub(crate) data: Vec<u8>,164 offset_data: Vec<OffsetDatum>,165 selector: Option<u32>,166}167168#[derive(Clone, Debug)]169struct OffsetDatum {170 171 offset_position: usize,172 173 data: Vec<u8>,174 175 176 offset_shift: usize,177}178179impl EvmDataWriter {180 181 pub fn new() -> Self {182 Self {183 data: vec![],184 offset_data: vec![],185 selector: None,186 }187 }188189 190 pub fn build(mut self) -> Vec<u8> {191 Self::bake_offsets(&mut self.data, self.offset_data);192193 if let Some(selector) = self.selector {194 let mut output = selector.to_be_bytes().to_vec();195 output.append(&mut self.data);196 output197 } else {198 self.data199 }200 }201202 203 fn bake_offsets(output: &mut Vec<u8>, offsets: Vec<OffsetDatum>) {204 for mut offset_datum in offsets {205 let offset_position = offset_datum.offset_position;206 let offset_position_end = offset_position + 32;207208 209 210 211 212 213 let free_space_offset = output.len() - offset_datum.offset_shift;214215 216 U256::from(free_space_offset)217 .to_big_endian(&mut output[offset_position..offset_position_end]);218219 220 output.append(&mut offset_datum.data);221 }222 }223224 225 226 fn write_raw_bytes(mut self, value: &[u8]) -> Self {227 self.data.extend_from_slice(value);228 self229 }230231 232 pub fn write<T: EvmData>(mut self, value: T) -> Self {233 T::write(&mut self, value);234 self235 }236237 238 239 240 241 242 243 pub fn write_pointer(&mut self, data: Vec<u8>) {244 let offset_position = self.data.len();245 H256::write(self, H256::repeat_byte(0xff));246247 self.offset_data.push(OffsetDatum {248 offset_position,249 data,250 offset_shift: 0,251 });252 }253}254255impl Default for EvmDataWriter {256 fn default() -> Self {257 Self::new()258 }259}260261262pub trait EvmData: Sized {263 fn read(reader: &mut EvmDataReader, gasometer: &Gasometer) -> EvmResult<Self>;264 fn write(writer: &mut EvmDataWriter, value: Self);265}266267impl EvmData for H256 {268 fn read(reader: &mut EvmDataReader, gasometer: &Gasometer) -> EvmResult<Self> {269 let range = reader.move_cursor(gasometer, 32)?;270271 let data = reader272 .input273 .get(range)274 .ok_or_else(|| gasometer.revert("tried to parse H256 out of bounds"))?;275276 Ok(H256::from_slice(data))277 }278279 fn write(writer: &mut EvmDataWriter, value: Self) {280 writer.data.extend_from_slice(value.as_bytes());281 }282}283284impl EvmData for Address {285 fn read(reader: &mut EvmDataReader, gasometer: &Gasometer) -> EvmResult<Self> {286 let range = reader.move_cursor(gasometer, 32)?;287288 let data = reader289 .input290 .get(range)291 .ok_or_else(|| gasometer.revert("tried to parse H160 out of bounds"))?;292293 Ok(H160::from_slice(&data[12..32]).into())294 }295296 fn write(writer: &mut EvmDataWriter, value: Self) {297 H256::write(writer, value.0.into());298 }299}300301impl EvmData for U256 {302 fn read(reader: &mut EvmDataReader, gasometer: &Gasometer) -> EvmResult<Self> {303 let range = reader.move_cursor(gasometer, 32)?;304305 let data = reader306 .input307 .get(range)308 .ok_or_else(|| gasometer.revert("tried to parse U256 out of bounds"))?;309310 Ok(U256::from_big_endian(data))311 }312313 fn write(writer: &mut EvmDataWriter, value: Self) {314 let mut buffer = [0u8; 32];315 value.to_big_endian(&mut buffer);316 writer.data.extend_from_slice(&buffer);317 }318}319320macro_rules! impl_evmdata_for_uints {321 ($($uint:ty, )*) => {322 $(323 impl EvmData for $uint {324 fn read(reader: &mut EvmDataReader, gasometer: &Gasometer) -> EvmResult<Self> {325 let range = reader.move_cursor(gasometer, 32)?;326327 let data = reader328 .input329 .get(range)330 .ok_or_else(|| gasometer.revert(alloc::format!(331 "tried to parse {} out of bounds", core::any::type_name::<Self>()332 )))?;333334 let mut buffer = [0u8; core::mem::size_of::<Self>()];335 buffer.copy_from_slice(&data[32 - core::mem::size_of::<Self>()..]);336 Ok(Self::from_be_bytes(buffer))337 }338339 fn write(writer: &mut EvmDataWriter, value: Self) {340 let mut buffer = [0u8; 32];341 buffer[32 - core::mem::size_of::<Self>()..].copy_from_slice(&value.to_be_bytes());342 writer.data.extend_from_slice(&buffer);343 }344 }345 )*346 };347}348349impl_evmdata_for_uints!(u16, u32, u64, u128,);350351352impl EvmData for u8 {353 fn read(reader: &mut EvmDataReader, gasometer: &Gasometer) -> EvmResult<Self> {354 let range = reader.move_cursor(gasometer, 32)?;355356 let data = reader357 .input358 .get(range)359 .ok_or_else(|| gasometer.revert("tried to parse u64 out of bounds"))?;360361 Ok(data[31])362 }363364 fn write(writer: &mut EvmDataWriter, value: Self) {365 let mut buffer = [0u8; 32];366 buffer[31] = value;367368 writer.data.extend_from_slice(&buffer);369 }370}371372impl EvmData for bool {373 fn read(reader: &mut EvmDataReader, gasometer: &Gasometer) -> EvmResult<Self> {374 let h256 = H256::read(reader, gasometer)375 .map_err(|_| gasometer.revert("tried to parse bool out of bounds"))?;376377 Ok(!h256.is_zero())378 }379380 fn write(writer: &mut EvmDataWriter, value: Self) {381 let mut buffer = [0u8; 32];382 if value {383 buffer[31] = 1;384 }385386 writer.data.extend_from_slice(&buffer);387 }388}389390impl<T: EvmData> EvmData for Vec<T> {391 fn read(reader: &mut EvmDataReader, gasometer: &Gasometer) -> EvmResult<Self> {392 let mut inner_reader = reader.read_pointer(gasometer)?;393394 let array_size: usize = inner_reader395 .read::<U256>(gasometer)396 .map_err(|_| gasometer.revert("tried to parse array length out of bounds"))?397 .try_into()398 .map_err(|_| gasometer.revert("array length is too large"))?;399400 let mut array = vec![];401402 let mut item_reader = EvmDataReader {403 input: inner_reader404 .input405 .get(32..)406 .ok_or_else(|| gasometer.revert("try to read array items out of bound"))?,407 cursor: 0,408 };409410 for _ in 0..array_size {411 array.push(item_reader.read(gasometer)?);412 }413414 Ok(array)415 }416417 fn write(writer: &mut EvmDataWriter, value: Self) {418 let mut inner_writer = EvmDataWriter::new().write(U256::from(value.len()));419420 for inner in value {421 422 423 424 425 let shift = inner_writer.data.len();426 let item_writer = EvmDataWriter::new().write(inner);427428 inner_writer = inner_writer.write_raw_bytes(&item_writer.data);429 for mut offset_datum in item_writer.offset_data {430 offset_datum.offset_shift += 32;431 offset_datum.offset_position += shift;432 inner_writer.offset_data.push(offset_datum);433 }434 }435436 writer.write_pointer(inner_writer.build());437 }438}439440impl EvmData for Bytes {441 fn read(reader: &mut EvmDataReader, gasometer: &Gasometer) -> EvmResult<Self> {442 let mut inner_reader = reader.read_pointer(gasometer)?;443444 445 let array_size: usize = inner_reader446 .read::<U256>(gasometer)447 .map_err(|_| gasometer.revert("tried to parse bytes/string length out of bounds"))?448 .try_into()449 .map_err(|_| gasometer.revert("bytes/string length is too large"))?;450451 452 let range = inner_reader.move_cursor(gasometer, array_size)?;453454 let data = inner_reader455 .input456 .get(range)457 .ok_or_else(|| gasometer.revert("tried to parse bytes/string out of bounds"))?;458459 let bytes = Self(data.to_owned());460461 Ok(bytes)462 }463464 fn write(writer: &mut EvmDataWriter, value: Self) {465 let length = value.0.len();466467 468 469 470 let chunks = length / 32;471 let padded_size = match length % 32 {472 0 => chunks * 32,473 _ => (chunks + 1) * 32,474 };475476 let mut value = value.0.to_vec();477 value.resize(padded_size, 0);478479 writer.write_pointer(480 EvmDataWriter::new()481 .write(U256::from(length))482 .write_raw_bytes(&value)483 .build(),484 );485 }486}