git.delta.rocks / unique-network / refs/commits / 626610cdfa29

difftreelog

source

crates/evm-coder/src/abi.rs20.2 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 {35	/// Is type dynamic sized.36	fn is_dynamic() -> bool;3738	/// Size for type aligned to [`ABI_ALIGNMENT`].39	fn size() -> usize;40}4142/// View into RLP data, which provides method to read typed items from it43#[derive(Clone)]44pub struct AbiReader<'i> {45	buf: &'i [u8],46	subresult_offset: usize,47	offset: usize,48}49impl<'i> AbiReader<'i> {50	/// Start reading RLP buffer, assuming there is no padding bytes51	pub fn new(buf: &'i [u8]) -> Self {52		Self {53			buf,54			subresult_offset: 0,55			offset: 0,56		}57	}58	/// Start reading RLP buffer, parsing first 4 bytes as selector59	pub fn new_call(buf: &'i [u8]) -> Result<(types::bytes4, Self)> {60		if buf.len() < 4 {61			return Err(Error::Error(ExitError::OutOfOffset));62		}63		let mut method_id = [0; 4];64		method_id.copy_from_slice(&buf[0..4]);6566		Ok((67			method_id,68			Self {69				buf,70				subresult_offset: 4,71				offset: 4,72			},73		))74	}7576	fn read_pad<const S: usize>(77		buf: &[u8],78		offset: usize,79		pad_start: usize,80		pad_size: usize,81		block_start: usize,82		block_size: usize,83	) -> Result<[u8; S]> {84		if buf.len() - offset < ABI_ALIGNMENT {85			return Err(Error::Error(ExitError::OutOfOffset));86		}87		let mut block = [0; S];88		let is_pad_zeroed = buf[pad_start..pad_size].iter().all(|&v| v == 0);89		if !is_pad_zeroed {90			return Err(Error::Error(ExitError::InvalidRange));91		}92		block.copy_from_slice(&buf[block_start..block_size]);93		Ok(block)94	}9596	fn read_padleft<const S: usize>(&mut self) -> Result<[u8; S]> {97		let offset = self.offset;98		self.offset += ABI_ALIGNMENT;99		Self::read_pad(100			self.buf,101			offset,102			offset,103			offset + ABI_ALIGNMENT - S,104			offset + ABI_ALIGNMENT - S,105			offset + ABI_ALIGNMENT,106		)107	}108109	fn read_padright<const S: usize>(&mut self) -> Result<[u8; S]> {110		let offset = self.offset;111		self.offset += ABI_ALIGNMENT;112		Self::read_pad(113			self.buf,114			offset,115			offset + S,116			offset + ABI_ALIGNMENT,117			offset,118			offset + S,119		)120	}121122	/// Read [`H160`] at current position, then advance123	pub fn address(&mut self) -> Result<H160> {124		Ok(H160(self.read_padleft()?))125	}126127	/// Read [`bool`] at current position, then advance128	pub fn bool(&mut self) -> Result<bool> {129		let data: [u8; 1] = self.read_padleft()?;130		match data[0] {131			0 => Ok(false),132			1 => Ok(true),133			_ => Err(Error::Error(ExitError::InvalidRange)),134		}135	}136137	/// Read [`[u8; 4]`] at current position, then advance138	pub fn bytes4(&mut self) -> Result<[u8; 4]> {139		self.read_padright()140	}141142	/// Read [`Vec<u8>`] at current position, then advance143	pub fn bytes(&mut self) -> Result<Vec<u8>> {144		let mut subresult = self.subresult(None)?;145		let length = subresult.uint32()? as usize;146		if subresult.buf.len() < subresult.offset + length {147			return Err(Error::Error(ExitError::OutOfOffset));148		}149		Ok(subresult.buf[subresult.offset..subresult.offset + length].into())150	}151152	/// Read [`string`] at current position, then advance153	pub fn string(&mut self) -> Result<string> {154		string::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange))155	}156157	/// Read [`u8`] at current position, then advance158	pub fn uint8(&mut self) -> Result<u8> {159		Ok(self.read_padleft::<1>()?[0])160	}161162	/// Read [`u32`] at current position, then advance163	pub fn uint32(&mut self) -> Result<u32> {164		Ok(u32::from_be_bytes(self.read_padleft()?))165	}166167	/// Read [`u128`] at current position, then advance168	pub fn uint128(&mut self) -> Result<u128> {169		Ok(u128::from_be_bytes(self.read_padleft()?))170	}171172	/// Read [`U256`] at current position, then advance173	pub fn uint256(&mut self) -> Result<U256> {174		let buf: [u8; 32] = self.read_padleft()?;175		Ok(U256::from_big_endian(&buf))176	}177178	/// Read [`u64`] at current position, then advance179	pub fn uint64(&mut self) -> Result<u64> {180		Ok(u64::from_be_bytes(self.read_padleft()?))181	}182183	/// Read [`usize`] at current position, then advance184	#[deprecated = "dangerous, as usize may have different width in wasm and native execution"]185	pub fn read_usize(&mut self) -> Result<usize> {186		Ok(usize::from_be_bytes(self.read_padleft()?))187	}188189	/// Slice recursive buffer, advance one word for buffer offset190	/// If `size` is [`None`] then [`Self::offset`] and [`Self::subresult_offset`] evals from [`Self::buf`].191	fn subresult(&mut self, size: Option<usize>) -> Result<AbiReader<'i>> {192		let subresult_offset = self.subresult_offset;193		let offset = if let Some(size) = size {194			self.offset += size;195			self.subresult_offset += size;196			0197		} else {198			self.uint32()? as usize199		};200201		if offset + self.subresult_offset > self.buf.len() {202			return Err(Error::Error(ExitError::InvalidRange));203		}204205		let new_offset = offset + subresult_offset;206		Ok(AbiReader {207			buf: self.buf,208			subresult_offset: new_offset,209			offset: new_offset,210		})211	}212213	/// Is this parser reached end of buffer?214	pub fn is_finished(&self) -> bool {215		self.buf.len() == self.offset216	}217}218219/// Writer for RLP encoded data220#[derive(Default)]221pub struct AbiWriter {222	static_part: Vec<u8>,223	dynamic_part: Vec<(usize, AbiWriter)>,224	had_call: bool,225}226impl AbiWriter {227	/// Initialize internal buffers for output data, assuming no padding required228	pub fn new() -> Self {229		Self::default()230	}231	/// Initialize internal buffers, inserting method selector at beginning232	pub fn new_call(method_id: u32) -> Self {233		let mut val = Self::new();234		val.static_part.extend(&method_id.to_be_bytes());235		val.had_call = true;236		val237	}238239	fn write_padleft(&mut self, block: &[u8]) {240		assert!(block.len() <= ABI_ALIGNMENT);241		self.static_part242			.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);243		self.static_part.extend(block);244	}245246	fn write_padright(&mut self, bytes: &[u8]) {247		assert!(bytes.len() <= ABI_ALIGNMENT);248		self.static_part.extend(bytes);249		self.static_part250			.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - bytes.len()]);251	}252253	/// Write [`H160`] to end of buffer254	pub fn address(&mut self, address: &H160) {255		self.write_padleft(&address.0)256	}257258	/// Write [`bool`] to end of buffer259	pub fn bool(&mut self, value: &bool) {260		self.write_padleft(&[if *value { 1 } else { 0 }])261	}262263	/// Write [`u8`] to end of buffer264	pub fn uint8(&mut self, value: &u8) {265		self.write_padleft(&[*value])266	}267268	/// Write [`u32`] to end of buffer269	pub fn uint32(&mut self, value: &u32) {270		self.write_padleft(&u32::to_be_bytes(*value))271	}272273	/// Write [`u128`] to end of buffer274	pub fn uint128(&mut self, value: &u128) {275		self.write_padleft(&u128::to_be_bytes(*value))276	}277278	/// Write [`U256`] to end of buffer279	pub fn uint256(&mut self, value: &U256) {280		let mut out = [0; 32];281		value.to_big_endian(&mut out);282		self.write_padleft(&out)283	}284285	/// Write [`usize`] to end of buffer286	#[deprecated = "dangerous, as usize may have different width in wasm and native execution"]287	pub fn write_usize(&mut self, value: &usize) {288		self.write_padleft(&usize::to_be_bytes(*value))289	}290291	/// Append recursive data, writing pending offset at end of buffer292	pub fn write_subresult(&mut self, result: Self) {293		self.dynamic_part.push((self.static_part.len(), result));294		// Empty block, to be filled later295		self.write_padleft(&[]);296	}297298	fn memory(&mut self, value: &[u8]) {299		let mut sub = Self::new();300		sub.uint32(&(value.len() as u32));301		for chunk in value.chunks(ABI_ALIGNMENT) {302			sub.write_padright(chunk);303		}304		self.write_subresult(sub);305	}306307	/// Append recursive [`str`] at end of buffer308	pub fn string(&mut self, value: &str) {309		self.memory(value.as_bytes())310	}311312	/// Append recursive [`[u8]`] at end of buffer313	pub fn bytes(&mut self, value: &[u8]) {314		self.memory(value)315	}316317	/// Finish writer, concatenating all internal buffers318	pub fn finish(mut self) -> Vec<u8> {319		for (static_offset, part) in self.dynamic_part {320			let part_offset = self.static_part.len() - if self.had_call { 4 } else { 0 };321322			let encoded_dynamic_offset = usize::to_be_bytes(part_offset);323			let start = static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len();324			let stop = static_offset + ABI_ALIGNMENT;325			self.static_part[start..stop].copy_from_slice(&encoded_dynamic_offset);326			self.static_part.extend(part.finish())327		}328		self.static_part329	}330}331332/// [`AbiReader`] implements reading of many types, but it should333/// be limited to types defined in spec334///335/// As this trait can't be made sealed,336/// instead of having `impl AbiRead for T`, we have `impl AbiRead<T> for AbiReader`337pub trait AbiRead<T> {338	/// Read item from current position, advanding decoder339	fn abi_read(&mut self) -> Result<T>;340}341342macro_rules! impl_abi_readable {343	($ty:ty, $method:ident, $dynamic:literal) => {344		impl TypeHelper for $ty {345			fn is_dynamic() -> bool {346				$dynamic347			}348349			fn size() -> usize {350				ABI_ALIGNMENT351			}352		}353		impl AbiRead<$ty> for AbiReader<'_> {354			fn abi_read(&mut self) -> Result<$ty> {355				self.$method()356			}357		}358	};359}360361impl_abi_readable!(u8, uint8, false);362impl_abi_readable!(u32, uint32, false);363impl_abi_readable!(u64, uint64, false);364impl_abi_readable!(u128, uint128, false);365impl_abi_readable!(U256, uint256, false);366impl_abi_readable!([u8; 4], bytes4, false);367impl_abi_readable!(H160, address, false);368impl_abi_readable!(Vec<u8>, bytes, true);369impl_abi_readable!(bool, bool, true);370impl_abi_readable!(string, string, true);371372mod sealed {373	/// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead374	pub trait CanBePlacedInVec {}375}376377impl sealed::CanBePlacedInVec for U256 {}378impl sealed::CanBePlacedInVec for string {}379impl sealed::CanBePlacedInVec for H160 {}380381impl<R: sealed::CanBePlacedInVec> AbiRead<Vec<R>> for AbiReader<'_>382where383	Self: AbiRead<R>,384{385	fn abi_read(&mut self) -> Result<Vec<R>> {386		let mut sub = self.subresult(None)?;387		let size = sub.uint32()? as usize;388		sub.subresult_offset = sub.offset;389		let mut out = Vec::with_capacity(size);390		for _ in 0..size {391			out.push(<Self as AbiRead<R>>::abi_read(&mut sub)?);392		}393		Ok(out)394	}395}396397macro_rules! impl_tuples {398	($($ident:ident)+) => {399		impl<$($ident: TypeHelper,)+> TypeHelper for ($($ident,)+)400		where401			$(402				$ident: TypeHelper,403			)+404		{405			fn is_dynamic() -> bool {406				false407				$(408					|| <$ident>::is_dynamic()409				)*410			}411412			fn size() -> usize {413				0 $(+ <$ident>::size())+414			}415		}416		impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}417		impl<$($ident),+> AbiRead<($($ident,)+)> for AbiReader<'_>418		where419			$(420				Self: AbiRead<$ident>,421			)+422			($($ident,)+): TypeHelper,423		{424			fn abi_read(&mut self) -> Result<($($ident,)+)> {425				let size = if !<($($ident,)+)>::is_dynamic() { Some(<($($ident,)+)>::size()) } else { None };426				let mut subresult = self.subresult(size)?;427				Ok((428					$(<Self as AbiRead<$ident>>::abi_read(&mut subresult)?,)+429				))430			}431		}432		#[allow(non_snake_case)]433		impl<$($ident),+> AbiWrite for ($($ident,)+)434		where435			$($ident: AbiWrite,)+436		{437			fn abi_write(&self, writer: &mut AbiWriter) {438				let ($($ident,)+) = self;439				$($ident.abi_write(writer);)+440			}441		}442	};443}444445impl_tuples! {A}446impl_tuples! {A B}447impl_tuples! {A B C}448impl_tuples! {A B C D}449impl_tuples! {A B C D E}450impl_tuples! {A B C D E F}451impl_tuples! {A B C D E F G}452impl_tuples! {A B C D E F G H}453impl_tuples! {A B C D E F G H I}454impl_tuples! {A B C D E F G H I J}455456/// For questions about inability to provide custom implementations,457/// see [`AbiRead`]458pub trait AbiWrite {459	/// Write value to end of specified encoder460	fn abi_write(&self, writer: &mut AbiWriter);461	/// Specialization for [`crate::solidity_interface`] implementation,462	/// see comment in `impl AbiWrite for ResultWithPostInfo`463	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {464		let mut writer = AbiWriter::new();465		self.abi_write(&mut writer);466		Ok(writer.into())467	}468}469470/// This particular AbiWrite implementation should be split to another trait,471/// which only implements `to_result`, but due to lack of specialization feature472/// in stable Rust, we can't have blanket impl of this trait `for T where T: AbiWrite`,473/// so here we abusing default trait methods for it474impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {475	fn abi_write(&self, _writer: &mut AbiWriter) {476		debug_assert!(false, "shouldn't be called, see comment")477	}478	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {479		match self {480			Ok(v) => Ok(WithPostDispatchInfo {481				post_info: v.post_info.clone(),482				data: {483					let mut out = AbiWriter::new();484					v.data.abi_write(&mut out);485					out486				},487			}),488			Err(e) => Err(e.clone()),489		}490	}491}492493macro_rules! impl_abi_writeable {494	($ty:ty, $method:ident) => {495		impl AbiWrite for $ty {496			fn abi_write(&self, writer: &mut AbiWriter) {497				writer.$method(&self)498			}499		}500	};501}502503impl_abi_writeable!(u8, uint8);504impl_abi_writeable!(u32, uint32);505impl_abi_writeable!(u128, uint128);506impl_abi_writeable!(U256, uint256);507impl_abi_writeable!(H160, address);508impl_abi_writeable!(bool, bool);509impl_abi_writeable!(&str, string);510impl AbiWrite for string {511	fn abi_write(&self, writer: &mut AbiWriter) {512		writer.string(self)513	}514}515// impl AbiWrite for Vec<u8> {516// 	fn abi_write(&self, writer: &mut AbiWriter) {517// 		writer.bytes(self)518// 	}519// }520521impl<T: AbiWrite> AbiWrite for Vec<T> {522	fn abi_write(&self, writer: &mut AbiWriter) {523		let mut sub = AbiWriter::new();524		(self.len() as u32).abi_write(&mut sub);525		for item in self {526			item.abi_write(&mut sub);527		}528		writer.write_subresult(sub);529	}530}531532impl AbiWrite for () {533	fn abi_write(&self, _writer: &mut AbiWriter) {}534}535536/// Helper macros to parse reader into variables537#[deprecated]538#[macro_export]539macro_rules! abi_decode {540	($reader:expr, $($name:ident: $typ:ident),+ $(,)?) => {541		$(542			let $name = $reader.$typ()?;543		)+544	}545}546547/// Helper macros to construct RLP-encoded buffer548#[deprecated]549#[macro_export]550macro_rules! abi_encode {551	($($typ:ident($value:expr)),* $(,)?) => {{552		#[allow(unused_mut)]553		let mut writer = ::evm_coder::abi::AbiWriter::new();554		$(555			writer.$typ($value);556		)*557		writer558	}};559	(call $val:expr; $($typ:ident($value:expr)),* $(,)?) => {{560		#[allow(unused_mut)]561		let mut writer = ::evm_coder::abi::AbiWriter::new_call($val);562		$(563			writer.$typ($value);564		)*565		writer566	}}567}568569#[cfg(test)]570pub mod test {571	use crate::{572		abi::{AbiRead, AbiWrite},573		types::{string, uint256, address},574	};575576	use super::{AbiReader, AbiWriter};577	use hex_literal::hex;578	use primitive_types::{H160, U256};579580	#[test]581	fn dynamic_after_static() {582		let mut encoder = AbiWriter::new();583		encoder.bool(&true);584		encoder.string("test");585		let encoded = encoder.finish();586587		let mut encoder = AbiWriter::new();588		encoder.bool(&true);589		// Offset to subresult590		encoder.uint32(&(32 * 2));591		// Len of "test"592		encoder.uint32(&4);593		encoder.write_padright(&[b't', b'e', b's', b't']);594		let alternative_encoded = encoder.finish();595596		assert_eq!(encoded, alternative_encoded);597598		let mut decoder = AbiReader::new(&encoded);599		assert!(decoder.bool().unwrap());600		assert_eq!(decoder.string().unwrap(), "test");601	}602603	#[test]604	fn mint_sample() {605		let (call, mut decoder) = AbiReader::new_call(&hex!(606			"607				50bb4e7f608				000000000000000000000000ad2c0954693c2b5404b7e50967d3481bea432374609				0000000000000000000000000000000000000000000000000000000000000001610				0000000000000000000000000000000000000000000000000000000000000060611				0000000000000000000000000000000000000000000000000000000000000008612				5465737420555249000000000000000000000000000000000000000000000000613			"614		))615		.unwrap();616		assert_eq!(call, u32::to_be_bytes(0x50bb4e7f));617		assert_eq!(618			format!("{:?}", decoder.address().unwrap()),619			"0xad2c0954693c2b5404b7e50967d3481bea432374"620		);621		assert_eq!(decoder.uint32().unwrap(), 1);622		assert_eq!(decoder.string().unwrap(), "Test URI");623	}624625	#[test]626	fn parse_vec_with_dynamic_type() {627		let decoded_data = (628			0x36543006,629			vec![630				(1.into(), "Test URI 0".to_string()),631				(11.into(), "Test URI 1".to_string()),632				(12.into(), "Test URI 2".to_string()),633			],634		);635636		let encoded_data = &hex!(637			"638				36543006639				00000000000000000000000053744e6da587ba10b32a2554d2efdcd985bc27a3 // address640				0000000000000000000000000000000000000000000000000000000000000040 // offset of (uint256, string)[]641				0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]642643				0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem644				00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem645				0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem646647				0000000000000000000000000000000000000000000000000000000000000001 // first token id?   					#60648				0000000000000000000000000000000000000000000000000000000000000040 // offset of string649				000000000000000000000000000000000000000000000000000000000000000a // size of string650				5465737420555249203000000000000000000000000000000000000000000000 // string651652				000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11?			#e0653				0000000000000000000000000000000000000000000000000000000000000040 // offset of string654				000000000000000000000000000000000000000000000000000000000000000a // size of string655				5465737420555249203100000000000000000000000000000000000000000000 // string656657				000000000000000000000000000000000000000000000000000000000000000c // third token id?  Why ==12?			#160658				0000000000000000000000000000000000000000000000000000000000000040 // offset of string659				000000000000000000000000000000000000000000000000000000000000000a // size of string660				5465737420555249203200000000000000000000000000000000000000000000 // string661			"662		);663664		let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap();665		assert_eq!(call, u32::to_be_bytes(decoded_data.0));666		let _ = decoder.address().unwrap();667		let data =668			<AbiReader<'_> as AbiRead<Vec<(uint256, string)>>>::abi_read(&mut decoder).unwrap();669		assert_eq!(data, decoded_data.1);670671		let mut writer = AbiWriter::new_call(decoded_data.0);672		decoded_data.1.abi_write(&mut writer);673		let ed = writer.finish();674		assert_eq!(encoded_data, ed.as_slice());675	}676677	#[test]678	fn parse_vec_with_simple_type() {679		let decoded_data = (680			0x1ACF2D55,681			vec![682				(683					H160(hex!("2D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC")),684					U256([10, 0, 0, 0]),685				),686				(687					H160(hex!("AB8E3D9134955566483B11E6825C9223B6737B10")),688					U256([20, 0, 0, 0]),689				),690				(691					H160(hex!("8C582BDF2953046705FC56F189385255EFC1BE18")),692					U256([30, 0, 0, 0]),693				),694			],695		);696697		let encoded_data = &hex!(698			"699				1ACF2D55700				0000000000000000000000000000000000000000000000000000000000000020 // offset of (address, uint256)[]701				0000000000000000000000000000000000000000000000000000000000000003 // length of (address, uint256)[]702703				0000000000000000000000002D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC // address704				000000000000000000000000000000000000000000000000000000000000000A // uint256705706				000000000000000000000000AB8E3D9134955566483B11E6825C9223B6737B10 // address707				0000000000000000000000000000000000000000000000000000000000000014 // uint256708709				0000000000000000000000008C582BDF2953046705FC56F189385255EFC1BE18 // address710				000000000000000000000000000000000000000000000000000000000000001E // uint256711			"712		);713714		let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap();715		assert_eq!(call, u32::to_be_bytes(decoded_data.0));716		let data =717			<AbiReader<'_> as AbiRead<Vec<(address, uint256)>>>::abi_read(&mut decoder).unwrap();718		assert_eq!(data.len(), 3);719		assert_eq!(data, decoded_data.1);720721		let mut writer = AbiWriter::new_call(decoded_data.0);722		decoded_data.1.abi_write(&mut writer);723		let ed = writer.finish();724		assert_eq!(encoded_data, ed.as_slice());725	}726}