Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Commit

Permalink
Configure InboundQueue allow list (paritytech#862)
Browse files Browse the repository at this point in the history
* added extrinsic

* removed array implementation, added remove item

* fmt

* add back in type info

* fixes

* fixes

* updated cumulus
  • Loading branch information
alistair-singh authored Jun 22, 2023
1 parent 3f08d9b commit 050bdf7
Show file tree
Hide file tree
Showing 7 changed files with 229 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ config_beacon_checkpoint()
send_governance_transact_from_relaychain $bridgehub_para_id "$check_point_call" 180000000000 900000
}

config_inbound_queue()
{
local pallet="30"
local callindex="01"
local payload="0x$pallet$callindex$(address_for OutboundQueue | cut -c3-)"
send_governance_transact_from_relaychain $bridgehub_para_id "$payload" 180000000000 900000
}

wait_beacon_chain_ready()
{
local initial_beacon_block=""
Expand All @@ -24,14 +32,15 @@ wait_beacon_chain_ready()
done
}

function configure_beacon()
function configure_bridgehub()
{
wait_beacon_chain_ready
config_beacon_checkpoint
config_inbound_queue
}

if [ -z "${from_start_services:-}" ]; then
echo "config beacon checkpoint only!"
configure_beacon
configure_bridgehub
wait
fi
8 changes: 4 additions & 4 deletions core/packages/test/scripts/start-services.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ echo "Config beefy client"
source scripts/configure-beefy.sh
configure_beefy

# 6. config beacon client
echo "Config beacon client"
source scripts/configure-beacon.sh
configure_beacon
# 6. config bridgehub
echo "Config bridgehub"
source scripts/configure-bridgehub.sh
configure_bridgehub

if [ "$skip_relayer" == "false" ]; then
# 7. start relayer
Expand Down
44 changes: 39 additions & 5 deletions parachain/pallets/inbound-queue/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use frame_support::{
};
use frame_system::ensure_signed;
use snowbridge_core::ParaId;
use sp_core::{ConstU32, H160};
use sp_core::H160;
use sp_runtime::traits::AccountIdConversion;
use sp_std::{collections::btree_set::BTreeSet, convert::TryFrom, vec::Vec};

Expand All @@ -40,8 +40,6 @@ use scale_info::TypeInfo;
type BalanceOf<T> =
<<T as Config>::Token as Inspect<<T as frame_system::Config>::AccountId>>::Balance;

type AllowListLength = ConstU32<8>;

#[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)]
pub enum MessageDispatchResult {
InvalidPayload,
Expand Down Expand Up @@ -75,6 +73,8 @@ pub mod pallet {
type XcmSender: SendXcm;

type WeightInfo: WeightInfo;

type AllowListLength: Get<u32>;
}

#[pallet::hooks]
Expand All @@ -84,6 +84,8 @@ pub mod pallet {
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T> {
MessageReceived { dest: ParaId, nonce: u64, result: MessageDispatchResult },
AllowListAdded { address: sp_core::H160 },
AllowListRemoved { address: sp_core::H160 },
}

#[pallet::error]
Expand All @@ -96,12 +98,14 @@ pub mod pallet {
InvalidNonce,
/// Cannot convert location
InvalidAccountConversion,
// Allow list is full.
AllowListFull,
}

#[pallet::storage]
#[pallet::getter(fn peer)]
pub type AllowList<T: Config> =
StorageValue<_, BoundedBTreeSet<H160, AllowListLength>, ValueQuery>;
StorageValue<_, BoundedBTreeSet<H160, T::AllowListLength>, ValueQuery>;

#[pallet::storage]
pub type Nonce<T: Config> = StorageMap<_, Twox64Concat, ParaId, u64, ValueQuery>;
Expand All @@ -120,7 +124,7 @@ pub mod pallet {
#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig {
fn build(&self) {
let allowlist: BoundedBTreeSet<H160, AllowListLength> =
let allowlist: BoundedBTreeSet<H160, T::AllowListLength> =
BTreeSet::from_iter(self.allowlist.clone().into_iter())
.try_into()
.expect("exceeded bound");
Expand Down Expand Up @@ -210,5 +214,35 @@ pub mod pallet {

Ok(())
}

#[pallet::call_index(1)]
#[pallet::weight({100_000_000})]
pub fn add_allow_list(origin: OriginFor<T>, address: sp_core::H160) -> DispatchResult {
ensure_root(origin)?;

let success = <AllowList<T>>::mutate(|allowlist| allowlist.try_insert(address).is_ok());

if success {
Self::deposit_event(Event::AllowListAdded { address });

Ok(())
} else {
Err(Error::<T>::AllowListFull.into())
}
}

#[pallet::call_index(2)]
#[pallet::weight({100_000_000})]
pub fn remove_allow_list(origin: OriginFor<T>, address: sp_core::H160) -> DispatchResult {
ensure_root(origin)?;

let removed = <AllowList<T>>::mutate(|allowlist| allowlist.remove(&address));

if removed {
Self::deposit_event(Event::AllowListRemoved { address });
}

Ok(())
}
}
}
121 changes: 120 additions & 1 deletion parachain/pallets/inbound-queue/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use frame_support::{
parameter_types,
traits::{ConstU64, Everything, GenesisBuild},
};
use sp_core::{H160, H256};
use sp_core::{ConstU32, H160, H256};
use sp_keyring::AccountKeyring as Keyring;
use sp_runtime::{
testing::Header,
Expand Down Expand Up @@ -110,6 +110,7 @@ impl inbound_queue::Config for Test {
type Reward = ConstU64<100>;
type XcmSender = ();
type WeightInfo = ();
type AllowListLength = ConstU32<2>;
}

fn last_events(n: usize) -> Vec<RuntimeEvent> {
Expand Down Expand Up @@ -288,3 +289,121 @@ fn test_submit_no_funds_to_reward_relayers() {
);
});
}

#[test]
fn test_add_allow_list_without_root_yields_bad_origin() {
new_tester_with_config(Default::default()).execute_with(|| {
let contract_address = hex!("0000000000000000000000000000000000000000").into();
let relayer: AccountId = Keyring::Bob.into();
let origin = RuntimeOrigin::signed(relayer);
assert_noop!(
InboundQueue::add_allow_list(origin, contract_address),
sp_runtime::DispatchError::BadOrigin,
);
});
}

#[test]
fn test_add_allow_list_with_root_succeeds() {
new_tester_with_config(Default::default()).execute_with(|| {
let origin = RuntimeOrigin::root();
let contract_address = hex!("0000000000000000000000000000000000000000").into();

assert_eq!(<AllowList<Test>>::get().len(), 0);
assert_ok!(InboundQueue::add_allow_list(origin, contract_address));

System::assert_last_event(RuntimeEvent::InboundQueue(crate::Event::AllowListAdded {
address: contract_address,
}));

assert_eq!(<AllowList<Test>>::get().len(), 1);
assert!(<AllowList<Test>>::get().contains(&contract_address));
});
}

#[test]
fn test_add_allow_list_ignores_duplicates() {
new_tester_with_config(Default::default()).execute_with(|| {
let origin = RuntimeOrigin::root();
let contract_address = hex!("0000000000000000000000000000000000000000").into();

assert_eq!(<AllowList<Test>>::get().len(), 0);
assert_ok!(InboundQueue::add_allow_list(origin.clone(), contract_address));
assert_eq!(<AllowList<Test>>::get().len(), 1);
assert!(<AllowList<Test>>::get().contains(&contract_address));
assert_ok!(InboundQueue::add_allow_list(origin, contract_address));
assert_eq!(<AllowList<Test>>::get().len(), 1);
assert!(<AllowList<Test>>::get().contains(&contract_address));
});
}

#[test]
fn test_add_allow_list_fails_when_exceeding_bounds() {
new_tester_with_config(Default::default()).execute_with(|| {
let origin = RuntimeOrigin::root();
let contract_address1 = hex!("0000000000000000000000000000000000000000").into();
let contract_address2 = hex!("1000000000000000000000000000000000000000").into();
let contract_address3 = hex!("3000000000000000000000000000000000000000").into();

assert_eq!(<AllowList<Test>>::get().len(), 0);

assert_ok!(InboundQueue::add_allow_list(origin.clone(), contract_address1));
assert_eq!(<AllowList<Test>>::get().len(), 1);

assert_ok!(InboundQueue::add_allow_list(origin.clone(), contract_address2));
assert_eq!(<AllowList<Test>>::get().len(), 2);

assert_noop!(
InboundQueue::add_allow_list(origin, contract_address3),
Error::<Test>::AllowListFull,
);
assert_eq!(<AllowList<Test>>::get().len(), 2);
});
}

#[test]
fn test_remove_allow_list_without_root_yields_bad_origin() {
new_tester_with_config(Default::default()).execute_with(|| {
let contract_address = hex!("0000000000000000000000000000000000000000").into();
let relayer: AccountId = Keyring::Bob.into();
let origin = RuntimeOrigin::signed(relayer);
assert_noop!(
InboundQueue::remove_allow_list(origin, contract_address),
sp_runtime::DispatchError::BadOrigin,
);
});
}

#[test]
fn test_remove_allow_list_with_root_succeeds() {
new_tester_with_config(Default::default()).execute_with(|| {
let origin = RuntimeOrigin::root();
let contract_address = hex!("0000000000000000000000000000000000000000").into();

assert_eq!(<AllowList<Test>>::get().len(), 0);
assert_ok!(InboundQueue::add_allow_list(origin.clone(), contract_address));
assert_eq!(<AllowList<Test>>::get().len(), 1);

assert_ok!(InboundQueue::remove_allow_list(origin, contract_address));
System::assert_last_event(RuntimeEvent::InboundQueue(crate::Event::AllowListRemoved {
address: contract_address,
}));

assert_eq!(<AllowList<Test>>::get().len(), 0);
assert!(!<AllowList<Test>>::get().contains(&contract_address));
});
}

#[test]
fn test_remove_allow_list_event_not_emitted_for_none_existent_item() {
new_tester_with_config(Default::default()).execute_with(|| {
let origin = RuntimeOrigin::root();
let contract_address = hex!("0000000000000000000000000000000000000000").into();

let start = System::event_count();
assert_ok!(InboundQueue::remove_allow_list(origin, contract_address));
let end = System::event_count();

assert_eq!(start, end); // No new events
});
}
6 changes: 4 additions & 2 deletions relayer/relays/execution/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,10 @@ func (r *Relay) Start(ctx context.Context, eg *errgroup.Group) error {
}

log.WithFields(log.Fields{
"paraNonce": paraNonce,
"ethNonce": ethNonce,
"ethBlockNumber": executionHeaderState.BlockNumber,
"laneId": r.config.Source.LaneID,
"paraNonce": paraNonce,
"ethNonce": ethNonce,
}).Info("Polled Nonces")

if paraNonce == ethNonce {
Expand Down
50 changes: 50 additions & 0 deletions smoketest/tests/create_token.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use snowbridge_smoketest::contracts::{native_tokens, weth9};

use std::{sync::Arc, time::Duration};

use ethers::{
core::types::Address,
middleware::SignerMiddleware,
providers::{Http, Provider},
signers::{LocalWallet, Signer},
};

// The deployment addresses of the following contracts are stable, unless we modify the order in
// contracts are deployed in DeployScript.sol.
const ETHEREUM_API: &str = "http://localhost:8545";
const ETHEREUM_KEY: &str = "0x5e002a1af63fd31f1c25258f3082dc889762664cb8f218d86da85dff8b07b342";
const NATIVE_TOKENS_CONTRACT: &str = "0x8cF6147918A5CBb672703F879f385036f8793a24";
const WETH_CONTRACT: &str = "0x440eDFFA1352B13227e8eE646f3Ea37456deC701";

#[tokio::test]
async fn create_tokens() {
let provider = Provider::<Http>::try_from(ETHEREUM_API)
.unwrap()
.interval(Duration::from_millis(10u64));

let wallet: LocalWallet = ETHEREUM_KEY
.parse::<LocalWallet>()
.unwrap()
.with_chain_id(15u64);

let client = SignerMiddleware::new(provider.clone(), wallet.clone());
let client = Arc::new(client);

let native_tokens_addr = NATIVE_TOKENS_CONTRACT.parse::<Address>().unwrap();
let native_tokens = native_tokens::NativeTokens::new(native_tokens_addr, client.clone());

let weth_addr = WETH_CONTRACT.parse::<Address>().unwrap();
let weth = weth9::WETH9::new(weth_addr, client.clone());

let receipt = native_tokens
.create(weth.address())
.value(1000)
.send()
.await
.unwrap()
.await
.unwrap()
.unwrap();

assert_eq!(receipt.status.unwrap().as_u64(), 1u64);
}

0 comments on commit 050bdf7

Please sign in to comment.