use codec::{Compact, Decode, Encode, Output};
#[cfg(all(feature = "std", feature = "type_info"))]
use scale_info::TypeInfo;
use sp_core::{hashing::blake2_256, H256};
use sp_runtime::{ConsensusEngineId, MultiSignature};
use serde::{Deserialize, Serialize};
use crate::basic_types::{AccountId, GenericAddress};
use crate::*;
pub type TxHash = H256;
pub type BlockHash = H256;
pub type BlockNumber = u32;
pub mod block_number {
use super::BlockNumber;
use sp_core::U256;
pub fn deserialize<'de, D>(d: D) -> Result<BlockNumber, D::Error>
where
D: serde::Deserializer<'de>,
{
let num: U256 = serde::Deserialize::deserialize(d)?;
Ok(num.as_u32())
}
}
#[derive(Clone, Debug, Encode, Decode, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Header {
pub parent_hash: BlockHash,
#[serde(deserialize_with = "block_number::deserialize")]
#[codec(compact)]
pub number: BlockNumber,
pub state_root: BlockHash,
pub extrinsics_root: BlockHash,
pub digest: Digest,
}
impl Header {
pub fn hash(&self) -> BlockHash {
H256(self.using_encoded(blake2_256))
}
}
impl From<Header> for sp_runtime::generic::Header<BlockNumber, sp_runtime::traits::BlakeTwo256> {
fn from(header: Header) -> Self {
let logs = header
.digest
.logs
.into_iter()
.map(|item| item.into())
.collect();
Self {
parent_hash: header.parent_hash,
number: header.number,
state_root: header.state_root,
extrinsics_root: header.extrinsics_root,
digest: sp_runtime::generic::Digest { logs },
}
}
}
#[derive(Clone, Debug, Encode, Decode, Serialize, Deserialize)]
pub struct Digest {
pub logs: Vec<DigestItem>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(try_from = "RawDigestItem")]
#[serde(into = "RawDigestItem")]
pub enum DigestItem {
PreRuntime(ConsensusEngineId, Vec<u8>),
Consensus(ConsensusEngineId, Vec<u8>),
Seal(ConsensusEngineId, Vec<u8>),
Other(Vec<u8>),
RuntimeEnvironmentUpdated,
}
impl Encode for DigestItem {
fn encode_to<T: Output + ?Sized>(&self, output: &mut T) {
let runtime_era: sp_runtime::generic::DigestItem = self.clone().into();
runtime_era.encode_to(output)
}
}
impl Decode for DigestItem {
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
let runtime_era = sp_runtime::generic::DigestItem::decode(input)?;
Ok(runtime_era.into())
}
}
impl From<sp_runtime::generic::DigestItem> for DigestItem {
fn from(r_item: sp_runtime::generic::DigestItem) -> Self {
use sp_runtime::generic::DigestItem::*;
match r_item {
PreRuntime(id, data) => Self::PreRuntime(id, data),
Consensus(id, data) => Self::Consensus(id, data),
Seal(id, data) => Self::Seal(id, data),
Other(data) => Self::Other(data),
RuntimeEnvironmentUpdated => Self::RuntimeEnvironmentUpdated,
}
}
}
impl From<DigestItem> for sp_runtime::generic::DigestItem {
fn from(item: DigestItem) -> Self {
match item {
DigestItem::PreRuntime(id, data) => Self::PreRuntime(id, data),
DigestItem::Consensus(id, data) => Self::Consensus(id, data),
DigestItem::Seal(id, data) => Self::Seal(id, data),
DigestItem::Other(data) => Self::Other(data),
DigestItem::RuntimeEnvironmentUpdated => Self::RuntimeEnvironmentUpdated,
}
}
}
impl TryFrom<RawDigestItem> for DigestItem {
type Error = crate::Error;
fn try_from(raw: RawDigestItem) -> Result<Self, Self::Error> {
let item = DigestItem::decode(&mut &raw.0[..])?;
Ok(item.into())
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RawDigestItem(
#[cfg_attr(feature = "serde", serde(with = "impl_serde::serialize"))] pub Vec<u8>,
);
impl From<DigestItem> for RawDigestItem {
fn from(item: DigestItem) -> Self {
Self(item.encode())
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct StorageData(
#[cfg_attr(feature = "serde", serde(with = "impl_serde::serialize"))] pub Vec<u8>,
);
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct StorageKey(
#[cfg_attr(feature = "serde", serde(with = "impl_serde::serialize"))] pub Vec<u8>,
);
pub type AdditionalSigned = (u32, u32, BlockHash, BlockHash, (), (), ());
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(all(feature = "std", feature = "type_info"), derive(TypeInfo))]
pub enum Era {
Immortal,
Mortal(u64, u64),
}
impl Encode for Era {
fn encode_to<T: Output + ?Sized>(&self, output: &mut T) {
let runtime_era: sp_runtime::generic::Era = self.clone().into();
runtime_era.encode_to(output)
}
}
impl Decode for Era {
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
let runtime_era = sp_runtime::generic::Era::decode(input)?;
Ok(runtime_era.into())
}
}
impl From<sp_runtime::generic::Era> for Era {
fn from(e: sp_runtime::generic::Era) -> Self {
match e {
sp_runtime::generic::Era::Immortal => Self::Immortal,
sp_runtime::generic::Era::Mortal(period, phase) => Self::Mortal(period, phase),
}
}
}
impl From<Era> for sp_runtime::generic::Era {
fn from(e: Era) -> Self {
match e {
Era::Immortal => Self::Immortal,
Era::Mortal(period, phase) => Self::Mortal(period, phase),
}
}
}
#[derive(Clone, Debug, Encode, Decode)]
pub struct Extra(sp_runtime::generic::Era, Compact<u32>, Compact<u128>);
impl Extra {
pub fn new(era: Era, nonce: u32) -> Self {
Self(era.into(), nonce.into(), 0u128.into())
}
pub fn nonce(&self) -> u32 {
self.1 .0
}
pub fn tip(&self) -> u128 {
self.2 .0
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Encoded(
#[cfg_attr(feature = "serde", serde(with = "impl_serde::serialize"))] pub Vec<u8>,
);
impl<T: Encode> From<&T> for Encoded {
fn from(other: &T) -> Self {
Self(other.encode())
}
}
impl Encode for Encoded {
fn size_hint(&self) -> usize {
self.0.len()
}
fn encode_to<T: Output + ?Sized>(&self, dest: &mut T) {
dest.write(&self.0);
}
}
impl Decode for Encoded {
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
if let Some(len) = input.remaining_len()? {
let mut data = vec![0u8; len];
input.read(&mut data.as_mut_slice())?;
Ok(Self(data))
} else {
let mut data = Vec::new();
while let Ok(b) = input.read_byte() {
data.push(b);
}
Ok(Self(data))
}
}
}
pub struct SignedPayload<'a>((&'a Encoded, &'a Extra, AdditionalSigned));
impl<'a> SignedPayload<'a> {
pub fn new(call: &'a Encoded, extra: &'a Extra, additional: AdditionalSigned) -> Self {
Self((call, extra, additional))
}
}
impl<'a> Encode for SignedPayload<'a> {
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.0.using_encoded(|payload| {
if payload.len() > 256 {
f(&blake2_256(payload)[..])
} else {
f(payload)
}
})
}
}
pub const EXTRINSIC_VERSION: u8 = 4;
#[derive(Clone, Debug)]
pub struct ExtrinsicV4 {
pub signature: Option<(GenericAddress, MultiSignature, Extra)>,
pub call: Encoded,
}
impl ExtrinsicV4 {
pub fn tx_hash(tx: &[u8]) -> TxHash {
H256(blake2_256(tx))
}
pub fn signed(account: AccountId, sig: MultiSignature, extra: Extra, call: Encoded) -> Self {
Self {
signature: Some((GenericAddress::from(account), sig, extra)),
call,
}
}
pub fn unsigned(call: Encoded) -> Self {
Self {
signature: None,
call,
}
}
pub fn as_hex_and_hash(&self) -> (String, TxHash) {
let tx = self.encode();
let tx_hash = Self::tx_hash(tx.as_slice());
let mut tx_hex = hex::encode(tx);
tx_hex.insert_str(0, "0x");
(tx_hex, tx_hash)
}
pub fn to_hex(&self) -> String {
let mut hex = hex::encode(self.encode());
hex.insert_str(0, "0x");
hex
}
}
impl Encode for ExtrinsicV4 {
fn encode(&self) -> Vec<u8> {
let mut buf = Vec::with_capacity(512);
match &self.signature {
Some(sig) => {
buf.push(EXTRINSIC_VERSION | 0b1000_0000);
sig.encode_to(&mut buf);
}
None => {
buf.push(EXTRINSIC_VERSION & 0b0111_1111);
}
}
self.call.encode_to(&mut buf);
buf.encode()
}
}
impl Decode for ExtrinsicV4 {
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
let _len: Compact<u32> = Decode::decode(input)?;
let version = input.read_byte()?;
let is_signed = version & 0b1000_0000 != 0;
if (version & 0b0111_1111) != EXTRINSIC_VERSION {
Err("Invalid EXTRINSIC_VERSION")?;
}
let signature = if is_signed {
let sig: (GenericAddress, MultiSignature, Extra) = Decode::decode(input)?;
Some(sig)
} else {
None
};
Ok(Self {
signature,
call: Decode::decode(input)?,
})
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct AccountInfo {
pub nonce: u32,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum TransactionStatus {
Future,
Ready,
Broadcast(Vec<String>),
InBlock(BlockHash),
Retracted(BlockHash),
FinalityTimeout(BlockHash),
Finalized(BlockHash),
Usurped(TxHash),
Dropped,
Invalid,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SignedBlock {
pub block: Block,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Block {
extrinsics: Vec<Encoded>,
header: Header,
}
impl Block {
pub fn find_extrinsic(&self, xt_hash: TxHash) -> Option<usize> {
self
.extrinsics
.iter()
.position(|xt| ExtrinsicV4::tx_hash(xt.0.as_slice()) == xt_hash)
}
pub fn parent(&self) -> BlockHash {
self.header.parent_hash
}
pub fn state_root(&self) -> BlockHash {
self.header.state_root
}
pub fn extrinsics_root(&self) -> BlockHash {
self.header.extrinsics_root
}
pub fn block_number(&self) -> BlockNumber {
self.header.number
}
pub fn to_string(&self) -> String {
format!("{:?}", self)
}
}
#[derive(Clone, Debug, Serialize, Deserialize, Decode, PartialEq, Eq)]
pub enum Phase {
ApplyExtrinsic(u32),
Finalization,
Initialization,
}
#[derive(Clone, Debug, Serialize, Decode)]
pub struct EventRecord<Event: RuntimeEnumTraits> {
pub phase: Phase,
pub event: Event,
pub topics: Vec<BlockHash>,
}
impl<Event: RuntimeEnumTraits> EventRecord<Event> {
pub fn name(&self) -> &'static str {
self.event.as_name()
}
pub fn short_doc(&self) -> &'static str {
self.event.as_short_doc()
}
pub fn docs(&self) -> &'static [&'static str] {
self.event.as_docs()
}
pub fn to_string(&self) -> String {
format!("{:#?}", self)
}
}
#[derive(Clone, Debug, Serialize, Decode, Default)]
pub struct EventRecords<Event: RuntimeEnumTraits>(pub Vec<EventRecord<Event>>);
impl<Event: RuntimeEnumTraits> EventRecords<Event> {
pub fn from_vec(mut events: Vec<EventRecord<Event>>, filter: Option<Phase>) -> Self {
if let Some(filter) = filter {
events.retain(|ev| ev.phase == filter);
}
Self(events)
}
pub fn to_string(&self) -> String {
format!("{:#?}", self.0)
}
}