mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-10 07:37:57 +00:00
49b6dfd2e5
* Cargo.lock after merge * Restore scale-info feature * Fully qualify TypeInfo derive * Skip PendingSwap T * Add missing skip_type_params attr * metadata docs features * Reduce pallet event attribute to struct * Cargo.lock * Update frame/balances/src/tests_composite.rs Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> * Line widths check * Cargo.lock * Add scale-info/std * Update frame/system/src/lib.rs Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> * Use `skip_type_params` to remove `TypeInfo` requirements on checks * Revert "Remove unused Call metadata stuff" This reverts commit 41311f85 * Skip BalanceSwapAction type parameter * Remove unused event metadata macro * Update frame-metadata * Update primitives/npos-elections/compact/src/codec.rs Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> * Manual TypeInfo for Header * Remove TypeInfo requirement for consts in BoundedVec etc. * Another TypeInfo bound removed * review: fix indentation * TypeInfo impls for Identity types * Add some todos to add custom TypeInfo impls * Update frame/support/procedural/src/pallet/expand/pallet_struct.rs Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> * Add some todos to add custom TypeInfo impls * Add a test for manual Data TypeInfo impl * Add custom TypeInfo impl for Vote * Era custom TypeInfo crimes * Revert finality-grandpa version to 0.14.z * review: renamed module to pallet_constants_metadata * New line at end of file * Add missing scale-info/std * Update frame/support/src/storage/types/mod.rs Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> * Remove StorageEntryType::Map unused flag * Add missing scale-info dependency after merge * SignedExtension::AdditionalSigned metadata * Update frame-metadata, use abbreviated docs and args fields * Update frame/example/Cargo.toml Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Add scale_info/std and remove unused scale-info dependency * Remove scale-info dependency * Remove treasury pallet::metadata * Remove redundant Event test * Add back scale-info as dev dependency * fix error metadata when no error defined in decl_module * Add Module3 to tests * Fix metadata test * Add docs feature to frame-support test * WIP fixing pallet metadata test * Remove redundant FunctionMetadata, FunctionArgumentMetadata as per https://github.com/paritytech/frame-metadata/pull/20 * Use main branch of frame-metadata * Use patch of scale-info for latest changes * Use latest patched scale-info * Manual TypeInfo for DigestItem * Manual TypeInfo for DigestItem * Update scale-info * Skip __Ignore variants for Error, depends on https://github.com/paritytech/scale-info/pull/117 * Named fields for FRAME v2 pallet Call variants * Named fields for FRAME v1 pallet Call variants * Add missing scale-info dependency * WIP expand benchmark call variant * fix benchmark with new function create a new function for each variant of a pallet call. This function is called by benchmarking macro in order not to break call creation with unnamed argument * fix tests * more fix * Fix staking tests * Fix offchain workers calls * Cherry pick rustfmt.toml from master * cargo +nightly-2021-06-22 fmt --all * Update to new call variant structs * More call variant struct updates * Remove unused import * More call variant structs * More call variant structs * Even more call variant structs * Mooar variant structs * Evermore variant structs * Call variant structs ad infinitum * Fmt * More call variants * Last call variant * Call variants all done? * Fix SS58Prefix type * Potential workaround for BitFlags<IdentityFields> TypeInfo * Enable docs capturing for Call, Event, and Error types * Fix IdentityFields TypeInfo * Remove metadata-docs feature * Add capture_docs = true for legacy Call, Event and Error types * Fmt * Fix metadata test type * Update benchmarks with call struct variants * Fmt * More test fixes * Fmt * Fix benches * Use latest capture_docs attr * Latest scale_info * Fmt * review: change &Vec to &[] * Remove pallet metadata attr * review: remove commented out test code * review: skip_type_params trailing comma suggestion * Update to scale-info 0.10.0 * Update construct_runtime ui tests, different because of metadata TypeInfo impls * Add some TypeInfo derives for UI tests * Update storage ensure span ui stderrs * Update call argument bound ui tests Possibly changed because change from tuple to struct variants? * Add scale-info dev dependency * Update to latest finality-grandpa release * review: missing newline * review: missing scale-info/std * review: remove duplicate scale-info/std * review: remove fully qualified TypeInfo * review: add missing scale-info/std * review: remove unnecessary imports. * Fmt * Use crates.io RC version of frame-metadata * Remove scale-info/std because it is a dev dependency * Add missing scale_info dev-dependency for test * Delete empty metadata folder * Fix sp_std import * review: improve manual UncheckedExtrinsic TypeInfo impl * review: use full scale-info for dev-dependency * Remove DefaultByteGetter impl * review: derive TypeInfo for generic header * Fmt * Update primitives/runtime/src/generic/unchecked_extrinsic.rs Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Update primitives/runtime/src/generic/unchecked_extrinsic.rs Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Update bin/node/executor/Cargo.toml Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update frame/identity/src/types.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update frame/support/src/dispatch.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Remove redundant derive * Simplify scale-info dependency * Strip underscore prefix from call variant struct names * Another underscore field * More underscore fields * Another underscore field * Update to frame-metadata 14.0.0-rc.2 with combined StorageEntryType::Map * Fmt * Revert weights formatting * Fix up some tests * Fix up some tests for StorageEntryTypeMetadata * scale-info dev dependency * Fix test error * Add missing TypeInfo derives * Add back missing scale-info dependency * Add back missing scale-info dependency * Fix npos compact impls * Cargo.lock * Fmt * Fix errors * Fmt * Fix renamed raw_solution field * Fix error * Fmt * Fix some benchmarks * Fmt * Stray R * Fix * Add missing TypeInfos * ui test fix * Fix line widths * Revert "ui test fix" This reverts commit 2d15ec058a216e3f92d713f1174603a2bb1eac65. * Upgrade to scale-info 0.11.0 * Revert "Upgrade to scale-info 0.11.0" This reverts commit 047bb179085a0059c36cd20ab405f55cf0867e28. * Add Runtime type * Update to scale-info 0.12 * Update to scale-info 1.0 * Update frame-metadata to version 14.0.0 * Patch finality-grandpa until release available * Fix metadata tests * Fix metadata tests * Fmt * Remove patched finality-grandpa * Fix tests, use scale_info imports * Fix pallet tests * Add BlockNumber TypeInfo bound * ui test fix * Cargo.lock * Remove pallet metadata * Cargo.lock * Add missing scale-info dependency * Remove pallet event metadata * Fix error * Fix collective errors * Semicolol * Fmt * Remove another metadata attribute * Add new variant to custom digest TypeInfo * Fmt * Cargo.lock from master * Remove comma lol * Fix example call error * Fix example call error properly Co-authored-by: Guillaume Thiolliere <gui.thiolliere@gmail.com> Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
494 lines
14 KiB
Rust
494 lines
14 KiB
Rust
// This file is part of Substrate.
|
|
|
|
// Copyright (C) 2017-2021 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.
|
|
|
|
//! Generic implementation of an unchecked (pre-verification) extrinsic.
|
|
|
|
use crate::{
|
|
generic::CheckedExtrinsic,
|
|
traits::{
|
|
self, Checkable, Extrinsic, ExtrinsicMetadata, IdentifyAccount, MaybeDisplay, Member,
|
|
SignedExtension,
|
|
},
|
|
transaction_validity::{InvalidTransaction, TransactionValidityError},
|
|
OpaqueExtrinsic,
|
|
};
|
|
use codec::{Compact, Decode, Encode, EncodeLike, Error, Input};
|
|
use scale_info::{build::Fields, meta_type, Path, StaticTypeInfo, Type, TypeInfo, TypeParameter};
|
|
use sp_io::hashing::blake2_256;
|
|
use sp_std::{fmt, prelude::*};
|
|
|
|
/// Current version of the [`UncheckedExtrinsic`] format.
|
|
const EXTRINSIC_VERSION: u8 = 4;
|
|
|
|
/// A extrinsic right from the external world. This is unchecked and so
|
|
/// can contain a signature.
|
|
#[derive(PartialEq, Eq, Clone)]
|
|
pub struct UncheckedExtrinsic<Address, Call, Signature, Extra>
|
|
where
|
|
Extra: SignedExtension,
|
|
{
|
|
/// The signature, address, number of extrinsics have come before from
|
|
/// the same signer and an era describing the longevity of this transaction,
|
|
/// if this is a signed extrinsic.
|
|
pub signature: Option<(Address, Signature, Extra)>,
|
|
/// The function that should be called.
|
|
pub function: Call,
|
|
}
|
|
|
|
/// Manual [`TypeInfo`] implementation because of custom encoding. The data is a valid encoded
|
|
/// `Vec<u8>`, but requires some logic to extract the signature and payload.
|
|
///
|
|
/// See [`UncheckedExtrinsic::encode`] and [`UncheckedExtrinsic::decode`].
|
|
impl<Address, Call, Signature, Extra> TypeInfo
|
|
for UncheckedExtrinsic<Address, Call, Signature, Extra>
|
|
where
|
|
Address: StaticTypeInfo,
|
|
Call: StaticTypeInfo,
|
|
Signature: StaticTypeInfo,
|
|
Extra: SignedExtension + StaticTypeInfo,
|
|
{
|
|
type Identity = UncheckedExtrinsic<Address, Call, Signature, Extra>;
|
|
|
|
fn type_info() -> Type {
|
|
Type::builder()
|
|
.path(Path::new("UncheckedExtrinsic", module_path!()))
|
|
// Include the type parameter types, even though they are not used directly in any of
|
|
// the described fields. These type definitions can be used by downstream consumers
|
|
// to help construct the custom decoding from the opaque bytes (see below).
|
|
.type_params(vec![
|
|
TypeParameter::new("Address", Some(meta_type::<Address>())),
|
|
TypeParameter::new("Call", Some(meta_type::<Call>())),
|
|
TypeParameter::new("Signature", Some(meta_type::<Signature>())),
|
|
TypeParameter::new("Extra", Some(meta_type::<Extra>())),
|
|
])
|
|
.docs(&["UncheckedExtrinsic raw bytes, requires custom decoding routine"])
|
|
// Because of the custom encoding, we can only accurately describe the encoding as an
|
|
// opaque `Vec<u8>`. Downstream consumers will need to manually implement the codec to
|
|
// encode/decode the `signature` and `function` fields.
|
|
.composite(Fields::unnamed().field(|f| f.ty::<Vec<u8>>()))
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "std")]
|
|
impl<Address, Call, Signature, Extra> parity_util_mem::MallocSizeOf
|
|
for UncheckedExtrinsic<Address, Call, Signature, Extra>
|
|
where
|
|
Extra: SignedExtension,
|
|
{
|
|
fn size_of(&self, _ops: &mut parity_util_mem::MallocSizeOfOps) -> usize {
|
|
// Instantiated only in runtime.
|
|
0
|
|
}
|
|
}
|
|
|
|
impl<Address, Call, Signature, Extra: SignedExtension>
|
|
UncheckedExtrinsic<Address, Call, Signature, Extra>
|
|
{
|
|
/// New instance of a signed extrinsic aka "transaction".
|
|
pub fn new_signed(function: Call, signed: Address, signature: Signature, extra: Extra) -> Self {
|
|
Self { signature: Some((signed, signature, extra)), function }
|
|
}
|
|
|
|
/// New instance of an unsigned extrinsic aka "inherent".
|
|
pub fn new_unsigned(function: Call) -> Self {
|
|
Self { signature: None, function }
|
|
}
|
|
}
|
|
|
|
impl<Address, Call, Signature, Extra: SignedExtension> Extrinsic
|
|
for UncheckedExtrinsic<Address, Call, Signature, Extra>
|
|
{
|
|
type Call = Call;
|
|
|
|
type SignaturePayload = (Address, Signature, Extra);
|
|
|
|
fn is_signed(&self) -> Option<bool> {
|
|
Some(self.signature.is_some())
|
|
}
|
|
|
|
fn new(function: Call, signed_data: Option<Self::SignaturePayload>) -> Option<Self> {
|
|
Some(if let Some((address, signature, extra)) = signed_data {
|
|
Self::new_signed(function, address, signature, extra)
|
|
} else {
|
|
Self::new_unsigned(function)
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<Address, AccountId, Call, Signature, Extra, Lookup> Checkable<Lookup>
|
|
for UncheckedExtrinsic<Address, Call, Signature, Extra>
|
|
where
|
|
Address: Member + MaybeDisplay,
|
|
Call: Encode + Member,
|
|
Signature: Member + traits::Verify,
|
|
<Signature as traits::Verify>::Signer: IdentifyAccount<AccountId = AccountId>,
|
|
Extra: SignedExtension<AccountId = AccountId>,
|
|
AccountId: Member + MaybeDisplay,
|
|
Lookup: traits::Lookup<Source = Address, Target = AccountId>,
|
|
{
|
|
type Checked = CheckedExtrinsic<AccountId, Call, Extra>;
|
|
|
|
fn check(self, lookup: &Lookup) -> Result<Self::Checked, TransactionValidityError> {
|
|
Ok(match self.signature {
|
|
Some((signed, signature, extra)) => {
|
|
let signed = lookup.lookup(signed)?;
|
|
let raw_payload = SignedPayload::new(self.function, extra)?;
|
|
if !raw_payload.using_encoded(|payload| signature.verify(payload, &signed)) {
|
|
return Err(InvalidTransaction::BadProof.into())
|
|
}
|
|
|
|
let (function, extra, _) = raw_payload.deconstruct();
|
|
CheckedExtrinsic { signed: Some((signed, extra)), function }
|
|
},
|
|
None => CheckedExtrinsic { signed: None, function: self.function },
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<Address, Call, Signature, Extra> ExtrinsicMetadata
|
|
for UncheckedExtrinsic<Address, Call, Signature, Extra>
|
|
where
|
|
Extra: SignedExtension,
|
|
{
|
|
const VERSION: u8 = EXTRINSIC_VERSION;
|
|
type SignedExtensions = Extra;
|
|
}
|
|
|
|
/// A payload that has been signed for an unchecked extrinsics.
|
|
///
|
|
/// Note that the payload that we sign to produce unchecked extrinsic signature
|
|
/// is going to be different than the `SignaturePayload` - so the thing the extrinsic
|
|
/// actually contains.
|
|
pub struct SignedPayload<Call, Extra: SignedExtension>((Call, Extra, Extra::AdditionalSigned));
|
|
|
|
impl<Call, Extra> SignedPayload<Call, Extra>
|
|
where
|
|
Call: Encode,
|
|
Extra: SignedExtension,
|
|
{
|
|
/// Create new `SignedPayload`.
|
|
///
|
|
/// This function may fail if `additional_signed` of `Extra` is not available.
|
|
pub fn new(call: Call, extra: Extra) -> Result<Self, TransactionValidityError> {
|
|
let additional_signed = extra.additional_signed()?;
|
|
let raw_payload = (call, extra, additional_signed);
|
|
Ok(Self(raw_payload))
|
|
}
|
|
|
|
/// Create new `SignedPayload` from raw components.
|
|
pub fn from_raw(call: Call, extra: Extra, additional_signed: Extra::AdditionalSigned) -> Self {
|
|
Self((call, extra, additional_signed))
|
|
}
|
|
|
|
/// Deconstruct the payload into it's components.
|
|
pub fn deconstruct(self) -> (Call, Extra, Extra::AdditionalSigned) {
|
|
self.0
|
|
}
|
|
}
|
|
|
|
impl<Call, Extra> Encode for SignedPayload<Call, Extra>
|
|
where
|
|
Call: Encode,
|
|
Extra: SignedExtension,
|
|
{
|
|
/// Get an encoded version of this payload.
|
|
///
|
|
/// Payloads longer than 256 bytes are going to be `blake2_256`-hashed.
|
|
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
|
|
self.0.using_encoded(|payload| {
|
|
if payload.len() > 256 {
|
|
f(&blake2_256(payload)[..])
|
|
} else {
|
|
f(payload)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<Call, Extra> EncodeLike for SignedPayload<Call, Extra>
|
|
where
|
|
Call: Encode,
|
|
Extra: SignedExtension,
|
|
{
|
|
}
|
|
|
|
impl<Address, Call, Signature, Extra> Decode for UncheckedExtrinsic<Address, Call, Signature, Extra>
|
|
where
|
|
Address: Decode,
|
|
Signature: Decode,
|
|
Call: Decode,
|
|
Extra: SignedExtension,
|
|
{
|
|
fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
|
|
// This is a little more complicated than usual since the binary format must be compatible
|
|
// with substrate's generic `Vec<u8>` type. Basically this just means accepting that there
|
|
// will be a prefix of vector length (we don't need
|
|
// to use this).
|
|
let _length_do_not_remove_me_see_above: Compact<u32> = Decode::decode(input)?;
|
|
|
|
let version = input.read_byte()?;
|
|
|
|
let is_signed = version & 0b1000_0000 != 0;
|
|
let version = version & 0b0111_1111;
|
|
if version != EXTRINSIC_VERSION {
|
|
return Err("Invalid transaction version".into())
|
|
}
|
|
|
|
Ok(Self {
|
|
signature: if is_signed { Some(Decode::decode(input)?) } else { None },
|
|
function: Decode::decode(input)?,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<Address, Call, Signature, Extra> Encode for UncheckedExtrinsic<Address, Call, Signature, Extra>
|
|
where
|
|
Address: Encode,
|
|
Signature: Encode,
|
|
Call: Encode,
|
|
Extra: SignedExtension,
|
|
{
|
|
fn encode(&self) -> Vec<u8> {
|
|
let mut tmp = Vec::with_capacity(sp_std::mem::size_of::<Self>());
|
|
|
|
// 1 byte version id.
|
|
match self.signature.as_ref() {
|
|
Some(s) => {
|
|
tmp.push(EXTRINSIC_VERSION | 0b1000_0000);
|
|
s.encode_to(&mut tmp);
|
|
},
|
|
None => {
|
|
tmp.push(EXTRINSIC_VERSION & 0b0111_1111);
|
|
},
|
|
}
|
|
self.function.encode_to(&mut tmp);
|
|
|
|
let compact_len = codec::Compact::<u32>(tmp.len() as u32);
|
|
|
|
// Allocate the output buffer with the correct length
|
|
let mut output = Vec::with_capacity(compact_len.size_hint() + tmp.len());
|
|
|
|
compact_len.encode_to(&mut output);
|
|
output.extend(tmp);
|
|
|
|
output
|
|
}
|
|
}
|
|
|
|
impl<Address, Call, Signature, Extra> EncodeLike
|
|
for UncheckedExtrinsic<Address, Call, Signature, Extra>
|
|
where
|
|
Address: Encode,
|
|
Signature: Encode,
|
|
Call: Encode,
|
|
Extra: SignedExtension,
|
|
{
|
|
}
|
|
|
|
#[cfg(feature = "std")]
|
|
impl<Address: Encode, Signature: Encode, Call: Encode, Extra: SignedExtension> serde::Serialize
|
|
for UncheckedExtrinsic<Address, Call, Signature, Extra>
|
|
{
|
|
fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: ::serde::Serializer,
|
|
{
|
|
self.using_encoded(|bytes| seq.serialize_bytes(bytes))
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "std")]
|
|
impl<'a, Address: Decode, Signature: Decode, Call: Decode, Extra: SignedExtension>
|
|
serde::Deserialize<'a> for UncheckedExtrinsic<Address, Call, Signature, Extra>
|
|
{
|
|
fn deserialize<D>(de: D) -> Result<Self, D::Error>
|
|
where
|
|
D: serde::Deserializer<'a>,
|
|
{
|
|
let r = sp_core::bytes::deserialize(de)?;
|
|
Decode::decode(&mut &r[..])
|
|
.map_err(|e| serde::de::Error::custom(format!("Decode error: {}", e)))
|
|
}
|
|
}
|
|
|
|
impl<Address, Call, Signature, Extra> fmt::Debug
|
|
for UncheckedExtrinsic<Address, Call, Signature, Extra>
|
|
where
|
|
Address: fmt::Debug,
|
|
Call: fmt::Debug,
|
|
Extra: SignedExtension,
|
|
{
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(
|
|
f,
|
|
"UncheckedExtrinsic({:?}, {:?})",
|
|
self.signature.as_ref().map(|x| (&x.0, &x.2)),
|
|
self.function,
|
|
)
|
|
}
|
|
}
|
|
|
|
impl<Address, Call, Signature, Extra> From<UncheckedExtrinsic<Address, Call, Signature, Extra>>
|
|
for OpaqueExtrinsic
|
|
where
|
|
Address: Encode,
|
|
Signature: Encode,
|
|
Call: Encode,
|
|
Extra: SignedExtension,
|
|
{
|
|
fn from(extrinsic: UncheckedExtrinsic<Address, Call, Signature, Extra>) -> Self {
|
|
Self::from_bytes(extrinsic.encode().as_slice()).expect(
|
|
"both OpaqueExtrinsic and UncheckedExtrinsic have encoding that is compatible with \
|
|
raw Vec<u8> encoding; qed",
|
|
)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::{
|
|
codec::{Decode, Encode},
|
|
testing::TestSignature as TestSig,
|
|
traits::{IdentityLookup, SignedExtension},
|
|
};
|
|
use sp_io::hashing::blake2_256;
|
|
|
|
type TestContext = IdentityLookup<u64>;
|
|
type TestAccountId = u64;
|
|
type TestCall = Vec<u8>;
|
|
|
|
const TEST_ACCOUNT: TestAccountId = 0;
|
|
|
|
// NOTE: this is demonstration. One can simply use `()` for testing.
|
|
#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, Ord, PartialOrd, TypeInfo)]
|
|
struct TestExtra;
|
|
impl SignedExtension for TestExtra {
|
|
const IDENTIFIER: &'static str = "TestExtra";
|
|
type AccountId = u64;
|
|
type Call = ();
|
|
type AdditionalSigned = ();
|
|
type Pre = ();
|
|
|
|
fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
type Ex = UncheckedExtrinsic<TestAccountId, TestCall, TestSig, TestExtra>;
|
|
type CEx = CheckedExtrinsic<TestAccountId, TestCall, TestExtra>;
|
|
|
|
#[test]
|
|
fn unsigned_codec_should_work() {
|
|
let ux = Ex::new_unsigned(vec![0u8; 0]);
|
|
let encoded = ux.encode();
|
|
assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux));
|
|
}
|
|
|
|
#[test]
|
|
fn signed_codec_should_work() {
|
|
let ux = Ex::new_signed(
|
|
vec![0u8; 0],
|
|
TEST_ACCOUNT,
|
|
TestSig(TEST_ACCOUNT, (vec![0u8; 0], TestExtra).encode()),
|
|
TestExtra,
|
|
);
|
|
let encoded = ux.encode();
|
|
assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux));
|
|
}
|
|
|
|
#[test]
|
|
fn large_signed_codec_should_work() {
|
|
let ux = Ex::new_signed(
|
|
vec![0u8; 0],
|
|
TEST_ACCOUNT,
|
|
TestSig(
|
|
TEST_ACCOUNT,
|
|
(vec![0u8; 257], TestExtra).using_encoded(blake2_256)[..].to_owned(),
|
|
),
|
|
TestExtra,
|
|
);
|
|
let encoded = ux.encode();
|
|
assert_eq!(Ex::decode(&mut &encoded[..]), Ok(ux));
|
|
}
|
|
|
|
#[test]
|
|
fn unsigned_check_should_work() {
|
|
let ux = Ex::new_unsigned(vec![0u8; 0]);
|
|
assert!(!ux.is_signed().unwrap_or(false));
|
|
assert!(<Ex as Checkable<TestContext>>::check(ux, &Default::default()).is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn badly_signed_check_should_fail() {
|
|
let ux = Ex::new_signed(
|
|
vec![0u8; 0],
|
|
TEST_ACCOUNT,
|
|
TestSig(TEST_ACCOUNT, vec![0u8; 0]),
|
|
TestExtra,
|
|
);
|
|
assert!(ux.is_signed().unwrap_or(false));
|
|
assert_eq!(
|
|
<Ex as Checkable<TestContext>>::check(ux, &Default::default()),
|
|
Err(InvalidTransaction::BadProof.into()),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn signed_check_should_work() {
|
|
let ux = Ex::new_signed(
|
|
vec![0u8; 0],
|
|
TEST_ACCOUNT,
|
|
TestSig(TEST_ACCOUNT, (vec![0u8; 0], TestExtra).encode()),
|
|
TestExtra,
|
|
);
|
|
assert!(ux.is_signed().unwrap_or(false));
|
|
assert_eq!(
|
|
<Ex as Checkable<TestContext>>::check(ux, &Default::default()),
|
|
Ok(CEx { signed: Some((TEST_ACCOUNT, TestExtra)), function: vec![0u8; 0] }),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn encoding_matches_vec() {
|
|
let ex = Ex::new_unsigned(vec![0u8; 0]);
|
|
let encoded = ex.encode();
|
|
let decoded = Ex::decode(&mut encoded.as_slice()).unwrap();
|
|
assert_eq!(decoded, ex);
|
|
let as_vec: Vec<u8> = Decode::decode(&mut encoded.as_slice()).unwrap();
|
|
assert_eq!(as_vec.encode(), encoded);
|
|
}
|
|
|
|
#[test]
|
|
fn conversion_to_opaque() {
|
|
let ux = Ex::new_unsigned(vec![0u8; 0]);
|
|
let encoded = ux.encode();
|
|
let opaque: OpaqueExtrinsic = ux.into();
|
|
let opaque_encoded = opaque.encode();
|
|
assert_eq!(opaque_encoded, encoded);
|
|
}
|
|
|
|
#[test]
|
|
fn large_bad_prefix_should_work() {
|
|
let encoded = Compact::<u32>::from(u32::MAX).encode();
|
|
assert_eq!(
|
|
Ex::decode(&mut &encoded[..]),
|
|
Err(Error::from("Not enough data to fill buffer"))
|
|
);
|
|
}
|
|
}
|