Skip to content

Commit

Permalink
feat(abi): introduce macro impl_codec for encoding ABIs
Browse files Browse the repository at this point in the history
  • Loading branch information
clearloop committed Dec 15, 2023
1 parent 4156945 commit 4ba923d
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 47 deletions.
46 changes: 46 additions & 0 deletions abi/src/codec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//! Serialization and Deserialization for Zink ABI.
use crate::{Abi, Error, Result};

/// Implement encoding and decoding for Zink ABI.
macro_rules! impl_codec {
($ty:ident) => {
impl $ty {
/// Convert self to bytes.
pub fn to_bytes(&self) -> Result<Vec<u8>> {
postcard::to_stdvec(self).map_err(Into::into)
}

/// Convert self to hex string.
pub fn to_hex(&self) -> Result<String> {
Ok(hex::encode(self.to_bytes()?))
}

/// Convert bytes to self.
pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Result<Self> {
postcard::from_bytes(bytes.as_ref()).map_err(Into::into)
}

/// Convert hex string to self.
pub fn from_hex(hex: impl AsRef<str>) -> Result<Self> {
Self::from_bytes(&hex::decode(hex.as_ref().trim_start_matches("0x"))?)
}
}

impl ToString for $ty {
fn to_string(&self) -> String {
self.to_hex().unwrap_or_default()
}
}

impl core::str::FromStr for $ty {
type Err = Error;

fn from_str(hex: &str) -> Result<Self> {
Self::from_hex(hex)
}
}
};
}

impl_codec!(Abi);
48 changes: 3 additions & 45 deletions abi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,10 @@
//! Utils for generating of zink ABI
pub use self::result::{Error, Result};
use serde::{Deserialize, Serialize};
use sha3::{Digest, Keccak256};

mod codec;
mod result;

/// Generate a keccak hash of the input (sha3)
pub fn keccak256(input: &[u8]) -> [u8; 32] {
let mut hasher = Keccak256::new();
hasher.update(input);
hasher.finalize().into()
}

/// Get function selector from function signature.
pub fn selector(input: &[u8]) -> [u8; 4] {
let mut selector = [0u8; 4];
selector.copy_from_slice(&keccak256(input)[..4]);

selector
}
pub mod util;

/// Function ABI.
#[derive(Debug, Clone, Serialize, Deserialize)]
Expand All @@ -38,34 +24,6 @@ impl Abi {
/// Get function selector.
pub fn selector(&self) -> [u8; 4] {
let sig = self.signature();
let mut selector = [0u8; 4];
selector.copy_from_slice(&keccak256(sig.as_bytes())[..4]);

selector
}

/// Parse ABI from bytes.
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
postcard::from_bytes(bytes).map_err(Into::into)
}

/// Decode ABI form hex string.
pub fn from_hex(hex: &str) -> Result<Self> {
Self::from_bytes(&hex::decode(hex)?)
}

/// Decode ABI form hex string.
pub fn from_hex_bytes(bytes: &[u8]) -> Result<Self> {
Self::from_hex(&String::from_utf8_lossy(bytes))
}

/// Convert ABI to hex string.
pub fn to_hex(&self) -> Result<String> {
self.to_bytes().map(hex::encode)
}

/// Convert ABI to bytes.
pub fn to_bytes(&self) -> Result<Vec<u8>> {
postcard::to_stdvec(&self).map_err(Into::into)
util::selector(&sig.as_bytes())
}
}
17 changes: 17 additions & 0 deletions abi/src/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! Zink ABI utils
use sha3::{Digest, Keccak256};

/// Generate a keccak hash of the input (sha3)
pub fn keccak256(input: &[u8]) -> [u8; 32] {
let mut hasher = Keccak256::new();
hasher.update(input);
hasher.finalize().into()
}

/// Get function selector from function signature.
pub fn selector(input: &[u8]) -> [u8; 4] {
let mut selector = [0u8; 4];
selector.copy_from_slice(&keccak256(input)[..4]);

selector
}
3 changes: 2 additions & 1 deletion codegen/src/dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ impl<'d> Dispatcher<'d> {
return Err(Error::FuncNotImported("emit_abi".into()));
}

Abi::from_hex_bytes(&self.data.load(offset, length as usize)?).map_err(Into::into)
let abi = self.data.load(offset, length as usize)?;
Abi::from_hex(String::from_utf8_lossy(&abi)).map_err(Into::into)
}

/// Emit return of ext function.
Expand Down
2 changes: 1 addition & 1 deletion zint/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ impl Contract {
return Err(anyhow!("no selector provided"));
}

calldata.extend_from_slice(&zabi::selector(&inputs[0].to_vec()));
calldata.extend_from_slice(&zabi::util::selector(&inputs[0].to_vec()));
inputs = &inputs[1..];
}

Expand Down

0 comments on commit 4ba923d

Please sign in to comment.