Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enforce UncheckedExtrinsicV4 for submit_extrinsic and add _opaque_extrinsic #421

Merged
merged 2 commits into from
Jan 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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