git.delta.rocks / unique-network / refs/commits / 67a4ea452077

difftreelog

source

crates/evm-coder/src/abi.rs19.6 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! Implementation of EVM RLP reader/writer1819#![allow(dead_code)]2021#[cfg(not(feature = "std"))]22use alloc::vec::Vec;23use evm_core::ExitError;24use primitive_types::{H160, U256};2526use crate::{27	execution::{Error, ResultWithPostInfo, WithPostDispatchInfo},28	types::{string, self},29};30use crate::execution::Result;3132const ABI_ALIGNMENT: usize = 32;3334trait TypeHelper<T> {35	fn is_dynamic() -> bool;36}3738/// View into RLP data, which provides method to read typed items from it39#[derive(Clone)]40pub struct AbiReader<'i> {41	buf: &'i [u8],42	subresult_offset: usize,43	offset: usize,44}45impl<'i> AbiReader<'i> {46	/// Start reading RLP buffer, assuming there is no padding bytes47	pub fn new(buf: &'i [u8]) -> Self {48		Self {49			buf,50			subresult_offset: 0,51			offset: 0,52		}53	}54	/// Start reading RLP buffer, parsing first 4 bytes as selector55	pub fn new_call(buf: &'i [u8]) -> Result<(types::bytes4, Self)> {56		if buf.len() < 4 {57			return Err(Error::Error(ExitError::OutOfOffset));58		}59		let mut method_id = [0; 4];60		method_id.copy_from_slice(&buf[0..4]);6162		Ok((63			method_id,64			Self {65				buf,66				subresult_offset: 4,67				offset: 4,68			},69		))70	}7172	fn read_pad<const S: usize>(73		buf: &[u8],74		offset: usize,75		pad_start: usize,76		pad_size: usize,77		block_start: usize,78		block_size: usize,79	) -> Result<[u8; S]> {80		if buf.len() - offset < ABI_ALIGNMENT {81			return Err(Error::Error(ExitError::OutOfOffset));82		}83		let mut block = [0; S];84		let is_pad_zeroed = buf[pad_start..pad_size].iter().all(|&v| v == 0);85		if !is_pad_zeroed {86			return Err(Error::Error(ExitError::InvalidRange));87		}88		block.copy_from_slice(&buf[block_start..block_size]);89		Ok(block)90	}9192	fn read_padleft<const S: usize>(&mut self) -> Result<[u8; S]> {93		let offset = self.offset;94		self.offset += ABI_ALIGNMENT;95		Self::read_pad(96			self.buf,97			offset,98			offset,99			offset + ABI_ALIGNMENT - S,100			offset + ABI_ALIGNMENT - S,101			offset + ABI_ALIGNMENT,102		)103	}104105	fn read_padright<const S: usize>(&mut self) -> Result<[u8; S]> {106		let offset = self.offset;107		self.offset += ABI_ALIGNMENT;108		Self::read_pad(109			self.buf,110			offset,111			offset + S,112			offset + ABI_ALIGNMENT,113			offset,114			offset + S,115		)116	}117118	/// Read [`H160`] at current position, then advance119	pub fn address(&mut self) -> Result<H160> {120		Ok(H160(self.read_padleft()?))121	}122123	/// Read [`bool`] at current position, then advance124	pub fn bool(&mut self) -> Result<bool> {125		let data: [u8; 1] = self.read_padleft()?;126		match data[0] {127			0 => Ok(false),128			1 => Ok(true),129			_ => Err(Error::Error(ExitError::InvalidRange)),130		}131	}132133	/// Read [`[u8; 4]`] at current position, then advance134	pub fn bytes4(&mut self) -> Result<[u8; 4]> {135		self.read_padright()136	}137138	/// Read [`Vec<u8>`] at current position, then advance139	pub fn bytes(&mut self) -> Result<Vec<u8>> {140		let mut subresult = self.subresult(None)?;141		let length = subresult.uint32()? as usize;142		if subresult.buf.len() < subresult.offset + length {143			return Err(Error::Error(ExitError::OutOfOffset));144		}145		Ok(subresult.buf[subresult.offset..subresult.offset + length].into())146	}147148	/// Read [`string`] at current position, then advance149	pub fn string(&mut self) -> Result<string> {150		string::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange))151	}152153	/// Read [`u8`] at current position, then advance154	pub fn uint8(&mut self) -> Result<u8> {155		Ok(self.read_padleft::<1>()?[0])156	}157158	/// Read [`u32`] at current position, then advance159	pub fn uint32(&mut self) -> Result<u32> {160		Ok(u32::from_be_bytes(self.read_padleft()?))161	}162163	/// Read [`u128`] at current position, then advance164	pub fn uint128(&mut self) -> Result<u128> {165		Ok(u128::from_be_bytes(self.read_padleft()?))166	}167168	/// Read [`U256`] at current position, then advance169	pub fn uint256(&mut self) -> Result<U256> {170		let buf: [u8; 32] = self.read_padleft()?;171		Ok(U256::from_big_endian(&buf))172	}173174	/// Read [`u64`] at current position, then advance175	pub fn uint64(&mut self) -> Result<u64> {176		Ok(u64::from_be_bytes(self.read_padleft()?))177	}178179	/// Read [`usize`] at current position, then advance180	#[deprecated = "dangerous, as usize may have different width in wasm and native execution"]181	pub fn read_usize(&mut self) -> Result<usize> {182		Ok(usize::from_be_bytes(self.read_padleft()?))183	}184185	/// Slice recursive buffer, advance one word for buffer offset186	/// If `size` is [`None`] then [`Self::offset`] and [`Self::subresult_offset`] evals from [`Self::buf`].187	fn subresult(&mut self, size: Option<usize>) -> Result<AbiReader<'i>> {188		let subresult_offset = self.subresult_offset;189		let offset = if let Some(size) = size {190			self.offset += size;191			self.subresult_offset += size;192			0193		} else {194			self.uint32()? as usize195		};196197		if offset + self.subresult_offset > self.buf.len() {198			return Err(Error::Error(ExitError::InvalidRange));199		}200201		let new_offset = offset + subresult_offset;202		Ok(AbiReader {203			buf: self.buf,204			subresult_offset: new_offset,205			offset: new_offset,206		})207	}208209	/// Is this parser reached end of buffer?210	pub fn is_finished(&self) -> bool {211		self.buf.len() == self.offset212	}213}214215/// Writer for RLP encoded data216#[derive(Default)]217pub struct AbiWriter {218	static_part: Vec<u8>,219	dynamic_part: Vec<(usize, AbiWriter)>,220	had_call: bool,221}222impl AbiWriter {223	/// Initialize internal buffers for output data, assuming no padding required224	pub fn new() -> Self {225		Self::default()226	}227	/// Initialize internal buffers, inserting method selector at beginning228	pub fn new_call(method_id: u32) -> Self {229		let mut val = Self::new();230		val.static_part.extend(&method_id.to_be_bytes());231		val.had_call = true;232		val233	}234235	fn write_padleft(&mut self, block: &[u8]) {236		assert!(block.len() <= ABI_ALIGNMENT);237		self.static_part238			.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);239		self.static_part.extend(block);240	}241242	fn write_padright(&mut self, bytes: &[u8]) {243		assert!(bytes.len() <= ABI_ALIGNMENT);244		self.static_part.extend(bytes);245		self.static_part246			.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - bytes.len()]);247	}248249	/// Write [`H160`] to end of buffer250	pub fn address(&mut self, address: &H160) {251		self.write_padleft(&address.0)252	}253254	/// Write [`bool`] to end of buffer255	pub fn bool(&mut self, value: &bool) {256		self.write_padleft(&[if *value { 1 } else { 0 }])257	}258259	/// Write [`u8`] to end of buffer260	pub fn uint8(&mut self, value: &u8) {261		self.write_padleft(&[*value])262	}263264	/// Write [`u32`] to end of buffer265	pub fn uint32(&mut self, value: &u32) {266		self.write_padleft(&u32::to_be_bytes(*value))267	}268269	/// Write [`u128`] to end of buffer270	pub fn uint128(&mut self, value: &u128) {271		self.write_padleft(&u128::to_be_bytes(*value))272	}273274	/// Write [`U256`] to end of buffer275	pub fn uint256(&mut self, value: &U256) {276		let mut out = [0; 32];277		value.to_big_endian(&mut out);278		self.write_padleft(&out)279	}280281	/// Write [`usize`] to end of buffer282	#[deprecated = "dangerous, as usize may have different width in wasm and native execution"]283	pub fn write_usize(&mut self, value: &usize) {284		self.write_padleft(&usize::to_be_bytes(*value))285	}286287	/// Append recursive data, writing pending offset at end of buffer288	pub fn write_subresult(&mut self, result: Self) {289		self.dynamic_part.push((self.static_part.len(), result));290		// Empty block, to be filled later291		self.write_padleft(&[]);292	}293294	fn memory(&mut self, value: &[u8]) {295		let mut sub = Self::new();296		sub.uint32(&(value.len() as u32));297		for chunk in value.chunks(ABI_ALIGNMENT) {298			sub.write_padright(chunk);299		}300		self.write_subresult(sub);301	}302303	/// Append recursive [`str`] at end of buffer304	pub fn string(&mut self, value: &str) {305		self.memory(value.as_bytes())306	}307308	/// Append recursive [`[u8]`] at end of buffer309	pub fn bytes(&mut self, value: &[u8]) {310		self.memory(value)311	}312313	/// Finish writer, concatenating all internal buffers314	pub fn finish(mut self) -> Vec<u8> {315		for (static_offset, part) in self.dynamic_part {316			let part_offset = self.static_part.len() - self.had_call.then(|| 4).unwrap_or(0);317318			let encoded_dynamic_offset = usize::to_be_bytes(part_offset);319			self.static_part[static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len()320				..static_offset + ABI_ALIGNMENT]321				.copy_from_slice(&encoded_dynamic_offset);322			self.static_part.extend(part.finish())323		}324		self.static_part325	}326}327328/// [`AbiReader`] implements reading of many types, but it should329/// be limited to types defined in spec330///331/// As this trait can't be made sealed,332/// instead of having `impl AbiRead for T`, we have `impl AbiRead<T> for AbiReader`333pub trait AbiRead<T> {334	/// Read item from current position, advanding decoder335	fn abi_read(&mut self) -> Result<T>;336337	/// Size for type aligned to [`ABI_ALIGNMENT`].338	fn size() -> usize;339}340341macro_rules! impl_abi_readable {342	($ty:ty, $method:ident, $dynamic:literal) => {343		impl TypeHelper<$ty> for $ty {344			fn is_dynamic() -> bool {345				$dynamic346			}347		}348		impl AbiRead<$ty> for AbiReader<'_> {349			fn abi_read(&mut self) -> Result<$ty> {350				self.$method()351			}352353			fn size() -> usize {354				ABI_ALIGNMENT355			}356		}357		impl AbiRead<$ty> for $ty {358			fn abi_read(&mut self) -> Result<$ty> {359				todo!("Refactor requered.")360			}361362			fn size() -> usize {363				ABI_ALIGNMENT364			}365		}366	};367}368369impl_abi_readable!(u8, uint8, false);370impl_abi_readable!(u32, uint32, false);371impl_abi_readable!(u64, uint64, false);372impl_abi_readable!(u128, uint128, false);373impl_abi_readable!(U256, uint256, false);374impl_abi_readable!([u8; 4], bytes4, false);375impl_abi_readable!(H160, address, false);376impl_abi_readable!(Vec<u8>, bytes, true);377impl_abi_readable!(bool, bool, true);378impl_abi_readable!(string, string, true);379380mod sealed {381	/// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead382	pub trait CanBePlacedInVec {}383}384385impl sealed::CanBePlacedInVec for U256 {}386impl sealed::CanBePlacedInVec for string {}387impl sealed::CanBePlacedInVec for H160 {}388389impl<R: sealed::CanBePlacedInVec> AbiRead<Vec<R>> for AbiReader<'_>390where391	Self: AbiRead<R>,392{393	fn abi_read(&mut self) -> Result<Vec<R>> {394		let mut sub = self.subresult(None)?;395		let size = sub.uint32()? as usize;396		sub.subresult_offset = sub.offset;397		let mut out = Vec::with_capacity(size);398		for _ in 0..size {399			out.push(<Self as AbiRead<R>>::abi_read(&mut sub)?);400		}401		Ok(out)402	}403404	fn size() -> usize {405		ABI_ALIGNMENT406	}407}408409macro_rules! impl_tuples {410	($($ident:ident)+) => {411		impl<$($ident: TypeHelper<$ident>,)+> TypeHelper<($($ident,)+)> for ($($ident,)+) {412			fn is_dynamic() -> bool {413				false414				$(415					|| <$ident>::is_dynamic()416				)*417			}418		}419		impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}420		impl<$($ident),+> AbiRead<($($ident,)+)> for AbiReader<'_>421		where422			$(423				Self: AbiRead<$ident>,424				$ident: AbiRead<$ident>,425			)+426			($($ident,)+): TypeHelper<($($ident,)+)>,427		{428			fn abi_read(&mut self) -> Result<($($ident,)+)> {429				let size = if !<($($ident,)+)>::is_dynamic() { Some(<Self as AbiRead<($($ident,)+)>>::size()) } else { None };430				let mut subresult = self.subresult(size)?;431				Ok((432					$(<Self as AbiRead<$ident>>::abi_read(&mut subresult)?,)+433				))434			}435436			fn size() -> usize {437				0 $(+ <$ident>::size())+438			}439		}440		#[allow(non_snake_case)]441		impl<$($ident),+> AbiWrite for &($($ident,)+)442		where443			$($ident: AbiWrite,)+444		{445			fn abi_write(&self, writer: &mut AbiWriter) {446				let ($($ident,)+) = self;447				$($ident.abi_write(writer);)+448			}449		}450	};451}452453impl_tuples! {A}454impl_tuples! {A B}455impl_tuples! {A B C}456impl_tuples! {A B C D}457impl_tuples! {A B C D E}458impl_tuples! {A B C D E F}459impl_tuples! {A B C D E F G}460impl_tuples! {A B C D E F G H}461impl_tuples! {A B C D E F G H I}462impl_tuples! {A B C D E F G H I J}463464/// For questions about inability to provide custom implementations,465/// see [`AbiRead`]466pub trait AbiWrite {467	/// Write value to end of specified encoder468	fn abi_write(&self, writer: &mut AbiWriter);469	/// Specialization for [`crate::solidity_interface`] implementation,470	/// see comment in `impl AbiWrite for ResultWithPostInfo`471	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {472		let mut writer = AbiWriter::new();473		self.abi_write(&mut writer);474		Ok(writer.into())475	}476}477478/// This particular AbiWrite implementation should be split to another trait,479/// which only implements `to_result`, but due to lack of specialization feature480/// in stable Rust, we can't have blanket impl of this trait `for T where T: AbiWrite`,481/// so here we abusing default trait methods for it482impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {483	fn abi_write(&self, _writer: &mut AbiWriter) {484		debug_assert!(false, "shouldn't be called, see comment")485	}486	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {487		match self {488			Ok(v) => Ok(WithPostDispatchInfo {489				post_info: v.post_info.clone(),490				data: {491					let mut out = AbiWriter::new();492					v.data.abi_write(&mut out);493					out494				},495			}),496			Err(e) => Err(e.clone()),497		}498	}499}500501macro_rules! impl_abi_writeable {502	($ty:ty, $method:ident) => {503		impl AbiWrite for $ty {504			fn abi_write(&self, writer: &mut AbiWriter) {505				writer.$method(&self)506			}507		}508	};509}510511impl_abi_writeable!(u8, uint8);512impl_abi_writeable!(u32, uint32);513impl_abi_writeable!(u128, uint128);514impl_abi_writeable!(U256, uint256);515impl_abi_writeable!(H160, address);516impl_abi_writeable!(bool, bool);517impl_abi_writeable!(&str, string);518impl AbiWrite for &string {519	fn abi_write(&self, writer: &mut AbiWriter) {520		writer.string(self)521	}522}523impl AbiWrite for &Vec<u8> {524	fn abi_write(&self, writer: &mut AbiWriter) {525		writer.bytes(self)526	}527}528529impl AbiWrite for () {530	fn abi_write(&self, _writer: &mut AbiWriter) {}531}532533/// Helper macros to parse reader into variables534#[deprecated]535#[macro_export]536macro_rules! abi_decode {537	($reader:expr, $($name:ident: $typ:ident),+ $(,)?) => {538		$(539			let $name = $reader.$typ()?;540		)+541	}542}543544/// Helper macros to construct RLP-encoded buffer545#[deprecated]546#[macro_export]547macro_rules! abi_encode {548	($($typ:ident($value:expr)),* $(,)?) => {{549		#[allow(unused_mut)]550		let mut writer = ::evm_coder::abi::AbiWriter::new();551		$(552			writer.$typ($value);553		)*554		writer555	}};556	(call $val:expr; $($typ:ident($value:expr)),* $(,)?) => {{557		#[allow(unused_mut)]558		let mut writer = ::evm_coder::abi::AbiWriter::new_call($val);559		$(560			writer.$typ($value);561		)*562		writer563	}}564}565566#[cfg(test)]567pub mod test {568	use crate::{569		abi::AbiRead,570		types::{string, uint256},571	};572573	use super::{AbiReader, AbiWriter};574	use hex_literal::hex;575576	#[test]577	fn dynamic_after_static() {578		let mut encoder = AbiWriter::new();579		encoder.bool(&true);580		encoder.string("test");581		let encoded = encoder.finish();582583		let mut encoder = AbiWriter::new();584		encoder.bool(&true);585		// Offset to subresult586		encoder.uint32(&(32 * 2));587		// Len of "test"588		encoder.uint32(&4);589		encoder.write_padright(&[b't', b'e', b's', b't']);590		let alternative_encoded = encoder.finish();591592		assert_eq!(encoded, alternative_encoded);593594		let mut decoder = AbiReader::new(&encoded);595		assert!(decoder.bool().unwrap());596		assert_eq!(decoder.string().unwrap(), "test");597	}598599	#[test]600	fn mint_sample() {601		let (call, mut decoder) = AbiReader::new_call(&hex!(602			"603				50bb4e7f604				000000000000000000000000ad2c0954693c2b5404b7e50967d3481bea432374605				0000000000000000000000000000000000000000000000000000000000000001606				0000000000000000000000000000000000000000000000000000000000000060607				0000000000000000000000000000000000000000000000000000000000000008608				5465737420555249000000000000000000000000000000000000000000000000609			"610		))611		.unwrap();612		assert_eq!(call, u32::to_be_bytes(0x50bb4e7f));613		assert_eq!(614			format!("{:?}", decoder.address().unwrap()),615			"0xad2c0954693c2b5404b7e50967d3481bea432374"616		);617		assert_eq!(decoder.uint32().unwrap(), 1);618		assert_eq!(decoder.string().unwrap(), "Test URI");619	}620621	#[test]622	fn mint_bulk() {623		let (call, mut decoder) = AbiReader::new_call(&hex!(624			"625				36543006626				00000000000000000000000053744e6da587ba10b32a2554d2efdcd985bc27a3 // address627				0000000000000000000000000000000000000000000000000000000000000040 // offset of (uint256, string)[]628				0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]629630				0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem631				00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem632				0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem633634				0000000000000000000000000000000000000000000000000000000000000001 // first token id?   					#60635				0000000000000000000000000000000000000000000000000000000000000040 // offset of string636				000000000000000000000000000000000000000000000000000000000000000a // size of string637				5465737420555249203000000000000000000000000000000000000000000000 // string638639				000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11?			#e0640				0000000000000000000000000000000000000000000000000000000000000040 // offset of string641				000000000000000000000000000000000000000000000000000000000000000a // size of string642				5465737420555249203100000000000000000000000000000000000000000000 // string643644				000000000000000000000000000000000000000000000000000000000000000c // third token id?  Why ==12?			#160645				0000000000000000000000000000000000000000000000000000000000000040 // offset of string646				000000000000000000000000000000000000000000000000000000000000000a // size of string647				5465737420555249203200000000000000000000000000000000000000000000 // string648			"649		))650		.unwrap();651		assert_eq!(call, u32::to_be_bytes(0x36543006));652		let _ = decoder.address().unwrap();653		let data =654			<AbiReader<'_> as AbiRead<Vec<(uint256, string)>>>::abi_read(&mut decoder).unwrap();655		assert_eq!(656			data,657			vec![658				(1.into(), "Test URI 0".to_string()),659				(11.into(), "Test URI 1".to_string()),660				(12.into(), "Test URI 2".to_string())661			]662		);663	}664665	#[test]666	fn parse_vec_with_simple_type() {667		use crate::types::address;668		use primitive_types::{H160, U256};669670		let (call, mut decoder) = AbiReader::new_call(&hex!(671			"672				1ACF2D55673				0000000000000000000000000000000000000000000000000000000000000020 // offset of (address, uint256)[]674				0000000000000000000000000000000000000000000000000000000000000003 // length of (address, uint256)[]675676				0000000000000000000000002D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC // address677				000000000000000000000000000000000000000000000000000000000000000A // uint256678679				000000000000000000000000AB8E3D9134955566483B11E6825C9223B6737B10 // address680				0000000000000000000000000000000000000000000000000000000000000014 // uint256681682				0000000000000000000000008C582BDF2953046705FC56F189385255EFC1BE18 // address683				000000000000000000000000000000000000000000000000000000000000001E // uint256684			"685		))686		.unwrap();687		assert_eq!(call, u32::to_be_bytes(0x1ACF2D55));688		let data =689			<AbiReader<'_> as AbiRead<Vec<(address, uint256)>>>::abi_read(&mut decoder).unwrap();690		assert_eq!(data.len(), 3);691		assert_eq!(692			data,693			vec![694				(695					H160(hex!("2D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC")),696					U256([10, 0, 0, 0])697				),698				(699					H160(hex!("AB8E3D9134955566483B11E6825C9223B6737B10")),700					U256([20, 0, 0, 0])701				),702				(703					H160(hex!("8C582BDF2953046705FC56F189385255EFC1BE18")),704					U256([30, 0, 0, 0])705				),706			]707		);708	}709}