From e83aee9f797c114e0c6fc7bed9c67f2f74cd2962 Mon Sep 17 00:00:00 2001
From: Thomas Niederberger <781000+Niederb@users.noreply.github.com>
Date: Tue, 5 Dec 2023 09:12:01 +0100
Subject: [PATCH 1/2] Create no_std example for extrinsic creation (#556)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Start version of example

* Start moving code from Api into example

* Move more code into example

* Make some progress with types

* Cleanup

* Cleanup

* Documentation

* Some cleanup

* Make it compile again

* Use compose_call

* Create call differently

* Switch to using AssetTip

* Cleanup

* Cleanup

* Merge compose_extrinsic_offline into compose_extrinsic_no_std

* Incorporate review feedback

* Cleanup of merging of the two examples (compose_extrinsic_offline.rs and compose_extrinsic_no_std.rs)

* Just run both approaches to create an extrinsic

* Remove duplicated example

* Have only extrinsic related code in the construction blocks

* Apply suggestions from code review

Co-authored-by: Bigna Härdi <bigna.h@hotmail.com>

* Move code below comment

---------

Co-authored-by: Bigna Härdi <bigna.h@hotmail.com>
---
 .github/workflows/ci.yml                      |   2 +-
 README.md                                     |   2 +-
 examples/examples/compose_extrinsic.rs        | 145 ++++++++++++++++++
 .../examples/compose_extrinsic_offline.rs     |  76 ---------
 primitives/src/extrinsics/extrinsic_params.rs |   2 +-
 5 files changed, 148 insertions(+), 79 deletions(-)
 create mode 100644 examples/examples/compose_extrinsic.rs
 delete mode 100644 examples/examples/compose_extrinsic_offline.rs

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a654e219f..393c6a9ff 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -143,7 +143,7 @@ jobs:
         os: [ ubuntu-latest ]
         example: [
           benchmark_bulk_xt,
-          compose_extrinsic_offline,
+          compose_extrinsic,
           custom_nonce,
           check_extrinsic_events,
           get_account_identity,
diff --git a/README.md b/README.md
index 8223f1169..cdc777eb4 100644
--- a/README.md
+++ b/README.md
@@ -52,7 +52,7 @@ The following examples can be found in the [examples](/examples/examples) folder
 
 * [benchmark_bulk_xt](/examples/examples/benchmark_bulk_xt.rs): Float the node with a series of transactions.
 * [check_extrinsic_events](/examples/examples/check_extrinsic_events.rs): Check and react according to events associated to an extrinsic.
-* [compose_extrinsic_offline](/examples/examples/compose_extrinsic_offline.rs): Compose an extrinsic without interacting with the node.
+* [compose_extrinsic](/examples/examples/compose_extrinsic.rs): Compose an extrinsic without interacting with the node or in no_std mode.
 * [contract_instantiate_with_code](/examples/examples/contract_instantiate_with_code.rs): Instantiate a contract on the chain.
 * [custom_nonce](/examples/examples/custom_nonce.rs): Compose an with a custom nonce.
 * [get_account_identity](/examples/examples/get_account_identity.rs): Create an custom Unchecked Extrinsic to set an account identity and retrieve it afterwards with a getter.
diff --git a/examples/examples/compose_extrinsic.rs b/examples/examples/compose_extrinsic.rs
new file mode 100644
index 000000000..f178bb3e0
--- /dev/null
+++ b/examples/examples/compose_extrinsic.rs
@@ -0,0 +1,145 @@
+/*
+	Copyright 2019 Supercomputing Systems AG
+	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.
+*/
+
+//! This example shows two special ways to create an extrinsic:
+//! - Compose an extrinsic in a no_std environment that works without having acces to an `Api` instance
+//! - Compose an extrinsic without asking the node for nonce and without knowing the metadata
+
+use codec::Compact;
+use kitchensink_runtime::{BalancesCall, RuntimeCall};
+use sp_keyring::AccountKeyring;
+use sp_runtime::{generic::Era, MultiAddress};
+use substrate_api_client::{
+	ac_compose_macros::{compose_call, compose_extrinsic_offline},
+	ac_primitives::{
+		config::Config, AssetRuntimeConfig, AssetTip, ExtrinsicParams, ExtrinsicSigner,
+		GenericAdditionalParams, SignExtrinsic,
+	},
+	rpc::JsonrpseeClient,
+	Api, GetChainInfo, SubmitAndWatch, XtStatus,
+};
+
+type AssetExtrinsicSigner = <AssetRuntimeConfig as Config>::ExtrinsicSigner;
+type AccountId = <AssetRuntimeConfig as Config>::AccountId;
+type ExtrinsicAddressOf<Signer> = <Signer as SignExtrinsic<AccountId>>::ExtrinsicAddress;
+
+type Hash = <AssetRuntimeConfig as Config>::Hash;
+/// Get the balance type from your node runtime and adapt it if necessary.
+type Balance = <AssetRuntimeConfig as Config>::Balance;
+/// We need AssetTip here, because the kitchensink runtime uses the asset pallet. Change to PlainTip if your node uses the balance pallet only.
+type AdditionalParams = GenericAdditionalParams<AssetTip<Balance>, Hash>;
+
+type Address = <AssetRuntimeConfig as Config>::Address;
+
+// To test this example with CI we run it against the Substrate kitchensink node, which uses the asset pallet.
+// Therefore, we need to use the `AssetRuntimeConfig` in this example.
+// ! However, most Substrate runtimes do not use the asset pallet at all. So if you run an example against your own node
+// you most likely should use `DefaultRuntimeConfig` instead.
+
+#[tokio::main]
+async fn main() {
+	env_logger::init();
+
+	// Initialize api and set the signer (sender) that is used to sign the extrinsics.
+	let signer = AccountKeyring::Alice.pair();
+	let client = JsonrpseeClient::with_default_url().unwrap();
+
+	let mut api = Api::<AssetRuntimeConfig, _>::new(client).unwrap();
+	let extrinsic_signer = ExtrinsicSigner::<AssetRuntimeConfig>::new(signer);
+	// Signer is needed to set the nonce and sign the extrinsic.
+	api.set_signer(extrinsic_signer.clone());
+
+	let recipient: Address = MultiAddress::Id(AccountKeyring::Bob.to_account_id());
+
+	// Get the last finalized header to retrieve information for Era for mortal transactions (online).
+	let last_finalized_header_hash = api.get_finalized_head().unwrap().unwrap();
+	let header = api.get_header(Some(last_finalized_header_hash)).unwrap().unwrap();
+	let period = 5;
+
+	// Construct extrinsic params needed for the extrinsic construction. For more information on what these parameters mean, take a look at Substrate docs: https://docs.substrate.io/reference/transaction-format/.
+	let additional_extrinsic_params: AdditionalParams = GenericAdditionalParams::new()
+		.era(Era::mortal(period, header.number.into()), last_finalized_header_hash)
+		.tip(0);
+
+	println!("Compose extrinsic in no_std environment (No Api instance)");
+	// Get information out of Api (online). This information could also be set offline in the `no_std`,
+	// but that would need to be static and adapted whenever the node changes.
+	// You can get the information directly from the node runtime file or the api of https://polkadot.js.org.
+	let spec_version = api.runtime_version().spec_version;
+	let transaction_version = api.runtime_version().transaction_version;
+	let genesis_hash = api.genesis_hash();
+	let metadata = api.metadata();
+	let signer_nonce = api.get_nonce().unwrap();
+	println!("[+] Alice's Account Nonce is {}", signer_nonce);
+
+	let recipients_extrinsic_address: ExtrinsicAddressOf<AssetExtrinsicSigner> =
+		recipient.clone().into();
+
+	// Construct an extrinsic using only functionality available in no_std
+	let xt = {
+		let extrinsic_params = <AssetRuntimeConfig as Config>::ExtrinsicParams::new(
+			spec_version,
+			transaction_version,
+			signer_nonce,
+			genesis_hash,
+			additional_extrinsic_params,
+		);
+
+		let call = compose_call!(
+			metadata,
+			"Balances",
+			"transfer_allow_death",
+			recipients_extrinsic_address,
+			Compact(4u32)
+		);
+		compose_extrinsic_offline!(extrinsic_signer, call, extrinsic_params)
+	};
+
+	println!("[+] Composed Extrinsic:\n {:?}", xt);
+	// To send the extrinsic to the node, we need an rpc client which is only available within std-environment. If you want to operate a rpc client in your own no-std environment, take a look at https://github.com/scs/substrate-api-client#rpc-client on how to implement one yourself.
+	let hash = api
+		.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock)
+		.unwrap()
+		.block_hash
+		.unwrap();
+	println!("[+] Extrinsic got included in block {:?}", hash);
+
+	println!();
+
+	println!("Compose extrinsic offline");
+	let signer_nonce = api.get_nonce().unwrap();
+	println!("[+] Alice's Account Nonce is {}", signer_nonce);
+
+	// Construct an extrinsic offline (without any calls to the node) with the help of the api client. For example, this allows you to set your own nonce (to achieve future calls or construct an extrsinic that must be sent at a later time).
+	let xt = {
+		// Set the additional params.
+		api.set_additional_params(additional_extrinsic_params);
+
+		// Compose the extrinsic (offline).
+		let call = RuntimeCall::Balances(BalancesCall::transfer_allow_death {
+			dest: recipient,
+			value: 42,
+		});
+		api.compose_extrinsic_offline(call, signer_nonce)
+	};
+
+	println!("[+] Composed Extrinsic:\n {:?}", xt);
+	let hash = api
+		.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock)
+		.unwrap()
+		.block_hash
+		.unwrap();
+	println!("[+] Extrinsic got included in block {:?}", hash);
+}
diff --git a/examples/examples/compose_extrinsic_offline.rs b/examples/examples/compose_extrinsic_offline.rs
deleted file mode 100644
index a69f3e795..000000000
--- a/examples/examples/compose_extrinsic_offline.rs
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-	Copyright 2019 Supercomputing Systems AG
-	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.
-*/
-
-//! 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 kitchensink_runtime::{BalancesCall, RuntimeCall};
-use sp_keyring::AccountKeyring;
-use sp_runtime::{generic::Era, MultiAddress};
-use substrate_api_client::{
-	ac_primitives::{AssetRuntimeConfig, ExtrinsicSigner, GenericAdditionalParams},
-	rpc::JsonrpseeClient,
-	Api, GetChainInfo, SubmitAndWatch, XtStatus,
-};
-
-// To test this example with CI we run it against the Substrate kitchensink node, which uses the asset pallet.
-// Therefore, we need to use the `AssetRuntimeConfig` in this example.
-// ! However, most Substrate runtimes do not use the asset pallet at all. So if you run an example against your own node
-// you most likely should use `DefaultRuntimeConfig` instead.
-
-#[tokio::main]
-async fn main() {
-	env_logger::init();
-
-	// Initialize api and set the signer (sender) that is used to sign the extrinsics.
-	let signer = AccountKeyring::Alice.pair();
-	let client = JsonrpseeClient::with_default_url().unwrap();
-	// Api::new(..) is not actually an offline call, but retrieves metadata and other information from the node.
-	// If this is not acceptable, use the Api::new_offline(..) function instead. There are no examples for this,
-	// because of the constantly changing substrate node. But check out our unit tests - there are Apis created with `new_offline`.
-	let mut api = Api::<AssetRuntimeConfig, _>::new(client).unwrap();
-	api.set_signer(ExtrinsicSigner::<AssetRuntimeConfig>::new(signer));
-
-	// Information for Era for mortal transactions (online).
-	let last_finalized_header_hash = api.get_finalized_head().unwrap().unwrap();
-	let header = api.get_header(Some(last_finalized_header_hash)).unwrap().unwrap();
-	let period = 5;
-	let tx_params = GenericAdditionalParams::new()
-		.era(Era::mortal(period, header.number.into()), last_finalized_header_hash)
-		.tip(0);
-
-	// Set the additional params.
-	api.set_additional_params(tx_params);
-
-	// Get the nonce of the signer account (online).
-	let signer_nonce = api.get_nonce().unwrap();
-	println!("[+] Alice's Account Nonce is {}\n", signer_nonce);
-
-	// Compose the extrinsic (offline).
-	let recipient = MultiAddress::Id(AccountKeyring::Bob.to_account_id());
-	let call =
-		RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: recipient, value: 42 });
-	let xt = api.compose_extrinsic_offline(call, signer_nonce);
-
-	println!("[+] Composed Extrinsic:\n {:?}\n", xt);
-
-	// Send and watch extrinsic until in block (online).
-	let block_hash = api
-		.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock)
-		.unwrap()
-		.block_hash
-		.unwrap();
-	println!("[+] Extrinsic got included in block {:?}", block_hash);
-}
diff --git a/primitives/src/extrinsics/extrinsic_params.rs b/primitives/src/extrinsics/extrinsic_params.rs
index 29a3a92eb..072035d0d 100644
--- a/primitives/src/extrinsics/extrinsic_params.rs
+++ b/primitives/src/extrinsics/extrinsic_params.rs
@@ -48,7 +48,7 @@ impl<Tip, Index> GenericSignedExtra<Tip, Index> {
 
 /// Default AdditionalSigned fields of a Polkadot/Substrate node.
 /// Order: (CheckNonZeroSender, CheckSpecVersion, CheckTxVersion, CheckGenesis, Check::Era, CheckNonce, CheckWeight, transactionPayment::ChargeTransactionPayment).
-// The order and types can must match the one defined in the runtime.
+// The order and types must match the one defined in the runtime.
 // Example: https://github.com/paritytech/substrate/blob/cbd8f1b56fd8ab9af0d9317432cc735264c89d70/bin/node/runtime/src/lib.rs#L1779-L1788
 // The `AdditionalSigned` is the tuple returned from the call SignedExtra::additional_signed().
 // Each member defined in the `SignedExtra` on the node side implements the trait `SignedExtension`, which

From fb108a7d1994705bbca50233e3bc66cec3726523 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 5 Dec 2023 09:13:03 +0100
Subject: [PATCH 2/2] Bump openssl from 0.10.57 to 0.10.60 (#681)

Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.57 to 0.10.60.
- [Release notes](https://github.com/sfackler/rust-openssl/releases)
- [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.57...openssl-v0.10.60)

---
updated-dependencies:
- dependency-name: openssl
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 Cargo.lock | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index b91eb53fa..159393931 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3160,9 +3160,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
 
 [[package]]
 name = "openssl"
-version = "0.10.57"
+version = "0.10.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c"
+checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800"
 dependencies = [
  "bitflags 2.4.1",
  "cfg-if 1.0.0",
@@ -3192,9 +3192,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.93"
+version = "0.9.96"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d"
+checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f"
 dependencies = [
  "cc",
  "libc",
@@ -6785,7 +6785,7 @@ version = "1.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if 0.1.10",
  "digest 0.10.7",
  "rand 0.8.5",
  "static_assertions",