Backport changes from polkadot-sdk/master (#2887)

* Add two new zombienet tests for bridges (manual run) (#3072)

extracted useful code from #2982

This PR:
- adds test 2 for Rococo <> Westend bridge: checks that relayer doesn't
submit any extra headers while there are no any messages;
- adds test 3 for Rococo <> Westend bridge: checks that relayer doesn't
submit any extra headers when there are messages;
- fixes most of comments from #2439 (like: log names, ability to run
specify test number when calling `run-tests.sh`).

Right now of all our tests, only test 2 is working (until BHs will be
upgraded to use async backing), so you can test it with
`./bridges/zombienet/run-tests.sh --test 2` locally.

(cherry picked from commit 2e6067d768)

* [cumulus] Improved check for sane bridge fees calculations (#3175)

- [x] change constants when CI fails (should fail :) )

On the AssetHubRococo: 1701175800126 -> 1700929825257 = 0.15 %
decreased.
```
Feb 02 12:59:05.520 ERROR bridges::estimate: `bridging::XcmBridgeHubRouterBaseFee` actual value: 1701175800126 for runtime: statemine-1006000 (statemine-0.tx14.au1)

Feb 02 13:02:40.647 ERROR bridges::estimate: `bridging::XcmBridgeHubRouterBaseFee` actual value: 1700929825257 for runtime: statemine-1006000 (statemine-0.tx14.au1)

```

On the AssetHubWestend: 2116038876326 -> 1641718372993 = 22.4 %
decreased.
```
Feb 02 12:56:00.880 ERROR bridges::estimate: `bridging::XcmBridgeHubRouterBaseFee` actual value: 2116038876326 for runtime: westmint-1006000 (westmint-0.tx14.au1)

Feb 02 13:04:42.515 ERROR bridges::estimate: `bridging::XcmBridgeHubRouterBaseFee` actual value: 1641718372993 for runtime: westmint-1006000 (westmint-0.tx14.au1)
```

(cherry picked from commit 74b597fcaf)

* Enable async backing on all testnet system chains (#2949)

Built on top of https://github.com/paritytech/polkadot-sdk/pull/2826/
which was a trial run.

Guide:
https://github.com/w3f/polkadot-wiki/blob/master/docs/maintain/maintain-guides-async-backing.md

---------

Signed-off-by: georgepisaltu <george.pisaltu@parity.io>
Co-authored-by: Branislav Kontur <bkontur@gmail.com>
Co-authored-by: Dónal Murray <donal.murray@parity.io>
Co-authored-by: Dmitry Sinyavin <dmitry.sinyavin@parity.io>
Co-authored-by: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com>
Co-authored-by: Svyatoslav Nikolsky <svyatonik@gmail.com>
Co-authored-by: Bastian Köcher <info@kchr.de>
Co-authored-by: georgepisaltu <52418509+georgepisaltu@users.noreply.github.com>
(cherry picked from commit 700d5f85b7)

* Introduce submit_finality_proof_ex call to bridges GRANDPA pallet (#3225)

backport of
https://github.com/paritytech/parity-bridges-common/pull/2821 (see
detailed description there)

(cherry picked from commit a462207158)

* Bridge zombienet tests refactoring (#3260)

Related to https://github.com/paritytech/polkadot-sdk/issues/3242

Reorganizing the bridge zombienet tests in order to:
- separate the environment spawning from the actual tests
- offer better control over the tests and some possibility to
orchestrate them as opposed to running everything from the zndsl file

Only rewrote the asset transfer test using this new "framework". The old
logic and old tests weren't functionally modified or deleted. The plan
is to get feedback on this approach first and if this is agreed upon,
migrate the other 2 tests later in separate PRs and also do other
improvements later.

(cherry picked from commit dfc8e4696c)

* Bridges: add test 0002 to CI (#3310)

Bridges: add test 0002 to CI
(cherry picked from commit 1b66bb51b5)

* Bridge zombienet tests - move all test scripts to the same folder (#3333)

Related to https://github.com/paritytech/polkadot-sdk/issues/3242

(cherry picked from commit 5fc7622cb3)

* Lift dependencies to the workspace (Part 2/x) (#3366)

Lifting some more dependencies to the workspace. Just using the
most-often updated ones for now.
It can be reproduced locally.

```sh
$ zepter transpose dependency lift-to-workspace --ignore-errors syn quote thiserror "regex:^serde.*"

$ zepter transpose dependency lift-to-workspace --version-resolver=highest syn quote thiserror "regex:^serde.*" --fix

$ taplo format --config .config/taplo.toml
```

---------

Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
(cherry picked from commit e89d0fca35)

* Add support for BHP local and BHK local (#3443)

Related to https://github.com/paritytech/polkadot-sdk/issues/3400

Extracting small parts of
https://github.com/paritytech/polkadot-sdk/pull/3429 into separate PR:

- Add support for BHP local and BHK local
- Increase the timeout for the bridge zomienet tests

(cherry picked from commit e4b6b8cd79)

* Bridge zombienet tests: move all "framework" files under one folder (#3462)

Related to https://github.com/paritytech/polkadot-sdk/issues/3400

Moving all bridges testing "framework" files under one folder in order
to be able to download the entire folder when we want to add tests in
other repos

No significant functional changes

(cherry picked from commit 6fc1d41d44)

* Bridge zombienet tests: Check amount received at destination (#3490)

Related to https://github.com/paritytech/polkadot-sdk/issues/3475

(cherry picked from commit 2cdda0e62d)

* FRAME: Create `TransactionExtension` as a replacement for `SignedExtension` (#2280)

Closes #2160

First part of [Extrinsic
Horizon](https://github.com/paritytech/polkadot-sdk/issues/2415)

Introduces a new trait `TransactionExtension` to replace
`SignedExtension`. Introduce the idea of transactions which obey the
runtime's extensions and have according Extension data (né Extra data)
yet do not have hard-coded signatures.

Deprecate the terminology of "Unsigned" when used for
transactions/extrinsics owing to there now being "proper" unsigned
transactions which obey the extension framework and "old-style" unsigned
which do not. Instead we have __*General*__ for the former and
__*Bare*__ for the latter. (Ultimately, the latter will be phased out as
a type of transaction, and Bare will only be used for Inherents.)

Types of extrinsic are now therefore:
- Bare (no hardcoded signature, no Extra data; used to be known as
"Unsigned")
- Bare transactions (deprecated): Gossiped, validated with
`ValidateUnsigned` (deprecated) and the `_bare_compat` bits of
`TransactionExtension` (deprecated).
  - Inherents: Not gossiped, validated with `ProvideInherent`.
- Extended (Extra data): Gossiped, validated via `TransactionExtension`.
  - Signed transactions (with a hardcoded signature).
  - General transactions (without a hardcoded signature).

`TransactionExtension` differs from `SignedExtension` because:
- A signature on the underlying transaction may validly not be present.
- It may alter the origin during validation.
- `pre_dispatch` is renamed to `prepare` and need not contain the checks
present in `validate`.
- `validate` and `prepare` is passed an `Origin` rather than a
`AccountId`.
- `validate` may pass arbitrary information into `prepare` via a new
user-specifiable type `Val`.
- `AdditionalSigned`/`additional_signed` is renamed to
`Implicit`/`implicit`. It is encoded *for the entire transaction* and
passed in to each extension as a new argument to `validate`. This
facilitates the ability of extensions to acts as underlying crypto.

There is a new `DispatchTransaction` trait which contains only default
function impls and is impl'ed for any `TransactionExtension` impler. It
provides several utility functions which reduce some of the tedium from
using `TransactionExtension` (indeed, none of its regular functions
should now need to be called directly).

Three transaction version discriminator ("versions") are now
permissible:
- 0b000000100: Bare (used to be called "Unsigned"): contains Signature
or Extra (extension data). After bare transactions are no longer
supported, this will strictly identify an Inherents only.
- 0b100000100: Old-school "Signed" Transaction: contains Signature and
Extra (extension data).
- 0b010000100: New-school "General" Transaction: contains Extra
(extension data), but no Signature.

For the New-school General Transaction, it becomes trivial for authors
to publish extensions to the mechanism for authorizing an Origin, e.g.
through new kinds of key-signing schemes, ZK proofs, pallet state,
mutations over pre-authenticated origins or any combination of the
above.

Wrap your `SignedExtension`s in `AsTransactionExtension`. This should be
accompanied by renaming your aggregate type in line with the new
terminology. E.g. Before:

```rust
/// The SignedExtension to the basic transaction logic.
pub type SignedExtra = (
	/* snip */
	MySpecialSignedExtension,
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic =
	generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
```

After:

```rust
/// The extension to the basic transaction logic.
pub type TxExtension = (
	/* snip */
	AsTransactionExtension<MySpecialSignedExtension>,
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic =
	generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, TxExtension>;
```

You'll also need to alter any transaction building logic to add a
`.into()` to make the conversion happen. E.g. Before:

```rust
fn construct_extrinsic(
		/* snip */
) -> UncheckedExtrinsic {
	let extra: SignedExtra = (
		/* snip */
		MySpecialSignedExtension::new(/* snip */),
	);
	let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap();
	let signature = payload.using_encoded(|e| sender.sign(e));
	UncheckedExtrinsic::new_signed(
		/* snip */
		Signature::Sr25519(signature),
		extra,
	)
}
```

After:

```rust
fn construct_extrinsic(
		/* snip */
) -> UncheckedExtrinsic {
	let tx_ext: TxExtension = (
		/* snip */
		MySpecialSignedExtension::new(/* snip */).into(),
	);
	let payload = SignedPayload::new(call.clone(), tx_ext.clone()).unwrap();
	let signature = payload.using_encoded(|e| sender.sign(e));
	UncheckedExtrinsic::new_signed(
		/* snip */
		Signature::Sr25519(signature),
		tx_ext,
	)
}
```

Most `SignedExtension`s can be trivially converted to become a
`TransactionExtension`. There are a few things to know.

- Instead of a single trait like `SignedExtension`, you should now
implement two traits individually: `TransactionExtensionBase` and
`TransactionExtension`.
- Weights are now a thing and must be provided via the new function `fn
weight`.

This trait takes care of anything which is not dependent on types
specific to your runtime, most notably `Call`.

- `AdditionalSigned`/`additional_signed` is renamed to
`Implicit`/`implicit`.
- Weight must be returned by implementing the `weight` function. If your
extension is associated with a pallet, you'll probably want to do this
via the pallet's existing benchmarking infrastructure.

Generally:
- `pre_dispatch` is now `prepare` and you *should not reexecute the
`validate` functionality in there*!
- You don't get an account ID any more; you get an origin instead. If
you need to presume an account ID, then you can use the trait function
`AsSystemOriginSigner::as_system_origin_signer`.
- You get an additional ticket, similar to `Pre`, called `Val`. This
defines data which is passed from `validate` into `prepare`. This is
important since you should not be duplicating logic from `validate` to
`prepare`, you need a way of passing your working from the former into
the latter. This is it.
- This trait takes two type parameters: `Call` and `Context`. `Call` is
the runtime call type which used to be an associated type; you can just
move it to become a type parameter for your trait impl. `Context` is not
currently used and you can safely implement over it as an unbounded
type.
- There's no `AccountId` associated type any more. Just remove it.

Regarding `validate`:
- You get three new parameters in `validate`; all can be ignored when
migrating from `SignedExtension`.
- `validate` returns a tuple on success; the second item in the tuple is
the new ticket type `Self::Val` which gets passed in to `prepare`. If
you use any information extracted during `validate` (off-chain and
on-chain, non-mutating) in `prepare` (on-chain, mutating) then you can
pass it through with this. For the tuple's last item, just return the
`origin` argument.

Regarding `prepare`:
- This is renamed from `pre_dispatch`, but there is one change:
- FUNCTIONALITY TO VALIDATE THE TRANSACTION NEED NOT BE DUPLICATED FROM
`validate`!!
- (This is different to `SignedExtension` which was required to run the
same checks in `pre_dispatch` as in `validate`.)

Regarding `post_dispatch`:
- Since there are no unsigned transactions handled by
`TransactionExtension`, `Pre` is always defined, so the first parameter
is `Self::Pre` rather than `Option<Self::Pre>`.

If you make use of `SignedExtension::validate_unsigned` or
`SignedExtension::pre_dispatch_unsigned`, then:
- Just use the regular versions of these functions instead.
- Have your logic execute in the case that the `origin` is `None`.
- Ensure your transaction creation logic creates a General Transaction
rather than a Bare Transaction; this means having to include all
`TransactionExtension`s' data.
- `ValidateUnsigned` can still be used (for now) if you need to be able
to construct transactions which contain none of the extension data,
however these will be phased out in stage 2 of the Transactions Horizon,
so you should consider moving to an extension-centric design.

- [x] Introduce `CheckSignature` impl of `TransactionExtension` to
ensure it's possible to have crypto be done wholly in a
`TransactionExtension`.
- [x] Deprecate `SignedExtension` and move all uses in codebase to
`TransactionExtension`.
  - [x] `ChargeTransactionPayment`
  - [x] `DummyExtension`
  - [x] `ChargeAssetTxPayment` (asset-tx-payment)
  - [x] `ChargeAssetTxPayment` (asset-conversion-tx-payment)
  - [x] `CheckWeight`
  - [x] `CheckTxVersion`
  - [x] `CheckSpecVersion`
  - [x] `CheckNonce`
  - [x] `CheckNonZeroSender`
  - [x] `CheckMortality`
  - [x] `CheckGenesis`
  - [x] `CheckOnlySudoAccount`
  - [x] `WatchDummy`
  - [x] `PrevalidateAttests`
  - [x] `GenericSignedExtension`
  - [x] `SignedExtension` (chain-polkadot-bulletin)
  - [x] `RefundSignedExtensionAdapter`
- [x] Implement `fn weight` across the board.
- [ ] Go through all pre-existing extensions which assume an account
signer and explicitly handle the possibility of another kind of origin.
- [x] `CheckNonce` should probably succeed in the case of a non-account
origin.
- [x] `CheckNonZeroSender` should succeed in the case of a non-account
origin.
- [x] `ChargeTransactionPayment` and family should fail in the case of a
non-account origin.
  - [ ]
- [x] Fix any broken tests.

---------

Signed-off-by: georgepisaltu <george.pisaltu@parity.io>
Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Signed-off-by: Alexandru Gheorghe <alexandru.gheorghe@parity.io>
Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>
Co-authored-by: Nikhil Gupta <17176722+gupnik@users.noreply.github.com>
Co-authored-by: georgepisaltu <52418509+georgepisaltu@users.noreply.github.com>
Co-authored-by: Chevdor <chevdor@users.noreply.github.com>
Co-authored-by: Bastian Köcher <git@kchr.de>
Co-authored-by: Maciej <maciej.zyszkiewicz@parity.io>
Co-authored-by: Javier Viola <javier@parity.io>
Co-authored-by: Marcin S. <marcin@realemail.net>
Co-authored-by: Tsvetomir Dimitrov <tsvetomir@parity.io>
Co-authored-by: Javier Bullrich <javier@bullrich.dev>
Co-authored-by: Koute <koute@users.noreply.github.com>
Co-authored-by: Adrian Catangiu <adrian@parity.io>
Co-authored-by: Vladimir Istyufeev <vladimir@parity.io>
Co-authored-by: Ross Bulat <ross@parity.io>
Co-authored-by: Gonçalo Pestana <g6pestana@gmail.com>
Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>
Co-authored-by: Svyatoslav Nikolsky <svyatonik@gmail.com>
Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com>
Co-authored-by: ordian <write@reusable.software>
Co-authored-by: Sebastian Kunert <skunert49@gmail.com>
Co-authored-by: Aaro Altonen <48052676+altonen@users.noreply.github.com>
Co-authored-by: Dmitry Markin <dmitry@markin.tech>
Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com>
Co-authored-by: Alexander Samusev <41779041+alvicsam@users.noreply.github.com>
Co-authored-by: Julian Eager <eagr@tutanota.com>
Co-authored-by: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com>
Co-authored-by: Davide Galassi <davxy@datawok.net>
Co-authored-by: Dónal Murray <donal.murray@parity.io>
Co-authored-by: yjh <yjh465402634@gmail.com>
Co-authored-by: Tom Mi <tommi@niemi.lol>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Will | Paradox | ParaNodes.io <79228812+paradox-tt@users.noreply.github.com>
Co-authored-by: Bastian Köcher <info@kchr.de>
Co-authored-by: Joshy Orndorff <JoshOrndorff@users.noreply.github.com>
Co-authored-by: Joshy Orndorff <git-user-email.h0ly5@simplelogin.com>
Co-authored-by: PG Herveou <pgherveou@gmail.com>
Co-authored-by: Alexander Theißen <alex.theissen@me.com>
Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: Juan Girini <juangirini@gmail.com>
Co-authored-by: bader y <ibnbassem@gmail.com>
Co-authored-by: James Wilson <james@jsdw.me>
Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
Co-authored-by: asynchronous rob <rphmeier@gmail.com>
Co-authored-by: Parth <desaiparth08@gmail.com>
Co-authored-by: Andrew Jones <ascjones@gmail.com>
Co-authored-by: Jonathan Udd <jonathan@dwellir.com>
Co-authored-by: Serban Iorga <serban@parity.io>
Co-authored-by: Egor_P <egor@parity.io>
Co-authored-by: Branislav Kontur <bkontur@gmail.com>
Co-authored-by: Evgeny Snitko <evgeny@parity.io>
Co-authored-by: Just van Stam <vstam1@users.noreply.github.com>
Co-authored-by: Francisco Aguirre <franciscoaguirreperez@gmail.com>
Co-authored-by: gupnik <nikhilgupta.iitk@gmail.com>
Co-authored-by: dzmitry-lahoda <dzmitry@lahoda.pro>
Co-authored-by: zhiqiangxu <652732310@qq.com>
Co-authored-by: Nazar Mokrynskyi <nazar@mokrynskyi.com>
Co-authored-by: Anwesh <anweshknayak@gmail.com>
Co-authored-by: cheme <emericchevalier.pro@gmail.com>
Co-authored-by: Sam Johnson <sam@durosoft.com>
Co-authored-by: kianenigma <kian@parity.io>
Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com>
Co-authored-by: Muharem <ismailov.m.h@gmail.com>
Co-authored-by: joepetrowski <joe@parity.io>
Co-authored-by: Alexandru Gheorghe <49718502+alexggh@users.noreply.github.com>
Co-authored-by: Gabriel Facco de Arruda <arrudagates@gmail.com>
Co-authored-by: Squirrel <gilescope@gmail.com>
Co-authored-by: Andrei Sandu <54316454+sandreim@users.noreply.github.com>
Co-authored-by: georgepisaltu <george.pisaltu@parity.io>
Co-authored-by: command-bot <>
(cherry picked from commit fd5f9292f5)

* Revert "FRAME: Create `TransactionExtension` as a replacement for `SignedExtension` (#2280)" (#3665)

This PR reverts #2280 which introduced `TransactionExtension` to replace
`SignedExtension`.

As a result of the discussion
[here](https://github.com/paritytech/polkadot-sdk/pull/3623#issuecomment-1986789700),
the changes will be reverted for now with plans to reintroduce the
concept in the future.

---------

Signed-off-by: georgepisaltu <george.pisaltu@parity.io>
(cherry picked from commit bbd51ce867)

* Increase timeout for assertions (#3680)

Prevents timeouts in ci like
https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/5516019

(cherry picked from commit c4c9257386)

* Removes `as [disambiguation_path]` from `derive_impl` usage (#3652)

Step in https://github.com/paritytech/polkadot-sdk/issues/171

This PR removes `as [disambiguation_path]` syntax from `derive_impl`
usage across the polkadot-sdk as introduced in
https://github.com/paritytech/polkadot-sdk/pull/3505

(cherry picked from commit 7099f6e1b1)

* Fix typo (#3691)

(cherry picked from commit 6b1179f13b)

* Bridge zombienet tests: remove unneeded accounts (#3700)

Bridge zombienet tests: remove unneeded accounts

(cherry picked from commit 0c6c837f68)

* Fix typos (#3753)

(cherry picked from commit 7241a8db7b)

* Update polkadot-sdk refs

* Fix dependency conflicts

* Fix build

* cargo fmt

* Fix spellcheck test

---------

Co-authored-by: Svyatoslav Nikolsky <svyatonik@gmail.com>
Co-authored-by: Branislav Kontur <bkontur@gmail.com>
Co-authored-by: Marcin S <marcin@realemail.net>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: Gavin Wood <gavin@parity.io>
Co-authored-by: georgepisaltu <52418509+georgepisaltu@users.noreply.github.com>
Co-authored-by: Javier Viola <363911+pepoviola@users.noreply.github.com>
Co-authored-by: gupnik <nikhilgupta.iitk@gmail.com>
Co-authored-by: jokess123 <163112061+jokess123@users.noreply.github.com>
Co-authored-by: slicejoke <163888128+slicejoke@users.noreply.github.com>
This commit is contained in:
Serban Iorga
2024-03-25 08:50:57 +01:00
committed by Bastian Köcher
parent 3643f721d4
commit 79d9164fd0
81 changed files with 3071 additions and 340 deletions
-1
View File
@@ -93,7 +93,6 @@ runtime-benchmarks = [
"pallet-bridge-messages/runtime-benchmarks",
"pallet-bridge-parachains/runtime-benchmarks",
"pallet-bridge-relayers/runtime-benchmarks",
"pallet-transaction-payment/runtime-benchmarks",
"pallet-utility/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
+31 -41
View File
@@ -105,48 +105,43 @@ macro_rules! generate_bridge_reject_obsolete_headers_and_messages {
($call:ty, $account_id:ty, $($filter_call:ty),*) => {
#[derive(Clone, codec::Decode, Default, codec::Encode, Eq, PartialEq, sp_runtime::RuntimeDebug, scale_info::TypeInfo)]
pub struct BridgeRejectObsoleteHeadersAndMessages;
impl sp_runtime::traits::TransactionExtensionBase for BridgeRejectObsoleteHeadersAndMessages {
impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteHeadersAndMessages {
const IDENTIFIER: &'static str = "BridgeRejectObsoleteHeadersAndMessages";
type Implicit = ();
}
impl<Context> sp_runtime::traits::TransactionExtension<$call, Context> for BridgeRejectObsoleteHeadersAndMessages {
type AccountId = $account_id;
type Call = $call;
type AdditionalSigned = ();
type Pre = ();
type Val = ();
fn additional_signed(&self) -> sp_std::result::Result<
(),
sp_runtime::transaction_validity::TransactionValidityError,
> {
Ok(())
}
fn validate(
&self,
origin: <$call as sp_runtime::traits::Dispatchable>::RuntimeOrigin,
call: &$call,
_info: &sp_runtime::traits::DispatchInfoOf<$call>,
_who: &Self::AccountId,
call: &Self::Call,
_info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
_len: usize,
_context: &mut Context,
_self_implicit: Self::Implicit,
_inherited_implication: &impl codec::Encode,
) -> Result<
(
sp_runtime::transaction_validity::ValidTransaction,
Self::Val,
<$call as sp_runtime::traits::Dispatchable>::RuntimeOrigin,
), sp_runtime::transaction_validity::TransactionValidityError
> {
let tx_validity = sp_runtime::transaction_validity::ValidTransaction::default();
) -> sp_runtime::transaction_validity::TransactionValidity {
let valid = sp_runtime::transaction_validity::ValidTransaction::default();
$(
let call_filter_validity = <$filter_call as $crate::BridgeRuntimeFilterCall<$call>>::validate(call)?;
let tx_validity = tx_validity.combine_with(call_filter_validity);
let valid = valid
.combine_with(<$filter_call as $crate::BridgeRuntimeFilterCall<$call>>::validate(call)?);
)*
Ok((tx_validity, (), origin))
Ok(valid)
}
fn prepare(
fn pre_dispatch(
self,
_val: Self::Val,
_origin: &<$call as sp_runtime::traits::Dispatchable>::RuntimeOrigin,
_call: &$call,
_info: &sp_runtime::traits::DispatchInfoOf<$call>,
_len: usize,
_context: &Context,
who: &Self::AccountId,
call: &Self::Call,
info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
len: usize,
) -> Result<Self::Pre, sp_runtime::transaction_validity::TransactionValidityError> {
Ok(())
self.validate(who, call, info, len).map(drop)
}
}
};
@@ -155,14 +150,12 @@ macro_rules! generate_bridge_reject_obsolete_headers_and_messages {
#[cfg(test)]
mod tests {
use crate::BridgeRuntimeFilterCall;
use codec::Encode;
use frame_support::assert_err;
use frame_support::{assert_err, assert_ok};
use sp_runtime::{
traits::DispatchTransaction,
traits::SignedExtension,
transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction},
};
#[derive(Encode)]
pub struct MockCall {
data: u32,
}
@@ -213,20 +206,17 @@ mod tests {
);
assert_err!(
BridgeRejectObsoleteHeadersAndMessages.validate_only((), &MockCall { data: 1 }, &(), 0),
BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 1 }, &(), 0),
InvalidTransaction::Custom(1)
);
assert_err!(
BridgeRejectObsoleteHeadersAndMessages.validate_only((), &MockCall { data: 2 }, &(), 0),
BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 2 }, &(), 0),
InvalidTransaction::Custom(2)
);
assert_eq!(
BridgeRejectObsoleteHeadersAndMessages
.validate_only((), &MockCall { data: 3 }, &(), 0)
.unwrap()
.0,
assert_ok!(
BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 3 }, &(), 0),
ValidTransaction { priority: 3, ..Default::default() }
)
}
+4 -3
View File
@@ -141,7 +141,7 @@ parameter_types! {
pub const ReserveId: [u8; 8] = *b"brdgrlrs";
}
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
impl frame_system::Config for TestRuntime {
type Hash = ThisChainHash;
type Hashing = ThisChainHasher;
@@ -158,13 +158,13 @@ impl pallet_utility::Config for TestRuntime {
type WeightInfo = ();
}
#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)]
#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)]
impl pallet_balances::Config for TestRuntime {
type ReserveIdentifier = [u8; 8];
type AccountStore = System;
}
#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig as pallet_transaction_payment::DefaultConfig)]
#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig)]
impl pallet_transaction_payment::Config for TestRuntime {
type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, ()>;
type OperationalFeeMultiplier = ConstU8<5>;
@@ -177,6 +177,7 @@ impl pallet_transaction_payment::Config for TestRuntime {
MinimumMultiplier,
MaximumMultiplier,
>;
type RuntimeEvent = RuntimeEvent;
}
impl pallet_bridge_grandpa::Config for TestRuntime {
@@ -128,7 +128,7 @@ mod integrity_tests {
Runtime::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
BalanceOf<Runtime>: Send + Sync + FixedPointOperand,
{
// esimate priority of transaction that delivers one message and has large tip
// estimate priority of transaction that delivers one message and has large tip
let maximal_messages_in_delivery_transaction =
Runtime::MaxUnconfirmedMessagesAtInboundLane::get();
let small_with_tip_priority =
@@ -169,15 +169,12 @@ mod integrity_tests {
// nodes to the proof (x0.5 because we expect some nodes to be reused)
let estimated_message_size = 512;
// let's say all our messages have the same dispatch weight
let estimated_message_dispatch_weight = <Runtime as pallet_bridge_messages::Config<
MessagesInstance,
>>::WeightInfo::message_dispatch_weight(
estimated_message_size
);
let estimated_message_dispatch_weight =
Runtime::WeightInfo::message_dispatch_weight(estimated_message_size);
// messages proof argument size is (for every message) messages size + some additional
// trie nodes. Some of them are reused by different messages, so let's take 2/3 of default
// "overhead" constant
let messages_proof_size = <Runtime as pallet_bridge_messages::Config<MessagesInstance>>::WeightInfo::expected_extra_storage_proof_size()
let messages_proof_size = Runtime::WeightInfo::expected_extra_storage_proof_size()
.saturating_mul(2)
.saturating_div(3)
.saturating_add(estimated_message_size)
@@ -185,7 +182,7 @@ mod integrity_tests {
// finally we are able to estimate transaction size and weight
let transaction_size = base_tx_size.saturating_add(messages_proof_size);
let transaction_weight = <Runtime as pallet_bridge_messages::Config<MessagesInstance>>::WeightInfo::receive_messages_proof_weight(
let transaction_weight = Runtime::WeightInfo::receive_messages_proof_weight(
&PreComputedSize(transaction_size as _),
messages as _,
estimated_message_dispatch_weight.saturating_mul(messages),
@@ -16,7 +16,7 @@
//! Signed extension that refunds relayer if he has delivered some new messages.
//! It also refunds transaction cost if the transaction is an `utility.batchAll()`
//! with calls that are: delivering new messsage and all necessary underlying headers
//! with calls that are: delivering new message and all necessary underlying headers
//! (parachain or relay chain).
use crate::messages_call_ext::{
@@ -48,12 +48,9 @@ use pallet_transaction_payment::{Config as TransactionPaymentConfig, OnChargeTra
use pallet_utility::{Call as UtilityCall, Config as UtilityConfig, Pallet as UtilityPallet};
use scale_info::TypeInfo;
use sp_runtime::{
traits::{
AsSystemOriginSigner, DispatchInfoOf, Dispatchable, Get, PostDispatchInfoOf,
TransactionExtension, TransactionExtensionBase, ValidateResult, Zero,
},
traits::{DispatchInfoOf, Dispatchable, Get, PostDispatchInfoOf, SignedExtension, Zero},
transaction_validity::{
InvalidTransaction, TransactionPriority, TransactionValidityError, ValidTransactionBuilder,
TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransactionBuilder,
},
DispatchResult, FixedPointOperand, RuntimeDebug,
};
@@ -242,8 +239,8 @@ pub enum RelayerAccountAction<AccountId, Reward> {
Slash(AccountId, RewardsAccountParams),
}
/// Everything common among our refund transaction extensions.
pub trait RefundTransactionExtension:
/// Everything common among our refund signed extensions.
pub trait RefundSignedExtension:
'static + Clone + Codec + sp_std::fmt::Debug + Default + Eq + PartialEq + Send + Sync + TypeInfo
where
<Self::Runtime as GrandpaConfig<Self::GrandpaInstance>>::BridgedChain:
@@ -459,8 +456,8 @@ where
}
}
/// Adapter that allow implementing `sp_runtime::traits::TransactionExtension` for any
/// `RefundTransactionExtension`.
/// Adapter that allow implementing `sp_runtime::traits::SignedExtension` for any
/// `RefundSignedExtension`.
#[derive(
DefaultNoBound,
CloneNoBound,
@@ -471,13 +468,12 @@ where
RuntimeDebugNoBound,
TypeInfo,
)]
pub struct RefundTransactionExtensionAdapter<T: RefundTransactionExtension>(T)
pub struct RefundSignedExtensionAdapter<T: RefundSignedExtension>(T)
where
<T::Runtime as GrandpaConfig<T::GrandpaInstance>>::BridgedChain:
Chain<BlockNumber = RelayBlockNumber>;
impl<T: RefundTransactionExtension> TransactionExtensionBase
for RefundTransactionExtensionAdapter<T>
impl<T: RefundSignedExtension> SignedExtension for RefundSignedExtensionAdapter<T>
where
<T::Runtime as GrandpaConfig<T::GrandpaInstance>>::BridgedChain:
Chain<BlockNumber = RelayBlockNumber>,
@@ -487,35 +483,22 @@ where
+ MessagesCallSubType<T::Runtime, <T::Msgs as RefundableMessagesLaneId>::Instance>,
{
const IDENTIFIER: &'static str = T::Id::STR;
type Implicit = ();
}
impl<T: RefundTransactionExtension, Context> TransactionExtension<CallOf<T::Runtime>, Context>
for RefundTransactionExtensionAdapter<T>
where
<T::Runtime as GrandpaConfig<T::GrandpaInstance>>::BridgedChain:
Chain<BlockNumber = RelayBlockNumber>,
CallOf<T::Runtime>: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>
+ IsSubType<CallableCallFor<UtilityPallet<T::Runtime>, T::Runtime>>
+ GrandpaCallSubType<T::Runtime, T::GrandpaInstance>
+ MessagesCallSubType<T::Runtime, <T::Msgs as RefundableMessagesLaneId>::Instance>,
<CallOf<T::Runtime> as Dispatchable>::RuntimeOrigin:
AsSystemOriginSigner<AccountIdOf<T::Runtime>> + Clone,
{
type AccountId = AccountIdOf<T::Runtime>;
type Call = CallOf<T::Runtime>;
type AdditionalSigned = ();
type Pre = Option<PreDispatchData<AccountIdOf<T::Runtime>>>;
type Val = Option<CallInfo>;
fn additional_signed(&self) -> Result<(), TransactionValidityError> {
Ok(())
}
fn validate(
&self,
origin: <CallOf<T::Runtime> as Dispatchable>::RuntimeOrigin,
call: &CallOf<T::Runtime>,
_info: &DispatchInfoOf<CallOf<T::Runtime>>,
who: &Self::AccountId,
call: &Self::Call,
_info: &DispatchInfoOf<Self::Call>,
_len: usize,
_context: &mut Context,
_self_implicit: Self::Implicit,
_inherited_implication: &impl Encode,
) -> ValidateResult<Self::Val, CallOf<T::Runtime>> {
let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?;
) -> TransactionValidity {
// this is the only relevant line of code for the `pre_dispatch`
//
// we're not calling `validate` from `pre_dispatch` directly because of performance
@@ -528,12 +511,12 @@ where
// we only boost priority of presumably correct message delivery transactions
let bundled_messages = match T::bundled_messages_for_priority_boost(parsed_call.as_ref()) {
Some(bundled_messages) => bundled_messages,
None => return Ok((Default::default(), parsed_call, origin)),
None => return Ok(Default::default()),
};
// we only boost priority if relayer has staked required balance
if !RelayersPallet::<T::Runtime>::is_registration_active(who) {
return Ok((Default::default(), parsed_call, origin))
return Ok(Default::default())
}
// compute priority boost
@@ -552,21 +535,20 @@ where
priority_boost,
);
let validity = valid_transaction.build()?;
Ok((validity, parsed_call, origin))
valid_transaction.build()
}
fn prepare(
fn pre_dispatch(
self,
val: Self::Val,
origin: &<CallOf<T::Runtime> as Dispatchable>::RuntimeOrigin,
_call: &CallOf<T::Runtime>,
_info: &DispatchInfoOf<CallOf<T::Runtime>>,
who: &Self::AccountId,
call: &Self::Call,
_info: &DispatchInfoOf<Self::Call>,
_len: usize,
_context: &Context,
) -> Result<Self::Pre, TransactionValidityError> {
let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?;
Ok(val.map(|call_info| {
// this is a relevant piece of `validate` that we need here (in `pre_dispatch`)
let parsed_call = T::parse_and_check_for_obsolete_call(call)?;
Ok(parsed_call.map(|call_info| {
log::trace!(
target: "runtime::bridge",
"{} via {:?} parsed bridge transaction in pre-dispatch: {:?}",
@@ -579,14 +561,13 @@ where
}
fn post_dispatch(
pre: Self::Pre,
info: &DispatchInfoOf<CallOf<T::Runtime>>,
post_info: &PostDispatchInfoOf<CallOf<T::Runtime>>,
pre: Option<Self::Pre>,
info: &DispatchInfoOf<Self::Call>,
post_info: &PostDispatchInfoOf<Self::Call>,
len: usize,
result: &DispatchResult,
_context: &Context,
) -> Result<(), TransactionValidityError> {
let call_result = T::analyze_call_result(Some(pre), info, post_info, len, result);
let call_result = T::analyze_call_result(pre, info, post_info, len, result);
match call_result {
RelayerAccountAction::None => (),
@@ -614,7 +595,7 @@ where
}
}
/// Transaction extension that refunds a relayer for new messages coming from a parachain.
/// Signed extension that refunds a relayer for new messages coming from a parachain.
///
/// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`)
/// with message delivery transaction. Batch may deliver either both relay chain header and
@@ -655,7 +636,7 @@ pub struct RefundBridgedParachainMessages<Runtime, Para, Msgs, Refund, Priority,
)>,
);
impl<Runtime, Para, Msgs, Refund, Priority, Id> RefundTransactionExtension
impl<Runtime, Para, Msgs, Refund, Priority, Id> RefundSignedExtension
for RefundBridgedParachainMessages<Runtime, Para, Msgs, Refund, Priority, Id>
where
Self: 'static + Send + Sync,
@@ -749,13 +730,13 @@ where
}
}
/// Transaction extension that refunds a relayer for new messages coming from a standalone (GRANDPA)
/// Signed extension that refunds a relayer for new messages coming from a standalone (GRANDPA)
/// chain.
///
/// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`)
/// with message delivery transaction. Batch may deliver either both relay chain header and
/// parachain head, or just parachain head. Corresponding headers must be used in messages proof
/// verification.
/// parachain head, or just parachain head. Corresponding headers must be used in messages
/// proof verification.
///
/// Extension does not refund transaction tip due to security reasons.
#[derive(
@@ -790,7 +771,7 @@ pub struct RefundBridgedGrandpaMessages<Runtime, GrandpaInstance, Msgs, Refund,
)>,
);
impl<Runtime, GrandpaInstance, Msgs, Refund, Priority, Id> RefundTransactionExtension
impl<Runtime, GrandpaInstance, Msgs, Refund, Priority, Id> RefundSignedExtension
for RefundBridgedGrandpaMessages<Runtime, GrandpaInstance, Msgs, Refund, Priority, Id>
where
Self: 'static + Send + Sync,
@@ -888,8 +869,8 @@ mod tests {
Call as ParachainsCall, Pallet as ParachainsPallet, RelayBlockHash,
};
use sp_runtime::{
traits::{ConstU64, DispatchTransaction, Header as HeaderT},
transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction},
traits::{ConstU64, Header as HeaderT},
transaction_validity::{InvalidTransaction, ValidTransaction},
DispatchError,
};
@@ -918,7 +899,7 @@ mod tests {
ConstU64<1>,
StrTestExtension,
>;
type TestGrandpaExtension = RefundTransactionExtensionAdapter<TestGrandpaExtensionProvider>;
type TestGrandpaExtension = RefundSignedExtensionAdapter<TestGrandpaExtensionProvider>;
type TestExtensionProvider = RefundBridgedParachainMessages<
TestRuntime,
DefaultRefundableParachainId<(), TestParachain>,
@@ -927,7 +908,7 @@ mod tests {
ConstU64<1>,
StrTestExtension,
>;
type TestExtension = RefundTransactionExtensionAdapter<TestExtensionProvider>;
type TestExtension = RefundSignedExtensionAdapter<TestExtensionProvider>;
fn initial_balance_of_relayer_account_at_this_chain() -> ThisChainBalance {
let test_stake: ThisChainBalance = TestStake::get();
@@ -1426,28 +1407,14 @@ mod tests {
fn run_validate(call: RuntimeCall) -> TransactionValidity {
let extension: TestExtension =
RefundTransactionExtensionAdapter(RefundBridgedParachainMessages(PhantomData));
extension
.validate_only(
Some(relayer_account_at_this_chain()).into(),
&call,
&DispatchInfo::default(),
0,
)
.map(|res| res.0)
RefundSignedExtensionAdapter(RefundBridgedParachainMessages(PhantomData));
extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0)
}
fn run_grandpa_validate(call: RuntimeCall) -> TransactionValidity {
let extension: TestGrandpaExtension =
RefundTransactionExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData));
extension
.validate_only(
Some(relayer_account_at_this_chain()).into(),
&call,
&DispatchInfo::default(),
0,
)
.map(|res| res.0)
RefundSignedExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData));
extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0)
}
fn run_validate_ignore_priority(call: RuntimeCall) -> TransactionValidity {
@@ -1461,30 +1428,16 @@ mod tests {
call: RuntimeCall,
) -> Result<Option<PreDispatchData<ThisChainAccountId>>, TransactionValidityError> {
let extension: TestExtension =
RefundTransactionExtensionAdapter(RefundBridgedParachainMessages(PhantomData));
extension
.validate_and_prepare(
Some(relayer_account_at_this_chain()).into(),
&call,
&DispatchInfo::default(),
0,
)
.map(|(pre, _)| pre)
RefundSignedExtensionAdapter(RefundBridgedParachainMessages(PhantomData));
extension.pre_dispatch(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0)
}
fn run_grandpa_pre_dispatch(
call: RuntimeCall,
) -> Result<Option<PreDispatchData<ThisChainAccountId>>, TransactionValidityError> {
let extension: TestGrandpaExtension =
RefundTransactionExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData));
extension
.validate_and_prepare(
Some(relayer_account_at_this_chain()).into(),
&call,
&DispatchInfo::default(),
0,
)
.map(|(pre, _)| pre)
RefundSignedExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData));
extension.pre_dispatch(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0)
}
fn dispatch_info() -> DispatchInfo {
@@ -1507,12 +1460,11 @@ mod tests {
dispatch_result: DispatchResult,
) {
let post_dispatch_result = TestExtension::post_dispatch(
pre_dispatch_data,
Some(pre_dispatch_data),
&dispatch_info(),
&post_dispatch_info(),
1024,
&dispatch_result,
&(),
);
assert_eq!(post_dispatch_result, Ok(()));
}
+1 -1
View File
@@ -27,7 +27,7 @@ for provided header.
There are two main things in GRANDPA that help building light clients:
- there's no need to import all headers of the bridged chain. Light client may import finalized headers or just
some of finalized headders that it consider useful. While the validators set stays the same, the client may
some of finalized headers that it consider useful. While the validators set stays the same, the client may
import any header that is finalized by this set;
- when validators set changes, the GRANDPA gadget adds next set to the header. So light client doesn't need to
+1 -1
View File
@@ -42,7 +42,7 @@ construct_runtime! {
}
}
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
impl frame_system::Config for TestRuntime {
type Block = Block;
}
+2 -2
View File
@@ -77,14 +77,14 @@ frame_support::construct_runtime! {
pub type DbWeight = RocksDbWeight;
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
impl frame_system::Config for TestRuntime {
type Block = Block;
type AccountData = pallet_balances::AccountData<Balance>;
type DbWeight = DbWeight;
}
#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)]
#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)]
impl pallet_balances::Config for TestRuntime {
type ReserveIdentifier = [u8; 8];
type AccountStore = System;
+1 -1
View File
@@ -161,7 +161,7 @@ construct_runtime! {
}
}
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
impl frame_system::Config for TestRuntime {
type Block = Block;
}
+2 -2
View File
@@ -59,14 +59,14 @@ parameter_types! {
pub const Lease: BlockNumber = 8;
}
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
impl frame_system::Config for TestRuntime {
type Block = Block;
type AccountData = pallet_balances::AccountData<Balance>;
type DbWeight = DbWeight;
}
#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)]
#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)]
impl pallet_balances::Config for TestRuntime {
type ReserveIdentifier = [u8; 8];
type AccountStore = System;
@@ -64,7 +64,7 @@ parameter_types! {
pub UnknownXcmVersionLocation: Location = Location::new(2, [GlobalConsensus(BridgedNetworkId::get()), Parachain(9999)]);
}
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
impl frame_system::Config for TestRuntime {
type Block = Block;
}
+2 -2
View File
@@ -64,7 +64,7 @@ parameter_types! {
pub const ExistentialDeposit: Balance = 1;
}
#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
impl frame_system::Config for TestRuntime {
type AccountId = AccountId;
type AccountData = pallet_balances::AccountData<Balance>;
@@ -72,7 +72,7 @@ impl frame_system::Config for TestRuntime {
type Lookup = IdentityLookup<Self::AccountId>;
}
#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)]
#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)]
impl pallet_balances::Config for TestRuntime {
type AccountStore = System;
}
@@ -26,7 +26,7 @@ pub use bp_polkadot_core::{
};
use bp_messages::*;
use bp_polkadot_core::SuffixedCommonTransactionExtension;
use bp_polkadot_core::SuffixedCommonSignedExtension;
use bp_runtime::extensions::{
BridgeRejectObsoleteHeadersAndMessages, RefundBridgedParachainMessagesSchema,
};
@@ -164,7 +164,7 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024;
pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096;
/// Signed extension that is used by all bridge hubs.
pub type TransactionExtension = SuffixedCommonTransactionExtension<(
pub type SignedExtension = SuffixedCommonSignedExtension<(
BridgeRejectObsoleteHeadersAndMessages,
RefundBridgedParachainMessagesSchema,
)>;
@@ -107,5 +107,5 @@ frame_support::parameter_types! {
/// Transaction fee that is paid at the Rococo BridgeHub for delivering single outbound message confirmation.
/// (initially was calculated by test `BridgeHubRococo::can_calculate_fee_for_complex_message_confirmation_transaction` + `33%`)
pub const BridgeHubRococoBaseConfirmationFeeInRocs: u128 = 5_380_904_835;
pub const BridgeHubRococoBaseConfirmationFeeInRocs: u128 = 5_380_829_647;
}
+2 -2
View File
@@ -59,8 +59,8 @@ impl ChainWithGrandpa for Kusama {
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
}
// The TransactionExtension used by Kusama.
pub use bp_polkadot_core::CommonTransactionExtension as TransactionExtension;
// The SignedExtension used by Kusama.
pub use bp_polkadot_core::CommonSignedExtension as SignedExtension;
/// Name of the parachains pallet in the Kusama runtime.
pub const PARAS_PALLET_NAME: &str = "Paras";
@@ -25,7 +25,7 @@ use bp_runtime::{
decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis,
extensions::{
CheckEra, CheckGenesis, CheckNonZeroSender, CheckNonce, CheckSpecVersion, CheckTxVersion,
CheckWeight, GenericTransactionExtension, GenericTransactionExtensionSchema,
CheckWeight, GenericSignedExtension, GenericSignedExtensionSchema,
},
Chain, ChainId, TransactionEra,
};
@@ -37,12 +37,7 @@ use frame_support::{
};
use frame_system::limits;
use scale_info::TypeInfo;
use sp_runtime::{
impl_tx_ext_default,
traits::{Dispatchable, TransactionExtensionBase},
transaction_validity::TransactionValidityError,
Perbill,
};
use sp_runtime::{traits::DispatchInfoOf, transaction_validity::TransactionValidityError, Perbill};
// This chain reuses most of Polkadot primitives.
pub use bp_polkadot_core::{
@@ -76,10 +71,10 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024;
pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096;
/// This signed extension is used to ensure that the chain transactions are signed by proper
pub type ValidateSigned = GenericTransactionExtensionSchema<(), ()>;
pub type ValidateSigned = GenericSignedExtensionSchema<(), ()>;
/// Signed extension schema, used by Polkadot Bulletin.
pub type TransactionExtensionSchema = GenericTransactionExtension<(
pub type SignedExtensionSchema = GenericSignedExtension<(
(
CheckNonZeroSender,
CheckSpecVersion,
@@ -92,30 +87,34 @@ pub type TransactionExtensionSchema = GenericTransactionExtension<(
ValidateSigned,
)>;
/// Transaction extension, used by Polkadot Bulletin.
/// Signed extension, used by Polkadot Bulletin.
#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)]
pub struct TransactionExtension(TransactionExtensionSchema);
pub struct SignedExtension(SignedExtensionSchema);
impl TransactionExtensionBase for TransactionExtension {
impl sp_runtime::traits::SignedExtension for SignedExtension {
const IDENTIFIER: &'static str = "Not needed.";
type Implicit = <TransactionExtensionSchema as TransactionExtensionBase>::Implicit;
type AccountId = ();
type Call = ();
type AdditionalSigned =
<SignedExtensionSchema as sp_runtime::traits::SignedExtension>::AdditionalSigned;
type Pre = ();
fn implicit(&self) -> Result<Self::Implicit, TransactionValidityError> {
<TransactionExtensionSchema as TransactionExtensionBase>::implicit(&self.0)
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError> {
self.0.additional_signed()
}
fn pre_dispatch(
self,
_who: &Self::AccountId,
_call: &Self::Call,
_info: &DispatchInfoOf<Self::Call>,
_len: usize,
) -> Result<Self::Pre, TransactionValidityError> {
Ok(())
}
}
impl<C, Context> sp_runtime::traits::TransactionExtension<C, Context> for TransactionExtension
where
C: Dispatchable,
{
type Pre = ();
type Val = ();
impl_tx_ext_default!(C; Context; validate prepare);
}
impl TransactionExtension {
impl SignedExtension {
/// Create signed extension from its components.
pub fn from_params(
spec_version: u32,
@@ -124,7 +123,7 @@ impl TransactionExtension {
genesis_hash: Hash,
nonce: Nonce,
) -> Self {
Self(GenericTransactionExtension::new(
Self(GenericSignedExtension::new(
(
(
(), // non-zero sender
+2 -2
View File
@@ -61,8 +61,8 @@ impl ChainWithGrandpa for Polkadot {
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
}
/// The TransactionExtension used by Polkadot.
pub type TransactionExtension = SuffixedCommonTransactionExtension<PrevalidateAttests>;
/// The SignedExtension used by Polkadot.
pub type SignedExtension = SuffixedCommonSignedExtension<PrevalidateAttests>;
/// Name of the parachains pallet in the Polkadot runtime.
pub const PARAS_PALLET_NAME: &str = "Paras";
+2 -2
View File
@@ -59,8 +59,8 @@ impl ChainWithGrandpa for Rococo {
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
}
// The TransactionExtension used by Rococo.
pub use bp_polkadot_core::CommonTransactionExtension as TransactionExtension;
// The SignedExtension used by Rococo.
pub use bp_polkadot_core::CommonSignedExtension as SignedExtension;
/// Name of the parachains pallet in the Rococo runtime.
pub const PARAS_PALLET_NAME: &str = "Paras";
+2 -2
View File
@@ -59,8 +59,8 @@ impl ChainWithGrandpa for Westend {
const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE;
}
// The TransactionExtension used by Westend.
pub use bp_polkadot_core::CommonTransactionExtension as TransactionExtension;
// The SignedExtension used by Westend.
pub use bp_polkadot_core::CommonSignedExtension as SignedExtension;
/// Name of the parachains pallet in the Rococo runtime.
pub const PARAS_PALLET_NAME: &str = "Paras";
+1 -1
View File
@@ -13,7 +13,7 @@ workspace = true
codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] }
parity-util-mem = { version = "0.12.0", optional = true }
scale-info = { version = "2.11.0", default-features = false, features = ["derive"] }
serde = { default-features = false, features = ["derive"], optional = true, workspace = true }
serde = { optional = true, features = ["derive"], workspace = true, default-features = true }
# Bridge Dependencies
+16 -21
View File
@@ -24,8 +24,8 @@ use bp_runtime::{
self,
extensions::{
ChargeTransactionPayment, CheckEra, CheckGenesis, CheckNonZeroSender, CheckNonce,
CheckSpecVersion, CheckTxVersion, CheckWeight, GenericTransactionExtension,
TransactionExtensionSchema,
CheckSpecVersion, CheckTxVersion, CheckWeight, GenericSignedExtension,
SignedExtensionSchema,
},
EncodedOrDecodedCall, StorageMapKeyProvider, TransactionEra,
};
@@ -229,12 +229,8 @@ pub type SignedBlock = generic::SignedBlock<Block>;
pub type Balance = u128;
/// Unchecked Extrinsic type.
pub type UncheckedExtrinsic<Call, TransactionExt> = generic::UncheckedExtrinsic<
AccountAddress,
EncodedOrDecodedCall<Call>,
Signature,
TransactionExt,
>;
pub type UncheckedExtrinsic<Call, SignedExt> =
generic::UncheckedExtrinsic<AccountAddress, EncodedOrDecodedCall<Call>, Signature, SignedExt>;
/// Account address, used by the Polkadot-like chain.
pub type Address = MultiAddress<AccountId, ()>;
@@ -279,7 +275,7 @@ impl AccountInfoStorageMapKeyProvider {
}
/// Extra signed extension data that is used by most chains.
pub type CommonTransactionExtra = (
pub type CommonSignedExtra = (
CheckNonZeroSender,
CheckSpecVersion,
CheckTxVersion,
@@ -290,12 +286,12 @@ pub type CommonTransactionExtra = (
ChargeTransactionPayment<Balance>,
);
/// Extra transaction extension data that starts with `CommonTransactionExtra`.
pub type SuffixedCommonTransactionExtension<Suffix> =
GenericTransactionExtension<(CommonTransactionExtra, Suffix)>;
/// Extra signed extension data that starts with `CommonSignedExtra`.
pub type SuffixedCommonSignedExtension<Suffix> =
GenericSignedExtension<(CommonSignedExtra, Suffix)>;
/// Helper trait to define some extra methods on `SuffixedCommonTransactionExtension`.
pub trait SuffixedCommonTransactionExtensionExt<Suffix: TransactionExtensionSchema> {
/// Helper trait to define some extra methods on `SuffixedCommonSignedExtension`.
pub trait SuffixedCommonSignedExtensionExt<Suffix: SignedExtensionSchema> {
/// Create signed extension from its components.
fn from_params(
spec_version: u32,
@@ -304,7 +300,7 @@ pub trait SuffixedCommonTransactionExtensionExt<Suffix: TransactionExtensionSche
genesis_hash: Hash,
nonce: Nonce,
tip: Balance,
extra: (Suffix::Payload, Suffix::Implicit),
extra: (Suffix::Payload, Suffix::AdditionalSigned),
) -> Self;
/// Return transaction nonce.
@@ -314,10 +310,9 @@ pub trait SuffixedCommonTransactionExtensionExt<Suffix: TransactionExtensionSche
fn tip(&self) -> Balance;
}
impl<Suffix> SuffixedCommonTransactionExtensionExt<Suffix>
for SuffixedCommonTransactionExtension<Suffix>
impl<Suffix> SuffixedCommonSignedExtensionExt<Suffix> for SuffixedCommonSignedExtension<Suffix>
where
Suffix: TransactionExtensionSchema,
Suffix: SignedExtensionSchema,
{
fn from_params(
spec_version: u32,
@@ -326,9 +321,9 @@ where
genesis_hash: Hash,
nonce: Nonce,
tip: Balance,
extra: (Suffix::Payload, Suffix::Implicit),
extra: (Suffix::Payload, Suffix::AdditionalSigned),
) -> Self {
GenericTransactionExtension::new(
GenericSignedExtension::new(
(
(
(), // non-zero sender
@@ -370,7 +365,7 @@ where
}
/// Signed extension that is used by most chains.
pub type CommonTransactionExtension = SuffixedCommonTransactionExtension<()>;
pub type CommonSignedExtension = SuffixedCommonSignedExtension<()>;
#[cfg(test)]
mod tests {
+67 -70
View File
@@ -20,138 +20,135 @@ use codec::{Compact, Decode, Encode};
use impl_trait_for_tuples::impl_for_tuples;
use scale_info::{StaticTypeInfo, TypeInfo};
use sp_runtime::{
impl_tx_ext_default,
traits::{Dispatchable, TransactionExtension, TransactionExtensionBase},
traits::{DispatchInfoOf, SignedExtension},
transaction_validity::TransactionValidityError,
};
use sp_std::{fmt::Debug, marker::PhantomData};
/// Trait that describes some properties of a `TransactionExtension` that are needed in order to
/// send a transaction to the chain.
pub trait TransactionExtensionSchema:
Encode + Decode + Debug + Eq + Clone + StaticTypeInfo
{
/// Trait that describes some properties of a `SignedExtension` that are needed in order to send a
/// transaction to the chain.
pub trait SignedExtensionSchema: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo {
/// A type of the data encoded as part of the transaction.
type Payload: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo;
/// Parameters which are part of the payload used to produce transaction signature,
/// but don't end up in the transaction itself (i.e. inherent part of the runtime).
type Implicit: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo;
type AdditionalSigned: Encode + Debug + Eq + Clone + StaticTypeInfo;
}
impl TransactionExtensionSchema for () {
impl SignedExtensionSchema for () {
type Payload = ();
type Implicit = ();
type AdditionalSigned = ();
}
/// An implementation of `TransactionExtensionSchema` using generic params.
/// An implementation of `SignedExtensionSchema` using generic params.
#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo)]
pub struct GenericTransactionExtensionSchema<P, S>(PhantomData<(P, S)>);
pub struct GenericSignedExtensionSchema<P, S>(PhantomData<(P, S)>);
impl<P, S> TransactionExtensionSchema for GenericTransactionExtensionSchema<P, S>
impl<P, S> SignedExtensionSchema for GenericSignedExtensionSchema<P, S>
where
P: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo,
S: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo,
S: Encode + Debug + Eq + Clone + StaticTypeInfo,
{
type Payload = P;
type Implicit = S;
type AdditionalSigned = S;
}
/// The `TransactionExtensionSchema` for `frame_system::CheckNonZeroSender`.
pub type CheckNonZeroSender = GenericTransactionExtensionSchema<(), ()>;
/// The `SignedExtensionSchema` for `frame_system::CheckNonZeroSender`.
pub type CheckNonZeroSender = GenericSignedExtensionSchema<(), ()>;
/// The `TransactionExtensionSchema` for `frame_system::CheckSpecVersion`.
pub type CheckSpecVersion = GenericTransactionExtensionSchema<(), u32>;
/// The `SignedExtensionSchema` for `frame_system::CheckSpecVersion`.
pub type CheckSpecVersion = GenericSignedExtensionSchema<(), u32>;
/// The `TransactionExtensionSchema` for `frame_system::CheckTxVersion`.
pub type CheckTxVersion = GenericTransactionExtensionSchema<(), u32>;
/// The `SignedExtensionSchema` for `frame_system::CheckTxVersion`.
pub type CheckTxVersion = GenericSignedExtensionSchema<(), u32>;
/// The `TransactionExtensionSchema` for `frame_system::CheckGenesis`.
pub type CheckGenesis<Hash> = GenericTransactionExtensionSchema<(), Hash>;
/// The `SignedExtensionSchema` for `frame_system::CheckGenesis`.
pub type CheckGenesis<Hash> = GenericSignedExtensionSchema<(), Hash>;
/// The `TransactionExtensionSchema` for `frame_system::CheckEra`.
pub type CheckEra<Hash> = GenericTransactionExtensionSchema<sp_runtime::generic::Era, Hash>;
/// The `SignedExtensionSchema` for `frame_system::CheckEra`.
pub type CheckEra<Hash> = GenericSignedExtensionSchema<sp_runtime::generic::Era, Hash>;
/// The `TransactionExtensionSchema` for `frame_system::CheckNonce`.
pub type CheckNonce<TxNonce> = GenericTransactionExtensionSchema<Compact<TxNonce>, ()>;
/// The `SignedExtensionSchema` for `frame_system::CheckNonce`.
pub type CheckNonce<TxNonce> = GenericSignedExtensionSchema<Compact<TxNonce>, ()>;
/// The `TransactionExtensionSchema` for `frame_system::CheckWeight`.
pub type CheckWeight = GenericTransactionExtensionSchema<(), ()>;
/// The `SignedExtensionSchema` for `frame_system::CheckWeight`.
pub type CheckWeight = GenericSignedExtensionSchema<(), ()>;
/// The `TransactionExtensionSchema` for `pallet_transaction_payment::ChargeTransactionPayment`.
pub type ChargeTransactionPayment<Balance> =
GenericTransactionExtensionSchema<Compact<Balance>, ()>;
/// The `SignedExtensionSchema` for `pallet_transaction_payment::ChargeTransactionPayment`.
pub type ChargeTransactionPayment<Balance> = GenericSignedExtensionSchema<Compact<Balance>, ()>;
/// The `TransactionExtensionSchema` for `polkadot-runtime-common::PrevalidateAttests`.
pub type PrevalidateAttests = GenericTransactionExtensionSchema<(), ()>;
/// The `SignedExtensionSchema` for `polkadot-runtime-common::PrevalidateAttests`.
pub type PrevalidateAttests = GenericSignedExtensionSchema<(), ()>;
/// The `TransactionExtensionSchema` for `BridgeRejectObsoleteHeadersAndMessages`.
pub type BridgeRejectObsoleteHeadersAndMessages = GenericTransactionExtensionSchema<(), ()>;
/// The `SignedExtensionSchema` for `BridgeRejectObsoleteHeadersAndMessages`.
pub type BridgeRejectObsoleteHeadersAndMessages = GenericSignedExtensionSchema<(), ()>;
/// The `TransactionExtensionSchema` for `RefundBridgedParachainMessages`.
/// The `SignedExtensionSchema` for `RefundBridgedParachainMessages`.
/// This schema is dedicated for `RefundBridgedParachainMessages` signed extension as
/// wildcard/placeholder, which relies on the scale encoding for `()` or `((), ())`, or `((), (),
/// ())` is the same. So runtime can contains any kind of tuple:
/// `(BridgeRefundBridgeHubRococoMessages)`
/// `(BridgeRefundBridgeHubRococoMessages, BridgeRefundBridgeHubWestendMessages)`
/// `(BridgeRefundParachainMessages1, ..., BridgeRefundParachainMessagesN)`
pub type RefundBridgedParachainMessagesSchema = GenericTransactionExtensionSchema<(), ()>;
pub type RefundBridgedParachainMessagesSchema = GenericSignedExtensionSchema<(), ()>;
#[impl_for_tuples(1, 12)]
impl TransactionExtensionSchema for Tuple {
impl SignedExtensionSchema for Tuple {
for_tuples!( type Payload = ( #( Tuple::Payload ),* ); );
for_tuples!( type Implicit = ( #( Tuple::Implicit ),* ); );
for_tuples!( type AdditionalSigned = ( #( Tuple::AdditionalSigned ),* ); );
}
/// A simplified version of signed extensions meant for producing signed transactions
/// and signed payloads in the client code.
#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)]
pub struct GenericTransactionExtension<S: TransactionExtensionSchema> {
pub struct GenericSignedExtension<S: SignedExtensionSchema> {
/// A payload that is included in the transaction.
pub payload: S::Payload,
#[codec(skip)]
// It may be set to `None` if extensions are decoded. We are never reconstructing transactions
// (and it makes no sense to do that) => decoded version of `TransactionExtensions` is only
// used to read fields of the `payload`. And when resigning transaction, we're reconstructing
// `TransactionExtensions` from scratch.
implicit: Option<S::Implicit>,
// (and it makes no sense to do that) => decoded version of `SignedExtensions` is only used to
// read fields of the `payload`. And when resigning transaction, we're reconstructing
// `SignedExtensions` from scratch.
additional_signed: Option<S::AdditionalSigned>,
}
impl<S: TransactionExtensionSchema> GenericTransactionExtension<S> {
/// Create new `GenericTransactionExtension` object.
pub fn new(payload: S::Payload, implicit: Option<S::Implicit>) -> Self {
Self { payload, implicit }
impl<S: SignedExtensionSchema> GenericSignedExtension<S> {
/// Create new `GenericSignedExtension` object.
pub fn new(payload: S::Payload, additional_signed: Option<S::AdditionalSigned>) -> Self {
Self { payload, additional_signed }
}
}
impl<S> TransactionExtensionBase for GenericTransactionExtension<S>
impl<S> SignedExtension for GenericSignedExtension<S>
where
S: TransactionExtensionSchema,
S: SignedExtensionSchema,
S::Payload: Send + Sync,
S::Implicit: Send + Sync,
S::AdditionalSigned: Send + Sync,
{
const IDENTIFIER: &'static str = "Not needed.";
type Implicit = S::Implicit;
type AccountId = ();
type Call = ();
type AdditionalSigned = S::AdditionalSigned;
type Pre = ();
fn implicit(&self) -> Result<Self::Implicit, TransactionValidityError> {
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError> {
// we shall not ever see this error in relay, because we are never signing decoded
// transactions. Instead we're constructing and signing new transactions. So the error code
// is kinda random here
self.implicit
.clone()
.ok_or(frame_support::unsigned::TransactionValidityError::Unknown(
self.additional_signed.clone().ok_or(
frame_support::unsigned::TransactionValidityError::Unknown(
frame_support::unsigned::UnknownTransaction::Custom(0xFF),
))
),
)
}
fn pre_dispatch(
self,
_who: &Self::AccountId,
_call: &Self::Call,
_info: &DispatchInfoOf<Self::Call>,
_len: usize,
) -> Result<Self::Pre, TransactionValidityError> {
Ok(())
}
}
impl<S, C, Context> TransactionExtension<C, Context> for GenericTransactionExtension<S>
where
C: Dispatchable,
S: TransactionExtensionSchema,
S::Payload: Send + Sync,
S::Implicit: Send + Sync,
{
type Pre = ();
type Val = ();
impl_tx_ext_default!(C; Context; validate prepare);
}
+1 -1
View File
@@ -11,7 +11,7 @@ workspace = true
[dependencies]
anyhow = "1.0"
async-std = "1.9.0"
async-trait = "0.1"
async-trait = "0.1.74"
codec = { package = "parity-scale-codec", version = "3.1.5" }
env_logger = "0.11"
futures = "0.3.30"
@@ -18,8 +18,8 @@
pub mod codegen_runtime;
use bp_bridge_hub_kusama::{TransactionExtension, AVERAGE_BLOCK_INTERVAL};
use bp_polkadot::SuffixedCommonTransactionExtensionExt;
use bp_bridge_hub_kusama::{SignedExtension, AVERAGE_BLOCK_INTERVAL};
use bp_polkadot::SuffixedCommonSignedExtensionExt;
use codec::Encode;
use relay_substrate_client::{
calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages,
@@ -37,8 +37,7 @@ pub type RuntimeCall = runtime_types::bridge_hub_kusama_runtime::RuntimeCall;
pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call;
pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call;
pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call;
type UncheckedExtrinsic =
bp_bridge_hub_kusama::UncheckedExtrinsic<RuntimeCall, TransactionExtension>;
type UncheckedExtrinsic = bp_bridge_hub_kusama::UncheckedExtrinsic<RuntimeCall, SignedExtension>;
type UtilityCall = runtime_types::pallet_utility::pallet::Call;
/// Kusama chain definition
@@ -88,7 +87,7 @@ impl ChainWithTransactions for BridgeHubKusama {
) -> Result<Self::SignedTransaction, SubstrateError> {
let raw_payload = SignedPayload::new(
unsigned.call,
TransactionExtension::from_params(
SignedExtension::from_params(
param.spec_version,
param.transaction_version,
unsigned.era,
@@ -18,8 +18,8 @@
pub mod codegen_runtime;
use bp_bridge_hub_polkadot::{TransactionExtension, AVERAGE_BLOCK_INTERVAL};
use bp_polkadot_core::SuffixedCommonTransactionExtensionExt;
use bp_bridge_hub_polkadot::{SignedExtension, AVERAGE_BLOCK_INTERVAL};
use bp_polkadot_core::SuffixedCommonSignedExtensionExt;
use codec::Encode;
use relay_substrate_client::{
calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages,
@@ -41,8 +41,7 @@ pub type BridgeKusamaMessagesCall = runtime_types::pallet_bridge_messages::palle
pub type BridgePolkadotBulletinGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call;
pub type BridgeKusamaGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call;
pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call;
type UncheckedExtrinsic =
bp_bridge_hub_polkadot::UncheckedExtrinsic<RuntimeCall, TransactionExtension>;
type UncheckedExtrinsic = bp_bridge_hub_polkadot::UncheckedExtrinsic<RuntimeCall, SignedExtension>;
type UtilityCall = runtime_types::pallet_utility::pallet::Call;
/// Polkadot chain definition
@@ -92,7 +91,7 @@ impl ChainWithTransactions for BridgeHubPolkadot {
) -> Result<Self::SignedTransaction, SubstrateError> {
let raw_payload = SignedPayload::new(
unsigned.call,
TransactionExtension::from_params(
SignedExtension::from_params(
param.spec_version,
param.transaction_version,
unsigned.era,
@@ -18,8 +18,8 @@
pub mod codegen_runtime;
use bp_bridge_hub_rococo::{TransactionExtension, AVERAGE_BLOCK_INTERVAL};
use bp_polkadot_core::SuffixedCommonTransactionExtensionExt;
use bp_bridge_hub_rococo::{SignedExtension, AVERAGE_BLOCK_INTERVAL};
use bp_polkadot_core::SuffixedCommonSignedExtensionExt;
use codec::Encode;
use relay_substrate_client::{
calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages,
@@ -39,8 +39,7 @@ pub type BridgeBulletinMessagesCall = runtime_types::pallet_bridge_messages::pal
pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call;
pub type BridgeBulletinGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call2;
pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call;
type UncheckedExtrinsic =
bp_bridge_hub_rococo::UncheckedExtrinsic<RuntimeCall, TransactionExtension>;
type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic<RuntimeCall, SignedExtension>;
type UtilityCall = runtime_types::pallet_utility::pallet::Call;
/// Rococo chain definition
@@ -90,7 +89,7 @@ impl ChainWithTransactions for BridgeHubRococo {
) -> Result<Self::SignedTransaction, SubstrateError> {
let raw_payload = SignedPayload::new(
unsigned.call,
TransactionExtension::from_params(
SignedExtension::from_params(
param.spec_version,
param.transaction_version,
unsigned.era,
@@ -18,8 +18,8 @@
pub mod codegen_runtime;
use bp_bridge_hub_westend::{TransactionExtension, AVERAGE_BLOCK_INTERVAL};
use bp_polkadot_core::SuffixedCommonTransactionExtensionExt;
use bp_bridge_hub_westend::{SignedExtension, AVERAGE_BLOCK_INTERVAL};
use bp_polkadot_core::SuffixedCommonSignedExtensionExt;
use codec::Encode;
use relay_substrate_client::{
calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages,
@@ -37,8 +37,7 @@ pub type RuntimeCall = runtime_types::bridge_hub_westend_runtime::RuntimeCall;
pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call;
pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call;
pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call;
type UncheckedExtrinsic =
bp_bridge_hub_westend::UncheckedExtrinsic<RuntimeCall, TransactionExtension>;
type UncheckedExtrinsic = bp_bridge_hub_westend::UncheckedExtrinsic<RuntimeCall, SignedExtension>;
type UtilityCall = runtime_types::pallet_utility::pallet::Call;
/// Westend chain definition
@@ -88,7 +87,7 @@ impl ChainWithTransactions for BridgeHubWestend {
) -> Result<Self::SignedTransaction, SubstrateError> {
let raw_payload = SignedPayload::new(
unsigned.call,
TransactionExtension::from_params(
SignedExtension::from_params(
param.spec_version,
param.transaction_version,
unsigned.era,
+3 -3
View File
@@ -19,7 +19,7 @@
pub mod codegen_runtime;
use bp_kusama::{AccountInfoStorageMapKeyProvider, KUSAMA_SYNCED_HEADERS_GRANDPA_INFO_METHOD};
use bp_polkadot_core::SuffixedCommonTransactionExtensionExt;
use bp_polkadot_core::SuffixedCommonSignedExtensionExt;
use codec::Encode;
use relay_substrate_client::{
Chain, ChainWithBalances, ChainWithGrandpa, ChainWithRuntimeVersion, ChainWithTransactions,
@@ -84,7 +84,7 @@ impl RelayChain for Kusama {
impl ChainWithTransactions for Kusama {
type AccountKeyPair = sp_core::sr25519::Pair;
type SignedTransaction =
bp_polkadot_core::UncheckedExtrinsic<Self::Call, bp_kusama::TransactionExtension>;
bp_polkadot_core::UncheckedExtrinsic<Self::Call, bp_kusama::SignedExtension>;
fn sign_transaction(
param: SignParam<Self>,
@@ -92,7 +92,7 @@ impl ChainWithTransactions for Kusama {
) -> Result<Self::SignedTransaction, SubstrateError> {
let raw_payload = SignedPayload::new(
unsigned.call,
bp_kusama::TransactionExtension::from_params(
bp_kusama::SignedExtension::from_params(
param.spec_version,
param.transaction_version,
unsigned.era,
@@ -100,10 +100,8 @@ impl ChainWithBalances for PolkadotBulletin {
impl ChainWithTransactions for PolkadotBulletin {
type AccountKeyPair = sp_core::sr25519::Pair;
type SignedTransaction = bp_polkadot_bulletin::UncheckedExtrinsic<
Self::Call,
bp_polkadot_bulletin::TransactionExtension,
>;
type SignedTransaction =
bp_polkadot_bulletin::UncheckedExtrinsic<Self::Call, bp_polkadot_bulletin::SignedExtension>;
fn sign_transaction(
param: SignParam<Self>,
@@ -111,7 +109,7 @@ impl ChainWithTransactions for PolkadotBulletin {
) -> Result<Self::SignedTransaction, SubstrateError> {
let raw_payload = SignedPayload::new(
unsigned.call,
bp_polkadot_bulletin::TransactionExtension::from_params(
bp_polkadot_bulletin::SignedExtension::from_params(
param.spec_version,
param.transaction_version,
unsigned.era,
+3 -3
View File
@@ -19,7 +19,7 @@
mod codegen_runtime;
use bp_polkadot::{AccountInfoStorageMapKeyProvider, POLKADOT_SYNCED_HEADERS_GRANDPA_INFO_METHOD};
use bp_polkadot_core::SuffixedCommonTransactionExtensionExt;
use bp_polkadot_core::SuffixedCommonSignedExtensionExt;
use codec::Encode;
use relay_substrate_client::{
Chain, ChainWithBalances, ChainWithGrandpa, ChainWithRuntimeVersion, ChainWithTransactions,
@@ -84,7 +84,7 @@ impl RelayChain for Polkadot {
impl ChainWithTransactions for Polkadot {
type AccountKeyPair = sp_core::sr25519::Pair;
type SignedTransaction =
bp_polkadot_core::UncheckedExtrinsic<Self::Call, bp_polkadot::TransactionExtension>;
bp_polkadot_core::UncheckedExtrinsic<Self::Call, bp_polkadot::SignedExtension>;
fn sign_transaction(
param: SignParam<Self>,
@@ -92,7 +92,7 @@ impl ChainWithTransactions for Polkadot {
) -> Result<Self::SignedTransaction, SubstrateError> {
let raw_payload = SignedPayload::new(
unsigned.call,
bp_polkadot::TransactionExtension::from_params(
bp_polkadot::SignedExtension::from_params(
param.spec_version,
param.transaction_version,
unsigned.era,
+3 -3
View File
@@ -18,7 +18,7 @@
pub mod codegen_runtime;
use bp_polkadot_core::SuffixedCommonTransactionExtensionExt;
use bp_polkadot_core::SuffixedCommonSignedExtensionExt;
use bp_rococo::ROCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD;
use codec::Encode;
use relay_substrate_client::{
@@ -84,7 +84,7 @@ impl RelayChain for Rococo {
impl ChainWithTransactions for Rococo {
type AccountKeyPair = sp_core::sr25519::Pair;
type SignedTransaction =
bp_polkadot_core::UncheckedExtrinsic<Self::Call, bp_rococo::TransactionExtension>;
bp_polkadot_core::UncheckedExtrinsic<Self::Call, bp_rococo::SignedExtension>;
fn sign_transaction(
param: SignParam<Self>,
@@ -92,7 +92,7 @@ impl ChainWithTransactions for Rococo {
) -> Result<Self::SignedTransaction, SubstrateError> {
let raw_payload = SignedPayload::new(
unsigned.call,
bp_rococo::TransactionExtension::from_params(
bp_rococo::SignedExtension::from_params(
param.spec_version,
param.transaction_version,
unsigned.era,
+1 -1
View File
@@ -10,7 +10,7 @@ workspace = true
[dependencies]
async-std = { version = "1.6.5", features = ["attributes"] }
async-trait = "0.1"
async-trait = "0.1.74"
codec = { package = "parity-scale-codec", version = "3.1.5" }
futures = "0.3.30"
jsonrpsee = { version = "0.17", features = ["macros", "ws-client"] }
+3 -3
View File
@@ -18,7 +18,7 @@
pub mod codegen_runtime;
use bp_polkadot_core::SuffixedCommonTransactionExtensionExt;
use bp_polkadot_core::SuffixedCommonSignedExtensionExt;
use bp_westend::WESTEND_SYNCED_HEADERS_GRANDPA_INFO_METHOD;
use codec::Encode;
use relay_substrate_client::{
@@ -84,7 +84,7 @@ impl ChainWithBalances for Westend {
impl ChainWithTransactions for Westend {
type AccountKeyPair = sp_core::sr25519::Pair;
type SignedTransaction =
bp_polkadot_core::UncheckedExtrinsic<Self::Call, bp_westend::TransactionExtension>;
bp_polkadot_core::UncheckedExtrinsic<Self::Call, bp_westend::SignedExtension>;
fn sign_transaction(
param: SignParam<Self>,
@@ -92,7 +92,7 @@ impl ChainWithTransactions for Westend {
) -> Result<Self::SignedTransaction, SubstrateError> {
let raw_payload = SignedPayload::new(
unsigned.call,
bp_westend::TransactionExtension::from_params(
bp_westend::SignedExtension::from_params(
param.spec_version,
param.transaction_version,
unsigned.era,
+1 -1
View File
@@ -11,7 +11,7 @@ workspace = true
[dependencies]
async-std = { version = "1.6.5", features = ["attributes"] }
async-trait = "0.1"
async-trait = "0.1.74"
bp-header-chain = { path = "../../primitives/header-chain" }
finality-relay = { path = "../finality" }
frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" }
+1 -1
View File
@@ -11,7 +11,7 @@ workspace = true
[dependencies]
async-std = "1.6.5"
async-trait = "0.1"
async-trait = "0.1.74"
backoff = "0.4"
bp-header-chain = { path = "../../primitives/header-chain" }
futures = "0.3.30"
@@ -11,7 +11,7 @@ workspace = true
[dependencies]
anyhow = "1.0"
async-std = "1.9.0"
async-trait = "0.1"
async-trait = "0.1.74"
codec = { package = "parity-scale-codec", version = "3.1.5" }
futures = "0.3.30"
hex = "0.4"
+1 -1
View File
@@ -10,7 +10,7 @@ workspace = true
[dependencies]
async-std = { version = "1.6.5", features = ["attributes"] }
async-trait = "0.1"
async-trait = "0.1.74"
env_logger = "0.11"
futures = "0.3.30"
hex = "0.4"
+1 -1
View File
@@ -10,7 +10,7 @@ workspace = true
[dependencies]
async-std = "1.6.5"
async-trait = "0.1"
async-trait = "0.1.74"
futures = "0.3.30"
log = { workspace = true }
relay-utils = { path = "../utils" }
+1 -1
View File
@@ -12,7 +12,7 @@ workspace = true
ansi_term = "0.12"
anyhow = "1.0"
async-std = "1.6.5"
async-trait = "0.1"
async-trait = "0.1.74"
backoff = "0.4"
isahc = "1.2"
env_logger = "0.11.3"
+31
View File
@@ -0,0 +1,31 @@
# Bridges Tests for Local Rococo <> Westend Bridge
This folder contains [zombienet](https://github.com/paritytech/zombienet/) based integration tests for both
onchain and offchain bridges code. Due to some
[technical difficulties](https://github.com/paritytech/parity-bridges-common/pull/2649#issue-1965339051), we
are using native zombienet provider, which means that you need to build some binaries locally.
To start those tests, you need to:
- download latest [zombienet release](https://github.com/paritytech/zombienet/releases);
- build Polkadot binary by running `cargo build -p polkadot --release --features fast-runtime` command in the
[`polkadot-sdk`](https://github.com/paritytech/polkadot-sdk) repository clone;
- build Polkadot Parachain binary by running `cargo build -p polkadot-parachain-bin --release` command in the
[`polkadot-sdk`](https://github.com/paritytech/polkadot-sdk) repository clone;
- ensure that you have [`node`](https://nodejs.org/en) installed. Additionally, we'll need globally installed
`polkadot/api-cli` package (use `npm install -g @polkadot/api-cli@beta` to install it);
- build Substrate relay by running `cargo build -p substrate-relay --release` command in the
[`parity-bridges-common`](https://github.com/paritytech/parity-bridges-common) repository clone.
- copy fresh `substrate-relay` binary, built in previous point, to the `~/local_bridge_testing/bin/substrate-relay`;
- change the `POLKADOT_SDK_PATH` and `ZOMBIENET_BINARY_PATH` (and ensure that the nearby variables
have correct values) in the `./run-tests.sh`.
After that, you could run tests with the `./run-tests.sh` command. Hopefully, it'll show the
"All tests have completed successfully" message in the end. Otherwise, it'll print paths to zombienet
process logs, which, in turn, may be used to track locations of all spinned relay and parachain nodes.
@@ -0,0 +1,88 @@
[settings]
node_spawn_timeout = 240
[relaychain]
default_command = "{{POLKADOT_BINARY}}"
default_args = [ "-lparachain=debug,xcm=trace" ]
chain = "rococo-local"
[[relaychain.nodes]]
name = "alice-rococo-validator"
validator = true
rpc_port = 9932
ws_port = 9942
balance = 2000000000000
[[relaychain.nodes]]
name = "bob-rococo-validator"
validator = true
rpc_port = 9933
ws_port = 9943
balance = 2000000000000
[[relaychain.nodes]]
name = "charlie-rococo-validator"
validator = true
rpc_port = 9934
ws_port = 9944
balance = 2000000000000
[[parachains]]
id = 1013
chain = "bridge-hub-rococo-local"
cumulus_based = true
# run alice as parachain collator
[[parachains.collators]]
name = "bridge-hub-rococo-collator1"
validator = true
command = "{{POLKADOT_PARACHAIN_BINARY}}"
rpc_port = 8933
ws_port = 8943
args = [
"-lparachain=debug,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace"
]
# run bob as parachain collator
[[parachains.collators]]
name = "bridge-hub-rococo-collator2"
validator = true
command = "{{POLKADOT_PARACHAIN_BINARY}}"
rpc_port = 8934
ws_port = 8944
args = [
"-lparachain=trace,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace"
]
[[parachains]]
id = 1000
chain = "asset-hub-rococo-local"
cumulus_based = true
[[parachains.collators]]
name = "asset-hub-rococo-collator1"
rpc_port = 9911
ws_port = 9910
command = "{{POLKADOT_PARACHAIN_BINARY}}"
args = [
"-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace"
]
[[parachains.collators]]
name = "asset-hub-rococo-collator2"
command = "{{POLKADOT_PARACHAIN_BINARY}}"
args = [
"-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace"
]
#[[hrmp_channels]]
#sender = 1000
#recipient = 1013
#max_capacity = 4
#max_message_size = 524288
#
#[[hrmp_channels]]
#sender = 1013
#recipient = 1000
#max_capacity = 4
#max_message_size = 524288
@@ -0,0 +1,88 @@
[settings]
node_spawn_timeout = 240
[relaychain]
default_command = "{{POLKADOT_BINARY}}"
default_args = [ "-lparachain=debug,xcm=trace" ]
chain = "westend-local"
[[relaychain.nodes]]
name = "alice-westend-validator"
validator = true
rpc_port = 9935
ws_port = 9945
balance = 2000000000000
[[relaychain.nodes]]
name = "bob-westend-validator"
validator = true
rpc_port = 9936
ws_port = 9946
balance = 2000000000000
[[relaychain.nodes]]
name = "charlie-westend-validator"
validator = true
rpc_port = 9937
ws_port = 9947
balance = 2000000000000
[[parachains]]
id = 1002
chain = "bridge-hub-westend-local"
cumulus_based = true
# run alice as parachain collator
[[parachains.collators]]
name = "bridge-hub-westend-collator1"
validator = true
command = "{{POLKADOT_PARACHAIN_BINARY}}"
rpc_port = 8935
ws_port = 8945
args = [
"-lparachain=debug,runtime::mmr=info,substrate=info,runtime=info,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace"
]
# run bob as parachain collator
[[parachains.collators]]
name = "bridge-hub-westend-collator2"
validator = true
command = "{{POLKADOT_PARACHAIN_BINARY}}"
rpc_port = 8936
ws_port = 8946
args = [
"-lparachain=trace,runtime::mmr=info,substrate=info,runtime=info,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace"
]
[[parachains]]
id = 1000
chain = "asset-hub-westend-local"
cumulus_based = true
[[parachains.collators]]
name = "asset-hub-westend-collator1"
rpc_port = 9011
ws_port = 9010
command = "{{POLKADOT_PARACHAIN_BINARY}}"
args = [
"-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace"
]
[[parachains.collators]]
name = "asset-hub-westend-collator2"
command = "{{POLKADOT_PARACHAIN_BINARY}}"
args = [
"-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace"
]
#[[hrmp_channels]]
#sender = 1000
#recipient = 1002
#max_capacity = 4
#max_message_size = 524288
#
#[[hrmp_channels]]
#sender = 1002
#recipient = 1000
#max_capacity = 4
#max_message_size = 524288
@@ -0,0 +1,401 @@
#!/bin/bash
# import common functions
source "$FRAMEWORK_PATH/utils/bridges.sh"
# Expected sovereign accounts.
#
# Generated by:
#
# #[test]
# fn generate_sovereign_accounts() {
# use sp_core::crypto::Ss58Codec;
# use polkadot_parachain_primitives::primitives::Sibling;
#
# parameter_types! {
# pub UniversalLocationAHR: InteriorMultiLocation = X2(GlobalConsensus(Rococo), Parachain(1000));
# pub UniversalLocationAHW: InteriorMultiLocation = X2(GlobalConsensus(Westend), Parachain(1000));
# }
#
# // SS58=42
# println!("GLOBAL_CONSENSUS_ROCOCO_SOVEREIGN_ACCOUNT=\"{}\"",
# frame_support::sp_runtime::AccountId32::new(
# GlobalConsensusConvertsFor::<UniversalLocationAHW, [u8; 32]>::convert_location(
# &MultiLocation { parents: 2, interior: X1(GlobalConsensus(Rococo)) }).unwrap()
# ).to_ss58check_with_version(42_u16.into())
# );
# println!("ASSET_HUB_WESTEND_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_WESTEND=\"{}\"",
# frame_support::sp_runtime::AccountId32::new(
# SiblingParachainConvertsVia::<Sibling, [u8; 32]>::convert_location(
# &MultiLocation { parents: 1, interior: X1(Parachain(1000)) }).unwrap()
# ).to_ss58check_with_version(42_u16.into())
# );
#
# // SS58=42
# println!("GLOBAL_CONSENSUS_WESTEND_SOVEREIGN_ACCOUNT=\"{}\"",
# frame_support::sp_runtime::AccountId32::new(
# GlobalConsensusConvertsFor::<UniversalLocationAHR, [u8; 32]>::convert_location(
# &MultiLocation { parents: 2, interior: X1(GlobalConsensus(Westend)) }).unwrap()
# ).to_ss58check_with_version(42_u16.into())
# );
# println!("ASSET_HUB_ROCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ROCOCO=\"{}\"",
# frame_support::sp_runtime::AccountId32::new(
# SiblingParachainConvertsVia::<Sibling, [u8; 32]>::convert_location(
# &MultiLocation { parents: 1, interior: X1(Parachain(1000)) }).unwrap()
# ).to_ss58check_with_version(42_u16.into())
# );
# }
GLOBAL_CONSENSUS_ROCOCO_SOVEREIGN_ACCOUNT="5GxRGwT8bU1JeBPTUXc7LEjZMxNrK8MyL2NJnkWFQJTQ4sii"
ASSET_HUB_WESTEND_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_WESTEND="5Eg2fntNprdN3FgH4sfEaaZhYtddZQSQUqvYJ1f2mLtinVhV"
GLOBAL_CONSENSUS_WESTEND_SOVEREIGN_ACCOUNT="5He2Qdztyxxa4GoagY6q1jaiLMmKy1gXS7PdZkhfj8ZG9hk5"
ASSET_HUB_ROCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ROCOCO="5Eg2fntNprdN3FgH4sfEaaZhYtddZQSQUqvYJ1f2mLtinVhV"
# Expected sovereign accounts for rewards on BridgeHubs.
#
# Generated by:
# #[test]
# fn generate_sovereign_accounts_for_rewards() {
# use bp_messages::LaneId;
# use bp_relayers::{PayRewardFromAccount, RewardsAccountOwner, RewardsAccountParams};
# use sp_core::crypto::Ss58Codec;
#
# // SS58=42
# println!(
# "ON_BRIDGE_HUB_ROCOCO_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_ThisChain=\"{}\"",
# frame_support::sp_runtime::AccountId32::new(
# PayRewardFromAccount::<[u8; 32], [u8; 32]>::rewards_account(RewardsAccountParams::new(
# LaneId([0, 0, 0, 2]),
# *b"bhwd",
# RewardsAccountOwner::ThisChain
# ))
# )
# .to_ss58check_with_version(42_u16.into())
# );
# // SS58=42
# println!(
# "ON_BRIDGE_HUB_ROCOCO_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_BridgedChain=\"{}\"",
# frame_support::sp_runtime::AccountId32::new(
# PayRewardFromAccount::<[u8; 32], [u8; 32]>::rewards_account(RewardsAccountParams::new(
# LaneId([0, 0, 0, 2]),
# *b"bhwd",
# RewardsAccountOwner::BridgedChain
# ))
# )
# .to_ss58check_with_version(42_u16.into())
# );
#
# // SS58=42
# println!(
# "ON_BRIDGE_HUB_WESTEND_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_ThisChain=\"{}\"",
# frame_support::sp_runtime::AccountId32::new(
# PayRewardFromAccount::<[u8; 32], [u8; 32]>::rewards_account(RewardsAccountParams::new(
# LaneId([0, 0, 0, 2]),
# *b"bhro",
# RewardsAccountOwner::ThisChain
# ))
# )
# .to_ss58check_with_version(42_u16.into())
# );
# // SS58=42
# println!(
# "ON_BRIDGE_HUB_WESTEND_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_BridgedChain=\"{}\"",
# frame_support::sp_runtime::AccountId32::new(
# PayRewardFromAccount::<[u8; 32], [u8; 32]>::rewards_account(RewardsAccountParams::new(
# LaneId([0, 0, 0, 2]),
# *b"bhro",
# RewardsAccountOwner::BridgedChain
# ))
# )
# .to_ss58check_with_version(42_u16.into())
# );
# }
ON_BRIDGE_HUB_ROCOCO_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_ThisChain="5EHnXaT5BhiSGP5hbdsoVGtzi2sQVgpDNToTxLYeQvKoMPEm"
ON_BRIDGE_HUB_ROCOCO_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_BridgedChain="5EHnXaT5BhiSGP5hbdt5EJSapXYbxEv678jyWHEUskCXcjqo"
ON_BRIDGE_HUB_WESTEND_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_ThisChain="5EHnXaT5BhiSGP5h9Rg8sgUJqoLym3iEaWUiboT8S9AT5xFh"
ON_BRIDGE_HUB_WESTEND_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_BridgedChain="5EHnXaT5BhiSGP5h9RgQci1txJ2BDbp7KBRE9k8xty3BMUSi"
LANE_ID="00000002"
XCM_VERSION=3
function init_ro_wnd() {
local relayer_path=$(ensure_relayer)
RUST_LOG=runtime=trace,rpc=trace,bridge=trace \
$relayer_path init-bridge rococo-to-bridge-hub-westend \
--source-host localhost \
--source-port 9942 \
--source-version-mode Auto \
--target-host localhost \
--target-port 8945 \
--target-version-mode Auto \
--target-signer //Bob
}
function init_wnd_ro() {
local relayer_path=$(ensure_relayer)
RUST_LOG=runtime=trace,rpc=trace,bridge=trace \
$relayer_path init-bridge westend-to-bridge-hub-rococo \
--source-host localhost \
--source-port 9945 \
--source-version-mode Auto \
--target-host localhost \
--target-port 8943 \
--target-version-mode Auto \
--target-signer //Bob
}
function run_relay() {
local relayer_path=$(ensure_relayer)
RUST_LOG=runtime=trace,rpc=trace,bridge=trace \
$relayer_path relay-headers-and-messages bridge-hub-rococo-bridge-hub-westend \
--rococo-host localhost \
--rococo-port 9942 \
--rococo-version-mode Auto \
--bridge-hub-rococo-host localhost \
--bridge-hub-rococo-port 8943 \
--bridge-hub-rococo-version-mode Auto \
--bridge-hub-rococo-signer //Charlie \
--bridge-hub-rococo-transactions-mortality 4 \
--westend-host localhost \
--westend-port 9945 \
--westend-version-mode Auto \
--bridge-hub-westend-host localhost \
--bridge-hub-westend-port 8945 \
--bridge-hub-westend-version-mode Auto \
--bridge-hub-westend-signer //Charlie \
--bridge-hub-westend-transactions-mortality 4 \
--lane "${LANE_ID}"
}
case "$1" in
run-relay)
init_wnd_ro
init_ro_wnd
run_relay
;;
init-asset-hub-rococo-local)
ensure_polkadot_js_api
# create foreign assets for native Westend token (governance call on Rococo)
force_create_foreign_asset \
"ws://127.0.0.1:9942" \
"//Alice" \
1000 \
"ws://127.0.0.1:9910" \
"$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Westend" } } }')" \
"$GLOBAL_CONSENSUS_WESTEND_SOVEREIGN_ACCOUNT" \
10000000000 \
true
# HRMP
open_hrmp_channels \
"ws://127.0.0.1:9942" \
"//Alice" \
1000 1013 4 524288
open_hrmp_channels \
"ws://127.0.0.1:9942" \
"//Alice" \
1013 1000 4 524288
# set XCM version of remote AssetHubWestend
force_xcm_version \
"ws://127.0.0.1:9942" \
"//Alice" \
1000 \
"ws://127.0.0.1:9910" \
"$(jq --null-input '{ "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Westend" }, { "Parachain": 1000 } ] } }')" \
$XCM_VERSION
;;
init-bridge-hub-rococo-local)
ensure_polkadot_js_api
# SA of sibling asset hub pays for the execution
transfer_balance \
"ws://127.0.0.1:8943" \
"//Alice" \
"$ASSET_HUB_ROCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ROCOCO" \
$((1000000000000 + 50000000000 * 20))
# drip SA of lane dedicated to asset hub for paying rewards for delivery
transfer_balance \
"ws://127.0.0.1:8943" \
"//Alice" \
"$ON_BRIDGE_HUB_ROCOCO_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_ThisChain" \
$((1000000000000 + 2000000000000))
# drip SA of lane dedicated to asset hub for paying rewards for delivery confirmation
transfer_balance \
"ws://127.0.0.1:8943" \
"//Alice" \
"$ON_BRIDGE_HUB_ROCOCO_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_BridgedChain" \
$((1000000000000 + 2000000000000))
# set XCM version of remote BridgeHubWestend
force_xcm_version \
"ws://127.0.0.1:9942" \
"//Alice" \
1013 \
"ws://127.0.0.1:8943" \
"$(jq --null-input '{ "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Westend" }, { "Parachain": 1002 } ] } }')" \
$XCM_VERSION
;;
init-asset-hub-westend-local)
ensure_polkadot_js_api
# create foreign assets for native Rococo token (governance call on Westend)
force_create_foreign_asset \
"ws://127.0.0.1:9945" \
"//Alice" \
1000 \
"ws://127.0.0.1:9010" \
"$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Rococo" } } }')" \
"$GLOBAL_CONSENSUS_ROCOCO_SOVEREIGN_ACCOUNT" \
10000000000 \
true
# HRMP
open_hrmp_channels \
"ws://127.0.0.1:9945" \
"//Alice" \
1000 1002 4 524288
open_hrmp_channels \
"ws://127.0.0.1:9945" \
"//Alice" \
1002 1000 4 524288
# set XCM version of remote AssetHubRococo
force_xcm_version \
"ws://127.0.0.1:9945" \
"//Alice" \
1000 \
"ws://127.0.0.1:9010" \
"$(jq --null-input '{ "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Rococo" }, { "Parachain": 1000 } ] } }')" \
$XCM_VERSION
;;
init-bridge-hub-westend-local)
# SA of sibling asset hub pays for the execution
transfer_balance \
"ws://127.0.0.1:8945" \
"//Alice" \
"$ASSET_HUB_WESTEND_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_WESTEND" \
$((1000000000000000 + 50000000000 * 20))
# drip SA of lane dedicated to asset hub for paying rewards for delivery
transfer_balance \
"ws://127.0.0.1:8945" \
"//Alice" \
"$ON_BRIDGE_HUB_WESTEND_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_ThisChain" \
$((1000000000000000 + 2000000000000))
# drip SA of lane dedicated to asset hub for paying rewards for delivery confirmation
transfer_balance \
"ws://127.0.0.1:8945" \
"//Alice" \
"$ON_BRIDGE_HUB_WESTEND_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_BridgedChain" \
$((1000000000000000 + 2000000000000))
# set XCM version of remote BridgeHubRococo
force_xcm_version \
"ws://127.0.0.1:9945" \
"//Alice" \
1002 \
"ws://127.0.0.1:8945" \
"$(jq --null-input '{ "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Rococo" }, { "Parachain": 1013 } ] } }')" \
$XCM_VERSION
;;
reserve-transfer-assets-from-asset-hub-rococo-local)
amount=$2
ensure_polkadot_js_api
# send ROCs to Alice account on AHW
limited_reserve_transfer_assets \
"ws://127.0.0.1:9910" \
"//Alice" \
"$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Westend" }, { "Parachain": 1000 } ] } } }')" \
"$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \
"$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": '$amount' } } ] }')" \
0 \
"Unlimited"
;;
withdraw-reserve-assets-from-asset-hub-rococo-local)
amount=$2
ensure_polkadot_js_api
# send back only 100000000000 wrappedWNDs to Alice account on AHW
limited_reserve_transfer_assets \
"ws://127.0.0.1:9910" \
"//Alice" \
"$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Westend" }, { "Parachain": 1000 } ] } } }')" \
"$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \
"$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 2, "interior": { "X1": { "GlobalConsensus": "Westend" } } } }, "fun": { "Fungible": '$amount' } } ] }')" \
0 \
"Unlimited"
;;
reserve-transfer-assets-from-asset-hub-westend-local)
amount=$2
ensure_polkadot_js_api
# send WNDs to Alice account on AHR
limited_reserve_transfer_assets \
"ws://127.0.0.1:9010" \
"//Alice" \
"$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Rococo" }, { "Parachain": 1000 } ] } } }')" \
"$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \
"$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": '$amount' } } ] }')" \
0 \
"Unlimited"
;;
withdraw-reserve-assets-from-asset-hub-westend-local)
amount=$2
ensure_polkadot_js_api
# send back only 100000000000 wrappedROCs to Alice account on AHR
limited_reserve_transfer_assets \
"ws://127.0.0.1:9010" \
"//Alice" \
"$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Rococo" }, { "Parachain": 1000 } ] } } }')" \
"$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \
"$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 2, "interior": { "X1": { "GlobalConsensus": "Rococo" } } } }, "fun": { "Fungible": '$amount' } } ] }')" \
0 \
"Unlimited"
;;
claim-rewards-bridge-hub-rococo-local)
ensure_polkadot_js_api
# bhwd -> [62, 68, 77, 64] -> 0x62687764
claim_rewards \
"ws://127.0.0.1:8943" \
"//Charlie" \
"0x${LANE_ID}" \
"0x62687764" \
"ThisChain"
claim_rewards \
"ws://127.0.0.1:8943" \
"//Charlie" \
"0x${LANE_ID}" \
"0x62687764" \
"BridgedChain"
;;
claim-rewards-bridge-hub-westend-local)
# bhro -> [62, 68, 72, 6f] -> 0x6268726f
claim_rewards \
"ws://127.0.0.1:8945" \
"//Charlie" \
"0x${LANE_ID}" \
"0x6268726f" \
"ThisChain"
claim_rewards \
"ws://127.0.0.1:8945" \
"//Charlie" \
"0x${LANE_ID}" \
"0x6268726f" \
"BridgedChain"
;;
stop)
pkill -f polkadot
pkill -f parachain
;;
import)
# to avoid trigger anything here
;;
*)
echo "A command is require. Supported commands for:
Local (zombienet) run:
- run-relay
- init-asset-hub-rococo-local
- init-bridge-hub-rococo-local
- init-asset-hub-westend-local
- init-bridge-hub-westend-local
- reserve-transfer-assets-from-asset-hub-rococo-local
- withdraw-reserve-assets-from-asset-hub-rococo-local
- reserve-transfer-assets-from-asset-hub-westend-local
- withdraw-reserve-assets-from-asset-hub-westend-local
- claim-rewards-bridge-hub-rococo-local
- claim-rewards-bridge-hub-westend-local";
exit 1
;;
esac
+3
View File
@@ -0,0 +1,3 @@
#!/bin/bash
$ENV_PATH/bridges_rococo_westend.sh "$@"
@@ -0,0 +1,8 @@
Description: Check if the HRMP channel between Rococo BH and Rococo AH was opened successfully
Network: ./bridge_hub_rococo_local_network.toml
Creds: config
# ensure that initialization has completed
asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wait-hrmp-channel-opened.js with "1013" within 300 seconds
@@ -0,0 +1,7 @@
Description: Check if the with-Westend GRANPDA pallet was initialized at Rococo BH
Network: ./bridge_hub_rococo_local_network.toml
Creds: config
# relay is already started - let's wait until with-Westend GRANPDA pallet is initialized at Rococo
bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/best-finalized-header-at-bridged-chain.js with "Westend,0" within 400 seconds
+70
View File
@@ -0,0 +1,70 @@
#!/bin/bash
set -e
trap "trap - SIGTERM && kill -9 -$$" SIGINT SIGTERM EXIT
source "$FRAMEWORK_PATH/utils/zombienet.sh"
# whether to init the chains (open HRMP channels, set XCM version, create reserve assets, etc)
init=0
start_relayer=0
while [ $# -ne 0 ]
do
arg="$1"
case "$arg" in
--init)
init=1
;;
--start-relayer)
start_relayer=1
;;
esac
shift
done
logs_dir=$TEST_DIR/logs
helper_script="${BASH_SOURCE%/*}/helper.sh"
rococo_def=${BASH_SOURCE%/*}/bridge_hub_rococo_local_network.toml
start_zombienet $TEST_DIR $rococo_def rococo_dir rococo_pid
echo
westend_def=${BASH_SOURCE%/*}/bridge_hub_westend_local_network.toml
start_zombienet $TEST_DIR $westend_def westend_dir westend_pid
echo
if [[ $init -eq 1 ]]; then
rococo_init_log=$logs_dir/rococo-init.log
echo -e "Setting up the rococo side of the bridge. Logs available at: $rococo_init_log\n"
westend_init_log=$logs_dir/westend-init.log
echo -e "Setting up the westend side of the bridge. Logs available at: $westend_init_log\n"
$helper_script init-asset-hub-rococo-local >> $rococo_init_log 2>&1 &
rococo_init_pid=$!
$helper_script init-asset-hub-westend-local >> $westend_init_log 2>&1 &
westend_init_pid=$!
wait -n $rococo_init_pid $westend_init_pid
$helper_script init-bridge-hub-rococo-local >> $rococo_init_log 2>&1 &
rococo_init_pid=$!
$helper_script init-bridge-hub-westend-local >> $westend_init_log 2>&1 &
westend_init_pid=$!
wait -n $rococo_init_pid $westend_init_pid
run_zndsl ${BASH_SOURCE%/*}/rococo-init.zndsl $rococo_dir
run_zndsl ${BASH_SOURCE%/*}/westend-init.zndsl $westend_dir
fi
if [[ $start_relayer -eq 1 ]]; then
${BASH_SOURCE%/*}/start_relayer.sh $rococo_dir $westend_dir relayer_pid
fi
echo $rococo_dir > $TEST_DIR/rococo.env
echo $westend_dir > $TEST_DIR/westend.env
echo
wait -n $rococo_pid $westend_pid $relayer_pid
kill -9 -$$
@@ -0,0 +1,23 @@
#!/bin/bash
set -e
source "$FRAMEWORK_PATH/utils/common.sh"
source "$FRAMEWORK_PATH/utils/zombienet.sh"
rococo_dir=$1
westend_dir=$2
__relayer_pid=$3
logs_dir=$TEST_DIR/logs
helper_script="${BASH_SOURCE%/*}/helper.sh"
relayer_log=$logs_dir/relayer.log
echo -e "Starting rococo-westend relayer. Logs available at: $relayer_log\n"
start_background_process "$helper_script run-relay" $relayer_log relayer_pid
run_zndsl ${BASH_SOURCE%/*}/rococo.zndsl $rococo_dir
run_zndsl ${BASH_SOURCE%/*}/westend.zndsl $westend_dir
eval $__relayer_pid="'$relayer_pid'"
@@ -0,0 +1,7 @@
Description: Check if the HRMP channel between Westend BH and Westend AH was opened successfully
Network: ./bridge_hub_westend_local_network.toml
Creds: config
# ensure that initialization has completed
asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wait-hrmp-channel-opened.js with "1002" within 600 seconds
@@ -0,0 +1,6 @@
Description: Check if the with-Rococo GRANPDA pallet was initialized at Westend BH
Network: ./bridge_hub_westend_local_network.toml
Creds: config
# relay is already started - let's wait until with-Rococo GRANPDA pallet is initialized at Westend
bridge-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/best-finalized-header-at-bridged-chain.js with "Rococo,0" within 400 seconds
@@ -0,0 +1,25 @@
async function run(nodeName, networkInfo, args) {
const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName];
const api = await zombie.connect(wsUri, userDefinedTypes);
// TODO: could be replaced with https://github.com/polkadot-js/api/issues/4930 (depends on metadata v15) later
const bridgedChainName = args[0];
const expectedBridgedChainHeaderNumber = Number(args[1]);
const runtimeApiMethod = bridgedChainName + "FinalityApi_best_finalized";
while (true) {
const encodedBestFinalizedHeaderId = await api.rpc.state.call(runtimeApiMethod, []);
const bestFinalizedHeaderId = api.createType("Option<BpRuntimeHeaderId>", encodedBestFinalizedHeaderId);
if (bestFinalizedHeaderId.isSome) {
const bestFinalizedHeaderNumber = Number(bestFinalizedHeaderId.unwrap().toHuman()[0]);
if (bestFinalizedHeaderNumber > expectedBridgedChainHeaderNumber) {
return bestFinalizedHeaderNumber;
}
}
// else sleep and retry
await new Promise((resolve) => setTimeout(resolve, 6000));
}
}
module.exports = { run }
@@ -0,0 +1,6 @@
module.exports = {
grandpaPalletName: "bridgeRococoGrandpa",
parachainsPalletName: "bridgeRococoParachains",
messagesPalletName: "bridgeRococoMessages",
bridgedBridgeHubParaId: 1013,
}
@@ -0,0 +1,6 @@
module.exports = {
grandpaPalletName: "bridgeWestendGrandpa",
parachainsPalletName: "bridgeWestendParachains",
messagesPalletName: "bridgeWestendMessages",
bridgedBridgeHubParaId: 1002,
}
@@ -0,0 +1,21 @@
async function run(nodeName, networkInfo, args) {
const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName];
const api = await zombie.connect(wsUri, userDefinedTypes);
const accountAddress = args[0];
const expectedIncrease = BigInt(args[1]);
const initialAccountData = await api.query.system.account(accountAddress);
const initialAccountBalance = initialAccountData.data['free'];
while (true) {
const accountData = await api.query.system.account(accountAddress);
const accountBalance = accountData.data['free'];
if (accountBalance > initialAccountBalance + expectedIncrease) {
return accountBalance;
}
// else sleep and retry
await new Promise((resolve) => setTimeout(resolve, 6000));
}
}
module.exports = {run}
@@ -0,0 +1,44 @@
const utils = require("./utils");
async function run(nodeName, networkInfo, args) {
const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName];
const api = await zombie.connect(wsUri, userDefinedTypes);
// parse arguments
const exitAfterSeconds = Number(args[0]);
const bridgedChain = require("./chains/" + args[1]);
// start listening to new blocks
let totalGrandpaHeaders = 0;
let initialParachainHeaderImported = false;
api.rpc.chain.subscribeNewHeads(async function (header) {
const apiAtParent = await api.at(header.parentHash);
const apiAtCurrent = await api.at(header.hash);
const currentEvents = await apiAtCurrent.query.system.events();
totalGrandpaHeaders += await utils.ensureOnlyMandatoryGrandpaHeadersImported(
bridgedChain,
apiAtParent,
apiAtCurrent,
currentEvents,
);
initialParachainHeaderImported = await utils.ensureOnlyInitialParachainHeaderImported(
bridgedChain,
apiAtParent,
apiAtCurrent,
currentEvents,
);
});
// wait given time
await new Promise(resolve => setTimeout(resolve, exitAfterSeconds * 1000));
// if we haven't seen any new GRANDPA or parachain headers => fail
if (totalGrandpaHeaders == 0) {
throw new Error("No bridged relay chain headers imported");
}
if (!initialParachainHeaderImported) {
throw new Error("No bridged parachain headers imported");
}
}
module.exports = { run }
@@ -0,0 +1,81 @@
const utils = require("./utils");
async function run(nodeName, networkInfo, args) {
const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName];
const api = await zombie.connect(wsUri, userDefinedTypes);
// parse arguments
const exitAfterSeconds = Number(args[0]);
const bridgedChain = require("./chains/" + args[1]);
// start listening to new blocks
let atLeastOneMessageReceived = false;
let atLeastOneMessageDelivered = false;
const unsubscribe = await api.rpc.chain.subscribeNewHeads(async function (header) {
const apiAtParent = await api.at(header.parentHash);
const apiAtCurrent = await api.at(header.hash);
const currentEvents = await apiAtCurrent.query.system.events();
const messagesReceived = currentEvents.find((record) => {
return record.event.section == bridgedChain.messagesPalletName
&& record.event.method == "MessagesReceived";
}) != undefined;
const messagesDelivered = currentEvents.find((record) => {
return record.event.section == bridgedChain.messagesPalletName &&
record.event.method == "MessagesDelivered";
}) != undefined;
const hasMessageUpdates = messagesReceived || messagesDelivered;
atLeastOneMessageReceived = atLeastOneMessageReceived || messagesReceived;
atLeastOneMessageDelivered = atLeastOneMessageDelivered || messagesDelivered;
if (!hasMessageUpdates) {
// if there are no any message update transactions, we only expect mandatory GRANDPA
// headers and initial parachain headers
await utils.ensureOnlyMandatoryGrandpaHeadersImported(
bridgedChain,
apiAtParent,
apiAtCurrent,
currentEvents,
);
await utils.ensureOnlyInitialParachainHeaderImported(
bridgedChain,
apiAtParent,
apiAtCurrent,
currentEvents,
);
} else {
const messageTransactions = (messagesReceived ? 1 : 0) + (messagesDelivered ? 1 : 0);
// otherwise we only accept at most one GRANDPA header
const newGrandpaHeaders = utils.countGrandpaHeaderImports(bridgedChain, currentEvents);
if (newGrandpaHeaders > 1) {
utils.logEvents(currentEvents);
throw new Error("Unexpected relay chain header import: " + newGrandpaHeaders + " / " + messageTransactions);
}
// ...and at most one parachain header
const newParachainHeaders = utils.countParachainHeaderImports(bridgedChain, currentEvents);
if (newParachainHeaders > 1) {
utils.logEvents(currentEvents);
throw new Error("Unexpected parachain header import: " + newParachainHeaders + " / " + messageTransactions);
}
}
});
// wait until we have received + delivered messages OR until timeout
await utils.pollUntil(
exitAfterSeconds,
() => { return atLeastOneMessageReceived && atLeastOneMessageDelivered; },
() => { unsubscribe(); },
() => {
if (!atLeastOneMessageReceived) {
throw new Error("No messages received from bridged chain");
}
if (!atLeastOneMessageDelivered) {
throw new Error("No messages delivered to bridged chain");
}
},
);
}
module.exports = { run }
@@ -0,0 +1,28 @@
async function run(nodeName, networkInfo, args) {
const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName];
const api = await zombie.connect(wsUri, userDefinedTypes);
// TODO: could be replaced with https://github.com/polkadot-js/api/issues/4930 (depends on metadata v15) later
const relayerAccountAddress = args[0];
const laneId = args[1];
const bridgedChainId = args[2];
const relayerFundOwner = args[3];
const expectedRelayerReward = BigInt(args[4]);
while (true) {
const relayerReward = await api.query.bridgeRelayers.relayerRewards(
relayerAccountAddress,
{ laneId: laneId, bridgedChainId: bridgedChainId, owner: relayerFundOwner }
);
if (relayerReward.isSome) {
const relayerRewardBalance = relayerReward.unwrap().toBigInt();
if (relayerRewardBalance > expectedRelayerReward) {
return relayerRewardBalance;
}
}
// else sleep and retry
await new Promise((resolve) => setTimeout(resolve, 6000));
}
}
module.exports = { run }
@@ -0,0 +1,103 @@
module.exports = {
logEvents: function(events) {
let stringifiedEvents = "";
events.forEach((record) => {
if (stringifiedEvents != "") {
stringifiedEvents += ", ";
}
stringifiedEvents += record.event.section + "::" + record.event.method;
});
console.log("Block events: " + stringifiedEvents);
},
countGrandpaHeaderImports: function(bridgedChain, events) {
return events.reduce(
(count, record) => {
const { event } = record;
if (event.section == bridgedChain.grandpaPalletName && event.method == "UpdatedBestFinalizedHeader") {
count += 1;
}
return count;
},
0,
);
},
countParachainHeaderImports: function(bridgedChain, events) {
return events.reduce(
(count, record) => {
const { event } = record;
if (event.section == bridgedChain.parachainsPalletName && event.method == "UpdatedParachainHead") {
count += 1;
}
return count;
},
0,
);
},
pollUntil: async function(
timeoutInSecs,
predicate,
cleanup,
onFailure,
) {
const begin = new Date().getTime();
const end = begin + timeoutInSecs * 1000;
while (new Date().getTime() < end) {
if (predicate()) {
cleanup();
return;
}
await new Promise(resolve => setTimeout(resolve, 100));
}
cleanup();
onFailure();
},
ensureOnlyMandatoryGrandpaHeadersImported: async function(
bridgedChain,
apiAtParent,
apiAtCurrent,
currentEvents,
) {
// remember id of bridged relay chain GRANDPA authorities set at parent block
const authoritySetAtParent = await apiAtParent.query[bridgedChain.grandpaPalletName].currentAuthoritySet();
const authoritySetIdAtParent = authoritySetAtParent["setId"];
// now read the id of bridged relay chain GRANDPA authorities set at current block
const authoritySetAtCurrent = await apiAtCurrent.query[bridgedChain.grandpaPalletName].currentAuthoritySet();
const authoritySetIdAtCurrent = authoritySetAtCurrent["setId"];
// we expect to see no more than `authoritySetIdAtCurrent - authoritySetIdAtParent` new GRANDPA headers
const maxNewGrandpaHeaders = authoritySetIdAtCurrent - authoritySetIdAtParent;
const newGrandpaHeaders = module.exports.countGrandpaHeaderImports(bridgedChain, currentEvents);
// check that our assumptions are correct
if (newGrandpaHeaders > maxNewGrandpaHeaders) {
module.exports.logEvents(currentEvents);
throw new Error("Unexpected relay chain header import: " + newGrandpaHeaders + " / " + maxNewGrandpaHeaders);
}
return newGrandpaHeaders;
},
ensureOnlyInitialParachainHeaderImported: async function(
bridgedChain,
apiAtParent,
apiAtCurrent,
currentEvents,
) {
// remember whether we already know bridged parachain header at a parent block
const bestBridgedParachainHeader = await apiAtParent.query[bridgedChain.parachainsPalletName].parasInfo(bridgedChain.bridgedBridgeHubParaId);;
const hasBestBridgedParachainHeader = bestBridgedParachainHeader.isSome;
// we expect to see: no more than `1` bridged parachain header if there were no parachain header before.
const maxNewParachainHeaders = hasBestBridgedParachainHeader ? 0 : 1;
const newParachainHeaders = module.exports.countParachainHeaderImports(bridgedChain, currentEvents);
// check that our assumptions are correct
if (newParachainHeaders > maxNewParachainHeaders) {
module.exports.logEvents(currentEvents);
throw new Error("Unexpected parachain header import: " + newParachainHeaders + " / " + maxNewParachainHeaders);
}
return hasBestBridgedParachainHeader;
},
}
@@ -0,0 +1,22 @@
async function run(nodeName, networkInfo, args) {
const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName];
const api = await zombie.connect(wsUri, userDefinedTypes);
const sibling = args[0];
while (true) {
const messagingStateAsObj = await api.query.parachainSystem.relevantMessagingState();
const messagingState = api.createType("Option<CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot>", messagingStateAsObj);
if (messagingState.isSome) {
const egressChannels = messagingState.unwrap().egressChannels;
if (egressChannels.find(x => x[0] == sibling)) {
return;
}
}
// else sleep and retry
await new Promise((resolve) => setTimeout(resolve, 6000));
}
}
module.exports = { run }
@@ -0,0 +1,26 @@
async function run(nodeName, networkInfo, args) {
const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName];
const api = await zombie.connect(wsUri, userDefinedTypes);
// TODO: could be replaced with https://github.com/polkadot-js/api/issues/4930 (depends on metadata v15) later
const accountAddress = args[0];
const expectedForeignAssetBalance = BigInt(args[1]);
const bridgedNetworkName = args[2];
while (true) {
const foreignAssetAccount = await api.query.foreignAssets.account(
{ parents: 2, interior: { X1: { GlobalConsensus: bridgedNetworkName } } },
accountAddress
);
if (foreignAssetAccount.isSome) {
const foreignAssetAccountBalance = foreignAssetAccount.unwrap().balance.toBigInt();
if (foreignAssetAccountBalance > expectedForeignAssetBalance) {
return foreignAssetAccountBalance;
}
}
// else sleep and retry
await new Promise((resolve) => setTimeout(resolve, 6000));
}
}
module.exports = { run }
+309
View File
@@ -0,0 +1,309 @@
#!/bin/bash
function relayer_path() {
local default_path=~/local_bridge_testing/bin/substrate-relay
local path="${SUBSTRATE_RELAY_BINARY:-$default_path}"
echo "$path"
}
function ensure_relayer() {
local path=$(relayer_path)
if [[ ! -f "$path" ]]; then
echo " Required substrate-relay binary '$path' does not exist!"
echo " You need to build it and copy to this location!"
echo " Please, check ./parachains/runtimes/bridge-hubs/README.md (Prepare/Build/Deploy)"
exit 1
fi
echo $path
}
function ensure_polkadot_js_api() {
if ! which polkadot-js-api &> /dev/null; then
echo ''
echo 'Required command `polkadot-js-api` not in PATH, please, install, e.g.:'
echo "npm install -g @polkadot/api-cli@beta"
echo " or"
echo "yarn global add @polkadot/api-cli"
echo ''
exit 1
fi
if ! which jq &> /dev/null; then
echo ''
echo 'Required command `jq` not in PATH, please, install, e.g.:'
echo "apt install -y jq"
echo ''
exit 1
fi
generate_hex_encoded_call_data "check" "--"
local retVal=$?
if [ $retVal -ne 0 ]; then
echo ""
echo ""
echo "-------------------"
echo "Installing (nodejs) sub module: ${BASH_SOURCE%/*}/generate_hex_encoded_call"
pushd ${BASH_SOURCE%/*}/generate_hex_encoded_call
npm install
popd
fi
}
function call_polkadot_js_api() {
# --noWait: without that argument `polkadot-js-api` waits until transaction is included into the block.
# With it, it just submits it to the tx pool and exits.
# --nonce -1: means to compute transaction nonce using `system_accountNextIndex` RPC, which includes all
# transaction that are in the tx pool.
polkadot-js-api --noWait --nonce -1 "$@"
}
function generate_hex_encoded_call_data() {
local type=$1
local endpoint=$2
local output=$3
shift
shift
shift
echo "Input params: $@"
node ${BASH_SOURCE%/*}/../utils/generate_hex_encoded_call "$type" "$endpoint" "$output" "$@"
local retVal=$?
if [ $type != "check" ]; then
local hex_encoded_data=$(cat $output)
echo "Generated hex-encoded bytes to file '$output': $hex_encoded_data"
fi
return $retVal
}
function transfer_balance() {
local runtime_para_endpoint=$1
local seed=$2
local target_account=$3
local amount=$4
echo " calling transfer_balance:"
echo " runtime_para_endpoint: ${runtime_para_endpoint}"
echo " seed: ${seed}"
echo " target_account: ${target_account}"
echo " amount: ${amount}"
echo "--------------------------------------------------"
call_polkadot_js_api \
--ws "${runtime_para_endpoint}" \
--seed "${seed?}" \
tx.balances.transferAllowDeath \
"${target_account}" \
"${amount}"
}
function send_governance_transact() {
local relay_url=$1
local relay_chain_seed=$2
local para_id=$3
local hex_encoded_data=$4
local require_weight_at_most_ref_time=$5
local require_weight_at_most_proof_size=$6
echo " calling send_governance_transact:"
echo " relay_url: ${relay_url}"
echo " relay_chain_seed: ${relay_chain_seed}"
echo " para_id: ${para_id}"
echo " hex_encoded_data: ${hex_encoded_data}"
echo " require_weight_at_most_ref_time: ${require_weight_at_most_ref_time}"
echo " require_weight_at_most_proof_size: ${require_weight_at_most_proof_size}"
echo " params:"
local dest=$(jq --null-input \
--arg para_id "$para_id" \
'{ "V3": { "parents": 0, "interior": { "X1": { "Parachain": $para_id } } } }')
local message=$(jq --null-input \
--argjson hex_encoded_data $hex_encoded_data \
--arg require_weight_at_most_ref_time "$require_weight_at_most_ref_time" \
--arg require_weight_at_most_proof_size "$require_weight_at_most_proof_size" \
'
{
"V3": [
{
"UnpaidExecution": {
"weight_limit": "Unlimited"
}
},
{
"Transact": {
"origin_kind": "Superuser",
"require_weight_at_most": {
"ref_time": $require_weight_at_most_ref_time,
"proof_size": $require_weight_at_most_proof_size,
},
"call": {
"encoded": $hex_encoded_data
}
}
}
]
}
')
echo ""
echo " dest:"
echo "${dest}"
echo ""
echo " message:"
echo "${message}"
echo ""
echo "--------------------------------------------------"
call_polkadot_js_api \
--ws "${relay_url?}" \
--seed "${relay_chain_seed?}" \
--sudo \
tx.xcmPallet.send \
"${dest}" \
"${message}"
}
function open_hrmp_channels() {
local relay_url=$1
local relay_chain_seed=$2
local sender_para_id=$3
local recipient_para_id=$4
local max_capacity=$5
local max_message_size=$6
echo " calling open_hrmp_channels:"
echo " relay_url: ${relay_url}"
echo " relay_chain_seed: ${relay_chain_seed}"
echo " sender_para_id: ${sender_para_id}"
echo " recipient_para_id: ${recipient_para_id}"
echo " max_capacity: ${max_capacity}"
echo " max_message_size: ${max_message_size}"
echo " params:"
echo "--------------------------------------------------"
call_polkadot_js_api \
--ws "${relay_url?}" \
--seed "${relay_chain_seed?}" \
--sudo \
tx.hrmp.forceOpenHrmpChannel \
${sender_para_id} \
${recipient_para_id} \
${max_capacity} \
${max_message_size}
}
function force_xcm_version() {
local relay_url=$1
local relay_chain_seed=$2
local runtime_para_id=$3
local runtime_para_endpoint=$4
local dest=$5
local xcm_version=$6
echo " calling force_xcm_version:"
echo " relay_url: ${relay_url}"
echo " relay_chain_seed: ${relay_chain_seed}"
echo " runtime_para_id: ${runtime_para_id}"
echo " runtime_para_endpoint: ${runtime_para_endpoint}"
echo " dest: ${dest}"
echo " xcm_version: ${xcm_version}"
echo " params:"
# 1. generate data for Transact (PolkadotXcm::force_xcm_version)
local tmp_output_file=$(mktemp)
generate_hex_encoded_call_data "force-xcm-version" "${runtime_para_endpoint}" "${tmp_output_file}" "$dest" "$xcm_version"
local hex_encoded_data=$(cat $tmp_output_file)
# 2. trigger governance call
send_governance_transact "${relay_url}" "${relay_chain_seed}" "${runtime_para_id}" "${hex_encoded_data}" 200000000 12000
}
function force_create_foreign_asset() {
local relay_url=$1
local relay_chain_seed=$2
local runtime_para_id=$3
local runtime_para_endpoint=$4
local asset_multilocation=$5
local asset_owner_account_id=$6
local min_balance=$7
local is_sufficient=$8
echo " calling force_create_foreign_asset:"
echo " relay_url: ${relay_url}"
echo " relay_chain_seed: ${relay_chain_seed}"
echo " runtime_para_id: ${runtime_para_id}"
echo " runtime_para_endpoint: ${runtime_para_endpoint}"
echo " asset_multilocation: ${asset_multilocation}"
echo " asset_owner_account_id: ${asset_owner_account_id}"
echo " min_balance: ${min_balance}"
echo " is_sufficient: ${is_sufficient}"
echo " params:"
# 1. generate data for Transact (ForeignAssets::force_create)
local tmp_output_file=$(mktemp)
generate_hex_encoded_call_data "force-create-asset" "${runtime_para_endpoint}" "${tmp_output_file}" "$asset_multilocation" "$asset_owner_account_id" $is_sufficient $min_balance
local hex_encoded_data=$(cat $tmp_output_file)
# 2. trigger governance call
send_governance_transact "${relay_url}" "${relay_chain_seed}" "${runtime_para_id}" "${hex_encoded_data}" 200000000 12000
}
function limited_reserve_transfer_assets() {
local url=$1
local seed=$2
local destination=$3
local beneficiary=$4
local assets=$5
local fee_asset_item=$6
local weight_limit=$7
echo " calling limited_reserve_transfer_assets:"
echo " url: ${url}"
echo " seed: ${seed}"
echo " destination: ${destination}"
echo " beneficiary: ${beneficiary}"
echo " assets: ${assets}"
echo " fee_asset_item: ${fee_asset_item}"
echo " weight_limit: ${weight_limit}"
echo ""
echo "--------------------------------------------------"
call_polkadot_js_api \
--ws "${url?}" \
--seed "${seed?}" \
tx.polkadotXcm.limitedReserveTransferAssets \
"${destination}" \
"${beneficiary}" \
"${assets}" \
"${fee_asset_item}" \
"${weight_limit}"
}
function claim_rewards() {
local runtime_para_endpoint=$1
local seed=$2
local lane_id=$3
local bridged_chain_id=$4
local owner=$5
echo " calling claim_rewards:"
echo " runtime_para_endpoint: ${runtime_para_endpoint}"
echo " seed: ${seed}"
echo " lane_id: ${lane_id}"
echo " bridged_chain_id: ${bridged_chain_id}"
echo " owner: ${owner}"
echo ""
local rewards_account_params=$(jq --null-input \
--arg lane_id "$lane_id" \
--arg bridged_chain_id "$bridged_chain_id" \
--arg owner "$owner" \
'{
"laneId": $lane_id,
"bridgedChainId": $bridged_chain_id,
"owner": $owner
}')
echo " rewards_account_params:"
echo "${rewards_account_params}"
echo "--------------------------------------------------"
call_polkadot_js_api \
--ws "${runtime_para_endpoint}" \
--seed "${seed?}" \
tx.bridgeRelayers.claimRewards \
"${rewards_account_params}"
}
+45
View File
@@ -0,0 +1,45 @@
#!/bin/bash
function start_background_process() {
local command=$1
local log_file=$2
local __pid=$3
$command > $log_file 2>&1 &
eval $__pid="'$!'"
}
function wait_for_process_file() {
local pid=$1
local file=$2
local timeout=$3
local __found=$4
local time=0
until [ -e $file ]; do
if ! kill -0 $pid; then
echo "Process finished unsuccessfully"
return
fi
if (( time++ >= timeout )); then
echo "Timeout waiting for file $file: $timeout seconds"
eval $__found=0
return
fi
sleep 1
done
echo "File $file found after $time seconds"
eval $__found=1
}
function ensure_process_file() {
local pid=$1
local file=$2
local timeout=$3
wait_for_process_file $pid $file $timeout file_found
if [ "$file_found" != "1" ]; then
exit 1
fi
}
@@ -0,0 +1,165 @@
const fs = require("fs");
const { exit } = require("process");
const { WsProvider, ApiPromise } = require("@polkadot/api");
const util = require("@polkadot/util");
// connect to a substrate chain and return the api object
async function connect(endpoint, types = {}) {
const provider = new WsProvider(endpoint);
const api = await ApiPromise.create({
provider,
types,
throwOnConnect: false,
});
return api;
}
function writeHexEncodedBytesToOutput(method, outputFile) {
console.log("Payload (hex): ", method.toHex());
console.log("Payload (bytes): ", Array.from(method.toU8a()));
console.log("Payload (plain): ", JSON.stringify(method));
fs.writeFileSync(outputFile, JSON.stringify(Array.from(method.toU8a())));
}
function remarkWithEvent(endpoint, outputFile) {
console.log(`Generating remarkWithEvent from RPC endpoint: ${endpoint} to outputFile: ${outputFile}`);
connect(endpoint)
.then((api) => {
const call = api.tx.system.remarkWithEvent("Hello");
writeHexEncodedBytesToOutput(call.method, outputFile);
exit(0);
})
.catch((e) => {
console.error(e);
exit(1);
});
}
function addExporterConfig(endpoint, outputFile, bridgedNetwork, bridgeConfig) {
console.log(`Generating addExporterConfig from RPC endpoint: ${endpoint} to outputFile: ${outputFile} based on bridgedNetwork: ${bridgedNetwork}, bridgeConfig: ${bridgeConfig}`);
connect(endpoint)
.then((api) => {
const call = api.tx.bridgeTransfer.addExporterConfig(bridgedNetwork, JSON.parse(bridgeConfig));
writeHexEncodedBytesToOutput(call.method, outputFile);
exit(0);
})
.catch((e) => {
console.error(e);
exit(1);
});
}
function addUniversalAlias(endpoint, outputFile, location, junction) {
console.log(`Generating addUniversalAlias from RPC endpoint: ${endpoint} to outputFile: ${outputFile} based on location: ${location}, junction: ${junction}`);
connect(endpoint)
.then((api) => {
const call = api.tx.bridgeTransfer.addUniversalAlias(JSON.parse(location), JSON.parse(junction));
writeHexEncodedBytesToOutput(call.method, outputFile);
exit(0);
})
.catch((e) => {
console.error(e);
exit(1);
});
}
function addReserveLocation(endpoint, outputFile, reserve_location) {
console.log(`Generating addReserveLocation from RPC endpoint: ${endpoint} to outputFile: ${outputFile} based on reserve_location: ${reserve_location}`);
connect(endpoint)
.then((api) => {
const call = api.tx.bridgeTransfer.addReserveLocation(JSON.parse(reserve_location));
writeHexEncodedBytesToOutput(call.method, outputFile);
exit(0);
})
.catch((e) => {
console.error(e);
exit(1);
});
}
function removeExporterConfig(endpoint, outputFile, bridgedNetwork) {
console.log(`Generating removeExporterConfig from RPC endpoint: ${endpoint} to outputFile: ${outputFile} based on bridgedNetwork: ${bridgedNetwork}`);
connect(endpoint)
.then((api) => {
const call = api.tx.bridgeTransfer.removeExporterConfig(bridgedNetwork);
writeHexEncodedBytesToOutput(call.method, outputFile);
exit(0);
})
.catch((e) => {
console.error(e);
exit(1);
});
}
function forceCreateAsset(endpoint, outputFile, assetId, assetOwnerAccountId, isSufficient, minBalance) {
var isSufficient = isSufficient == "true" ? true : false;
console.log(`Generating forceCreateAsset from RPC endpoint: ${endpoint} to outputFile: ${outputFile} based on assetId: ${assetId}, assetOwnerAccountId: ${assetOwnerAccountId}, isSufficient: ${isSufficient}, minBalance: ${minBalance}`);
connect(endpoint)
.then((api) => {
const call = api.tx.foreignAssets.forceCreate(JSON.parse(assetId), assetOwnerAccountId, isSufficient, minBalance);
writeHexEncodedBytesToOutput(call.method, outputFile);
exit(0);
})
.catch((e) => {
console.error(e);
exit(1);
});
}
function forceXcmVersion(endpoint, outputFile, dest, xcm_version) {
console.log(`Generating forceXcmVersion from RPC endpoint: ${endpoint} to outputFile: ${outputFile}, dest: ${dest}, xcm_version: ${xcm_version}`);
connect(endpoint)
.then((api) => {
const call = api.tx.polkadotXcm.forceXcmVersion(JSON.parse(dest), xcm_version);
writeHexEncodedBytesToOutput(call.method, outputFile);
exit(0);
})
.catch((e) => {
console.error(e);
exit(1);
});
}
if (!process.argv[2] || !process.argv[3]) {
console.log("usage: node ./script/generate_hex_encoded_call <type> <endpoint> <output hex-encoded data file> <input message>");
exit(1);
}
const type = process.argv[2];
const rpcEnpoint = process.argv[3];
const output = process.argv[4];
const inputArgs = process.argv.slice(5, process.argv.length);
console.log(`Generating hex-encoded call data for:`);
console.log(` type: ${type}`);
console.log(` rpcEnpoint: ${rpcEnpoint}`);
console.log(` output: ${output}`);
console.log(` inputArgs: ${inputArgs}`);
switch (type) {
case 'remark-with-event':
remarkWithEvent(rpcEnpoint, output);
break;
case 'add-exporter-config':
addExporterConfig(rpcEnpoint, output, inputArgs[0], inputArgs[1]);
break;
case 'remove-exporter-config':
removeExporterConfig(rpcEnpoint, output, inputArgs[0], inputArgs[1]);
break;
case 'add-universal-alias':
addUniversalAlias(rpcEnpoint, output, inputArgs[0], inputArgs[1]);
break;
case 'add-reserve-location':
addReserveLocation(rpcEnpoint, output, inputArgs[0]);
break;
case 'force-create-asset':
forceCreateAsset(rpcEnpoint, output, inputArgs[0], inputArgs[1], inputArgs[2], inputArgs[3]);
break;
case 'force-xcm-version':
forceXcmVersion(rpcEnpoint, output, inputArgs[0], inputArgs[1]);
break;
case 'check':
console.log(`Checking nodejs installation, if you see this everything is ready!`);
break;
default:
console.log(`Sorry, we are out of ${type} - not yet supported!`);
}
@@ -0,0 +1,759 @@
{
"name": "y",
"version": "y",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "y",
"version": "y",
"license": "MIT",
"dependencies": {
"@polkadot/api": "^10.11",
"@polkadot/util": "^12.6"
}
},
"node_modules/@noble/curves": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz",
"integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==",
"dependencies": {
"@noble/hashes": "1.3.3"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@noble/hashes": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz",
"integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==",
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@polkadot/api": {
"version": "10.11.2",
"resolved": "https://registry.npmjs.org/@polkadot/api/-/api-10.11.2.tgz",
"integrity": "sha512-AorCZxCWCoTtdbl4DPUZh+ACe/pbLIS1BkdQY0AFJuZllm0x/yWzjgampcPd5jQAA/O3iKShRBkZqj6Mk9yG/A==",
"dependencies": {
"@polkadot/api-augment": "10.11.2",
"@polkadot/api-base": "10.11.2",
"@polkadot/api-derive": "10.11.2",
"@polkadot/keyring": "^12.6.2",
"@polkadot/rpc-augment": "10.11.2",
"@polkadot/rpc-core": "10.11.2",
"@polkadot/rpc-provider": "10.11.2",
"@polkadot/types": "10.11.2",
"@polkadot/types-augment": "10.11.2",
"@polkadot/types-codec": "10.11.2",
"@polkadot/types-create": "10.11.2",
"@polkadot/types-known": "10.11.2",
"@polkadot/util": "^12.6.2",
"@polkadot/util-crypto": "^12.6.2",
"eventemitter3": "^5.0.1",
"rxjs": "^7.8.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/api-augment": {
"version": "10.11.2",
"resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-10.11.2.tgz",
"integrity": "sha512-PTpnqpezc75qBqUtgrc0GYB8h9UHjfbHSRZamAbecIVAJ2/zc6CqtnldeaBlIu1IKTgBzi3FFtTyYu+ZGbNT2Q==",
"dependencies": {
"@polkadot/api-base": "10.11.2",
"@polkadot/rpc-augment": "10.11.2",
"@polkadot/types": "10.11.2",
"@polkadot/types-augment": "10.11.2",
"@polkadot/types-codec": "10.11.2",
"@polkadot/util": "^12.6.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/api-base": {
"version": "10.11.2",
"resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-10.11.2.tgz",
"integrity": "sha512-4LIjaUfO9nOzilxo7XqzYKCNMtmUypdk8oHPdrRnSjKEsnK7vDsNi+979z2KXNXd2KFSCFHENmI523fYnMnReg==",
"dependencies": {
"@polkadot/rpc-core": "10.11.2",
"@polkadot/types": "10.11.2",
"@polkadot/util": "^12.6.2",
"rxjs": "^7.8.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/api-derive": {
"version": "10.11.2",
"resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-10.11.2.tgz",
"integrity": "sha512-m3BQbPionkd1iSlknddxnL2hDtolPIsT+aRyrtn4zgMRPoLjHFmTmovvg8RaUyYofJtZeYrnjMw0mdxiSXx7eA==",
"dependencies": {
"@polkadot/api": "10.11.2",
"@polkadot/api-augment": "10.11.2",
"@polkadot/api-base": "10.11.2",
"@polkadot/rpc-core": "10.11.2",
"@polkadot/types": "10.11.2",
"@polkadot/types-codec": "10.11.2",
"@polkadot/util": "^12.6.2",
"@polkadot/util-crypto": "^12.6.2",
"rxjs": "^7.8.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/keyring": {
"version": "12.6.2",
"resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-12.6.2.tgz",
"integrity": "sha512-O3Q7GVmRYm8q7HuB3S0+Yf/q/EB2egKRRU3fv9b3B7V+A52tKzA+vIwEmNVaD1g5FKW9oB97rmpggs0zaKFqHw==",
"dependencies": {
"@polkadot/util": "12.6.2",
"@polkadot/util-crypto": "12.6.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@polkadot/util": "12.6.2",
"@polkadot/util-crypto": "12.6.2"
}
},
"node_modules/@polkadot/networks": {
"version": "12.6.2",
"resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-12.6.2.tgz",
"integrity": "sha512-1oWtZm1IvPWqvMrldVH6NI2gBoCndl5GEwx7lAuQWGr7eNL+6Bdc5K3Z9T0MzFvDGoi2/CBqjX9dRKo39pDC/w==",
"dependencies": {
"@polkadot/util": "12.6.2",
"@substrate/ss58-registry": "^1.44.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/rpc-augment": {
"version": "10.11.2",
"resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-10.11.2.tgz",
"integrity": "sha512-9AhT0WW81/8jYbRcAC6PRmuxXqNhJje8OYiulBQHbG1DTCcjAfz+6VQBke9BwTStzPq7d526+yyBKD17O3zlAA==",
"dependencies": {
"@polkadot/rpc-core": "10.11.2",
"@polkadot/types": "10.11.2",
"@polkadot/types-codec": "10.11.2",
"@polkadot/util": "^12.6.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/rpc-core": {
"version": "10.11.2",
"resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-10.11.2.tgz",
"integrity": "sha512-Ot0CFLWx8sZhLZog20WDuniPA01Bk2StNDsdAQgcFKPwZw6ShPaZQCHuKLQK6I6DodOrem9FXX7c1hvoKJP5Ww==",
"dependencies": {
"@polkadot/rpc-augment": "10.11.2",
"@polkadot/rpc-provider": "10.11.2",
"@polkadot/types": "10.11.2",
"@polkadot/util": "^12.6.2",
"rxjs": "^7.8.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/rpc-provider": {
"version": "10.11.2",
"resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-10.11.2.tgz",
"integrity": "sha512-he5jWMpDJp7e+vUzTZDzpkB7ps3H8psRally+/ZvZZScPvFEjfczT7I1WWY9h58s8+ImeVP/lkXjL9h/gUOt3Q==",
"dependencies": {
"@polkadot/keyring": "^12.6.2",
"@polkadot/types": "10.11.2",
"@polkadot/types-support": "10.11.2",
"@polkadot/util": "^12.6.2",
"@polkadot/util-crypto": "^12.6.2",
"@polkadot/x-fetch": "^12.6.2",
"@polkadot/x-global": "^12.6.2",
"@polkadot/x-ws": "^12.6.2",
"eventemitter3": "^5.0.1",
"mock-socket": "^9.3.1",
"nock": "^13.4.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"@substrate/connect": "0.7.35"
}
},
"node_modules/@polkadot/types": {
"version": "10.11.2",
"resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.11.2.tgz",
"integrity": "sha512-d52j3xXni+C8GdYZVTSfu8ROAnzXFMlyRvXtor0PudUc8UQHOaC4+mYAkTBGA2gKdmL8MHSfRSbhcxHhsikY6Q==",
"dependencies": {
"@polkadot/keyring": "^12.6.2",
"@polkadot/types-augment": "10.11.2",
"@polkadot/types-codec": "10.11.2",
"@polkadot/types-create": "10.11.2",
"@polkadot/util": "^12.6.2",
"@polkadot/util-crypto": "^12.6.2",
"rxjs": "^7.8.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/types-augment": {
"version": "10.11.2",
"resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-10.11.2.tgz",
"integrity": "sha512-8eB8ew04wZiE5GnmFvEFW1euJWmF62SGxb1O+8wL3zoUtB9Xgo1vB6w6xbTrd+HLV6jNSeXXnbbF1BEUvi9cNg==",
"dependencies": {
"@polkadot/types": "10.11.2",
"@polkadot/types-codec": "10.11.2",
"@polkadot/util": "^12.6.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/types-codec": {
"version": "10.11.2",
"resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-10.11.2.tgz",
"integrity": "sha512-3xjOQL+LOOMzYqlgP9ROL0FQnzU8lGflgYewzau7AsDlFziSEtb49a9BpYo6zil4koC+QB8zQ9OHGFumG08T8w==",
"dependencies": {
"@polkadot/util": "^12.6.2",
"@polkadot/x-bigint": "^12.6.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/types-create": {
"version": "10.11.2",
"resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-10.11.2.tgz",
"integrity": "sha512-SJt23NxYvefRxVZZm6mT9ed1pR6FDoIGQ3xUpbjhTLfU2wuhpKjekMVorYQ6z/gK2JLMu2kV92Ardsz+6GX5XQ==",
"dependencies": {
"@polkadot/types-codec": "10.11.2",
"@polkadot/util": "^12.6.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/types-known": {
"version": "10.11.2",
"resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-10.11.2.tgz",
"integrity": "sha512-kbEIX7NUQFxpDB0FFGNyXX/odY7jbp56RGD+Z4A731fW2xh/DgAQrI994xTzuh0c0EqPE26oQm3kATSpseqo9w==",
"dependencies": {
"@polkadot/networks": "^12.6.2",
"@polkadot/types": "10.11.2",
"@polkadot/types-codec": "10.11.2",
"@polkadot/types-create": "10.11.2",
"@polkadot/util": "^12.6.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/types-support": {
"version": "10.11.2",
"resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-10.11.2.tgz",
"integrity": "sha512-X11hoykFYv/3efg4coZy2hUOUc97JhjQMJLzDhHniFwGLlYU8MeLnPdCVGkXx0xDDjTo4/ptS1XpZ5HYcg+gRw==",
"dependencies": {
"@polkadot/util": "^12.6.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/util": {
"version": "12.6.2",
"resolved": "https://registry.npmjs.org/@polkadot/util/-/util-12.6.2.tgz",
"integrity": "sha512-l8TubR7CLEY47240uki0TQzFvtnxFIO7uI/0GoWzpYD/O62EIAMRsuY01N4DuwgKq2ZWD59WhzsLYmA5K6ksdw==",
"dependencies": {
"@polkadot/x-bigint": "12.6.2",
"@polkadot/x-global": "12.6.2",
"@polkadot/x-textdecoder": "12.6.2",
"@polkadot/x-textencoder": "12.6.2",
"@types/bn.js": "^5.1.5",
"bn.js": "^5.2.1",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/util-crypto": {
"version": "12.6.2",
"resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-12.6.2.tgz",
"integrity": "sha512-FEWI/dJ7wDMNN1WOzZAjQoIcCP/3vz3wvAp5QQm+lOrzOLj0iDmaIGIcBkz8HVm3ErfSe/uKP0KS4jgV/ib+Mg==",
"dependencies": {
"@noble/curves": "^1.3.0",
"@noble/hashes": "^1.3.3",
"@polkadot/networks": "12.6.2",
"@polkadot/util": "12.6.2",
"@polkadot/wasm-crypto": "^7.3.2",
"@polkadot/wasm-util": "^7.3.2",
"@polkadot/x-bigint": "12.6.2",
"@polkadot/x-randomvalues": "12.6.2",
"@scure/base": "^1.1.5",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@polkadot/util": "12.6.2"
}
},
"node_modules/@polkadot/wasm-bridge": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@polkadot/wasm-bridge/-/wasm-bridge-7.3.2.tgz",
"integrity": "sha512-AJEXChcf/nKXd5Q/YLEV5dXQMle3UNT7jcXYmIffZAo/KI394a+/24PaISyQjoNC0fkzS1Q8T5pnGGHmXiVz2g==",
"dependencies": {
"@polkadot/wasm-util": "7.3.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@polkadot/util": "*",
"@polkadot/x-randomvalues": "*"
}
},
"node_modules/@polkadot/wasm-crypto": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-7.3.2.tgz",
"integrity": "sha512-+neIDLSJ6jjVXsjyZ5oLSv16oIpwp+PxFqTUaZdZDoA2EyFRQB8pP7+qLsMNk+WJuhuJ4qXil/7XiOnZYZ+wxw==",
"dependencies": {
"@polkadot/wasm-bridge": "7.3.2",
"@polkadot/wasm-crypto-asmjs": "7.3.2",
"@polkadot/wasm-crypto-init": "7.3.2",
"@polkadot/wasm-crypto-wasm": "7.3.2",
"@polkadot/wasm-util": "7.3.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@polkadot/util": "*",
"@polkadot/x-randomvalues": "*"
}
},
"node_modules/@polkadot/wasm-crypto-asmjs": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.3.2.tgz",
"integrity": "sha512-QP5eiUqUFur/2UoF2KKKYJcesc71fXhQFLT3D4ZjG28Mfk2ZPI0QNRUfpcxVQmIUpV5USHg4geCBNuCYsMm20Q==",
"dependencies": {
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@polkadot/util": "*"
}
},
"node_modules/@polkadot/wasm-crypto-init": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.3.2.tgz",
"integrity": "sha512-FPq73zGmvZtnuJaFV44brze3Lkrki3b4PebxCy9Fplw8nTmisKo9Xxtfew08r0njyYh+uiJRAxPCXadkC9sc8g==",
"dependencies": {
"@polkadot/wasm-bridge": "7.3.2",
"@polkadot/wasm-crypto-asmjs": "7.3.2",
"@polkadot/wasm-crypto-wasm": "7.3.2",
"@polkadot/wasm-util": "7.3.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@polkadot/util": "*",
"@polkadot/x-randomvalues": "*"
}
},
"node_modules/@polkadot/wasm-crypto-wasm": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.3.2.tgz",
"integrity": "sha512-15wd0EMv9IXs5Abp1ZKpKKAVyZPhATIAHfKsyoWCEFDLSOA0/K0QGOxzrAlsrdUkiKZOq7uzSIgIDgW8okx2Mw==",
"dependencies": {
"@polkadot/wasm-util": "7.3.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@polkadot/util": "*"
}
},
"node_modules/@polkadot/wasm-util": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.3.2.tgz",
"integrity": "sha512-bmD+Dxo1lTZyZNxbyPE380wd82QsX+43mgCm40boyKrRppXEyQmWT98v/Poc7chLuskYb6X8IQ6lvvK2bGR4Tg==",
"dependencies": {
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@polkadot/util": "*"
}
},
"node_modules/@polkadot/x-bigint": {
"version": "12.6.2",
"resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-12.6.2.tgz",
"integrity": "sha512-HSIk60uFPX4GOFZSnIF7VYJz7WZA7tpFJsne7SzxOooRwMTWEtw3fUpFy5cYYOeLh17/kHH1Y7SVcuxzVLc74Q==",
"dependencies": {
"@polkadot/x-global": "12.6.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/x-fetch": {
"version": "12.6.2",
"resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-12.6.2.tgz",
"integrity": "sha512-8wM/Z9JJPWN1pzSpU7XxTI1ldj/AfC8hKioBlUahZ8gUiJaOF7K9XEFCrCDLis/A1BoOu7Ne6WMx/vsJJIbDWw==",
"dependencies": {
"@polkadot/x-global": "12.6.2",
"node-fetch": "^3.3.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/x-global": {
"version": "12.6.2",
"resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-12.6.2.tgz",
"integrity": "sha512-a8d6m+PW98jmsYDtAWp88qS4dl8DyqUBsd0S+WgyfSMtpEXu6v9nXDgPZgwF5xdDvXhm+P0ZfVkVTnIGrScb5g==",
"dependencies": {
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/x-randomvalues": {
"version": "12.6.2",
"resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-12.6.2.tgz",
"integrity": "sha512-Vr8uG7rH2IcNJwtyf5ebdODMcr0XjoCpUbI91Zv6AlKVYOGKZlKLYJHIwpTaKKB+7KPWyQrk4Mlym/rS7v9feg==",
"dependencies": {
"@polkadot/x-global": "12.6.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@polkadot/util": "12.6.2",
"@polkadot/wasm-util": "*"
}
},
"node_modules/@polkadot/x-textdecoder": {
"version": "12.6.2",
"resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-12.6.2.tgz",
"integrity": "sha512-M1Bir7tYvNappfpFWXOJcnxUhBUFWkUFIdJSyH0zs5LmFtFdbKAeiDXxSp2Swp5ddOZdZgPac294/o2TnQKN1w==",
"dependencies": {
"@polkadot/x-global": "12.6.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/x-textencoder": {
"version": "12.6.2",
"resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-12.6.2.tgz",
"integrity": "sha512-4N+3UVCpI489tUJ6cv3uf0PjOHvgGp9Dl+SZRLgFGt9mvxnvpW/7+XBADRMtlG4xi5gaRK7bgl5bmY6OMDsNdw==",
"dependencies": {
"@polkadot/x-global": "12.6.2",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@polkadot/x-ws": {
"version": "12.6.2",
"resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-12.6.2.tgz",
"integrity": "sha512-cGZWo7K5eRRQCRl2LrcyCYsrc3lRbTlixZh3AzgU8uX4wASVGRlNWi/Hf4TtHNe1ExCDmxabJzdIsABIfrr7xw==",
"dependencies": {
"@polkadot/x-global": "12.6.2",
"tslib": "^2.6.2",
"ws": "^8.15.1"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@scure/base": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.5.tgz",
"integrity": "sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==",
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@substrate/connect": {
"version": "0.7.35",
"resolved": "https://registry.npmjs.org/@substrate/connect/-/connect-0.7.35.tgz",
"integrity": "sha512-Io8vkalbwaye+7yXfG1Nj52tOOoJln2bMlc7Q9Yy3vEWqZEVkgKmcPVzbwV0CWL3QD+KMPDA2Dnw/X7EdwgoLw==",
"hasInstallScript": true,
"optional": true,
"dependencies": {
"@substrate/connect-extension-protocol": "^1.0.1",
"smoldot": "2.0.7"
}
},
"node_modules/@substrate/connect-extension-protocol": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@substrate/connect-extension-protocol/-/connect-extension-protocol-1.0.1.tgz",
"integrity": "sha512-161JhCC1csjH3GE5mPLEd7HbWtwNSPJBg3p1Ksz9SFlTzj/bgEwudiRN2y5i0MoLGCIJRYKyKGMxVnd29PzNjg==",
"optional": true
},
"node_modules/@substrate/ss58-registry": {
"version": "1.44.0",
"resolved": "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.44.0.tgz",
"integrity": "sha512-7lQ/7mMCzVNSEfDS4BCqnRnKCFKpcOaPrxMeGTXHX1YQzM/m2BBHjbK2C3dJvjv7GYxMiaTq/HdWQj1xS6ss+A=="
},
"node_modules/@types/bn.js": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz",
"integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/node": {
"version": "20.10.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz",
"integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==",
"dependencies": {
"undici-types": "~5.26.4"
}
},
"node_modules/bn.js": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
"integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ=="
},
"node_modules/data-uri-to-buffer": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
"engines": {
"node": ">= 12"
}
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/eventemitter3": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="
},
"node_modules/fetch-blob": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/jimmywarting"
},
{
"type": "paypal",
"url": "https://paypal.me/jimmywarting"
}
],
"dependencies": {
"node-domexception": "^1.0.0",
"web-streams-polyfill": "^3.0.3"
},
"engines": {
"node": "^12.20 || >= 14.13"
}
},
"node_modules/formdata-polyfill": {
"version": "4.0.10",
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
"dependencies": {
"fetch-blob": "^3.1.2"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
},
"node_modules/mock-socket": {
"version": "9.3.1",
"resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.3.1.tgz",
"integrity": "sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw==",
"engines": {
"node": ">= 8"
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/nock": {
"version": "13.4.0",
"resolved": "https://registry.npmjs.org/nock/-/nock-13.4.0.tgz",
"integrity": "sha512-W8NVHjO/LCTNA64yxAPHV/K47LpGYcVzgKd3Q0n6owhwvD0Dgoterc25R4rnZbckJEb6Loxz1f5QMuJpJnbSyQ==",
"dependencies": {
"debug": "^4.1.0",
"json-stringify-safe": "^5.0.1",
"propagate": "^2.0.0"
},
"engines": {
"node": ">= 10.13"
}
},
"node_modules/node-domexception": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/jimmywarting"
},
{
"type": "github",
"url": "https://paypal.me/jimmywarting"
}
],
"engines": {
"node": ">=10.5.0"
}
},
"node_modules/node-fetch": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
"dependencies": {
"data-uri-to-buffer": "^4.0.0",
"fetch-blob": "^3.1.4",
"formdata-polyfill": "^4.0.10"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/node-fetch"
}
},
"node_modules/propagate": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz",
"integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==",
"engines": {
"node": ">= 8"
}
},
"node_modules/rxjs": {
"version": "7.8.1",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/smoldot": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/smoldot/-/smoldot-2.0.7.tgz",
"integrity": "sha512-VAOBqEen6vises36/zgrmAT1GWk2qE3X8AGnO7lmQFdskbKx8EovnwS22rtPAG+Y1Rk23/S22kDJUdPANyPkBA==",
"optional": true,
"dependencies": {
"ws": "^8.8.1"
}
},
"node_modules/tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
},
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
},
"node_modules/web-streams-polyfill": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
"integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
"engines": {
"node": ">= 8"
}
},
"node_modules/ws": {
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz",
"integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
}
}
}
@@ -0,0 +1,11 @@
{
"name": "y",
"version": "y",
"description": "create a scale hex-encoded call values from given message",
"main": "index.js",
"license": "MIT",
"dependencies": {
"@polkadot/api": "^10.11",
"@polkadot/util": "^12.6"
}
}
@@ -0,0 +1,39 @@
#!/bin/bash
source "${BASH_SOURCE%/*}/common.sh"
function start_zombienet() {
local test_dir=$1
local definition_path=$2
local __zombienet_dir=$3
local __zombienet_pid=$4
local zombienet_name=`basename $definition_path .toml`
local zombienet_dir=$test_dir/$zombienet_name
eval $__zombienet_dir="'$zombienet_dir'"
mkdir -p $zombienet_dir
rm -rf $zombienet_dir
local logs_dir=$test_dir/logs
mkdir -p $logs_dir
local zombienet_log=$logs_dir/$zombienet_name.log
echo "Starting $zombienet_name zombienet. Logs available at: $zombienet_log"
start_background_process \
"$ZOMBIENET_BINARY spawn --dir $zombienet_dir --provider native $definition_path" \
"$zombienet_log" zombienet_pid
ensure_process_file $zombienet_pid "$zombienet_dir/zombie.json" 180
echo "$zombienet_name zombienet started successfully"
eval $__zombienet_pid="'$zombienet_pid'"
}
function run_zndsl() {
local zndsl_file=$1
local zombienet_dir=$2
echo "Running $zndsl_file."
$ZOMBIENET_BINARY test --dir $zombienet_dir --provider native $zndsl_file $zombienet_dir/zombie.json
echo
}
+48
View File
@@ -0,0 +1,48 @@
#!/bin/bash
set -e
trap 'kill -9 -$$ || echo "Environment already teared down"' SIGINT SIGTERM EXIT
test=$1
shift
# whether to use paths for zombienet+bridges tests container or for local testing
ZOMBIENET_DOCKER_PATHS=0
while [ $# -ne 0 ]
do
arg="$1"
case "$arg" in
--docker)
ZOMBIENET_DOCKER_PATHS=1
;;
esac
shift
done
export POLKADOT_SDK_PATH=`realpath ${BASH_SOURCE%/*}/../..`
export FRAMEWORK_PATH=`realpath ${BASH_SOURCE%/*}/framework`
# set path to binaries
if [ "$ZOMBIENET_DOCKER_PATHS" -eq 1 ]; then
# otherwise zombienet uses some hardcoded paths
unset RUN_IN_CONTAINER
unset ZOMBIENET_IMAGE
export POLKADOT_BINARY=/usr/local/bin/polkadot
export POLKADOT_PARACHAIN_BINARY=/usr/local/bin/polkadot-parachain
export ZOMBIENET_BINARY=/usr/local/bin/zombie
export SUBSTRATE_RELAY_BINARY=/usr/local/bin/substrate-relay
else
export POLKADOT_BINARY=$POLKADOT_SDK_PATH/target/release/polkadot
export POLKADOT_PARACHAIN_BINARY=$POLKADOT_SDK_PATH/target/release/polkadot-parachain
export ZOMBIENET_BINARY=~/local_bridge_testing/bin/zombienet-linux-x64
export SUBSTRATE_RELAY_BINARY=~/local_bridge_testing/bin/substrate-relay
fi
export TEST_DIR=`mktemp -d /tmp/bridges-tests-run-XXXXX`
echo -e "Test folder: $TEST_DIR\n"
${BASH_SOURCE%/*}/tests/$test/run.sh
+138
View File
@@ -0,0 +1,138 @@
#!/bin/bash
set -x
shopt -s nullglob
trap "trap - SIGINT SIGTERM EXIT && killall -q -9 substrate-relay && kill -- -$$" SIGINT SIGTERM EXIT
# run tests in range [TESTS_BEGIN; TESTS_END)
TESTS_BEGIN=1
TESTS_END=1000
# whether to use paths for zombienet+bridges tests container or for local testing
ZOMBIENET_DOCKER_PATHS=0
while [ $# -ne 0 ]
do
arg="$1"
case "$arg" in
--docker)
ZOMBIENET_DOCKER_PATHS=1
;;
--test)
shift
TESTS_BEGIN="$1"
TESTS_END="$1"
;;
esac
shift
done
# assuming that we'll be using native provide && all processes will be executing locally
# (we need absolute paths here, because they're used when scripts are called by zombienet from tmp folders)
export POLKADOT_SDK_PATH=`realpath $(dirname "$0")/../..`
export BRIDGE_TESTS_FOLDER=$POLKADOT_SDK_PATH/bridges/testing/tests
# set pathc to binaries
if [ "$ZOMBIENET_DOCKER_PATHS" -eq 1 ]; then
export POLKADOT_BINARY=/usr/local/bin/polkadot
export POLKADOT_PARACHAIN_BINARY=/usr/local/bin/polkadot-parachain
export SUBSTRATE_RELAY_BINARY=/usr/local/bin/substrate-relay
export ZOMBIENET_BINARY_PATH=/usr/local/bin/zombie
else
export POLKADOT_BINARY=$POLKADOT_SDK_PATH/target/release/polkadot
export POLKADOT_PARACHAIN_BINARY=$POLKADOT_SDK_PATH/target/release/polkadot-parachain
export SUBSTRATE_RELAY_BINARY=~/local_bridge_testing/bin/substrate-relay
export ZOMBIENET_BINARY_PATH=~/local_bridge_testing/bin/zombienet-linux
fi
# check if `wait` supports -p flag
if [ `printf "$BASH_VERSION\n5.1" | sort -V | head -n 1` = "5.1" ]; then IS_BASH_5_1=1; else IS_BASH_5_1=0; fi
# bridge configuration
export LANE_ID="00000002"
# tests configuration
ALL_TESTS_FOLDER=`mktemp -d /tmp/bridges-zombienet-tests.XXXXX`
function start_coproc() {
local command=$1
local name=$2
local logname=`basename $name`
local coproc_log=`mktemp -p $TEST_FOLDER $logname.XXXXX`
coproc COPROC {
# otherwise zombienet uses some hardcoded paths
unset RUN_IN_CONTAINER
unset ZOMBIENET_IMAGE
$command >$coproc_log 2>&1
}
TEST_COPROCS[$COPROC_PID, 0]=$name
TEST_COPROCS[$COPROC_PID, 1]=$coproc_log
echo "Spawned $name coprocess. StdOut + StdErr: $coproc_log"
return $COPROC_PID
}
# execute every test from tests folder
TEST_INDEX=$TESTS_BEGIN
while true
do
declare -A TEST_COPROCS
TEST_COPROCS_COUNT=0
TEST_PREFIX=$(printf "%04d" $TEST_INDEX)
# it'll be used by the `sync-exit.sh` script
export TEST_FOLDER=`mktemp -d -p $ALL_TESTS_FOLDER test-$TEST_PREFIX.XXXXX`
# check if there are no more tests
zndsl_files=($BRIDGE_TESTS_FOLDER/$TEST_PREFIX-*.zndsl)
if [ ${#zndsl_files[@]} -eq 0 ]; then
break
fi
# start tests
for zndsl_file in "${zndsl_files[@]}"; do
start_coproc "$ZOMBIENET_BINARY_PATH --provider native test $zndsl_file" "$zndsl_file"
echo -n "1">>$TEST_FOLDER/exit-sync
((TEST_COPROCS_COUNT++))
done
# wait until all tests are completed
for n in `seq 1 $TEST_COPROCS_COUNT`; do
if [ "$IS_BASH_5_1" -eq 1 ]; then
wait -n -p COPROC_PID
exit_code=$?
coproc_name=${TEST_COPROCS[$COPROC_PID, 0]}
coproc_log=${TEST_COPROCS[$COPROC_PID, 1]}
coproc_stdout=$(cat $coproc_log)
else
wait -n
exit_code=$?
coproc_name="<unknown>"
coproc_stdout="<unknown>"
fi
echo "Process $coproc_name has finished with exit code: $exit_code"
# if exit code is not zero, exit
if [ $exit_code -ne 0 ]; then
echo "====================================================================="
echo "=== Shutting down. Log of failed process below ==="
echo "====================================================================="
echo "$coproc_stdout"
exit 1
fi
done
# proceed to next index
((TEST_INDEX++))
if [ "$TEST_INDEX" -ge "$TESTS_END" ]; then
break
fi
# kill relay here - it is started manually by tests
killall substrate-relay
done
echo "====================================================================="
echo "=== All tests have completed successfully ==="
echo "====================================================================="
+7
View File
@@ -0,0 +1,7 @@
#!/bin/bash
INVOKE_LOG=`mktemp -p $TEST_FOLDER invoke.XXXXX`
pushd $POLKADOT_SDK_PATH/bridges/testing/environments/rococo-westend
./bridges_rococo_westend.sh $1 >$INVOKE_LOG 2>&1
popd
+7
View File
@@ -0,0 +1,7 @@
#!/bin/bash
RELAY_LOG=`mktemp -p $TEST_FOLDER relay.XXXXX`
pushd $POLKADOT_SDK_PATH/bridges/testing/environments/rococo-westend
./bridges_rococo_westend.sh run-relay >$RELAY_LOG 2>&1&
popd
+14
View File
@@ -0,0 +1,14 @@
#!/bin/bash
set -e
# every network adds a char to the file, let's remove ours
truncate -s -1 $TEST_FOLDER/exit-sync
# when all chars are removed, then our test is done
while true
do
if [ `stat --printf="%s" $TEST_FOLDER/exit-sync` -eq 0 ]; then
exit
fi
sleep 100
done
@@ -0,0 +1,12 @@
Description: User is able to transfer ROC from Rococo Asset Hub to Westend Asset Hub and back
Network: {{ENV_PATH}}/bridge_hub_westend_local_network.toml
Creds: config
# send 5 ROC to //Alice from Rococo AH to Westend AH
asset-hub-westend-collator1: run {{ENV_PATH}}/helper.sh with "reserve-transfer-assets-from-asset-hub-rococo-local 5000000000000" within 120 seconds
# check that //Alice received at least 4.8 ROC on Westend AH
asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,4800000000000,Rococo" within 600 seconds
# check that the relayer //Charlie is rewarded by Westend AH
bridge-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x6268726F,ThisChain,0" within 30 seconds
+25
View File
@@ -0,0 +1,25 @@
#!/bin/bash
set -e
source "${BASH_SOURCE%/*}/../../framework/utils/common.sh"
source "${BASH_SOURCE%/*}/../../framework/utils/zombienet.sh"
export ENV_PATH=`realpath ${BASH_SOURCE%/*}/../../environments/rococo-westend`
$ENV_PATH/spawn.sh --init --start-relayer &
env_pid=$!
ensure_process_file $env_pid $TEST_DIR/rococo.env 600
rococo_dir=`cat $TEST_DIR/rococo.env`
echo
ensure_process_file $env_pid $TEST_DIR/westend.env 300
westend_dir=`cat $TEST_DIR/westend.env`
echo
run_zndsl ${BASH_SOURCE%/*}/roc-reaches-westend.zndsl $westend_dir
run_zndsl ${BASH_SOURCE%/*}/wnd-reaches-rococo.zndsl $rococo_dir
run_zndsl ${BASH_SOURCE%/*}/wroc-reaches-rococo.zndsl $rococo_dir
run_zndsl ${BASH_SOURCE%/*}/wwnd-reaches-westend.zndsl $westend_dir
@@ -0,0 +1,12 @@
Description: User is able to transfer WND from Westend Asset Hub to Rococo Asset Hub and back
Network: {{ENV_PATH}}/bridge_hub_rococo_local_network.toml
Creds: config
# send 5 WND to //Alice from Westend AH to Rococo AH
asset-hub-rococo-collator1: run {{ENV_PATH}}/helper.sh with "reserve-transfer-assets-from-asset-hub-westend-local 5000000000000" within 120 seconds
# check that //Alice received at least 4.8 WND on Rococo AH
asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,4800000000000,Westend" within 600 seconds
# check that the relayer //Charlie is rewarded by Rococo AH
bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x62687764,ThisChain,0" within 30 seconds
@@ -0,0 +1,10 @@
Description: User is able to transfer ROC from Rococo Asset Hub to Westend Asset Hub and back
Network: {{ENV_PATH}}/bridge_hub_westend_local_network.toml
Creds: config
# send 3 wROC back to Alice from Westend AH to Rococo AH
asset-hub-rococo-collator1: run {{ENV_PATH}}/helper.sh with "withdraw-reserve-assets-from-asset-hub-westend-local 3000000000000" within 120 seconds
# check that //Alice received at least 2.8 wROC on Rococo AH
# (we wait until //Alice account increases here - there are no other transactions that may increase it)
asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,2800000000000" within 600 seconds
@@ -0,0 +1,10 @@
Description: User is able to transfer ROC from Rococo Asset Hub to Westend Asset Hub and back
Network: {{ENV_PATH}}/bridge_hub_westend_local_network.toml
Creds: config
# send 3 wWND back to Alice from Rococo AH to Westend AH
asset-hub-westend-collator1: run {{ENV_PATH}}/helper.sh with "withdraw-reserve-assets-from-asset-hub-rococo-local 3000000000000" within 120 seconds
# check that //Alice received at least 2.8 wWND on Westend AH
# (we wait until //Alice account increases here - there are no other transactions that may increase it)
asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,2800000000000" within 600 seconds
@@ -0,0 +1,8 @@
Description: While relayer is idle, we only sync mandatory Rococo (and a single Rococo BH) headers to Westend BH.
Network: {{ENV_PATH}}/bridge_hub_westend_local_network.toml
Creds: config
# ensure that relayer is only syncing mandatory headers while idle. This includes both headers that were
# generated while relay was offline and those in the next 100 seconds while script is active.
bridge-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/only-mandatory-headers-synced-when-idle.js with "300,rococo-at-westend" within 600 seconds
@@ -0,0 +1,35 @@
#!/bin/bash
set -e
source "${BASH_SOURCE%/*}/../../framework/utils/common.sh"
source "${BASH_SOURCE%/*}/../../framework/utils/zombienet.sh"
export ENV_PATH=`realpath ${BASH_SOURCE%/*}/../../environments/rococo-westend`
$ENV_PATH/spawn.sh &
env_pid=$!
ensure_process_file $env_pid $TEST_DIR/rococo.env 600
rococo_dir=`cat $TEST_DIR/rococo.env`
echo
ensure_process_file $env_pid $TEST_DIR/westend.env 300
westend_dir=`cat $TEST_DIR/westend.env`
echo
# Sleep for some time before starting the relayer. We want to sleep for at least 1 session,
# which is expected to be 60 seconds for the test environment.
echo -e "Sleeping 90s before starting relayer ...\n"
sleep 90
${BASH_SOURCE%/*}/../../environments/rococo-westend/start_relayer.sh $rococo_dir $westend_dir relayer_pid
# Sometimes the relayer syncs multiple parachain heads in the begining leading to test failures.
# See issue: https://github.com/paritytech/parity-bridges-common/issues/2838.
# TODO: Remove this sleep after the issue is fixed.
echo -e "Sleeping 180s before runing the tests ...\n"
sleep 180
run_zndsl ${BASH_SOURCE%/*}/rococo-to-westend.zndsl $westend_dir
run_zndsl ${BASH_SOURCE%/*}/westend-to-rococo.zndsl $rococo_dir
@@ -0,0 +1,7 @@
Description: While relayer is idle, we only sync mandatory Westend (and a single Westend BH) headers to Rococo BH.
Network: {{ENV_PATH}}/bridge_hub_rococo_local_network.toml
Creds: config
# ensure that relayer is only syncing mandatory headers while idle. This includes both headers that were
# generated while relay was offline and those in the next 100 seconds while script is active.
bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/only-mandatory-headers-synced-when-idle.js with "300,westend-at-rococo" within 600 seconds
@@ -0,0 +1,26 @@
Description: While relayer is active, we only sync mandatory and required Rococo (and Rococo BH) headers to Westend BH.
Network: ../environments/rococo-westend/bridge_hub_westend_local_network.toml
Creds: config
# step 1: initialize Westend AH
asset-hub-westend-collator1: run ../scripts/invoke-script.sh with "init-asset-hub-westend-local" within 60 seconds
# step 2: initialize Westend bridge hub
bridge-hub-westend-collator1: run ../scripts/invoke-script.sh with "init-bridge-hub-westend-local" within 60 seconds
# step 3: ensure that initialization has completed
asset-hub-westend-collator1: js-script ../js-helpers/wait-hrmp-channel-opened.js with "1002" within 600 seconds
# step 4: send message from Westend to Rococo
asset-hub-westend-collator1: run ../scripts/invoke-script.sh with "reserve-transfer-assets-from-asset-hub-westend-local" within 60 seconds
# step 5: start relayer
# (we are starting it after sending the message to be sure that relayer won't relay messages before our js script
# will be started at step 6)
# (it is started by sibling 0003-required-headers-synced-while-active-westend-to-rococo.zndsl)
# step 6: ensure that relayer won't sync any extra headers while delivering messages and confirmations
bridge-hub-westend-collator1: js-script ../js-helpers/only-required-headers-synced-when-active.js with "500,rococo-at-westend" within 600 seconds
# wait until other network test has completed OR exit with an error too
asset-hub-westend-collator1: run ../scripts/sync-exit.sh within 600 seconds
@@ -0,0 +1,26 @@
Description: While relayer is active, we only sync mandatory and required Westend (and Westend BH) headers to Rococo BH.
Network: ../environments/rococo-westend/bridge_hub_rococo_local_network.toml
Creds: config
# step 1: initialize Rococo AH
asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "init-asset-hub-rococo-local" within 60 seconds
# step 2: initialize Rococo bridge hub
bridge-hub-rococo-collator1: run ../scripts/invoke-script.sh with "init-bridge-hub-rococo-local" within 60 seconds
# step 3: ensure that initialization has completed
asset-hub-rococo-collator1: js-script ../js-helpers/wait-hrmp-channel-opened.js with "1013" within 600 seconds
# step 4: send message from Rococo to Westend
asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "reserve-transfer-assets-from-asset-hub-rococo-local" within 60 seconds
# step 5: start relayer
# (we are starting it after sending the message to be sure that relayer won't relay messages before our js script
# will be started at step 6)
bridge-hub-rococo-collator1: run ../scripts/start-relayer.sh within 60 seconds
# step 6: ensure that relayer won't sync any extra headers while delivering messages and confirmations
bridge-hub-rococo-collator1: js-script ../js-helpers/only-required-headers-synced-when-active.js with "500,westend-at-rococo" within 600 seconds
# wait until other network test has completed OR exit with an error too
asset-hub-rococo-collator1: run ../scripts/sync-exit.sh within 600 seconds