feat: initialize Kurdistan SDK - independent fork of Polkadot SDK

This commit is contained in:
2025-12-13 15:44:15 +03:00
commit 286de54384
6841 changed files with 1848356 additions and 0 deletions
@@ -0,0 +1,281 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Pezkuwi.
// Pezkuwi is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Pezkuwi is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Pezkuwi. If not, see <http://www.gnu.org/licenses/>.
//! Tests specific to the bridging primitives
use super::mock::*;
use crate::{universal_exports::*, WithTopicSource};
use frame_support::{parameter_types, traits::Get};
use std::{cell::RefCell, marker::PhantomData};
use xcm::AlwaysLatest;
use xcm_executor::{
traits::{export_xcm, validate_export},
XcmExecutor,
};
use SendError::*;
mod local_para_para;
mod local_relay_relay;
mod paid_remote_relay_relay;
mod remote_para_para;
mod remote_para_para_via_relay;
mod remote_relay_relay;
mod universal_exports;
parameter_types! {
pub Local: NetworkId = ByGenesis([0; 32]);
pub Remote: NetworkId = ByGenesis([1; 32]);
pub Price: Assets = Assets::from((Here, 100u128));
pub static UsingTopic: bool = false;
}
std::thread_local! {
static BRIDGE_TRAFFIC: RefCell<Vec<Vec<u8>>> = RefCell::new(Vec::new());
}
fn maybe_with_topic(f: impl Fn()) {
UsingTopic::set(false);
f();
UsingTopic::set(true);
f();
}
fn xcm_with_topic<T>(topic: XcmHash, mut xcm: Vec<Instruction<T>>) -> Xcm<T> {
if UsingTopic::get() {
xcm.push(SetTopic(topic));
}
Xcm(xcm)
}
fn fake_id() -> XcmHash {
[255; 32]
}
fn test_weight(mut count: u64) -> Weight {
if UsingTopic::get() {
count += 1;
}
Weight::from_parts(count * 10, count * 10)
}
fn maybe_forward_id_for(topic: &XcmHash) -> XcmHash {
match UsingTopic::get() {
true => *topic,
false => fake_id(),
}
}
enum TestTicket<T: SendXcm> {
Basic(T::Ticket),
Topic(<WithTopicSource<T, ()> as SendXcm>::Ticket),
}
struct TestTopic<R>(PhantomData<R>);
impl<R: SendXcm> SendXcm for TestTopic<R> {
type Ticket = TestTicket<R>;
fn deliver(ticket: Self::Ticket) -> core::result::Result<XcmHash, SendError> {
match ticket {
TestTicket::Basic(t) => R::deliver(t),
TestTicket::Topic(t) => WithTopicSource::<R, ()>::deliver(t),
}
}
fn validate(
destination: &mut Option<Location>,
message: &mut Option<Xcm<()>>,
) -> SendResult<Self::Ticket> {
Ok(if UsingTopic::get() {
let (t, a) = WithTopicSource::<R, ()>::validate(destination, message)?;
(TestTicket::Topic(t), a)
} else {
let (t, a) = R::validate(destination, message)?;
(TestTicket::Basic(t), a)
})
}
}
struct TestBridge<D>(PhantomData<D>);
impl<D: DispatchBlob> TestBridge<D> {
fn service() -> u64 {
BRIDGE_TRAFFIC
.with(|t| t.borrow_mut().drain(..).map(|b| D::dispatch_blob(b).map_or(0, |()| 1)).sum())
}
}
impl<D: DispatchBlob> HaulBlob for TestBridge<D> {
fn haul_blob(blob: Vec<u8>) -> Result<(), HaulBlobError> {
BRIDGE_TRAFFIC.with(|t| t.borrow_mut().push(blob));
Ok(())
}
}
std::thread_local! {
static REMOTE_INCOMING_XCM: RefCell<Vec<(Location, Xcm<()>)>> = RefCell::new(Vec::new());
}
struct TestRemoteIncomingRouter;
impl SendXcm for TestRemoteIncomingRouter {
type Ticket = (Location, Xcm<()>);
fn validate(
dest: &mut Option<Location>,
msg: &mut Option<Xcm<()>>,
) -> SendResult<(Location, Xcm<()>)> {
let pair = (dest.take().unwrap(), msg.take().unwrap());
Ok((pair, Assets::new()))
}
fn deliver(pair: (Location, Xcm<()>)) -> Result<XcmHash, SendError> {
let hash = fake_id();
REMOTE_INCOMING_XCM.with(|q| q.borrow_mut().push(pair));
Ok(hash)
}
}
fn take_received_remote_messages() -> Vec<(Location, Xcm<()>)> {
REMOTE_INCOMING_XCM.with(|r| r.replace(vec![]))
}
/// This is a dummy router which accepts messages destined for `Remote` from `Local`
/// and then executes them for free in a context simulated to be like that of our `Remote`.
struct UnpaidExecutingRouter<Local, Remote, RemoteExporter>(
PhantomData<(Local, Remote, RemoteExporter)>,
);
fn price<RemoteExporter: ExportXcm>(
n: NetworkId,
c: u32,
s: &InteriorLocation,
d: &InteriorLocation,
m: &Xcm<()>,
) -> Result<Assets, SendError> {
Ok(validate_export::<RemoteExporter>(n, c, s.clone(), d.clone(), m.clone())?.1)
}
fn deliver<RemoteExporter: ExportXcm>(
n: NetworkId,
c: u32,
s: InteriorLocation,
d: InteriorLocation,
m: Xcm<()>,
) -> Result<XcmHash, SendError> {
export_xcm::<RemoteExporter>(n, c, s, d, m).map(|(hash, _)| hash)
}
#[derive(Eq, PartialEq, Clone, Debug)]
pub struct LogEntry {
local: Junctions,
remote: Junctions,
id: XcmHash,
message: Xcm<()>,
outcome: Outcome,
paid: bool,
}
parameter_types! {
pub static RoutingLog: Vec<LogEntry> = vec![];
}
impl<Local: Get<Junctions>, Remote: Get<Junctions>, RemoteExporter: ExportXcm> SendXcm
for UnpaidExecutingRouter<Local, Remote, RemoteExporter>
{
type Ticket = Xcm<()>;
fn validate(
destination: &mut Option<Location>,
message: &mut Option<Xcm<()>>,
) -> SendResult<Xcm<()>> {
let expect_dest = Remote::get().relative_to(&Local::get());
if destination.as_ref().ok_or(MissingArgument)? != &expect_dest {
return Err(NotApplicable);
}
let message = message.take().ok_or(MissingArgument)?;
Ok((message, Assets::new()))
}
fn deliver(message: Xcm<()>) -> Result<XcmHash, SendError> {
// We now pretend that the message was delivered from `Local` to `Remote`, and execute
// so we need to ensure that the `TestConfig` is set up properly for executing as
// though it is `Remote`.
ExecutorUniversalLocation::set(Remote::get());
let origin = Local::get().relative_to(&Remote::get());
AllowUnpaidFrom::set(vec![origin.clone()]);
set_exporter_override(price::<RemoteExporter>, deliver::<RemoteExporter>);
// Then we execute it:
let mut id = fake_id();
let outcome = XcmExecutor::<TestConfig>::prepare_and_execute(
origin,
message.clone().into(),
&mut id,
Weight::from_parts(2_000_000_000_000, 2_000_000_000_000),
Weight::zero(),
);
let local = Local::get();
let remote = Remote::get();
let entry = LogEntry { local, remote, id, message, outcome: outcome.clone(), paid: false };
RoutingLog::mutate(|l| l.push(entry));
match outcome {
Outcome::Complete { .. } => Ok(id),
Outcome::Incomplete { .. } => Err(Transport("Error executing")),
Outcome::Error(_) => Err(Transport("Unable to execute")),
}
}
}
/// This is a dummy router which accepts messages destined for `Remote` from `Local`
/// and then executes them in a context simulated to be like that of our `Remote`. Payment is
/// needed.
struct ExecutingRouter<Local, Remote, RemoteExporter>(PhantomData<(Local, Remote, RemoteExporter)>);
impl<Local: Get<Junctions>, Remote: Get<Junctions>, RemoteExporter: ExportXcm> SendXcm
for ExecutingRouter<Local, Remote, RemoteExporter>
{
type Ticket = Xcm<()>;
fn validate(
destination: &mut Option<Location>,
message: &mut Option<Xcm<()>>,
) -> SendResult<Xcm<()>> {
let expect_dest = Remote::get().relative_to(&Local::get());
if destination.as_ref().ok_or(MissingArgument)? != &expect_dest {
return Err(NotApplicable);
}
let message = message.take().ok_or(MissingArgument)?;
Ok((message, Assets::new()))
}
fn deliver(message: Xcm<()>) -> Result<XcmHash, SendError> {
// We now pretend that the message was delivered from `Local` to `Remote`, and execute
// so we need to ensure that the `TestConfig` is set up properly for executing as
// though it is `Remote`.
ExecutorUniversalLocation::set(Remote::get());
let origin = Local::get().relative_to(&Remote::get());
AllowPaidFrom::set(vec![origin.clone()]);
set_exporter_override(price::<RemoteExporter>, deliver::<RemoteExporter>);
// Then we execute it:
let mut id = fake_id();
let outcome = XcmExecutor::<TestConfig>::prepare_and_execute(
origin,
message.clone().into(),
&mut id,
Weight::from_parts(2_000_000_000_000, 2_000_000_000_000),
Weight::zero(),
);
let local = Local::get();
let remote = Remote::get();
let entry = LogEntry { local, remote, id, message, outcome: outcome.clone(), paid: true };
RoutingLog::mutate(|l| l.push(entry));
match outcome {
Outcome::Complete { .. } => Ok(id),
Outcome::Incomplete { .. } => Err(Transport("Error executing")),
Outcome::Error(_) => Err(Transport("Unable to execute")),
}
}
}