mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-22 16:08:00 +00:00
b6b9ac65c7
* TransactionExtensions basic support for V5 VerifySignature and renames * WIP: subxt-core v5 transaction support * Subxt to support V5 extrinsics * WIP tests failing with wsm trap error * Actually encode mortality to fix tx encode issue * fmt * rename to sign_with_account_and_signature * Add explicit methods for v4 and v5 ext construction * clippy * fix wasm example and no mut self where not needed * fix doc example * another doc fix * Add tests for tx encoding and fix v5 encode issue * add copyright and todo * refactor APIs to have clear v4/v5 split in core and slightly nicer split in subxt proper * rename Partial/SubmittableExtrinsic to *Transaction * Remove SignerT::address since it's not needed * doc fixes * fmt * doc fixes * Fix comment number * Clarify panic behaviour of inject_signature * fmt
150 lines
4.6 KiB
Rust
150 lines
4.6 KiB
Rust
// Copyright 2019-2025 Parity Technologies (UK) Ltd.
|
|
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
|
// see LICENSE for license details.
|
|
|
|
use crate::utils::node_runtime;
|
|
use crate::{subxt_test, test_context};
|
|
use core::ops::Deref;
|
|
use frame_decode::extrinsics::ExtrinsicType;
|
|
use subxt_signer::sr25519::dev;
|
|
|
|
// TODO: When VerifySignature exists on the substrate kitchensink runtime,
|
|
// let's try actuallty submitting v4 and v5 signed extrinsics to verify that
|
|
// they are actually accepted by the node.
|
|
|
|
#[subxt_test]
|
|
async fn v4_unsigned_encode_decode() -> Result<(), subxt::Error> {
|
|
let ctx = test_context().await;
|
|
let api = ctx.client();
|
|
let md = api.metadata();
|
|
|
|
let call = node_runtime::tx()
|
|
.balances()
|
|
.transfer_allow_death(dev::bob().public_key().into(), 1000);
|
|
|
|
let tx_bytes = api.tx().create_v4_unsigned(&call).unwrap().into_encoded();
|
|
let tx_bytes_cursor = &mut &*tx_bytes;
|
|
|
|
let decoded = frame_decode::extrinsics::decode_extrinsic(
|
|
tx_bytes_cursor,
|
|
md.deref(),
|
|
api.metadata().types(),
|
|
)
|
|
.unwrap();
|
|
|
|
assert_eq!(tx_bytes_cursor.len(), 0);
|
|
assert_eq!(decoded.version(), 4);
|
|
assert_eq!(decoded.ty(), ExtrinsicType::Bare);
|
|
assert_eq!(decoded.pallet_name(), "Balances");
|
|
assert_eq!(decoded.call_name(), "transfer_allow_death");
|
|
assert!(decoded.signature_payload().is_none());
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[subxt_test]
|
|
async fn v5_bare_encode_decode() -> Result<(), subxt::Error> {
|
|
let ctx = test_context().await;
|
|
let api = ctx.client();
|
|
let md = api.metadata();
|
|
|
|
let call = node_runtime::tx()
|
|
.balances()
|
|
.transfer_allow_death(dev::bob().public_key().into(), 1000);
|
|
|
|
let tx_bytes = api.tx().create_v5_bare(&call).unwrap().into_encoded();
|
|
let tx_bytes_cursor = &mut &*tx_bytes;
|
|
|
|
let decoded = frame_decode::extrinsics::decode_extrinsic(
|
|
tx_bytes_cursor,
|
|
md.deref(),
|
|
api.metadata().types(),
|
|
)
|
|
.unwrap();
|
|
|
|
assert_eq!(tx_bytes_cursor.len(), 0);
|
|
assert_eq!(decoded.version(), 5);
|
|
assert_eq!(decoded.ty(), ExtrinsicType::Bare);
|
|
assert_eq!(decoded.pallet_name(), "Balances");
|
|
assert_eq!(decoded.call_name(), "transfer_allow_death");
|
|
assert!(decoded.transaction_extension_payload().is_none());
|
|
assert!(decoded.signature_payload().is_none());
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[subxt_test]
|
|
async fn v4_signed_encode_decode() -> Result<(), subxt::Error> {
|
|
let ctx = test_context().await;
|
|
let api = ctx.client();
|
|
let md = api.metadata();
|
|
|
|
let call = node_runtime::tx()
|
|
.balances()
|
|
.transfer_allow_death(dev::bob().public_key().into(), 1000);
|
|
|
|
let tx_bytes = api
|
|
.tx()
|
|
.create_v4_partial(&call, &dev::alice().public_key().into(), Default::default())
|
|
.await
|
|
.unwrap()
|
|
.sign(&dev::alice())
|
|
.into_encoded();
|
|
let tx_bytes_cursor = &mut &*tx_bytes;
|
|
|
|
let decoded = frame_decode::extrinsics::decode_extrinsic(
|
|
tx_bytes_cursor,
|
|
md.deref(),
|
|
api.metadata().types(),
|
|
)
|
|
.unwrap();
|
|
|
|
assert_eq!(tx_bytes_cursor.len(), 0);
|
|
assert_eq!(decoded.version(), 4);
|
|
assert_eq!(decoded.ty(), ExtrinsicType::Signed);
|
|
assert_eq!(decoded.pallet_name(), "Balances");
|
|
assert_eq!(decoded.call_name(), "transfer_allow_death");
|
|
assert!(decoded.signature_payload().is_some());
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[subxt_test]
|
|
async fn v5_general_encode_decode() -> Result<(), subxt::Error> {
|
|
let ctx = test_context().await;
|
|
let api = ctx.client();
|
|
let md = api.metadata();
|
|
let dummy_signer = dev::alice();
|
|
|
|
let call = node_runtime::tx()
|
|
.balances()
|
|
.transfer_allow_death(dev::bob().public_key().into(), 1000);
|
|
|
|
let tx_bytes = api
|
|
.tx()
|
|
.create_v5_partial(&call, &dev::alice().public_key().into(), Default::default())
|
|
.await
|
|
.unwrap()
|
|
.sign(&dummy_signer) // No signature payload is added, but may be inserted into tx extensions.
|
|
.into_encoded();
|
|
let tx_bytes_cursor = &mut &*tx_bytes;
|
|
|
|
let decoded = frame_decode::extrinsics::decode_extrinsic(
|
|
tx_bytes_cursor,
|
|
md.deref(),
|
|
api.metadata().types(),
|
|
)
|
|
.unwrap();
|
|
|
|
assert_eq!(tx_bytes_cursor.len(), 0);
|
|
assert_eq!(decoded.version(), 5);
|
|
assert_eq!(decoded.ty(), ExtrinsicType::General);
|
|
assert_eq!(decoded.pallet_name(), "Balances");
|
|
assert_eq!(decoded.call_name(), "transfer_allow_death");
|
|
assert!(decoded.transaction_extension_payload().is_some());
|
|
// v5 general extrinsics have no signature payload; signature in tx extensions:
|
|
assert!(decoded.signature_payload().is_none());
|
|
|
|
Ok(())
|
|
}
|