feat: Rebrand Polkadot/Substrate references to PezkuwiChain
This commit systematically rebrands various references from Parity Technologies' Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk. Key changes include: - Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks. - Modified internal documentation and code comments to reflect PezkuwiChain naming and structure. - Replaced direct references to with or specific paths within the for XCM, Pezkuwi, and other modules. - Cleaned up deprecated issue and PR references in various and files, particularly in and modules. - Adjusted image and logo URLs in documentation to point to PezkuwiChain assets. - Removed or rephrased comments related to external Polkadot/Substrate PRs and issues. This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
//! The [`CheckMetadataHash`] transaction extension.
|
||||
//!
|
||||
//! The extension for optionally checking the metadata hash. For information how it works and what
|
||||
//! it does exactly, see the docs of [`CheckMetadataHash`].
|
||||
//!
|
||||
//! # Integration
|
||||
//!
|
||||
//! As any transaction extension you will need to add it to your runtime transaction extensions:
|
||||
#![doc = docify::embed!("src/tests.rs", add_metadata_hash_extension)]
|
||||
//! As the extension requires the `RUNTIME_METADATA_HASH` environment variable to be present at
|
||||
//! compile time, it requires a little bit more setup. To have this environment variable available
|
||||
//! at compile time required to tell the `bizinikiwi-wasm-builder` to do so:
|
||||
#![doc = docify::embed!("src/tests.rs", enable_metadata_hash_in_wasm_builder)]
|
||||
//! As generating the metadata hash requires to compile the runtime twice, it is
|
||||
//! recommended to only enable the metadata hash generation when doing a build for a release or when
|
||||
//! you want to test this feature.
|
||||
|
||||
extern crate alloc;
|
||||
/// For our tests
|
||||
extern crate self as pezframe_metadata_hash_extension;
|
||||
|
||||
use codec::{Decode, DecodeWithMemTracking, Encode};
|
||||
use pezframe_support::{pezpallet_prelude::Weight, DebugNoBound};
|
||||
use pezframe_system::Config;
|
||||
use scale_info::TypeInfo;
|
||||
use pezsp_runtime::{
|
||||
impl_tx_ext_default,
|
||||
traits::TransactionExtension,
|
||||
transaction_validity::{TransactionValidityError, UnknownTransaction},
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// The mode of [`CheckMetadataHash`].
|
||||
#[derive(Decode, Encode, DecodeWithMemTracking, PartialEq, Debug, TypeInfo, Clone, Copy, Eq)]
|
||||
enum Mode {
|
||||
Disabled,
|
||||
Enabled,
|
||||
}
|
||||
|
||||
/// Wrapper around the metadata hash and from where to get it from.
|
||||
#[derive(Default, Debug, PartialEq, Clone, Copy, Eq)]
|
||||
enum MetadataHash {
|
||||
/// Fetch it from the `RUNTIME_METADATA_HASH` env variable at compile time.
|
||||
#[default]
|
||||
FetchFromEnv,
|
||||
/// Use the given metadata hash.
|
||||
Custom([u8; 32]),
|
||||
}
|
||||
|
||||
const RUNTIME_METADATA: Option<[u8; 32]> = if let Some(hex) = option_env!("RUNTIME_METADATA_HASH") {
|
||||
match const_hex::const_decode_to_array(hex.as_bytes()) {
|
||||
Ok(hex) => Some(hex),
|
||||
Err(_) => panic!(
|
||||
"Invalid RUNTIME_METADATA_HASH environment variable: it must be a 32 \
|
||||
bytes value in hexadecimal: e.g. 0x123ABCabd...123ABCabc. Upper case or lower case, \
|
||||
0x prefix is optional."
|
||||
),
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
impl MetadataHash {
|
||||
/// Returns the metadata hash.
|
||||
fn hash(&self) -> Option<[u8; 32]> {
|
||||
match self {
|
||||
Self::FetchFromEnv => RUNTIME_METADATA,
|
||||
Self::Custom(hash) => Some(*hash),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension for optionally verifying the metadata hash.
|
||||
///
|
||||
/// The metadata hash is cryptographical representation of the runtime metadata. This metadata hash
|
||||
/// is build as described in [RFC78](https://polkadot-fellows.github.io/RFCs/approved/0078-merkleized-metadata.html).
|
||||
/// This metadata hash should give users the confidence that what they build with an online wallet
|
||||
/// is the same they are signing with their offline wallet and then applying on chain. To ensure
|
||||
/// that the online wallet is not tricking the offline wallet into decoding and showing an incorrect
|
||||
/// extrinsic, the offline wallet will include the metadata hash into the extension implicit and
|
||||
/// the runtime will then do the same. If the metadata hash doesn't match, the signature
|
||||
/// verification will fail and thus, the transaction will be rejected. The RFC contains more details
|
||||
/// on how it works.
|
||||
///
|
||||
/// The extension adds one byte (the `mode`) to the size of the extrinsic. This one byte is
|
||||
/// controlling if the metadata hash should be added to the implicit or not. Mode `0` means that
|
||||
/// the metadata hash is not added and thus, `None` is added to the implicit. Mode `1` means that
|
||||
/// the metadata hash is added and thus, `Some(metadata_hash)` is added to the implicit. Further
|
||||
/// values of `mode` are reserved for future changes.
|
||||
///
|
||||
/// The metadata hash is read from the environment variable `RUNTIME_METADATA_HASH`. This
|
||||
/// environment variable is for example set by the `bizinikiwi-wasm-builder` when the feature for
|
||||
/// generating the metadata hash is enabled. If the environment variable is not set and `mode = 1`
|
||||
/// is passed, the transaction is rejected with [`UnknownTransaction::CannotLookup`].
|
||||
#[derive(Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, TypeInfo, DebugNoBound)]
|
||||
#[scale_info(skip_type_params(T))]
|
||||
pub struct CheckMetadataHash<T> {
|
||||
_phantom: core::marker::PhantomData<T>,
|
||||
mode: Mode,
|
||||
#[codec(skip)]
|
||||
metadata_hash: MetadataHash,
|
||||
}
|
||||
|
||||
impl<T> CheckMetadataHash<T> {
|
||||
/// Creates new `TransactionExtension` to check metadata hash.
|
||||
pub fn new(enable: bool) -> Self {
|
||||
Self {
|
||||
_phantom: core::marker::PhantomData,
|
||||
mode: if enable { Mode::Enabled } else { Mode::Disabled },
|
||||
metadata_hash: MetadataHash::FetchFromEnv,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an instance that uses the given `metadata_hash`.
|
||||
///
|
||||
/// This is useful for testing the extension.
|
||||
pub fn new_with_custom_hash(metadata_hash: [u8; 32]) -> Self {
|
||||
Self {
|
||||
_phantom: core::marker::PhantomData,
|
||||
mode: Mode::Enabled,
|
||||
metadata_hash: MetadataHash::Custom(metadata_hash),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config + Send + Sync> TransactionExtension<T::RuntimeCall> for CheckMetadataHash<T> {
|
||||
const IDENTIFIER: &'static str = "CheckMetadataHash";
|
||||
type Implicit = Option<[u8; 32]>;
|
||||
fn implicit(&self) -> Result<Self::Implicit, TransactionValidityError> {
|
||||
let signed = match self.mode {
|
||||
Mode::Disabled => None,
|
||||
Mode::Enabled => match self.metadata_hash.hash() {
|
||||
Some(hash) => Some(hash),
|
||||
None => return Err(UnknownTransaction::CannotLookup.into()),
|
||||
},
|
||||
};
|
||||
|
||||
log::debug!(
|
||||
target: "runtime::metadata-hash",
|
||||
"CheckMetadataHash::implicit => {:?}",
|
||||
signed.as_ref().map(|h| array_bytes::bytes2hex("0x", h)),
|
||||
);
|
||||
|
||||
Ok(signed)
|
||||
}
|
||||
type Val = ();
|
||||
type Pre = ();
|
||||
|
||||
fn weight(&self, _: &T::RuntimeCall) -> Weight {
|
||||
// The weight is the weight of implicit, it consists of a few match operation, it is
|
||||
// negligible.
|
||||
Weight::zero()
|
||||
}
|
||||
|
||||
impl_tx_ext_default!(T::RuntimeCall; validate prepare);
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
// This file is part of Bizinikiwi.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::CheckMetadataHash;
|
||||
use codec::{Decode, Encode};
|
||||
use frame_metadata::RuntimeMetadataPrefixed;
|
||||
use pezframe_support::{
|
||||
derive_impl,
|
||||
pezpallet_prelude::{InvalidTransaction, TransactionValidityError},
|
||||
};
|
||||
use merkleized_metadata::{generate_metadata_digest, ExtraInfo};
|
||||
use pezsp_api::{Metadata, ProvideRuntimeApi};
|
||||
use pezsp_runtime::{
|
||||
traits::{ExtrinsicLike, TransactionExtension},
|
||||
transaction_validity::{TransactionSource, UnknownTransaction},
|
||||
};
|
||||
use pezsp_transaction_pool::runtime_api::TaggedTransactionQueue;
|
||||
use bizinikiwi_test_runtime_client::{
|
||||
prelude::*,
|
||||
runtime::{self, ExtrinsicBuilder},
|
||||
DefaultTestClientBuilderExt, TestClientBuilder,
|
||||
};
|
||||
|
||||
type Block = pezframe_system::mocking::MockBlock<Test>;
|
||||
|
||||
pezframe_support::construct_runtime! {
|
||||
pub enum Test {
|
||||
System: pezframe_system,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
|
||||
impl pezframe_system::Config for Test {
|
||||
type Block = Block;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_when_no_metadata_hash_was_passed() {
|
||||
let ext = CheckMetadataHash::<Test>::decode(&mut &1u8.encode()[..]).unwrap();
|
||||
assert_eq!(Err(UnknownTransaction::CannotLookup.into()), ext.implicit());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_unknown_mode() {
|
||||
assert!(CheckMetadataHash::<Test>::decode(&mut &50u8.encode()[..]).is_err());
|
||||
}
|
||||
|
||||
/// Generate the metadata hash for the `test-runtime`.
|
||||
fn generate_metadata_hash(metadata: RuntimeMetadataPrefixed) -> [u8; 32] {
|
||||
let runtime_version = runtime::VERSION;
|
||||
let base58_prefix = 0;
|
||||
|
||||
let extra_info = ExtraInfo {
|
||||
spec_version: runtime_version.spec_version,
|
||||
spec_name: runtime_version.spec_name.into(),
|
||||
base58_prefix,
|
||||
decimals: 10,
|
||||
token_symbol: "TOKEN".into(),
|
||||
};
|
||||
|
||||
generate_metadata_digest(&metadata.1, extra_info).unwrap().hash()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ensure_check_metadata_works_on_real_extrinsics() {
|
||||
pezsp_tracing::try_init_simple();
|
||||
|
||||
let client = TestClientBuilder::new().build();
|
||||
let runtime_api = client.runtime_api();
|
||||
let best_hash = client.chain_info().best_hash;
|
||||
|
||||
let metadata = RuntimeMetadataPrefixed::decode(
|
||||
&mut &runtime_api.metadata_at_version(best_hash, 15).unwrap().unwrap()[..],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let valid_transaction = ExtrinsicBuilder::new_include_data(vec![1, 2, 3])
|
||||
.metadata_hash(generate_metadata_hash(metadata))
|
||||
.build();
|
||||
// Ensure that the transaction is signed.
|
||||
assert!(!valid_transaction.is_bare());
|
||||
|
||||
runtime_api
|
||||
.validate_transaction(best_hash, TransactionSource::External, valid_transaction, best_hash)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
// Including some random metadata hash should make the transaction invalid.
|
||||
let invalid_transaction = ExtrinsicBuilder::new_include_data(vec![1, 2, 3])
|
||||
.metadata_hash([10u8; 32])
|
||||
.build();
|
||||
// Ensure that the transaction is signed.
|
||||
assert!(!invalid_transaction.is_bare());
|
||||
|
||||
assert_eq!(
|
||||
TransactionValidityError::from(InvalidTransaction::BadProof),
|
||||
runtime_api
|
||||
.validate_transaction(
|
||||
best_hash,
|
||||
TransactionSource::External,
|
||||
invalid_transaction,
|
||||
best_hash
|
||||
)
|
||||
.unwrap()
|
||||
.unwrap_err()
|
||||
);
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
mod docs {
|
||||
use super::*;
|
||||
|
||||
#[docify::export]
|
||||
mod add_metadata_hash_extension {
|
||||
pezframe_support::construct_runtime! {
|
||||
pub enum Runtime {
|
||||
System: pezframe_system,
|
||||
}
|
||||
}
|
||||
|
||||
/// The `TransactionExtension` to the basic transaction logic.
|
||||
pub type TxExtension = (
|
||||
pezframe_system::AuthorizeCall<Runtime>,
|
||||
pezframe_system::CheckNonZeroSender<Runtime>,
|
||||
pezframe_system::CheckSpecVersion<Runtime>,
|
||||
pezframe_system::CheckTxVersion<Runtime>,
|
||||
pezframe_system::CheckGenesis<Runtime>,
|
||||
pezframe_system::CheckMortality<Runtime>,
|
||||
pezframe_system::CheckNonce<Runtime>,
|
||||
pezframe_system::CheckWeight<Runtime>,
|
||||
// Add the `CheckMetadataHash` extension.
|
||||
// The position in this list is not important, so we could also add it to beginning.
|
||||
pezframe_metadata_hash_extension::CheckMetadataHash<Runtime>,
|
||||
pezframe_system::WeightReclaim<Runtime>,
|
||||
);
|
||||
|
||||
/// In your runtime this will be your real address type.
|
||||
type Address = ();
|
||||
/// In your runtime this will be your real signature type.
|
||||
type Signature = ();
|
||||
|
||||
/// Unchecked extrinsic type as expected by this runtime.
|
||||
pub type UncheckedExtrinsic =
|
||||
pezsp_runtime::generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, TxExtension>;
|
||||
}
|
||||
|
||||
// Put here to not have it in the docs as well.
|
||||
#[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)]
|
||||
impl pezframe_system::Config for add_metadata_hash_extension::Runtime {
|
||||
type Block = Block;
|
||||
type RuntimeEvent = add_metadata_hash_extension::RuntimeEvent;
|
||||
type RuntimeOrigin = add_metadata_hash_extension::RuntimeOrigin;
|
||||
type RuntimeCall = add_metadata_hash_extension::RuntimeCall;
|
||||
type PalletInfo = add_metadata_hash_extension::PalletInfo;
|
||||
}
|
||||
|
||||
#[docify::export]
|
||||
fn enable_metadata_hash_in_wasm_builder() {
|
||||
bizinikiwi_wasm_builder::WasmBuilder::init_with_defaults()
|
||||
// Requires the `metadata-hash` feature to be activated.
|
||||
// You need to pass the main token symbol and its number of decimals.
|
||||
.enable_metadata_hash("TOKEN", 12)
|
||||
// The runtime will be build twice and the second time the `RUNTIME_METADATA_HASH`
|
||||
// environment variable will be set for the `CheckMetadataHash` extension.
|
||||
.build()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user