Skip to content

Commit

Permalink
TON Bridge (#83)
Browse files Browse the repository at this point in the history
* Add types

Signed-off-by: Vladimir Stepanenko <[email protected]>

* Add jetton app

Signed-off-by: Vladimir Stepanenko <[email protected]>

* Remove unneeded config fields

Signed-off-by: Vladimir Stepanenko <[email protected]>

* Fix calls encoding

Signed-off-by: Vladimir Stepanenko <[email protected]>

* Default additional data

Signed-off-by: Vladimir Stepanenko <[email protected]>

* Generic call origin

Signed-off-by: Vladimir Stepanenko <[email protected]>

* Generic dispatch

Signed-off-by: Vladimir Stepanenko <[email protected]>

* Add TON commitment support

Signed-off-by: Vladimir Stepanenko <[email protected]>

* Fix TON call decoding

Signed-off-by: Vladimir Stepanenko <[email protected]>

* Improve TonBalance type

Signed-off-by: Vladimir Stepanenko <[email protected]>

* Fix TON bridge verification

Signed-off-by: Vladimir Stepanenko <[email protected]>

* Fix and add tests

Signed-off-by: Vladimir Stepanenko <[email protected]>

* Fix clippy warnings

Signed-off-by: Vladimir Stepanenko <[email protected]>

* Fix dispatch benchmarks

Signed-off-by: Vladimir Stepanenko <[email protected]>

* Add weights

Signed-off-by: Vladimir Stepanenko <[email protected]>

* Fix docs

Signed-off-by: Vladimir Stepanenko <[email protected]>

---------

Signed-off-by: Vladimir Stepanenko <[email protected]>
  • Loading branch information
vovac12 authored Aug 1, 2024
1 parent c1d5bd0 commit 2269286
Show file tree
Hide file tree
Showing 27 changed files with 2,181 additions and 87 deletions.
26 changes: 26 additions & 0 deletions Cargo.lock

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

107 changes: 92 additions & 15 deletions pallets/channel/src/inbound/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ pub use pallet::*;
pub mod pallet {
use super::*;
use bridge_types::evm::AdditionalEVMInboundData;
use bridge_types::types::MessageStatus;
use bridge_types::ton::{AdditionalTONInboundData, TonAddress, TonNetworkId};
use bridge_types::types::{GenericAdditionalInboundData, MessageStatus};
use bridge_types::{EVMChainId, GenericNetworkId, GenericTimepoint};
use frame_support::log::warn;
use frame_support::pallet_prelude::{InvalidTransaction, *};
Expand All @@ -76,14 +77,11 @@ pub mod pallet {
type Verifier: Verifier;

/// Verifier module for message verification.
type SubstrateMessageDispatch: MessageDispatch<Self, SubNetworkId, MessageId, ()>;

/// Verifier module for message verification.
type EVMMessageDispatch: MessageDispatch<
type MessageDispatch: MessageDispatch<
Self,
EVMChainId,
GenericNetworkId,
MessageId,
AdditionalEVMInboundData,
GenericAdditionalInboundData,
>;

type OutboundChannel: OutboundChannel<
Expand Down Expand Up @@ -141,6 +139,10 @@ pub mod pallet {
pub type EVMChannelAddresses<T: Config> =
StorageMap<_, Identity, EVMChainId, H160, OptionQuery>;

#[pallet::storage]
pub type TONChannelAddresses<T: Config> =
StorageMap<_, Identity, TonNetworkId, TonAddress, OptionQuery>;

/// The current storage version.
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);

Expand Down Expand Up @@ -192,15 +194,18 @@ pub mod pallet {
<T as frame_system::Config>::BlockWeights::get().max_block
}
bridge_types::evm::Commitment::Inbound(commitment) => {
T::EVMMessageDispatch::dispatch_weight(&commitment.payload)
T::MessageDispatch::dispatch_weight(&commitment.payload)
}
bridge_types::evm::Commitment::StatusReport(_) => Default::default(),
bridge_types::evm::Commitment::BaseFeeUpdate(_) => Default::default(),
},
bridge_types::GenericCommitment::TON(bridge_types::ton::Commitment::Inbound(
commitment,
)) => T::MessageDispatch::dispatch_weight(&commitment.payload),
bridge_types::GenericCommitment::Sub(commitment) => commitment
.messages
.iter()
.map(|m| T::SubstrateMessageDispatch::dispatch_weight(&m.payload))
.map(|m| T::MessageDispatch::dispatch_weight(&m.payload))
.fold(Weight::zero(), |acc, w| acc.saturating_add(w)),
};

Expand All @@ -218,6 +223,13 @@ pub mod pallet {
Ok(())
}

fn ensure_ton_channel(network_id: TonNetworkId, channel: TonAddress) -> DispatchResult {
let channel_address =
TONChannelAddresses::<T>::get(network_id).ok_or(Error::<T>::InvalidNetwork)?;
ensure!(channel_address == channel, Error::<T>::InvalidSourceChannel);
Ok(())
}

fn ensure_channel_nonce(network_id: GenericNetworkId, new_nonce: u64) -> DispatchResult {
let nonce = ChannelNonces::<T>::get(network_id);
ensure!(nonce + 1 == new_nonce, Error::<T>::InvalidNonce);
Expand Down Expand Up @@ -254,6 +266,49 @@ pub mod pallet {
Ok(())
}

fn handle_ton_commitment(
network_id: TonNetworkId,
commitment: bridge_types::ton::Commitment<T::MaxMessagePayloadSize>,
) -> DispatchResult {
Self::verify_ton_commitment(network_id, &commitment)?;
let network_id = GenericNetworkId::TON(network_id);
match commitment {
bridge_types::ton::Commitment::Inbound(inbound_commitment) => {
Self::update_channel_nonce(network_id, inbound_commitment.nonce)?;
let message_id = MessageId::basic(
network_id,
T::ThisNetworkId::get(),
inbound_commitment.nonce,
);
T::MessageDispatch::dispatch(
network_id,
message_id,
GenericTimepoint::TON(inbound_commitment.transaction_id),
&inbound_commitment.payload,
AdditionalTONInboundData {
source: inbound_commitment.source,
}
.into(),
);
}
}
Ok(())
}

fn verify_ton_commitment(
ton_network_id: TonNetworkId,
commitment: &bridge_types::ton::Commitment<T::MaxMessagePayloadSize>,
) -> DispatchResult {
let network_id = GenericNetworkId::TON(ton_network_id);
match commitment {
bridge_types::ton::Commitment::Inbound(inbound_commitment) => {
Self::ensure_ton_channel(ton_network_id, inbound_commitment.channel)?;
Self::ensure_channel_nonce(network_id, inbound_commitment.nonce)?;
}
}
Ok(())
}

fn handle_evm_commitment(
chain_id: EVMChainId,
commitment: bridge_types::evm::Commitment<
Expand All @@ -271,14 +326,15 @@ pub mod pallet {
T::ThisNetworkId::get(),
inbound_commitment.nonce,
);
T::EVMMessageDispatch::dispatch(
chain_id,
T::MessageDispatch::dispatch(
chain_id.into(),
message_id,
GenericTimepoint::EVM(inbound_commitment.block_number),
&inbound_commitment.payload,
AdditionalEVMInboundData {
source: inbound_commitment.source,
},
}
.into(),
);
}
bridge_types::evm::Commitment::StatusReport(status_report) => {
Expand Down Expand Up @@ -377,12 +433,12 @@ pub mod pallet {
commitment.nonce,
idx as u64,
);
T::SubstrateMessageDispatch::dispatch(
sub_network_id,
T::MessageDispatch::dispatch(
sub_network_id.into(),
message_id,
message.timepoint,
&message.payload,
(),
GenericAdditionalInboundData::Sub,
);
}
Ok(())
Expand Down Expand Up @@ -426,6 +482,10 @@ pub mod pallet {
GenericNetworkId::Sub(sub_network_id),
bridge_types::GenericCommitment::Sub(sub_commitment),
) => Self::handle_sub_commitment(sub_network_id, sub_commitment)?,
(
GenericNetworkId::TON(ton_network_id),
bridge_types::GenericCommitment::TON(ton_commitment),
) => Self::handle_ton_commitment(ton_network_id, ton_commitment)?,
_ => {
frame_support::fail!(Error::<T>::InvalidCommitment);
}
Expand All @@ -444,6 +504,18 @@ pub mod pallet {
EVMChannelAddresses::<T>::insert(network_id, channel_address);
Ok(().into())
}

#[pallet::call_index(2)]
#[pallet::weight(0)]
pub fn register_ton_channel(
origin: OriginFor<T>,
network_id: TonNetworkId,
channel_address: TonAddress,
) -> DispatchResultWithPostInfo {
ensure_root(origin)?;
TONChannelAddresses::<T>::insert(network_id, channel_address);
Ok(().into())
}
}

#[pallet::validate_unsigned]
Expand All @@ -468,6 +540,11 @@ pub mod pallet {
bridge_types::GenericCommitment::Sub(sub_commitment),
) => Self::verify_sub_commitment(*sub_network_id, sub_commitment)
.map_err(|_| InvalidTransaction::BadProof)?,
(
GenericNetworkId::TON(ton_network_id),
bridge_types::GenericCommitment::TON(ton_commitment),
) => Self::verify_ton_commitment(*ton_network_id, ton_commitment)
.map_err(|_| InvalidTransaction::BadProof)?,
_ => {
return Err(InvalidTransaction::BadProof.into());
}
Expand Down
27 changes: 6 additions & 21 deletions pallets/channel/src/inbound/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use super::*;
use bridge_types::evm::AdditionalEVMInboundData;
use bridge_types::substrate::BridgeMessage;
use bridge_types::types::GenericAdditionalInboundData;
use codec::{Decode, Encode, MaxEncodedLen};

use frame_support::traits::{Everything, UnfilteredDispatchable};
Expand Down Expand Up @@ -159,6 +159,7 @@ impl Verifier for MockVerifier {
fn verify(network_id: GenericNetworkId, _hash: H256, _proof: &Vec<u8>) -> DispatchResult {
let network_id = match network_id {
bridge_types::GenericNetworkId::EVM(_)
| bridge_types::GenericNetworkId::TON(_)
| bridge_types::GenericNetworkId::EVMLegacy(_) => {
return Err(Error::<Test>::InvalidNetwork.into())
}
Expand All @@ -184,30 +185,15 @@ impl Verifier for MockVerifier {
// Mock Dispatch
pub struct MockMessageDispatch;

impl MessageDispatch<Test, SubNetworkId, MessageId, ()> for MockMessageDispatch {
fn dispatch(_: SubNetworkId, _: MessageId, _: GenericTimepoint, _: &[u8], _: ()) {}

fn dispatch_weight(_: &[u8]) -> frame_support::weights::Weight {
Default::default()
}

#[cfg(feature = "runtime-benchmarks")]
fn successful_dispatch_event(
_: MessageId,
) -> Option<<Test as frame_system::Config>::RuntimeEvent> {
None
}
}

impl MessageDispatch<Test, EVMChainId, MessageId, AdditionalEVMInboundData>
impl MessageDispatch<Test, GenericNetworkId, MessageId, GenericAdditionalInboundData>
for MockMessageDispatch
{
fn dispatch(
_: EVMChainId,
_: GenericNetworkId,
_: MessageId,
_: GenericTimepoint,
_: &[u8],
_: AdditionalEVMInboundData,
_: GenericAdditionalInboundData,
) {
}

Expand Down Expand Up @@ -265,8 +251,7 @@ impl bridge_inbound_channel::Config for Test {
type OutboundChannel = OutboundChannelImpl;
type RuntimeEvent = RuntimeEvent;
type Verifier = MockVerifier;
type EVMMessageDispatch = MockMessageDispatch;
type SubstrateMessageDispatch = MockMessageDispatch;
type MessageDispatch = MockMessageDispatch;
type UnsignedLongevity = ConstU64<100>;
type UnsignedPriority = ConstU64<100>;
type MaxMessagePayloadSize = MaxMessagePayloadSize;
Expand Down
4 changes: 4 additions & 0 deletions pallets/channel/src/outbound/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,10 @@ pub mod pallet {
error!("EVMLegacy messages are not supported by this channel (if you noticed this message, please report it)");
return <T as Config>::WeightInfo::on_initialize_no_messages();
}
GenericNetworkId::TON(_) => {
error!("TON messages are not supported yet by this channel (if you noticed this message, please report it)");
return <T as Config>::WeightInfo::on_initialize_no_messages();
}
};

let commitment_hash = commitment.hash();
Expand Down
2 changes: 1 addition & 1 deletion pallets/dispatch/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "dispatch"
description = "Snowbridge Dispatch Pallet"
description = "Dispatch Pallet"
version = "0.1.1"
edition = "2021"
authors = ['Polka Biome Ltd. <[email protected]>']
Expand Down
14 changes: 7 additions & 7 deletions pallets/dispatch/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@
use super::*;
use bridge_types::evm::AdditionalEVMInboundData;
use bridge_types::traits::MessageDispatch;
use bridge_types::types::GenericAdditionalInboundData;
use bridge_types::types::MessageId;
use bridge_types::EVMChainId;
use bridge_types::GenericNetworkId;
use bridge_types::SubNetworkId;
use frame_benchmarking::benchmarks_instance_pallet;
Expand All @@ -59,8 +59,8 @@ benchmarks_instance_pallet! {
where
<T as crate::Config<I>>::OriginOutput:
bridge_types::traits::BridgeOriginOutput<
NetworkId = EVMChainId,
Additional = AdditionalEVMInboundData
NetworkId = GenericNetworkId,
Additional = GenericAdditionalInboundData
>,
T: crate::Config<I, MessageId = MessageId>,
crate::Event::<T, I>: Into<<T as frame_system::Config>::RuntimeEvent>
Expand All @@ -69,14 +69,14 @@ benchmarks_instance_pallet! {
let message_id = MessageId::basic(GenericNetworkId::EVM([1u8; 32].into()), GenericNetworkId::Sub(SubNetworkId::Mainnet), 1);
}: {
crate::Pallet::<T, I>::dispatch(
[1u8; 32].into(),
H256::repeat_byte(1).into(),
message_id,
Default::default(),
// system.remark()
&[0, 0, 0],
AdditionalEVMInboundData {
source: Default::default()
}
}.into()
)
}
verify {
Expand All @@ -87,13 +87,13 @@ benchmarks_instance_pallet! {
let message_id = MessageId::basic(GenericNetworkId::EVM([1u8; 32].into()), GenericNetworkId::Sub(SubNetworkId::Mainnet), 1);
}: {
crate::Pallet::<T, I>::dispatch(
[1u8; 32].into(),
H256::repeat_byte(1).into(),
message_id,
Default::default(),
&[],
AdditionalEVMInboundData {
source: Default::default()
}
}.into()
)
}
verify {
Expand Down
7 changes: 4 additions & 3 deletions pallets/dispatch/src/mock.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;
use bridge_types::evm::AdditionalEVMInboundData;
use bridge_types::types;
use bridge_types::EVMChainId;
use bridge_types::types::GenericAdditionalInboundData;
use bridge_types::GenericNetworkId;
use frame_support::parameter_types;
use frame_support::traits::{ConstU32, Everything};
use sp_core::H256;
Expand Down Expand Up @@ -69,7 +69,8 @@ impl Contains<RuntimeCall> for CallFilter {

impl dispatch::Config for Test {
type RuntimeEvent = RuntimeEvent;
type OriginOutput = types::CallOriginOutput<EVMChainId, H256, AdditionalEVMInboundData>;
type OriginOutput =
types::CallOriginOutput<GenericNetworkId, H256, GenericAdditionalInboundData>;
type Origin = RuntimeOrigin;
type MessageId = types::MessageId;
type Hashing = Keccak256;
Expand Down
Loading

0 comments on commit 2269286

Please sign in to comment.