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
#[cfg(not(feature = "std"))]
extern crate alloc;

use crate::grandpa::GrandpaJustification;
use crate::{Config, EncodedBlockHash, EncodedBlockNumber, Error};
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use codec::Decode;
use frame_support::Parameter;
use num_traits::AsPrimitive;
use sp_runtime::generic;
use sp_runtime::traits::{
    AtLeast32BitUnsigned, Hash as HashT, Header as HeaderT, MaybeDisplay,
    MaybeSerializeDeserialize, Member, Saturating, SimpleBitOps,
};
use sp_std::hash::Hash;
use sp_std::str::FromStr;

pub(crate) type OpaqueExtrinsic = Vec<u8>;
pub type SignedBlock<Header> = generic::SignedBlock<generic::Block<Header, OpaqueExtrinsic>>;

/// Minimal Substrate-based chain representation that may be used from no_std environment.
pub trait Chain {
    /// A type that fulfills the abstract idea of what a Substrate block number is.
    // Constraints come from the associated Number type of `sp_runtime::traits::Header`
    // See here for more info:
    // https://crates.parity.io/sp_runtime/traits/trait.Header.html#associatedtype.Number
    //
    // Note that the `AsPrimitive<usize>` trait is required by the GRANDPA justification
    // verifier, and is not usually part of a Substrate Header's Number type.
    type BlockNumber: Parameter
        + Member
        + MaybeSerializeDeserialize
        + Hash
        + Copy
        + Default
        + MaybeDisplay
        + AtLeast32BitUnsigned
        + FromStr
        + AsPrimitive<usize>
        + Default
        + Saturating;

    /// A type that fulfills the abstract idea of what a Substrate hash is.
    // Constraints come from the associated Hash type of `sp_runtime::traits::Header`
    // See here for more info:
    // https://crates.parity.io/sp_runtime/traits/trait.Header.html#associatedtype.Hash
    type Hash: Parameter
        + Member
        + MaybeSerializeDeserialize
        + Hash
        + Ord
        + Copy
        + MaybeDisplay
        + Default
        + SimpleBitOps
        + AsRef<[u8]>
        + AsMut<[u8]>;

    /// A type that fulfills the abstract idea of what a Substrate header is.
    // See here for more info:
    // https://crates.parity.io/sp_runtime/traits/trait.Header.html
    type Header: Parameter
        + HeaderT<Number = Self::BlockNumber, Hash = Self::Hash>
        + MaybeSerializeDeserialize;

    /// A type that fulfills the abstract idea of what a Substrate hasher (a type
    /// that produces hashes) is.
    // Constraints come from the associated Hashing type of `sp_runtime::traits::Header`
    // See here for more info:
    // https://crates.parity.io/sp_runtime/traits/trait.Header.html#associatedtype.Hashing
    type Hasher: HashT<Output = Self::Hash>;

    fn decode_block<T: Config>(block: &[u8]) -> Result<SignedBlock<Self::Header>, Error<T>> {
        SignedBlock::<Self::Header>::decode(&mut &*block).map_err(|error| {
            log::error!("Cannot decode block, error: {:?}", error);
            Error::<T>::FailedDecodingBlock
        })
    }

    fn decode_header<T: Config>(header: &[u8]) -> Result<Self::Header, Error<T>> {
        Self::Header::decode(&mut &*header).map_err(|error| {
            log::error!("Cannot decode header, error: {:?}", error);
            Error::<T>::FailedDecodingHeader
        })
    }

    fn decode_grandpa_justifications<T: Config>(
        justifications: &[u8],
    ) -> Result<GrandpaJustification<Self::Header>, Error<T>> {
        GrandpaJustification::<Self::Header>::decode(&mut &*justifications).map_err(|error| {
            log::error!("Cannot decode justifications, error: {:?}", error);
            Error::<T>::FailedDecodingJustifications
        })
    }

    fn decode_block_number_and_hash<T: Config>(
        pair: (EncodedBlockNumber, EncodedBlockHash),
    ) -> Result<(Self::BlockNumber, Self::Hash), Error<T>> {
        let number = Self::decode_block_number::<T>(pair.0.as_slice())?;
        let hash = Self::decode_block_hash::<T>(pair.1.as_slice())?;
        Ok((number, hash))
    }

    fn decode_block_number<T: Config>(number: &[u8]) -> Result<Self::BlockNumber, Error<T>> {
        Self::BlockNumber::decode(&mut &*number).map_err(|error| {
            log::error!("Cannot decode block number, error: {:?}", error);
            Error::<T>::FailedDecodingBlockNumber
        })
    }

    fn decode_block_hash<T: Config>(hash: &[u8]) -> Result<Self::Hash, Error<T>> {
        Self::Hash::decode(&mut &*hash).map_err(|error| {
            log::error!("Cannot decode block hash, error: {:?}", error);
            Error::<T>::FailedDecodingBlockHash
        })
    }
}