Skip to content

Commit

Permalink
Implement Cairo encoding for sum types (#48)
Browse files Browse the repository at this point in the history
* Refactor CombineEncoders to accept type level list of encoders

* Add HList! macro to simplify encoder list

* Add variant encoder and deref encoder

* Implement Option encoder

* Reorganize sum types

* Add sum macro

* Fix lint
  • Loading branch information
soareschen authored Aug 12, 2024
1 parent 2260a5e commit 16ff7ea
Show file tree
Hide file tree
Showing 17 changed files with 203 additions and 26 deletions.
2 changes: 0 additions & 2 deletions relayer/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion relayer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ rust-version = "1.79"
overflow-checks = true

[workspace.dependencies]
ibc = { version = "0.53.0" }
cgp-core = { version = "0.1.0" }
cgp-error-eyre = { version = "0.1.0" }
cgp-component-macro = { version = "0.1.0" }
Expand Down
4 changes: 1 addition & 3 deletions relayer/crates/cairo-encoding-components/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,4 @@ cgp-core = { workspace = true }
hermes-relayer-components = { workspace = true }
hermes-encoding-components = { workspace = true }

starknet = { workspace = true }
serde_json = { workspace = true }
cairo-lang-starknet-classes = { workspace = true }
starknet = { workspace = true }
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,36 @@ use cgp_core::error::HasErrorType;

use crate::traits::encode_mut::{HasEncodeBufferType, MutEncoder};

pub struct Combine<EncoderA, EncoderB>(pub PhantomData<(EncoderA, EncoderB)>);
pub struct CombineEncoders<Encoders>(pub PhantomData<Encoders>);

impl<Encoding, Strategy, EncoderA, EncoderB, Value> MutEncoder<Encoding, Strategy, Value>
for Combine<EncoderA, EncoderB>
impl<Encoding, Strategy, Encoder, InEncoders, Value> MutEncoder<Encoding, Strategy, Value>
for CombineEncoders<(Encoder, InEncoders)>
where
Encoding: HasEncodeBufferType + HasErrorType,
EncoderA: MutEncoder<Encoding, Strategy, Value>,
EncoderB: MutEncoder<Encoding, Strategy, Value>,
Encoder: MutEncoder<Encoding, Strategy, Value>,
CombineEncoders<InEncoders>: MutEncoder<Encoding, Strategy, Value>,
{
fn encode_mut(
encoding: &Encoding,
value: &Value,
buffer: &mut Encoding::EncodeBuffer,
) -> Result<(), Encoding::Error> {
EncoderA::encode_mut(encoding, value, buffer)?;
EncoderB::encode_mut(encoding, value, buffer)?;
Encoder::encode_mut(encoding, value, buffer)?;
<CombineEncoders<InEncoders>>::encode_mut(encoding, value, buffer)?;

Ok(())
}
}

impl<Encoding, Strategy, Value> MutEncoder<Encoding, Strategy, Value> for CombineEncoders<()>
where
Encoding: HasEncodeBufferType + HasErrorType,
{
fn encode_mut(
_encoding: &Encoding,
_value: &Value,
_buffer: &mut Encoding::EncodeBuffer,
) -> Result<(), Encoding::Error> {
Ok(())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ pub mod field;
pub mod from_felt;
pub mod from_u128;
pub mod iter;
pub mod option;
pub mod pair;
pub mod reference;
pub mod string;
pub mod u128;
pub mod u256;
pub mod unit;
pub mod variant;
pub mod vec;
pub mod with_context;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use cgp_core::error::HasErrorType;

use crate::impls::encode_mut::variant::SumEncoders;
use crate::impls::encode_mut::with_context::EncodeWithContext;
use crate::traits::encode_mut::{HasEncodeBufferType, MutEncoder};
use crate::types::either::Either;
use crate::types::nat::Z;
use crate::{HList, Sum};

pub struct EncodeOption;

pub type OptionEncoder = SumEncoders<Z, HList![EncodeWithContext, EncodeWithContext]>;

impl<Encoding, Strategy, Value> MutEncoder<Encoding, Strategy, Option<Value>> for EncodeOption
where
Encoding: HasEncodeBufferType + HasErrorType,
OptionEncoder: for<'a> MutEncoder<Encoding, Strategy, Sum![&'a Value, ()]>,
{
fn encode_mut(
encoding: &Encoding,
value: &Option<Value>,
buffer: &mut Encoding::EncodeBuffer,
) -> Result<(), Encoding::Error> {
let sum = match value {
Some(value) => Either::Left(value),
None => Either::Right(Either::Left(())),
};

OptionEncoder::encode_mut(encoding, &sum, buffer)?;

Ok(())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use std::ops::Deref;

use crate::traits::encode_mut::{CanEncodeMut, MutEncoder};

pub struct EncodeDeref;

impl<Encoding, Strategy, Value> MutEncoder<Encoding, Strategy, Value> for EncodeDeref
where
Encoding: CanEncodeMut<Strategy, Value::Target>,
Value: Deref,
Value::Target: Sized,
{
fn encode_mut(
encoding: &Encoding,
value: &Value,
buffer: &mut Encoding::EncodeBuffer,
) -> Result<(), Encoding::Error> {
encoding.encode_mut(value.deref(), buffer)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use std::marker::PhantomData;

use cgp_core::error::HasErrorType;

use crate::traits::encode_mut::{HasEncodeBufferType, MutEncoder};
use crate::types::either::{Either, Void};
use crate::types::nat::{Nat, S};

pub struct SumEncoders<N, Encoders>(pub PhantomData<(N, Encoders)>);

impl<Encoding, Strategy, ValueA, ValueB, N, Encoder, InEncoders>
MutEncoder<Encoding, Strategy, Either<ValueA, ValueB>> for SumEncoders<N, (Encoder, InEncoders)>
where
Encoding: HasEncodeBufferType + HasErrorType,
Encoder: MutEncoder<Encoding, Strategy, ValueA>,
N: Nat,
SumEncoders<S<N>, InEncoders>: MutEncoder<Encoding, Strategy, ValueB>,
{
fn encode_mut(
encoding: &Encoding,
value: &Either<ValueA, ValueB>,
buffer: &mut <Encoding as HasEncodeBufferType>::EncodeBuffer,
) -> Result<(), <Encoding as HasErrorType>::Error> {
match value {
Either::Left(value) => Encoder::encode_mut(encoding, value, buffer),
Either::Right(value) => {
<SumEncoders<S<N>, InEncoders>>::encode_mut(encoding, value, buffer)
}
}
}
}

impl<Encoding, Strategy, N> MutEncoder<Encoding, Strategy, Void> for SumEncoders<N, ()>
where
Encoding: HasEncodeBufferType + HasErrorType,
{
fn encode_mut(
_encoding: &Encoding,
_value: &Void,
_buffer: &mut Encoding::EncodeBuffer,
) -> Result<(), Encoding::Error> {
Ok(())
}
}
2 changes: 2 additions & 0 deletions relayer/crates/cairo-encoding-components/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@

pub mod components;
pub mod impls;
pub mod macros;
pub mod strategy;
pub mod traits;
pub mod types;
31 changes: 31 additions & 0 deletions relayer/crates/cairo-encoding-components/src/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#[macro_export]
macro_rules! HList {
( $(,)? ) => {
()
};
( $e:ty ) => {
( $e, () )
};
( $e:ty, $($tail:tt)* ) => {
( $e, $crate::HList!( $($tail)* ) )
};
}

#[macro_export]
macro_rules! Sum {
( $(,)? ) => {
$crate::types::either::Void
};
( $e:ty ) => {
$crate::types::either::Either<
$e,
$crate::types::either::Void
>
};
( $e:ty, $($tail:tt)* ) => {
$crate::types::either::Either<
$e,
$crate::Sum!( $($tail)* )
>
};
}
6 changes: 6 additions & 0 deletions relayer/crates/cairo-encoding-components/src/types/either.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pub enum Either<A, B> {
Left(A),
Right(B),
}

pub enum Void {}
2 changes: 2 additions & 0 deletions relayer/crates/cairo-encoding-components/src/types/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod either;
pub mod nat;
17 changes: 17 additions & 0 deletions relayer/crates/cairo-encoding-components/src/types/nat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use core::marker::PhantomData;

pub struct Z;

pub struct S<N>(pub PhantomData<N>);

pub trait Nat {
const N: usize;
}

impl Nat for Z {
const N: usize = 0;
}

impl<N: Nat> Nat for S<N> {
const N: usize = N::N + 1;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use cgp_core::prelude::*;
use hermes_cairo_encoding_components::impls::encode_mut::combine::Combine;
use hermes_cairo_encoding_components::impls::encode_mut::combine::CombineEncoders;
use hermes_cairo_encoding_components::impls::encode_mut::field::EncodeField;
use hermes_cairo_encoding_components::HList;
use starknet::core::types::{Felt, U256};

#[derive(HasField)]
Expand All @@ -12,13 +13,12 @@ pub struct DeployErc20TokenMessage {
pub owner: Felt,
}

pub type DeployErc20TokenMessageEncoder = Combine<
EncodeField<symbol!("name")>,
Combine<
pub type DeployErc20TokenMessageEncoder = CombineEncoders<
HList![
EncodeField<symbol!("name")>,
EncodeField<symbol!("symbol")>,
Combine<
EncodeField<symbol!("fixed_supply")>,
Combine<EncodeField<symbol!("recipient")>, EncodeField<symbol!("owner")>>,
>,
>,
EncodeField<symbol!("fixed_supply")>,
EncodeField<symbol!("recipient")>,
EncodeField<symbol!("owner")>,
],
>;
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use cgp_core::prelude::*;
use hermes_cairo_encoding_components::impls::encode_mut::combine::Combine;
use hermes_cairo_encoding_components::impls::encode_mut::combine::CombineEncoders;
use hermes_cairo_encoding_components::impls::encode_mut::field::EncodeField;
use hermes_cairo_encoding_components::strategy::ViaCairo;
use hermes_cairo_encoding_components::HList;
use hermes_encoding_components::traits::encoder::CanEncode;
use hermes_encoding_components::traits::has_encoding::HasEncoding;
use hermes_relayer_components::chain::traits::types::message::HasMessageType;
Expand All @@ -26,8 +27,12 @@ pub struct TransferErc20TokenMessage {
pub amount: U256,
}

pub type TransferErc20TokenMessageEncoder =
Combine<EncodeField<symbol!("recipient")>, EncodeField<symbol!("amount")>>;
pub type TransferErc20TokenMessageEncoder = CombineEncoders<
HList![
EncodeField<symbol!("recipient")>,
EncodeField<symbol!("amount")>
],
>;

impl<Chain, Encoding> TransferTokenMessageBuilder<Chain> for BuildTransferErc20TokenMessage
where
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use cgp_core::prelude::*;
use hermes_cairo_encoding_components::components::encode_mut::*;
use hermes_cairo_encoding_components::components::encoding::*;
use hermes_cairo_encoding_components::impls::encode_mut::delegate::DelegateEncodeMutComponents;
use hermes_cairo_encoding_components::impls::encode_mut::option::EncodeOption;
use hermes_cairo_encoding_components::impls::encode_mut::pair::EncodeCons;
use hermes_cairo_encoding_components::impls::encode_mut::reference::EncodeDeref;
use hermes_cairo_encoding_components::impls::encode_mut::with_context::EncodeWithContext;
use hermes_cairo_encoding_components::strategy::ViaCairo;
use hermes_cairo_encoding_components::traits::decode_mut::{
Expand Down Expand Up @@ -74,6 +76,8 @@ with_cairo_encode_mut_components! {

delegate_components! {
StarknetEncodeMutComponents {
<'a, V> (ViaCairo, &'a V): EncodeDeref,
<V> (ViaCairo, Option<V>): EncodeOption,
(ViaCairo, TransferErc20TokenMessage): TransferErc20TokenMessageEncoder,
(ViaCairo, DeployErc20TokenMessage): DeployErc20TokenMessageEncoder,
}
Expand Down Expand Up @@ -118,6 +122,8 @@ pub trait CanUseCairoEncoding:
+ CanEncodeAndDecode<ViaCairo, String>
+ CanEncode<ViaCairo, TransferErc20TokenMessage>
+ CanEncode<ViaCairo, DeployErc20TokenMessage>
+ CanEncode<ViaCairo, Option<String>>
+ for<'a> CanEncode<ViaCairo, &'a String>
{
}

Expand Down
2 changes: 1 addition & 1 deletion relayer/crates/starknet-integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ hermes-cosmos-integration-tests = { workspace = true }
starknet = { workspace = true }
url = { workspace = true }
eyre = { workspace = true }
tokio = { workspace = true }
tokio = { workspace = true, features = [ "full" ] }
serde_json = { workspace = true }

0 comments on commit 16ff7ea

Please sign in to comment.