Skip to content

Commit

Permalink
Enforce UncheckedExtrinsicV4 for submit_extrinsic and add `_opaqu…
Browse files Browse the repository at this point in the history
…e_extrinsic` (#421)
  • Loading branch information
haerdib authored Jan 9, 2023
1 parent 7828a89 commit c1cad34
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 45 deletions.
2 changes: 1 addition & 1 deletion examples/examples/batch_payout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ async fn main() {
if payout_calls_len > 0 {
let batching = api.batch(payout_calls);
let results_hash = api
.submit_and_watch_extrinsic_until(batching.encode(), XtStatus::InBlock)
.submit_and_watch_extrinsic_until(batching, XtStatus::InBlock)
.unwrap()
.block_hash
.unwrap();
Expand Down
3 changes: 1 addition & 2 deletions examples/examples/benchmark_bulk_xt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
// run this against test node with
// > substrate-test-node --dev --execution native --ws-port 9979 -ltxpool=debug

use codec::Encode;
use kitchensink_runtime::{BalancesCall, Runtime, RuntimeCall};
use sp_keyring::AccountKeyring;
use substrate_api_client::{
Expand Down Expand Up @@ -53,7 +52,7 @@ async fn main() {
let xt = api.compose_extrinsic_offline(call, nonce);

println!("Sending extrinsic with nonce {}", nonce);
let _tx_hash = api.submit_extrinsic(xt.encode()).unwrap();
let _tx_hash = api.submit_extrinsic(xt).unwrap();

nonce += 1;
}
Expand Down
3 changes: 1 addition & 2 deletions examples/examples/compose_extrinsic_offline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
//! This example shows how to use the compose_extrinsic_offline macro which generates an extrinsic
//! without asking the node for nonce and does not need to know the metadata

use codec::Encode;
use kitchensink_runtime::{BalancesCall, Runtime, RuntimeCall};
use sp_keyring::AccountKeyring;
use sp_runtime::{generic::Era, MultiAddress};
Expand Down Expand Up @@ -65,7 +64,7 @@ async fn main() {

// Send and watch extrinsic until in block (online).
let block_hash = api
.submit_and_watch_extrinsic_until(xt.encode(), XtStatus::InBlock)
.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock)
.unwrap()
.block_hash
.unwrap();
Expand Down
6 changes: 3 additions & 3 deletions examples/examples/contract_instantiate_with_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

//! This example is community maintained and not CI tested, therefore it may not work as is.

use codec::{Decode, Encode};
use codec::Decode;
use kitchensink_runtime::Runtime;
use sp_keyring::AccountKeyring;
use substrate_api_client::{
Expand Down Expand Up @@ -70,7 +70,7 @@ async fn main() {

println!("[+] Creating a contract instance with extrinsic:\n\n{:?}\n", xt);
let block_hash = api
.submit_and_watch_extrinsic_until(xt.encode(), XtStatus::InBlock)
.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock)
.unwrap()
.block_hash
.unwrap();
Expand All @@ -85,6 +85,6 @@ async fn main() {
let xt = api.contract_call(args.contract.into(), 500_000, 500_000, vec![0u8]);

println!("[+] Calling the contract with extrinsic Extrinsic:\n{:?}\n\n", xt);
let report = api.submit_and_watch_extrinsic_until(xt.encode(), XtStatus::Finalized).unwrap();
let report = api.submit_and_watch_extrinsic_until(xt, XtStatus::Finalized).unwrap();
println!("[+] Extrinsic got finalized. Extrinsic Hash: {:?}", report.extrinsic_hash);
}
3 changes: 1 addition & 2 deletions examples/examples/custom_nonce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
//! This example shows how to use the compose_extrinsic_offline macro which generates an extrinsic
//! without asking the node for nonce and does not need to know the metadata

use codec::Encode;
use kitchensink_runtime::{BalancesCall, Runtime, RuntimeCall};
use sp_keyring::AccountKeyring;
use sp_runtime::{generic::Era, MultiAddress};
Expand Down Expand Up @@ -59,7 +58,7 @@ async fn main() {
println!("[+] Composed Extrinsic:\n {:?}\n", xt);

// Send and watch extrinsic until InBlock.
match api.submit_and_watch_extrinsic_until(xt.encode(), XtStatus::InBlock) {
match api.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock) {
Err(error) => {
println!("Retrieved error {:?}", error);
assert!(format!("{:?}", error).contains("Future"));
Expand Down
4 changes: 2 additions & 2 deletions examples/examples/event_error_details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

use codec::{Decode, Encode};
use codec::Decode;
use kitchensink_runtime::Runtime;
use sp_keyring::AccountKeyring;
use sp_runtime::{AccountId32 as AccountId, MultiAddress};
Expand Down Expand Up @@ -60,7 +60,7 @@ async fn main() {
println!("[+] Composed extrinsic: {:?}\n", xt);

// Send and watch extrinsic until Ready.
let _tx_hash = api.submit_and_watch_extrinsic_until(xt.encode(), XtStatus::Ready).unwrap();
let _tx_hash = api.submit_and_watch_extrinsic_until(xt, XtStatus::Ready).unwrap();
println!("[+] Transaction got included into the TxPool.");

// Subscribe to system events. We expect the transfer to fail as Alice wants to transfer all her balance.
Expand Down
3 changes: 1 addition & 2 deletions examples/examples/get_account_identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

//! Example to show how to get the account identity display name from the identity pallet.

use codec::Encode;
use frame_support::traits::Currency;
use kitchensink_runtime::Runtime as KitchensinkRuntime;
use pallet_identity::{Data, IdentityInfo, Registration};
Expand Down Expand Up @@ -65,7 +64,7 @@ async fn main() {

// Send and watch extrinsic until InBlock.
let _block_hash = api
.submit_and_watch_extrinsic_until(xt.encode(), XtStatus::InBlock)
.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock)
.unwrap()
.block_hash
.unwrap();
Expand Down
4 changes: 2 additions & 2 deletions examples/examples/sudo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
//! This example shows how to use the compose_extrinsic macro to create an extrinsic for any (custom)
//! module, whereas the desired module and call are supplied as a string.

use codec::{Compact, Encode};
use codec::Compact;
use kitchensink_runtime::Runtime;
use sp_keyring::AccountKeyring;
use substrate_api_client::{
Expand Down Expand Up @@ -56,7 +56,7 @@ async fn main() {

// Send and watch extrinsic until in block.
let block_hash = api
.submit_and_watch_extrinsic_until(xt.encode(), XtStatus::InBlock)
.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock)
.unwrap()
.block_hash
.unwrap();
Expand Down
3 changes: 1 addition & 2 deletions examples/examples/transfer_with_tungstenite_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

//! Very simple example that shows how to use a predefined extrinsic from the extrinsic module.

use codec::Encode;
use kitchensink_runtime::Runtime;
use sp_core::{
crypto::{Pair, Ss58Codec},
Expand Down Expand Up @@ -61,7 +60,7 @@ fn main() {

// Send and watch extrinsic until in block.
let block_hash = api
.submit_and_watch_extrinsic_until(xt.encode(), XtStatus::InBlock)
.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock)
.unwrap()
.block_hash
.unwrap();
Expand Down
3 changes: 1 addition & 2 deletions examples/examples/transfer_with_ws_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

//! Very simple example that shows how to use a predefined extrinsic from the extrinsic module.

use codec::Encode;
use kitchensink_runtime::Runtime;
use sp_core::{
crypto::{Pair, Ss58Codec},
Expand Down Expand Up @@ -59,7 +58,7 @@ fn main() {

// Send and watch extrinsic until in block.
let block_hash = api
.submit_and_watch_extrinsic_until(xt.encode(), XtStatus::InBlock)
.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock)
.unwrap()
.block_hash
.unwrap();
Expand Down
126 changes: 109 additions & 17 deletions src/api/rpc_api/author.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{
api::{Error, Result},
rpc::{HandleSubscription, Request, Subscribe},
utils, Api, Events, ExtrinsicReport, FromHexString, GetBlock, GetStorage, Phase, ToHexString,
TransactionStatus, XtStatus,
TransactionStatus, UncheckedExtrinsicV4, XtStatus,
};
use ac_compose_macros::rpc_params;
use ac_node_api::EventDetails;
Expand All @@ -35,9 +35,19 @@ pub type TransactionSubscriptionFor<Client, Hash> =
pub trait SubmitExtrinsic {
type Hash;

/// Submit an extrsinic to the substrate node, without watching.
/// Retruns the extrinsic hash.
fn submit_extrinsic(&self, encoded_extrinsic: Vec<u8>) -> Result<Self::Hash>;
/// Submit an encodable extrinsic to the substrate node.
/// Returns the extrinsic hash.
fn submit_extrinsic<Call, SignedExtra>(
&self,
extrinsic: UncheckedExtrinsicV4<Call, SignedExtra>,
) -> Result<Self::Hash>
where
Call: Encode,
SignedExtra: Encode;

/// Submit an encoded, opaque extrsinic to the substrate node.
/// Returns the extrinsic hash.
fn submit_opaque_extrinsic(&self, encoded_extrinsic: Vec<u8>) -> Result<Self::Hash>;
}

impl<Signer, Client, Params, Runtime> SubmitExtrinsic for Api<Signer, Client, Params, Runtime>
Expand All @@ -48,7 +58,18 @@ where
{
type Hash = Runtime::Hash;

fn submit_extrinsic(&self, encoded_extrinsic: Vec<u8>) -> Result<Self::Hash> {
fn submit_extrinsic<Call, SignedExtra>(
&self,
extrinsic: UncheckedExtrinsicV4<Call, SignedExtra>,
) -> Result<Self::Hash>
where
Call: Encode,
SignedExtra: Encode,
{
self.submit_opaque_extrinsic(extrinsic.encode())
}

fn submit_opaque_extrinsic(&self, encoded_extrinsic: Vec<u8>) -> Result<Self::Hash> {
let hex_encoded_xt = encoded_extrinsic.to_hex();
debug!("sending extrinsic: {:?}", hex_encoded_xt);
let xt_hash =
Expand All @@ -62,17 +83,39 @@ where
Client: Subscribe,
Hash: DeserializeOwned,
{
/// Submit an extrinsic an return a websocket Subscription to watch the
/// extrinsic progress.
fn submit_and_watch_extrinsic(
/// Submit an extrinsic an return a websocket Subscription
/// to watch the extrinsic progress.
fn submit_and_watch_extrinsic<Call, SignedExtra>(
&self,
extrinsic: UncheckedExtrinsicV4<Call, SignedExtra>,
) -> Result<TransactionSubscriptionFor<Client, Hash>>
where
Call: Encode,
SignedExtra: Encode;

/// Submit an encoded, opaque extrinsic an return a websocket Subscription to
/// watch the extrinsic progress.
fn submit_and_watch_opaque_extrinsic(
&self,
encoded_extrinsic: Vec<u8>,
) -> Result<TransactionSubscriptionFor<Client, Hash>>;

/// Submit an extrinsic and watch in until the desired status is reached,
/// if no error is encountered previously.
/// Submit an extrinsic and watch in until the desired status
/// is reached, if no error is encountered previously.
// This method is blocking.
fn submit_and_watch_extrinsic_until(
fn submit_and_watch_extrinsic_until<Call, SignedExtra>(
&self,
extrinsic: UncheckedExtrinsicV4<Call, SignedExtra>,
watch_until: XtStatus,
) -> Result<ExtrinsicReport<Hash>>
where
Call: Encode,
SignedExtra: Encode;

/// Submit an encoded, opaque extrinsic and watch in until the desired status
/// is reached, if no error is encountered previously.
// This method is blocking.
fn submit_and_watch_opaque_extrinsic_until(
&self,
encoded_extrinsic: Vec<u8>,
watch_until: XtStatus,
Expand All @@ -89,7 +132,21 @@ where
/// - wait_for_finalized = true => Finalized
/// and check if the extrinsic has been successful or not.
// This method is blocking.
fn submit_and_watch_extrinsic_until_success(
fn submit_and_watch_extrinsic_until_success<Call, SignedExtra>(
&self,
extrinsic: UncheckedExtrinsicV4<Call, SignedExtra>,
wait_for_finalized: bool,
) -> Result<ExtrinsicReport<Hash>>
where
Call: Encode,
SignedExtra: Encode;

/// Submit an encoded, opaque extrinsic and watch it until
/// - wait_for_finalized = false => InBlock
/// - wait_for_finalized = true => Finalized
/// and check if the extrinsic has been successful or not.
// This method is blocking.
fn submit_and_watch_opaque_extrinsic_until_success(
&self,
encoded_extrinsic: Vec<u8>,
wait_for_finalized: bool,
Expand All @@ -105,7 +162,17 @@ where
Runtime::Hashing: HashTrait<Output = Runtime::Hash>,
Runtime::Hash: FromHexString,
{
fn submit_and_watch_extrinsic(
fn submit_and_watch_extrinsic<Call, SignedExtra>(
&self,
extrinsic: UncheckedExtrinsicV4<Call, SignedExtra>,
) -> Result<TransactionSubscriptionFor<Client, Runtime::Hash>>
where
Call: Encode,
SignedExtra: Encode,
{
self.submit_and_watch_opaque_extrinsic(extrinsic.encode())
}
fn submit_and_watch_opaque_extrinsic(
&self,
encoded_extrinsic: Vec<u8>,
) -> Result<TransactionSubscriptionFor<Client, Runtime::Hash>> {
Expand All @@ -118,14 +185,26 @@ where
.map_err(|e| e.into())
}

fn submit_and_watch_extrinsic_until(
fn submit_and_watch_extrinsic_until<Call, SignedExtra>(
&self,
extrinsic: UncheckedExtrinsicV4<Call, SignedExtra>,
watch_until: XtStatus,
) -> Result<ExtrinsicReport<Runtime::Hash>>
where
Call: Encode,
SignedExtra: Encode,
{
self.submit_and_watch_opaque_extrinsic_until(extrinsic.encode(), watch_until)
}

fn submit_and_watch_opaque_extrinsic_until(
&self,
encoded_extrinsic: Vec<u8>,
watch_until: XtStatus,
) -> Result<ExtrinsicReport<Runtime::Hash>> {
let tx_hash = Runtime::Hashing::hash_of(&encoded_extrinsic);
let mut subscription: TransactionSubscriptionFor<Client, Runtime::Hash> =
self.submit_and_watch_extrinsic(encoded_extrinsic)?;
self.submit_and_watch_opaque_extrinsic(encoded_extrinsic)?;

while let Some(transaction_status) = subscription.next() {
let transaction_status = transaction_status?;
Expand Down Expand Up @@ -164,7 +243,19 @@ where
Runtime::Hashing: HashTrait<Output = Runtime::Hash>,
Runtime::Hash: FromHexString,
{
fn submit_and_watch_extrinsic_until_success(
fn submit_and_watch_extrinsic_until_success<Call, SignedExtra>(
&self,
extrinsic: UncheckedExtrinsicV4<Call, SignedExtra>,
wait_for_finalized: bool,
) -> Result<ExtrinsicReport<Runtime::Hash>>
where
Call: Encode,
SignedExtra: Encode,
{
self.submit_and_watch_opaque_extrinsic_until_success(extrinsic.encode(), wait_for_finalized)
}

fn submit_and_watch_opaque_extrinsic_until_success(
&self,
encoded_extrinsic: Vec<u8>,
wait_for_finalized: bool,
Expand All @@ -173,7 +264,8 @@ where
true => XtStatus::Finalized,
false => XtStatus::InBlock,
};
let mut report = self.submit_and_watch_extrinsic_until(encoded_extrinsic, xt_status)?;
let mut report =
self.submit_and_watch_opaque_extrinsic_until(encoded_extrinsic, xt_status)?;

let block_hash = report.block_hash.ok_or(Error::NoBlockHash)?;
let extrinsic_index =
Expand Down
Loading

0 comments on commit c1cad34

Please sign in to comment.