1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//! This module is the core of Tuxedo's parachain support.
//!
//! The types and methods defined in this crate are of equal importance to
//! those in the `tuxedo-core` crate, and this crate should be considered
//! a simple extension to that one and equally "core"y. The reason Tuxedo
//! separates the parachain specific aspects is because Polkadot and Cumulus
//! are quite heavy to compile, and sovereign chains are able to completely avoid it.
//!
//! It's primary jobs are to
//! * Manage transient storage details for the parachain inherent, specifically the relay
//!   parent block number.
//! * Provide collation information to the client side collator service.
//! * Implement the `validate_block` function required by relay chain validators.
//!   This task is achieved through the `register_validate_block!` macro.
//!
//! This code is inspired by, cumulus pallet parachain system
//! https://paritytech.github.io/polkadot-sdk/master/cumulus_pallet_parachain_system/index.html

#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(test)]
mod tests;
#[cfg(not(feature = "std"))]
#[doc(hidden)]
pub mod validate_block;

mod collation_api;
mod relay_state_snapshot;
pub use collation_api::ParachainExecutiveExtension;
use parity_scale_codec::{Decode, Encode};

#[cfg(not(feature = "std"))]
#[doc(hidden)]
mod trie_cache;

#[cfg(not(feature = "std"))]
#[doc(hidden)]
pub use bytes;
#[cfg(not(feature = "std"))]
#[doc(hidden)]
pub use parity_scale_codec::decode_from_bytes;
#[cfg(not(feature = "std"))]
#[doc(hidden)]
pub use polkadot_parachain_primitives;
#[cfg(not(feature = "std"))]
#[doc(hidden)]
pub use sp_runtime::traits::GetRuntimeBlockType;
#[cfg(not(feature = "std"))]
#[doc(hidden)]
pub use sp_std;

/// Re-export of the Tuxedo-core crate. This allows parachain-specific
/// Tuxedo-pieces to depend only on tuxedo-parachain-core without worrying about
/// accidental version mismatches.
pub use tuxedo_core;

use cumulus_primitives_parachain_inherent::ParachainInherentData;
use tuxedo_core::{
    dynamic_typing::UtxoData,
    support_macros::{CloneNoBound, DebugNoBound},
    ConstraintChecker,
};

/// A transient storage key that will hold the block number of the relay chain parent
/// that is associated with the current parachain block. This data enters the parachain
/// through the parachain inherent
const RELAY_PARENT_NUMBER_KEY: &[u8] = b"relay_parent_number";

/// An abstraction over reading the ambiently available relay parent block number.
/// This allows it to be mocked during tests and not require actual externalities.
pub trait GetRelayParentNumberStorage {
    fn get() -> u32;
}

/// An abstraction over setting the ambiently available relay parent block number.
/// This allows it to be mocked during tests and require actual externalities.
pub trait SetRelayParentNumberStorage {
    fn set(new_parent_number: u32);
}

/// A public interface for accessing and mutating the relay parent number. This is
/// expected to be called from the parachain piece
pub enum RelayParentNumberStorage {}

impl GetRelayParentNumberStorage for RelayParentNumberStorage {
    fn get() -> u32 {
        let encoded = sp_io::storage::get(RELAY_PARENT_NUMBER_KEY)
            .expect("Some relay parent number should always be stored");
        Decode::decode(&mut &encoded[..])
            .expect("properly encoded relay parent number should have been stored.")
    }
}

impl SetRelayParentNumberStorage for RelayParentNumberStorage {
    fn set(new_parent_number: u32) {
        sp_io::storage::set(RELAY_PARENT_NUMBER_KEY, &new_parent_number.encode());
    }
}

/// A mock version of the RelayParentNumberStorage that can be used in tests without externalities.
pub enum MockRelayParentNumberStorage {}

impl SetRelayParentNumberStorage for MockRelayParentNumberStorage {
    fn set(_new_parent_number: u32) {}
}

/// Basically the same as
/// [`ValidationParams`](polkadot_parachain_primitives::primitives::ValidationParams), but a little
/// bit optimized for our use case here.
///
/// `block_data` and `head_data` are represented as [`bytes::Bytes`] to make them reuse
/// the memory of the input parameter of the exported `validate_blocks` function.
///
/// The layout of this type must match exactly the layout of
/// [`ValidationParams`](polkadot_parachain_primitives::primitives::ValidationParams) to have the
/// same SCALE encoding.
#[derive(parity_scale_codec::Decode)]
#[cfg_attr(feature = "std", derive(parity_scale_codec::Encode))]
#[doc(hidden)]
pub struct MemoryOptimizedValidationParams {
    pub parent_head: bytes::Bytes,
    pub block_data: bytes::Bytes,
    pub relay_parent_number: cumulus_primitives_core::relay_chain::BlockNumber,
    pub relay_parent_storage_root: cumulus_primitives_core::relay_chain::Hash,
}

/// Prepares a Tuxedo runtime to be parachain compatible by doing two main tasks.
///
/// 1. Wraps the provided constraint checker in another layer of aggregation including the parachain
///    inherent piece
/// 2. Registers the `validate_block` function that is used by parachains to validate blocks on a
///    validator when building to wasm. This is skipped when building to std.
///
/// Expects as parameters a Verifier, a non-yet-parachain-ready ConstraintChecker, and a ParaId.
pub use tuxedo_parachainify::parachainify;

// Having to do this wrapping is one more reason to abandon this UtxoData trait,
// and go for a more strongly typed aggregate type approach.
// Tracking issue: https://github.com/Off-Narrative-Labs/Tuxedo/issues/153
/// A wrapper type around Cumulus's ParachainInherentData type that can be stored.
#[derive(Encode, Decode, DebugNoBound, CloneNoBound, scale_info::TypeInfo)]
/// A wrapper type around Cumulus's ParachainInherentData type.
/// This type is convertible Into and From the inner type.
/// This is necessary so that we can implement the `UtxoData` trait.
pub struct ParachainInherentDataUtxo(ParachainInherentData);

impl UtxoData for ParachainInherentDataUtxo {
    const TYPE_ID: [u8; 4] = *b"para";
}

impl From<ParachainInherentDataUtxo> for ParachainInherentData {
    fn from(val: ParachainInherentDataUtxo) -> Self {
        val.0
    }
}

impl From<ParachainInherentData> for ParachainInherentDataUtxo {
    fn from(value: ParachainInherentData) -> Self {
        Self(value)
    }
}

/// A way for the relay chain validators to determine whether a particular parachain
/// extrinsic is the parachain inherent and whether the parachain inherent data can
/// be extracted from it.
pub trait ParachainConstraintChecker: ConstraintChecker {
    fn is_parachain(&self) -> bool;
}