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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
//! APIs and utilities for working with Substrate's Inherents in Tuxedo based chains.
//!
//! # Substrate inherents
//!
//! Inherents are a Substrate feature that allows block authors to insert some transactions directly
//! into the body of the block. Inherents are similar to pre-runtime digests which allow authors to
//! insert info into the block header. However inherents go in the block body and therefore must be transactions.
//!
//! Classic usecases for inherents are injecting and updating environmental information such as a block timestamp,
//! information about the relay chain (if the current chain is a parachain), or information about who should receive the block reward.
//!
//! In order to allow the runtime to construct such transactions while keeping the cleint opaque, there are special APIs
//! for creating inherents and performing off-chain validation of inherents. That's right, inherents also offer
//! a special API to have their environmental data checked off-chain before the block is executed.
//!
//! # Complexities in UTXO chains
//!
//! In account based systems, the classic way to use an inherent is that the block inserts a transaction providing some data like a timestamp.
//! When the extrinsic executed it, overwrites the previously stored timestamp in a dedicated storage item.
//!
//! In UTXO chains, there are no storage items, and all state is local to a UTXO. This is the case with, for example, the timestamp as well.
//! This means that when the author calls into the runtime with a timestamp, the transaction that is returned must include the correct reference
//! to the UTXO that contained the previous best timestamp. This is the crux of the problem: there is no easy way to know the location of
//! the previous timestamp in the utxo-space from inside the runtime.
//!
//! # Scraping the Parent Block
//!
//! The solution is to provide the entirety of the previous block to the runtime when asking it to construct inherents.
//! This module provides an inherent data provider that does just this. Any Tuxedo runtime that uses inherents (At least ones
//! that update environmental data), needs to include this foundational previous block inherent data provider
//! so that the Tuxedo executive can scrape it to find the output references of the previous inherent transactions.

use parity_scale_codec::{Decode, Encode};
use scale_info::TypeInfo;
use serde::{Deserialize, Serialize};
use sp_core::H256;
use sp_inherents::{
    CheckInherentsResult, InherentData, InherentIdentifier, IsFatalError, MakeFatalError,
};
use sp_std::{vec, vec::Vec};

use crate::{types::Transaction, ConstraintChecker, SimpleConstraintChecker, Verifier};

/// An inherent identifier for the Tuxedo parent block inherent
pub const PARENT_INHERENT_IDENTIFIER: InherentIdentifier = *b"prnt_blk";

/// An inherent data provider that inserts the previous block into the inherent data.
/// This data does NOT go into an extrinsic.
#[cfg(feature = "std")]
pub struct ParentBlockInherentDataProvider<Block>(pub Block);

#[cfg(feature = "std")]
impl<B> sp_std::ops::Deref for ParentBlockInherentDataProvider<B> {
    type Target = B;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
#[cfg(feature = "std")]
#[async_trait::async_trait]
impl<B: sp_runtime::traits::Block> sp_inherents::InherentDataProvider
    for ParentBlockInherentDataProvider<B>
{
    async fn provide_inherent_data(
        &self,
        inherent_data: &mut InherentData,
    ) -> Result<(), sp_inherents::Error> {
        inherent_data.put_data(PARENT_INHERENT_IDENTIFIER, &self.0)
    }

    async fn try_handle_error(
        &self,
        identifier: &InherentIdentifier,
        error: &[u8],
    ) -> Option<Result<(), sp_inherents::Error>> {
        if identifier == &PARENT_INHERENT_IDENTIFIER {
            println!("UH OH! INHERENT ERROR!!!!!!!!!!!!!!!!!!!!!!");
            Some(Err(sp_inherents::Error::Application(Box::from(
                <String as parity_scale_codec::Decode>::decode(&mut &error[..]).ok()?,
            ))))
        } else {
            None
        }
    }
}

/// Tuxedo's controlled interface around Substrate's concept of inherents.
///
/// This interface assumes that each inherent will appear exactly once in each block.
/// This will be verified off-chain by nodes before block execution begins.
///
/// This interface is stricter and more structured, and therefore simpler than FRAME's.
/// If you need to do something more powerful (which you probably don't) and you
/// understand exactly how Substrate's block authoring and Tuxedo's piece aggregation works
/// (which you probably don't) you can directly implement the `InherentInternal` trait
/// which is more powerful (and dangerous).
pub trait InherentHooks: SimpleConstraintChecker + Sized {
    type Error: Encode + IsFatalError;

    const INHERENT_IDENTIFIER: InherentIdentifier;

    /// Create the inherent extrinsic to insert into a block that is being authored locally.
    /// The inherent data is supplied by the authoring node.
    fn create_inherent<V: Verifier>(
        authoring_inherent_data: &InherentData,
        previous_inherent: (Transaction<V, Self>, H256),
    ) -> Transaction<V, Self>;

    /// Perform off-chain pre-execution checks on the inherent.
    /// The inherent data is supplied by the importing node.
    /// The inherent data available here is not guaranteed to be the
    /// same as what is available at authoring time.
    fn check_inherent<V>(
        importing_inherent_data: &InherentData,
        inherent: Transaction<V, Self>,
        results: &mut CheckInherentsResult,
    );

    /// Return the genesis transactions that are required for this inherent.
    fn genesis_transactions<V: Verifier>() -> Vec<Transaction<V, Self>> {
        Vec::new()
    }
}

/// An adapter type to declare, at the runtime level, that Tuxedo pieces provide custom inherent hooks.
///
/// This adapter type satisfies the executive's expectations by implementing both `ConstraintChecker`.
/// The inherent logic checks to be sure that exactly one inherent is present before plumbing through to
/// the underlying `TuxedoInherent` implementation.
///
/// This type should encode exactly like the inner type.
#[derive(
    Serialize, Deserialize, Eq, PartialEq, Debug, Decode, Default, Encode, TypeInfo, Clone, Copy,
)]
pub struct InherentAdapter<C>(C);

/// Helper to transform an entire transaction by wrapping the constraint checker.
fn wrap_transaction<V, C>(unwrapped: Transaction<V, C>) -> Transaction<V, InherentAdapter<C>> {
    Transaction {
        inputs: unwrapped.inputs,
        peeks: unwrapped.peeks,
        outputs: unwrapped.outputs,
        checker: InherentAdapter(unwrapped.checker),
    }
}

// I wonder if this should be a deref impl instead?
/// Helper to transform an entire transaction by unwrapping the constraint checker.
fn unwrap_transaction<V, C>(wrapped: Transaction<V, InherentAdapter<C>>) -> Transaction<V, C> {
    Transaction {
        inputs: wrapped.inputs,
        peeks: wrapped.peeks,
        outputs: wrapped.outputs,
        checker: wrapped.checker.0,
    }
}

impl<C: SimpleConstraintChecker + InherentHooks + 'static> ConstraintChecker
    for InherentAdapter<C>
{
    type Error = <C as SimpleConstraintChecker>::Error;

    fn check(
        &self,
        input_data: &[crate::dynamic_typing::DynamicallyTypedData],
        evicted_input_data: &[crate::dynamic_typing::DynamicallyTypedData],
        peek_data: &[crate::dynamic_typing::DynamicallyTypedData],
        output_data: &[crate::dynamic_typing::DynamicallyTypedData],
    ) -> Result<sp_runtime::transaction_validity::TransactionPriority, Self::Error> {
        SimpleConstraintChecker::check(
            &self.0,
            input_data,
            evicted_input_data,
            peek_data,
            output_data,
        )
    }

    fn is_inherent(&self) -> bool {
        true
    }

    fn create_inherents<V: Verifier>(
        authoring_inherent_data: &InherentData,
        previous_inherents: Vec<(Transaction<V, Self>, H256)>,
    ) -> Vec<Transaction<V, Self>> {
        if previous_inherents.len() > 1 {
            panic!("Authoring a leaf inherent constraint checker, but multiple previous inherents were supplied.")
        }

        let (previous_inherent, hash) = previous_inherents
            .first()
            .cloned()
            .expect("Previous inherent exists.");
        let current_inherent = wrap_transaction(<C as InherentHooks>::create_inherent(
            authoring_inherent_data,
            (unwrap_transaction(previous_inherent), hash),
        ));

        vec![current_inherent]
    }

    fn check_inherents<V: Clone>(
        importing_inherent_data: &InherentData,
        inherents: Vec<Transaction<V, Self>>,
        results: &mut CheckInherentsResult,
    ) {
        if inherents.is_empty() {
            results
                .put_error(
                    *b"12345678",
                    &MakeFatalError::from(
                        "Tuxedo inherent expected exactly one inherent extrinsic but found zero",
                    ),
                )
                .expect("Should be able to put an error.");
            return;
        } else if inherents.len() > 1 {
            results
                .put_error(*b"12345678", &MakeFatalError::from("Tuxedo inherent expected exactly one inherent extrinsic but found multiple"))
                .expect("Should be able to put an error.");
            return;
        }
        let inherent = inherents
            .first()
            .cloned()
            .expect("Previous inherent exists.");
        <C as InherentHooks>::check_inherent(
            importing_inherent_data,
            unwrap_transaction(inherent),
            results,
        )
    }

    fn genesis_transactions<V: Verifier>() -> Vec<Transaction<V, Self>> {
        <C as InherentHooks>::genesis_transactions()
            .into_iter()
            .map(|gtx| wrap_transaction(gtx))
            .collect()
    }
}