Skip to content

Commit

Permalink
feat: reject unathorized relayers
Browse files Browse the repository at this point in the history
  • Loading branch information
Farhad-Shabani committed Jan 17, 2025
1 parent d9200b8 commit 87ad5ca
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 5 deletions.
16 changes: 16 additions & 0 deletions cairo-contracts/packages/contracts/src/core.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ pub mod IBCCore {
use starknet_ibc_core::connection::ConnectionEventEmitterComponent;
use starknet_ibc_core::connection::ConnectionHandlerComponent;
use starknet_ibc_core::router::RouterHandlerComponent;
use starknet_ibc_utils::governance::IBCGovernanceComponent;

// -----------------------------------------------------------
// Setup Governance Component
// -----------------------------------------------------------

component!(path: IBCGovernanceComponent, storage: governance, event: IBCGovernanceEvent);

#[abi(embed_v0)]
impl IBCGovernanceImpl = IBCGovernanceComponent::Governance<ContractState>;
impl IBCGovernanceInternalImpl = IBCGovernanceComponent::GovernanceInternalImpl<ContractState>;

// -----------------------------------------------------------
// Setup Client Components
Expand Down Expand Up @@ -77,6 +88,8 @@ pub mod IBCCore {

#[storage]
struct Storage {
#[substorage(v0)]
governance: IBCGovernanceComponent::Storage,
#[substorage(v0)]
client_emitter: ClientEventEmitterComponent::Storage,
#[substorage(v0)]
Expand All @@ -96,6 +109,8 @@ pub mod IBCCore {
#[event]
#[derive(Debug, Drop, starknet::Event)]
pub enum Event {
#[flat]
IBCGovernanceEvent: IBCGovernanceComponent::Event,
#[flat]
ClientEventEmitterEvent: ClientEventEmitterComponent::Event,
#[flat]
Expand All @@ -114,6 +129,7 @@ pub mod IBCCore {

#[constructor]
fn constructor(ref self: ContractState) {
self.governance.initializer();
self.client_handler.initializer();
self.router_handler.initializer();
}
Expand Down
63 changes: 59 additions & 4 deletions cairo-contracts/packages/core/src/client/components/handler.cairo
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#[starknet::component]
pub mod ClientHandlerComponent {
use core::num::traits::Zero;
use starknet::ContractAddress;
use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess};
use starknet::storage::{
Map, StorageMapReadAccess, StorageMapWriteAccess, Vec, VecTrait, MutableVecTrait,
StoragePointerReadAccess, StoragePointerWriteAccess
};
use starknet::{ContractAddress, get_caller_address};
use starknet_ibc_core::client::ClientEventEmitterComponent::ClientEventEmitterTrait;
use starknet_ibc_core::client::ClientEventEmitterComponent;
use starknet_ibc_core::client::interface::{IClientHandler, IRegisterClient};
Expand All @@ -11,9 +14,14 @@ pub mod ClientHandlerComponent {
CreateResponse, UpdateResponse, ClientErrors, ClientContract, ClientContractHandlerTrait
};
use starknet_ibc_core::host::{ClientId, ClientIdImpl};
use starknet_ibc_utils::governance::IBCGovernanceComponent::GovernanceInternalTrait;
use starknet_ibc_utils::governance::IBCGovernanceComponent;

#[storage]
pub struct Storage {
// NOTE: Temporary relayer whitelist for phase two,
// to be replaced after Comet client contract is implemented.
allowed_relayers: Vec<ContractAddress>,
supported_clients: Map<felt252, ContractAddress>,
}

Expand All @@ -29,7 +37,9 @@ pub mod ClientHandlerComponent {
pub impl ClientInitializerImpl<
TContractState, +HasComponent<TContractState>, +Drop<TContractState>
> of ClientInitializerTrait<TContractState> {
fn initializer(ref self: ComponentState<TContractState>) {}
fn initializer(ref self: ComponentState<TContractState>) {
self.write_allowed_relayer(get_caller_address());
}
}

// -----------------------------------------------------------
Expand All @@ -41,7 +51,7 @@ pub mod ClientHandlerComponent {
TContractState,
+HasComponent<TContractState>,
+Drop<TContractState>,
impl EventEmitter: ClientEventEmitterComponent::HasComponent<TContractState>
impl EventEmitter: ClientEventEmitterComponent::HasComponent<TContractState>,
> of IClientHandler<ComponentState<TContractState>> {
fn create_client(
ref self: ComponentState<TContractState>, msg: MsgCreateClient
Expand All @@ -58,6 +68,8 @@ pub mod ClientHandlerComponent {
fn update_client(
ref self: ComponentState<TContractState>, msg: MsgUpdateClient
) -> UpdateResponse {
assert(self.in_allowed_relayers(get_caller_address()), ClientErrors::INVALID_RELAYER);

let mut client = self.get_client(msg.client_id.client_type);

let update_result = client.update(msg.clone());
Expand Down Expand Up @@ -105,6 +117,28 @@ pub mod ClientHandlerComponent {
}
}

// -----------------------------------------------------------
// Allowed Relayers
// -----------------------------------------------------------

#[generate_trait]
pub impl RegisterRelayerImpl<
TContractState,
+HasComponent<TContractState>,
+Drop<TContractState>,
impl Governance: IBCGovernanceComponent::HasComponent<TContractState>
> of RegisterRelayerTrait<TContractState> {
fn register_relayer(
ref self: ComponentState<TContractState>, relayer_address: ContractAddress
) {
let governor = get_dep_component!(@self, Governance).governor();

assert(governor == get_caller_address(), ClientErrors::INVALID_GOVERNOR);

self.write_allowed_relayer(relayer_address);
}
}

// -----------------------------------------------------------
// Client Internal
// -----------------------------------------------------------
Expand All @@ -128,6 +162,21 @@ pub mod ClientHandlerComponent {
pub(crate) impl ClientReaderImpl<
TContractState, +HasComponent<TContractState>, +Drop<TContractState>
> of ClientReaderTrait<TContractState> {
fn in_allowed_relayers(
self: @ComponentState<TContractState>, caller: ContractAddress
) -> bool {
let mut allowed = false;
let mut i = 0;
while i < self.allowed_relayers.len() {
if self.allowed_relayers.at(i).read() == caller {
allowed = true;
break;
}
i += 1;
};
allowed
}

fn read_supported_client(
self: @ComponentState<TContractState>, client_type: felt252
) -> ContractAddress {
Expand All @@ -143,6 +192,12 @@ pub mod ClientHandlerComponent {
pub(crate) impl ClientWriterImpl<
TContractState, +HasComponent<TContractState>, +Drop<TContractState>
> of ClientWriterTrait<TContractState> {
fn write_allowed_relayer(
ref self: ComponentState<TContractState>, relayer_address: ContractAddress
) {
self.allowed_relayers.append().write(relayer_address);
}

fn write_supported_client(
ref self: ComponentState<TContractState>,
client_type: felt252,
Expand Down
2 changes: 2 additions & 0 deletions cairo-contracts/packages/core/src/client/errors.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ pub mod ClientErrors {
pub const EMPTY_CLIENT_MESSAGE: felt252 = 'ICS02: empty client message';
pub const INACTIVE_CLIENT: felt252 = 'ICS02: inactive client';
pub const INVALID_PROOF_HEIGHT: felt252 = 'ICS04: invalid proof height';
pub const INVALID_GOVERNOR: felt252 = 'ICS02: invalid governor';
pub const INVALID_RELAYER: felt252 = 'ICS02: invalid relayer';
pub const INVALID_SUBSTITUTE_CLIENT_ID: felt252 = 'ICS02: invalid subs client id';
pub const OVERFLOWED_HEIGHT: felt252 = 'ICS02: overflowed height';
pub const OVERFLOWED_TIMESTAMP: felt252 = 'ICS02: overflowed timestamp';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#[starknet::component]
pub mod IBCGovernanceComponent {
use starknet::storage::StoragePointerWriteAccess;
use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess};
use starknet::{ContractAddress, get_caller_address};
use starknet_ibc_utils::governance::IGovernance;

Expand All @@ -25,6 +25,10 @@ pub mod IBCGovernanceComponent {
fn initializer(ref self: ComponentState<TContractState>) {
self.governor.write(get_caller_address());
}

fn governor(self: @ComponentState<TContractState>) -> ContractAddress {
self.governor.read()
}
}
}

0 comments on commit 87ad5ca

Please sign in to comment.