Skip to content

Commit

Permalink
Introduce OpaqueBundle and integrate tx pool in bundle production (#206)
Browse files Browse the repository at this point in the history
* Introduce OpaqueBundle and integrate tx pool in bundle production

`OpaqueBundle` with opaque extrinsics will be used on primary chain
as the primary chain does not care about the extrinsic format, it can be
evolved as `CompactBundle` or something like that in the future.

This PR also starts an initial transaction pool integration in bundle
production, not the final version, but should be a step towards it.

Co-authored-by: Nazar Mokrynskyi <nazar@mokrynskyi.com>
  • Loading branch information
liuchengxu and nazar-pc committed Dec 18, 2021
1 parent 74c6f0e commit c463b53
Show file tree
Hide file tree
Showing 21 changed files with 214 additions and 82 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/rust.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ jobs:
uses: actions-rs/toolchain@v1
# TODO: Below can be removed when https://github.com/actions-rs/toolchain/issues/126 is resolved
with:
toolchain: nightly
# TODO: roll back to nightly on new wasmtime release, ref https://github.com/bytecodealliance/rustix/issues/142
toolchain: nightly-2021-12-14
target: wasm32-unknown-unknown
override: true
components: rustfmt, clippy
Expand Down Expand Up @@ -110,7 +111,8 @@ jobs:
uses: actions-rs/toolchain@v1
# TODO: Below can be removed when https://github.com/actions-rs/toolchain/issues/126 is resolved
with:
toolchain: nightly
# TODO: roll back to nightly on new wasmtime release, ref https://github.com/bytecodealliance/rustix/issues/142
toolchain: nightly-2021-12-14
target: wasm32-unknown-unknown
override: true
components: rustfmt, clippy
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/rustdoc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ jobs:
- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
# TODO: roll back to nightly on new wasmtime release, ref https://github.com/bytecodealliance/rustix/issues/142
toolchain: nightly-2021-12-14
target: wasm32-unknown-unknown
profile: minimal
override: true
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/snapshot-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ jobs:
uses: actions-rs/toolchain@v1
# TODO: Below can be removed when https://github.com/actions-rs/toolchain/issues/126 is resolved
with:
toolchain: nightly
# TODO: roll back to nightly on new wasmtime release, ref https://github.com/bytecodealliance/rustix/issues/142
toolchain: nightly-2021-12-14
target: wasm32-unknown-unknown
override: true

Expand Down
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Dockerfile-farmer
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
FROM ubuntu:20.04

# TODO: roll back to nightly on new wasmtime release, ref https://github.com/bytecodealliance/rustix/issues/142
ARG RUSTC_VERSION=nightly-2021-12-14

WORKDIR /code

RUN \
Expand All @@ -10,7 +13,7 @@ RUN \
git \
llvm \
clang && \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain nightly
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain $RUSTC_VERSION

RUN /root/.cargo/bin/rustup target add wasm32-unknown-unknown

Expand Down
5 changes: 4 additions & 1 deletion Dockerfile-node
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
FROM ubuntu:20.04

# TODO: roll back to nightly on new wasmtime release, ref https://github.com/bytecodealliance/rustix/issues/142
ARG RUSTC_VERSION=nightly-2021-12-14

WORKDIR /code

RUN \
Expand All @@ -10,7 +13,7 @@ RUN \
git \
llvm \
clang && \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain nightly
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain $RUSTC_VERSION

RUN /root/.cargo/bin/rustup target add wasm32-unknown-unknown

Expand Down
12 changes: 6 additions & 6 deletions crates/cirrus-node-primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use serde::{Deserialize, Serialize};
use sp_application_crypto::KeyTypeId;
use sp_consensus_slots::Slot;
use sp_core::bytes;
use sp_executor::{Bundle, ExecutionReceipt};
use sp_executor::{ExecutionReceipt, OpaqueBundle};
use sp_runtime::traits::Hash as HashT;
use std::pin::Pin;
use subspace_core_primitives::Tag;
Expand Down Expand Up @@ -83,13 +83,13 @@ pub struct CollationResult {

/// Result of the [`BundlerFn`] invocation.
pub struct BundleResult {
/// The bundle that was built.
pub bundle: Bundle,
/// The opaque bundle that was built.
pub opaque_bundle: OpaqueBundle,
}

impl BundleResult {
pub fn to_bundle(self) -> Bundle {
self.bundle
pub fn to_opaque_bundle(self) -> OpaqueBundle {
self.opaque_bundle
}
}

Expand Down Expand Up @@ -163,7 +163,7 @@ pub type BundlerFn = Box<
///
/// Returns an optional [`ProcessorResult`].
pub type ProcessorFn = Box<
dyn Fn(Hash, Vec<Bundle>) -> Pin<Box<dyn Future<Output = Option<ProcessorResult>> + Send>>
dyn Fn(Hash, Vec<OpaqueBundle>) -> Pin<Box<dyn Future<Output = Option<ProcessorResult>> + Send>>
+ Send
+ Sync,
>;
Expand Down
21 changes: 12 additions & 9 deletions crates/pallet-executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

use frame_system::offchain::SubmitTransaction;
pub use pallet::*;
use sp_executor::{Bundle, ExecutionReceipt, FraudProof};
use sp_executor::{ExecutionReceipt, FraudProof, OpaqueBundle};

// TODO: proper error value
const INVALID_FRAUD_PROOF: u8 = 100;
Expand All @@ -30,7 +30,7 @@ mod pallet {
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use sp_core::H256;
use sp_executor::{Bundle, ExecutionReceipt, FraudProof};
use sp_executor::{ExecutionReceipt, FraudProof, OpaqueBundle};

#[pallet::config]
pub trait Config: frame_system::Config {
Expand Down Expand Up @@ -125,17 +125,20 @@ mod pallet {
}

#[pallet::weight((10_000, Pays::No))]
pub fn submit_transaction_bundle(origin: OriginFor<T>, bundle: Bundle) -> DispatchResult {
pub fn submit_transaction_bundle(
origin: OriginFor<T>,
opaque_bundle: OpaqueBundle,
) -> DispatchResult {
ensure_none(origin)?;

log::debug!(
target: "runtime::subspace::executor",
"Submitting transaction bundle: {:?}",
bundle
opaque_bundle
);

Self::deposit_event(Event::TransactionBundleStored {
bundle_hash: bundle.hash(),
bundle_hash: opaque_bundle.hash(),
});

Ok(())
Expand Down Expand Up @@ -209,12 +212,12 @@ mod pallet {
.propagate(true)
.build()
}
Call::submit_transaction_bundle { bundle } => {
Call::submit_transaction_bundle { opaque_bundle } => {
// TODO: validate the Proof-of-Election

ValidTransaction::with_tag_prefix("SubspaceSubmitTransactionBundle")
.priority(TransactionPriority::MAX)
.and_provides(bundle.hash())
.and_provides(opaque_bundle.hash())
.longevity(TransactionLongevity::MAX)
// We need this extrinsic to be propagted to the farmer nodes.
.propagate(true)
Expand Down Expand Up @@ -313,9 +316,9 @@ where

/// Submits an unsigned extrinsic [`Call::submit_transaction_bundle`].
pub fn submit_transaction_bundle_unsigned(
bundle: Bundle,
opaque_bundle: OpaqueBundle,
) -> frame_support::pallet_prelude::DispatchResult {
let call = Call::submit_transaction_bundle { bundle };
let call = Call::submit_transaction_bundle { opaque_bundle };

match SubmitTransaction::<T, Call<T>>::submit_unsigned_transaction(call.into()) {
Ok(()) => log::info!(
Expand Down
76 changes: 66 additions & 10 deletions crates/sp-executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,83 @@

use parity_scale_codec::{Decode, Encode};
use scale_info::TypeInfo;
use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT};
use sp_core::H256;
use sp_runtime::traits::{BlakeTwo256, Block as BlockT, Hash as HashT, Header as HeaderT};
use sp_runtime::{OpaqueExtrinsic, RuntimeDebug};
use sp_std::vec::Vec;
use sp_trie::StorageProof;

/// Dummy bundle header.
pub type BundleHeader = Vec<u8>;
/// Header of transaction bundle.
#[derive(Decode, Encode, TypeInfo, PartialEq, Eq, Clone, RuntimeDebug)]
pub struct BundleHeader {
/// The slot number.
pub slot_number: u64,
/// The merkle root of the extrinsics.
pub extrinsics_root: H256,
}

impl BundleHeader {
/// Returns the hash of this header.
pub fn hash(&self) -> H256 {
BlakeTwo256::hash_of(self)
}
}

/// Transaction bundle
#[derive(Decode, Encode, TypeInfo, PartialEq, Eq, Clone, RuntimeDebug)]
pub struct Bundle {
pub struct Bundle<Extrinsic> {
/// The bundle header.
pub header: BundleHeader,
/// THe accompanying extrinsics.
pub opaque_transactions: Vec<u8>,
pub extrinsics: Vec<Extrinsic>,
}

impl<Extrinsic> Bundle<Extrinsic> {
/// Returns the hash of this bundle.
pub fn hash(&self) -> H256 {
self.header.hash()
}
}

// TODO: Replace with `sp_runtime::OpaqueExtrinsic` once Substrate is upgraded with
// https://github.com/paritytech/substrate/pull/10504 included
/// Encoded extrinsic.
#[derive(Decode, Encode, TypeInfo, PartialEq, Eq, Clone, RuntimeDebug)]
pub struct EncodedExtrinsic(Vec<u8>);

impl From<Vec<u8>> for EncodedExtrinsic {
fn from(inner: Vec<u8>) -> Self {
Self(inner)
}
}

impl Bundle {
/// Bundle with opaque extrinsics.
#[derive(Decode, Encode, TypeInfo, PartialEq, Eq, Clone, RuntimeDebug)]
pub struct OpaqueBundle {
/// The bundle header.
pub header: BundleHeader,
/// THe accompanying opaque extrinsics.
pub opaque_extrinsics: Vec<EncodedExtrinsic>,
}

impl OpaqueBundle {
/// Returns the hash of this bundle.
pub fn hash(&self) -> sp_core::H256 {
sp_runtime::traits::BlakeTwo256::hash(&self.header)
pub fn hash(&self) -> H256 {
self.header.hash()
}
}

impl<Extrinsic: Encode> From<Bundle<Extrinsic>> for OpaqueBundle {
fn from(bundle: Bundle<Extrinsic>) -> Self {
let Bundle { header, extrinsics } = bundle;
let opaque_extrinsics = extrinsics
.into_iter()
.map(|xt| xt.encode().into())
.collect();
Self {
header,
opaque_extrinsics,
}
}
}

Expand Down Expand Up @@ -85,13 +141,13 @@ sp_api::decl_runtime_apis! {
) -> Option<()>;

/// Submits the transaction bundle via an unsigned extrinsic.
fn submit_transaction_bundle_unsigned(bundle: Bundle) -> Option<()>;
fn submit_transaction_bundle_unsigned(opaque_bundle: OpaqueBundle) -> Option<()>;

/// Submits the fraud proof via an unsigned extrinsic.
fn submit_fraud_proof_unsigned(fraud_proof: FraudProof) -> Option<()>;

/// Extract the bundles from extrinsics in a block.
fn extract_bundles(extrinsics: Vec<OpaqueExtrinsic>) -> Vec<Bundle>;
fn extract_bundles(extrinsics: Vec<OpaqueExtrinsic>) -> Vec<OpaqueBundle>;

/// Returns the block hash given the block number.
fn head_hash(
Expand Down
14 changes: 7 additions & 7 deletions crates/subspace-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use sp_consensus_subspace::{
SubspaceGenesisConfiguration,
};
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_executor::{Bundle, FraudProof};
use sp_executor::{FraudProof, OpaqueBundle};
use sp_runtime::traits::{
AccountIdLookup, BlakeTwo256, Block as BlockT, DispatchInfoOf, Header as HeaderT,
PostDispatchInfoOf, Zero,
Expand Down Expand Up @@ -734,17 +734,17 @@ fn extract_block_object_mapping(block: Block) -> BlockObjectMapping {
block_object_mapping
}

fn extract_bundles(extrinsics: Vec<OpaqueExtrinsic>) -> Vec<Bundle> {
fn extract_bundles(extrinsics: Vec<OpaqueExtrinsic>) -> Vec<OpaqueBundle> {
extrinsics
.into_iter()
.filter_map(|opaque_extrinsic| {
match <UncheckedExtrinsic>::decode(&mut opaque_extrinsic.encode().as_slice()) {
Ok(uxt) => {
if let Call::Executor(pallet_executor::Call::submit_transaction_bundle {
bundle,
opaque_bundle,
}) = uxt.function
{
Some(bundle)
Some(opaque_bundle)
} else {
None
}
Expand Down Expand Up @@ -902,15 +902,15 @@ impl_runtime_apis! {
Executor::submit_execution_receipt_unsigned(execution_receipt).ok()
}

fn submit_transaction_bundle_unsigned(bundle: Bundle) -> Option<()> {
Executor::submit_transaction_bundle_unsigned(bundle).ok()
fn submit_transaction_bundle_unsigned(opaque_bundle: OpaqueBundle) -> Option<()> {
Executor::submit_transaction_bundle_unsigned(opaque_bundle).ok()
}

fn submit_fraud_proof_unsigned(fraud_proof: FraudProof) -> Option<()> {
Executor::submit_fraud_proof_unsigned(fraud_proof).ok()
}

fn extract_bundles(extrinsics: Vec<OpaqueExtrinsic>) -> Vec<Bundle> {
fn extract_bundles(extrinsics: Vec<OpaqueExtrinsic>) -> Vec<OpaqueBundle> {
extract_bundles(extrinsics)
}

Expand Down
4 changes: 3 additions & 1 deletion cumulus/client/cirrus-executor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,22 @@ edition = "2021"

[dependencies]
# Substrate dependencies
sc-client-api = { git = "https://github.com/paritytech/substrate", rev = "b6c1c1bcfa5d831bfd1f278064d7af757f9b38f5" }
sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", rev = "b6c1c1bcfa5d831bfd1f278064d7af757f9b38f5" }
sp-runtime = { git = "https://github.com/paritytech/substrate", rev = "b6c1c1bcfa5d831bfd1f278064d7af757f9b38f5" }
sp-core = { git = "https://github.com/paritytech/substrate", rev = "b6c1c1bcfa5d831bfd1f278064d7af757f9b38f5" }
sp-consensus = { git = "https://github.com/paritytech/substrate", rev = "b6c1c1bcfa5d831bfd1f278064d7af757f9b38f5" }
sp-api = { git = "https://github.com/paritytech/substrate", rev = "b6c1c1bcfa5d831bfd1f278064d7af757f9b38f5" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", rev = "b6c1c1bcfa5d831bfd1f278064d7af757f9b38f5" }
sp-trie = { git = "https://github.com/paritytech/substrate", rev = "b6c1c1bcfa5d831bfd1f278064d7af757f9b38f5" }
sc-client-api = { git = "https://github.com/paritytech/substrate", rev = "b6c1c1bcfa5d831bfd1f278064d7af757f9b38f5" }

# Cumulus dependencies
cumulus-client-consensus-common = { path = "../consensus/common" }

# Other dependencies
codec = { package = "parity-scale-codec", version = "2.3.0", features = [ "derive" ] }
futures = { version = "0.3.1", features = ["compat"] }
futures-timer = "3.0.1"
parking_lot = "0.10.2"
tracing = "0.1.25"

Expand Down
Loading

0 comments on commit c463b53

Please sign in to comment.