Derivable Encode & Decode (#509)

* Derive macro for simple structs.

* Derive Encode/Decode wherever we can.

* Derive for enums.

* Support discriminant.

* Get rid of some repetition.

* Support custom indices.

* Derive codec for enums wherever possible.

* Fix no_std

* WASM rebuilt

* Avoid excessive import.

* Fix compilation.

* Address review grumbles.
This commit is contained in:
Tomasz Drwięga
2018-08-08 17:47:22 +02:00
committed by Sergey Pepyakin
parent 6eece0174e
commit 96b3a8f92f
65 changed files with 936 additions and 1511 deletions
+23
View File
@@ -3,6 +3,7 @@ name = "adder"
version = "0.1.0"
dependencies = [
"polkadot-parachain 0.1.0",
"substrate-codec-derive 0.1.0",
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1953,6 +1954,7 @@ dependencies = [
"rhododendron 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-bft 0.1.0",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-network 0.1.0",
"substrate-primitives 0.1.0",
"tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1964,6 +1966,7 @@ version = "0.1.0"
dependencies = [
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"wasmi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1976,6 +1979,7 @@ dependencies = [
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-primitives 0.1.0",
"substrate-runtime-std 0.1.0",
@@ -2047,6 +2051,7 @@ version = "0.1.0"
dependencies = [
"polkadot-primitives 0.1.0",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-primitives 0.1.0",
]
@@ -2722,6 +2727,7 @@ dependencies = [
"patricia-trie 0.1.0 (git+https://github.com/paritytech/parity.git)",
"substrate-client 0.1.0",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-executor 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-primitives 0.1.0",
@@ -2737,6 +2743,16 @@ dependencies = [
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-codec-derive"
version = "0.1.0"
dependencies = [
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-executor"
version = "0.1.0"
@@ -2829,6 +2845,7 @@ dependencies = [
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-client 0.1.0",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-keyring 0.1.0",
"substrate-network-libp2p 0.1.0",
"substrate-primitives 0.1.0",
@@ -2875,6 +2892,7 @@ dependencies = [
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-runtime-std 0.1.0",
"substrate-serializer 0.1.0",
"twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2990,6 +3008,7 @@ dependencies = [
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-consensus 0.1.0",
"substrate-runtime-io 0.1.0",
@@ -3047,6 +3066,7 @@ dependencies = [
"serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
"substrate-runtime-std 0.1.0",
@@ -3172,6 +3192,7 @@ dependencies = [
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-runtime-std 0.1.0",
"substrate-runtime-support 0.1.0",
]
@@ -3223,6 +3244,7 @@ dependencies = [
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-primitives 0.1.0",
]
@@ -3282,6 +3304,7 @@ dependencies = [
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-keyring 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
+1
View File
@@ -41,6 +41,7 @@ members = [
"substrate/client",
"substrate/client/db",
"substrate/codec",
"substrate/codec/derive",
"substrate/environmental",
"substrate/executor",
"substrate/extrinsic-pool",
+16 -3
View File
@@ -639,7 +639,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-hex"
version = "2.0.0"
source = "git+https://github.com/rphmeier/rustc-hex.git#ee2ec40b9062ac7769ccb9dc891d6dc2cc9009d7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc_version"
@@ -706,6 +706,15 @@ dependencies = [
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-codec-derive"
version = "0.1.0"
dependencies = [
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-keyring"
version = "0.1.0"
@@ -723,10 +732,11 @@ dependencies = [
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
"rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)",
"rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-runtime-std 0.1.0",
"twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
@@ -781,6 +791,7 @@ dependencies = [
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-consensus 0.1.0",
"substrate-runtime-io 0.1.0",
@@ -831,6 +842,7 @@ dependencies = [
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
"substrate-runtime-std 0.1.0",
@@ -954,6 +966,7 @@ dependencies = [
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-runtime-std 0.1.0",
"substrate-runtime-support 0.1.0",
]
@@ -1206,7 +1219,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rlp 0.2.1 (git+https://github.com/paritytech/parity.git)" = "<none>"
"checksum rlp 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "89db7f8dfdd5eb7ab3ac3ece7a07fd273a680b4b224cb231181280e8996f9f0b"
"checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e"
"checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "<none>"
"checksum rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b03280c2813907a030785570c577fb27d3deec8da4c18566751ade94de0ace"
"checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+1
View File
@@ -12,6 +12,7 @@ polkadot-consensus = { path = "../consensus" }
polkadot-primitives = { path = "../primitives" }
substrate-bft = { path = "../../substrate/bft" }
substrate-codec = { path = "../../substrate/codec" }
substrate-codec-derive = { path = "../../substrate/codec/derive" }
substrate-network = { path = "../../substrate/network" }
substrate-primitives = { path = "../../substrate/primitives" }
ed25519 = { path = "../../substrate/ed25519" }
@@ -18,7 +18,6 @@
use polkadot_primitives::{AccountId, Hash};
use polkadot_primitives::parachain::{Id as ParaId, Collation};
use codec;
use futures::sync::oneshot;
@@ -28,7 +27,7 @@ use std::time::{Duration, Instant};
const COLLATION_LIFETIME: Duration = Duration::from_secs(60 * 5);
/// The role of the collator. Whether they're the primary or backup for this parachain.
#[derive(PartialEq, Debug, Clone, Copy)]
#[derive(PartialEq, Debug, Clone, Copy, Encode, Decode)]
pub enum Role {
/// Primary collators should send collations whenever it's time.
Primary = 0,
@@ -36,22 +35,6 @@ pub enum Role {
Backup = 1,
}
impl codec::Encode for Role {
fn encode_to<T: codec::Output>(&self, dest: &mut T) {
dest.push_byte(*self as u8);
}
}
impl codec::Decode for Role {
fn decode<I: codec::Input>(input: &mut I) -> Option<Self> {
match input.read_byte()? {
x if x == Role::Primary as u8 => Some(Role::Primary),
x if x == Role::Backup as u8 => Some(Role::Backup),
_ => None,
}
}
}
/// A maintenance action for the collator set.
#[derive(PartialEq, Debug)]
#[allow(dead_code)]
+5 -81
View File
@@ -38,13 +38,15 @@ extern crate rhododendron;
#[macro_use]
extern crate log;
#[macro_use]
extern crate substrate_codec_derive;
mod collator_pool;
mod local_collations;
mod router;
pub mod consensus;
use codec::{Decode, Encode, Input, Output};
use codec::{Decode, Encode};
use futures::sync::oneshot;
use parking_lot::Mutex;
use polkadot_consensus::{Statement, SignedStatement, GenericStatement};
@@ -74,36 +76,11 @@ type FullStatus = GenericFullStatus<Block>;
pub type NetworkService = ::substrate_network::Service<Block, PolkadotProtocol>;
/// Status of a Polkadot node.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct Status {
collating_for: Option<(AccountId, ParaId)>,
}
impl Encode for Status {
fn encode_to<T: codec::Output>(&self, dest: &mut T) {
match self.collating_for {
Some(ref details) => {
dest.push_byte(1);
dest.push(details);
}
None => {
dest.push_byte(0);
}
}
}
}
impl Decode for Status {
fn decode<I: codec::Input>(input: &mut I) -> Option<Self> {
let collating_for = match input.read_byte()? {
0 => None,
1 => Some(Decode::decode(input)?),
_ => return None,
};
Some(Status { collating_for })
}
}
struct BlockDataRequest {
attempted_peers: HashSet<SessionKey>,
consensus_parent: Hash,
@@ -207,7 +184,7 @@ impl CurrentConsensus {
}
/// Polkadot-specific messages.
#[derive(Debug)]
#[derive(Debug, Encode, Decode)]
pub enum Message {
/// signed statement and localized parent hash.
Statement(Hash, SignedStatement),
@@ -224,59 +201,6 @@ pub enum Message {
Collation(Hash, Collation),
}
impl Encode for Message {
fn encode_to<T: Output>(&self, dest: &mut T) {
match *self {
Message::Statement(ref h, ref s) => {
dest.push_byte(0);
dest.push(h);
dest.push(s);
}
Message::SessionKey(ref k) => {
dest.push_byte(1);
dest.push(k);
}
Message::RequestBlockData(ref id, ref r, ref d) => {
dest.push_byte(2);
dest.push(id);
dest.push(r);
dest.push(d);
}
Message::BlockData(ref id, ref d) => {
dest.push_byte(3);
dest.push(id);
dest.push(d);
}
Message::CollatorRole(ref r) => {
dest.push_byte(4);
dest.push(r);
}
Message::Collation(ref h, ref c) => {
dest.push_byte(5);
dest.push(h);
dest.push(c);
}
}
}
}
impl Decode for Message {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
match input.read_byte()? {
0 => Some(Message::Statement(Decode::decode(input)?, Decode::decode(input)?)),
1 => Some(Message::SessionKey(Decode::decode(input)?)),
2 => {
let x: (_, _, _) = Decode::decode(input)?;
Some(Message::RequestBlockData(x.0, x.1, x.2))
}
3 => Some(Message::BlockData(Decode::decode(input)?, Decode::decode(input)?)),
4 => Some(Message::CollatorRole(Decode::decode(input)?)),
5 => Some(Message::Collation(Decode::decode(input)?, Decode::decode(input)?)),
_ => None,
}
}
}
fn send_polkadot_message(ctx: &mut Context<Block>, to: NodeIndex, message: Message) {
trace!(target: "p_net", "Sending polkadot message to {}: {:?}", to, message);
let encoded = message.encode();
+1
View File
@@ -6,6 +6,7 @@ description = "Types and utilities for creating and working with parachains"
[dependencies]
substrate-codec = { path = "../../substrate/codec", default-features = false }
substrate-codec-derive = { path = "../../substrate/codec/derive", default-features = false }
wasmi = { version = "0.4", optional = true }
error-chain = { version = "0.12", optional = true }
+6 -33
View File
@@ -46,6 +46,9 @@
/// Re-export of substrate-codec.
pub extern crate substrate_codec as codec;
#[macro_use]
extern crate substrate_codec_derive;
#[cfg(not(feature = "std"))]
extern crate alloc;
@@ -61,14 +64,14 @@ extern crate error_chain;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use codec::{Encode, Decode, Input, Output};
use codec::{Encode, Decode};
#[cfg(feature = "std")]
pub mod wasm;
/// Validation parameters for evaluating the parachain validity function.
// TODO: consolidated ingress and balance downloads
#[derive(PartialEq, Eq)]
#[derive(PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct ValidationParams {
/// The collation body.
@@ -77,45 +80,15 @@ pub struct ValidationParams {
pub parent_head: Vec<u8>,
}
impl Encode for ValidationParams {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.block_data);
dest.push(&self.parent_head);
}
}
impl Decode for ValidationParams {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(ValidationParams {
block_data: Decode::decode(input)?,
parent_head: Decode::decode(input)?,
})
}
}
/// The result of parachain validation.
// TODO: egress and balance uploads
#[derive(PartialEq, Eq)]
#[derive(PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct ValidationResult {
/// New head data that should be included in the relay chain state.
pub head_data: Vec<u8>
}
impl Encode for ValidationResult {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.head_data);
}
}
impl Decode for ValidationResult {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(ValidationResult {
head_data: Decode::decode(input)?,
})
}
}
/// Load the validation params from memory when implementing a Rust parachain.
///
/// Offset and length must have been provided by the validation
+13 -44
View File
@@ -16,66 +16,35 @@
//! Basic parachain that adds a number as part of its state.
#[macro_use]
extern crate substrate_codec_derive;
extern crate substrate_codec as codec;
extern crate polkadot_parachain as parachain;
extern crate tiny_keccak;
use parachain::ValidationParams;
use parachain::codec::{Decode, Encode, Input, Output};
use codec::{Decode, Encode};
// Head data for this parachain.
#[derive(Default, Clone)]
/// Head data for this parachain.
#[derive(Default, Clone, Encode, Decode)]
struct HeadData {
// Block number
/// Block number
number: u64,
// parent block keccak256
/// parent block keccak256
parent_hash: [u8; 32],
// hash of post-execution state.
/// hash of post-execution state.
post_state: [u8; 32],
}
impl Encode for HeadData {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.number);
dest.push(&self.parent_hash);
dest.push(&self.post_state);
}
}
impl Decode for HeadData {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(HeadData {
number: Decode::decode(input)?,
parent_hash: Decode::decode(input)?,
post_state: Decode::decode(input)?,
})
}
}
// Block data for this parachain.
#[derive(Default, Clone)]
/// Block data for this parachain.
#[derive(Default, Clone, Encode, Decode)]
struct BlockData {
// State to begin from.
/// State to begin from.
state: u64,
// Amount to add (overflowing)
/// Amount to add (overflowing)
add: u64,
}
impl Encode for BlockData {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.state);
dest.push(&self.add);
}
}
impl Decode for BlockData {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(BlockData {
state: Decode::decode(input)?,
add: Decode::decode(input)?,
})
}
}
const TEST_CODE: &[u8] = include_bytes!("res/adder.wasm");
fn hash_state(state: u64) -> [u8; 32] {
Binary file not shown.
+1
View File
@@ -7,6 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
serde = { version = "1.0", default_features = false }
serde_derive = { version = "1.0", optional = true }
substrate-codec = { path = "../../substrate/codec", default_features = false }
substrate-codec-derive = { path = "../../substrate/codec/derive", default_features = false }
substrate-primitives = { path = "../../substrate/primitives", default_features = false }
substrate-runtime-std = { path = "../../substrate/runtime-std", default_features = false }
substrate-runtime-primitives = { path = "../../substrate/runtime/primitives", default_features = false }
+6 -16
View File
@@ -21,13 +21,16 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]
extern crate substrate_runtime_std as rstd;
extern crate substrate_codec as codec;
extern crate substrate_primitives as primitives;
extern crate substrate_runtime_primitives as runtime_primitives;
extern crate substrate_runtime_std as rstd;
#[cfg(test)]
extern crate substrate_serializer;
extern crate substrate_codec as codec;
#[macro_use]
extern crate substrate_codec_derive;
#[cfg(feature = "std")]
#[macro_use]
@@ -42,7 +45,6 @@ use primitives::bytes;
use rstd::prelude::*;
use runtime_primitives::traits::BlakeTwo256;
use runtime_primitives::generic;
use codec::{Encode, Decode, Input, Output};
pub mod parachain;
@@ -105,18 +107,6 @@ pub type Balance = u128;
pub type BlockId = generic::BlockId<Block>;
/// A log entry in the block.
#[derive(PartialEq, Eq, Clone, Default)]
#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Log(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
impl Decode for Log {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Vec::<u8>::decode(input).map(Log)
}
}
impl Encode for Log {
fn encode_to<T: Output>(&self, dest: &mut T) {
self.0.encode_to(dest)
}
}
+8 -129
View File
@@ -16,7 +16,6 @@
//! Polkadot parachain types.
use codec::{Encode, Decode, Input, Output};
use rstd::prelude::*;
use rstd::cmp::Ordering;
use super::Hash;
@@ -28,7 +27,7 @@ use primitives::bytes;
pub type CandidateSignature = ::runtime_primitives::Ed25519Signature;
/// Unique identifier of a parachain.
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Id(u32);
@@ -47,20 +46,8 @@ impl Id {
}
}
impl Decode for Id {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
u32::decode(input).map(Id)
}
}
impl Encode for Id {
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.0.using_encoded(f)
}
}
/// Identifier for a chain, either one of a number of parachains or the relay chain.
#[derive(Copy, Clone, PartialEq)]
#[derive(Copy, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum Chain {
/// The relay chain.
@@ -69,31 +56,8 @@ pub enum Chain {
Parachain(Id),
}
impl Decode for Chain {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
let disc = input.read_byte()?;
match disc {
0 => Some(Chain::Relay),
1 => Some(Chain::Parachain(Decode::decode(input)?)),
_ => None,
}
}
}
impl Encode for Chain {
fn encode_to<T: Output>(&self, dest: &mut T) {
match *self {
Chain::Relay => { dest.push_byte(0); }
Chain::Parachain(id) => {
dest.push_byte(1u8);
dest.push(&id);
}
}
}
}
/// The duty roster specifying what jobs each validator must do.
#[derive(Clone, PartialEq)]
#[derive(Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Default, Debug))]
pub struct DutyRoster {
/// Lookup from validator index to chain on which that validator has a duty to validate.
@@ -103,22 +67,6 @@ pub struct DutyRoster {
pub guarantor_duty: Vec<Chain>,
}
impl Decode for DutyRoster {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(DutyRoster {
validator_duty: Decode::decode(input)?,
guarantor_duty: Decode::decode(input)?,
})
}
}
impl Encode for DutyRoster {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.validator_duty);
dest.push(&self.guarantor_duty);
}
}
/// Extrinsic data for a parachain.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
@@ -127,7 +75,7 @@ impl Encode for DutyRoster {
pub struct Extrinsic;
/// Candidate receipt type.
#[derive(PartialEq, Eq, Clone)]
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
@@ -150,34 +98,6 @@ pub struct CandidateReceipt {
pub block_data_hash: Hash,
}
impl Encode for CandidateReceipt {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.parachain_index);
dest.push(&self.collator);
dest.push(&self.signature);
dest.push(&self.head_data.0);
dest.push(&self.balance_uploads);
dest.push(&self.egress_queue_roots);
dest.push(&self.fees);
dest.push(&self.block_data_hash);
}
}
impl Decode for CandidateReceipt {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(CandidateReceipt {
parachain_index: Decode::decode(input)?,
collator: Decode::decode(input)?,
signature: Decode::decode(input)?,
head_data: Decode::decode(input).map(HeadData)?,
balance_uploads: Decode::decode(input)?,
egress_queue_roots: Decode::decode(input)?,
fees: Decode::decode(input)?,
block_data_hash: Decode::decode(input)?,
})
}
}
impl CandidateReceipt {
/// Get the blake2_256 hash
#[cfg(feature = "std")]
@@ -213,7 +133,7 @@ impl Ord for CandidateReceipt {
}
/// A full collation.
#[derive(PartialEq, Eq, Clone)]
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
@@ -224,22 +144,6 @@ pub struct Collation {
pub receipt: CandidateReceipt,
}
impl Decode for Collation {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(Collation {
block_data: Decode::decode(input)?,
receipt: Decode::decode(input)?,
})
}
}
impl Encode for Collation {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.block_data);
dest.push(&self.receipt);
}
}
/// Parachain ingress queue message.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
@@ -256,7 +160,7 @@ pub struct ConsolidatedIngress(pub Vec<(Id, Vec<Message>)>);
/// Parachain block data.
///
/// contains everything required to validate para-block, may contain block and witness data
#[derive(PartialEq, Eq, Clone)]
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct BlockData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
@@ -268,26 +172,13 @@ impl BlockData {
BlakeTwo256::hash(&self.0[..])
}
}
impl Decode for BlockData {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(BlockData(Decode::decode(input)?))
}
}
impl Encode for BlockData {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.0);
}
}
/// Parachain header raw bytes wrapper type.
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Header(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Parachain head data included in the chain.
#[derive(PartialEq, Eq, Clone, PartialOrd, Ord)]
#[derive(PartialEq, Eq, Clone, PartialOrd, Ord, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct HeadData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
@@ -297,22 +188,10 @@ pub struct HeadData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8
pub struct ValidationCode(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Activitiy bit field
#[derive(PartialEq, Eq, Clone, Default)]
#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Activity(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
impl Decode for Activity {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Vec::<u8>::decode(input).map(Activity)
}
}
impl Encode for Activity {
fn encode_to<T: Output>(&self, dest: &mut T) {
self.0.encode_to(dest)
}
}
/// Statements which can be made about parachain candidates.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
+17 -3
View File
@@ -454,6 +454,7 @@ dependencies = [
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-primitives 0.1.0",
"substrate-runtime-std 0.1.0",
@@ -639,7 +640,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-hex"
version = "2.0.0"
source = "git+https://github.com/rphmeier/rustc-hex.git#ee2ec40b9062ac7769ccb9dc891d6dc2cc9009d7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc_version"
@@ -706,6 +707,15 @@ dependencies = [
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-codec-derive"
version = "0.1.0"
dependencies = [
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-keyring"
version = "0.1.0"
@@ -723,10 +733,11 @@ dependencies = [
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
"rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)",
"rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-runtime-std 0.1.0",
"twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
@@ -781,6 +792,7 @@ dependencies = [
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-consensus 0.1.0",
"substrate-runtime-io 0.1.0",
@@ -831,6 +843,7 @@ dependencies = [
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
"substrate-runtime-std 0.1.0",
@@ -954,6 +967,7 @@ dependencies = [
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-runtime-std 0.1.0",
"substrate-runtime-support 0.1.0",
]
@@ -1206,7 +1220,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rlp 0.2.1 (git+https://github.com/paritytech/parity.git)" = "<none>"
"checksum rlp 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "89db7f8dfdd5eb7ab3ac3ece7a07fd273a680b4b224cb231181280e8996f9f0b"
"checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e"
"checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "<none>"
"checksum rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b03280c2813907a030785570c577fb27d3deec8da4c18566751ade94de0ace"
"checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
@@ -5,5 +5,6 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
substrate-codec = { path = "../../substrate/codec" }
substrate-codec-derive = { path = "../../substrate/codec/derive" }
substrate-primitives = { path = "../../substrate/primitives" }
polkadot-primitives = { path = "../primitives" }
@@ -31,8 +31,6 @@ use std::collections::hash_map::{HashMap, Entry};
use std::hash::Hash;
use std::fmt::Debug;
use codec::{Decode, Encode, Input, Output};
/// Context for the statement table.
pub trait Context {
/// A authority ID
@@ -70,78 +68,30 @@ pub trait Context {
}
/// Statements circulated among peers.
#[derive(PartialEq, Eq, Debug, Clone)]
#[derive(PartialEq, Eq, Debug, Clone, Encode, Decode)]
pub enum Statement<C, D> {
/// Broadcast by a authority to indicate that this is his candidate for
/// inclusion.
///
/// Broadcasting two different candidate messages per round is not allowed.
#[codec(index = "1")]
Candidate(C),
/// Broadcast by a authority to attest that the candidate with given digest
/// is valid.
#[codec(index = "2")]
Valid(D),
/// Broadcast by a authority to attest that the auxiliary data for a candidate
/// with given digest is available.
Available(D),
/// Broadcast by a authority to attest that the candidate with given digest
/// is invalid.
#[codec(index = "3")]
Invalid(D),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
enum StatementKind {
Candidate = 1,
Valid = 2,
Invalid = 3,
Available = 4,
}
impl<C: Encode, D: Encode> Encode for Statement<C, D> {
fn encode_to<T: Output>(&self, dest: &mut T) {
match *self {
Statement::Candidate(ref candidate) => {
dest.push_byte(StatementKind::Candidate as u8);
dest.push(candidate);
}
Statement::Valid(ref digest) => {
dest.push_byte(StatementKind::Valid as u8);
dest.push(digest);
}
Statement::Invalid(ref digest) => {
dest.push_byte(StatementKind::Invalid as u8);
dest.push(digest);
}
Statement::Available(ref digest) => {
dest.push_byte(StatementKind::Available as u8);
dest.push(digest);
}
}
}
}
impl<C: Decode, D: Decode> Decode for Statement<C, D> {
fn decode<I: Input>(value: &mut I) -> Option<Self> {
match value.read_byte() {
Some(x) if x == StatementKind::Candidate as u8 => {
Decode::decode(value).map(Statement::Candidate)
}
Some(x) if x == StatementKind::Valid as u8 => {
Decode::decode(value).map(Statement::Valid)
}
Some(x) if x == StatementKind::Invalid as u8 => {
Decode::decode(value).map(Statement::Invalid)
}
Some(x) if x == StatementKind::Available as u8 => {
Decode::decode(value).map(Statement::Available)
}
_ => None,
}
}
/// Broadcast by a authority to attest that the auxiliary data for a candidate
/// with given digest is available.
#[codec(index = "4")]
Available(D),
}
/// A signed statement.
#[derive(PartialEq, Eq, Debug, Clone)]
#[derive(PartialEq, Eq, Debug, Clone, Encode, Decode)]
pub struct SignedStatement<C, D, V, S> {
/// The statement.
pub statement: Statement<C, D>,
@@ -151,23 +101,6 @@ pub struct SignedStatement<C, D, V, S> {
pub sender: V,
}
impl<C: Encode, D: Encode, V: Encode, S: Encode> Encode for SignedStatement<C, D, V, S> {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.statement);
dest.push(&self.signature);
dest.push(&self.sender);
}
}
impl<C: Decode, D: Decode, V: Decode, S: Decode> Decode for SignedStatement<C, D, V, S> {
fn decode<I: Input>(value: &mut I) -> Option<Self> {
Some(SignedStatement {
statement: Decode::decode(value)?,
signature: Decode::decode(value)?,
sender: Decode::decode(value)?,
})
}
}
/// Misbehavior: voting more than one way on candidate validity.
///
/// Since there are three possible ways to vote, a double vote is possible in
@@ -18,6 +18,9 @@ extern crate substrate_codec as codec;
extern crate substrate_primitives;
extern crate polkadot_primitives as primitives;
#[macro_use]
extern crate substrate_codec_derive;
pub mod generic;
pub use generic::Table;
@@ -6,4 +6,5 @@ description = "Test parachain which adds to a number as its state transition"
[dependencies]
polkadot-parachain = { path = "../../parachain/", default-features = false }
substrate-codec-derive = { path = "../../../substrate/codec/derive", default-features = false }
tiny-keccak = "1.4"
@@ -18,13 +18,16 @@
#![no_std]
#[macro_use]
extern crate substrate_codec_derive;
extern crate polkadot_parachain as parachain;
extern crate tiny_keccak;
use parachain::codec::{Decode, Encode, Input, Output};
use parachain::codec::{self, Encode};
/// Head data for this parachain.
#[derive(Default, Clone, Hash, Eq, PartialEq)]
#[derive(Default, Clone, Hash, Eq, PartialEq, Encode, Decode)]
pub struct HeadData {
/// Block number
pub number: u64,
@@ -40,26 +43,8 @@ impl HeadData {
}
}
impl Encode for HeadData {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.number);
dest.push(&self.parent_hash);
dest.push(&self.post_state);
}
}
impl Decode for HeadData {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(HeadData {
number: Decode::decode(input)?,
parent_hash: Decode::decode(input)?,
post_state: Decode::decode(input)?,
})
}
}
/// Block data for this parachain.
#[derive(Default, Clone)]
#[derive(Default, Clone, Encode, Decode)]
pub struct BlockData {
/// State to begin from.
pub state: u64,
@@ -67,22 +52,6 @@ pub struct BlockData {
pub add: u64,
}
impl Encode for BlockData {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.state);
dest.push(&self.add);
}
}
impl Decode for BlockData {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(BlockData {
state: Decode::decode(input)?,
add: Decode::decode(input)?,
})
}
}
pub fn hash_state(state: u64) -> [u8; 32] {
::tiny_keccak::keccak256(state.encode().as_slice())
}
+1
View File
@@ -18,6 +18,7 @@ substrate-client = { path = "../../../substrate/client" }
substrate-state-machine = { path = "../../../substrate/state-machine" }
substrate-runtime-support = { path = "../../../substrate/runtime-support" }
substrate-codec = { path = "../../../substrate/codec" }
substrate-codec-derive = { path = "../../../substrate/codec/derive" }
substrate-executor = { path = "../../../substrate/executor" }
substrate-state-db = { path = "../../../substrate/state-db" }
+2 -17
View File
@@ -23,7 +23,7 @@ use kvdb::{KeyValueDB, DBTransaction};
use client::blockchain::Cache as BlockchainCache;
use client::error::Result as ClientResult;
use codec::{Codec, Encode, Decode, Input, Output};
use codec::{Codec, Encode, Decode};
use primitives::AuthorityId;
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{Block as BlockT, As, NumberFor};
@@ -107,6 +107,7 @@ pub struct Entry<N, T: Clone> {
/// Internal representation of the single cache entry. The entry points to the
/// previous entry in the cache, allowing us to traverse back in time in list-style.
#[derive(Encode, Decode)]
#[cfg_attr(test, derive(Debug, PartialEq))]
struct StorageEntry<N, T> {
/// None if valid from the beginning
@@ -298,22 +299,6 @@ fn read_storage_entry<Block, T>(
.map_err(db_err)
}
impl<N: Encode, T: Encode> Encode for StorageEntry<N, T> {
fn encode_to<O: Output>(&self, dest: &mut O) {
dest.push(&self.prev_valid_from);
dest.push(&self.value);
}
}
impl<N: Decode, T: Decode> Decode for StorageEntry<N, T> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(StorageEntry {
prev_valid_from: Decode::decode(input)?,
value: Decode::decode(input)?,
})
}
}
#[cfg(test)]
mod tests {
use runtime_primitives::testing::Block as RawBlock;
+3
View File
@@ -33,6 +33,9 @@ extern crate substrate_state_db as state_db;
#[macro_use]
extern crate log;
#[macro_use]
extern crate substrate_codec_derive;
#[cfg(test)]
extern crate kvdb_memorydb;
@@ -0,0 +1,20 @@
[package]
name = "substrate-codec-derive"
description = "Serialization and deserialization derive macro"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[lib]
proc-macro = true
[dependencies]
syn = "0.14"
quote = "0.6"
proc-macro2 = "0.4"
[dev-dependencies]
substrate-codec = { path = "../" }
[features]
default = ["std"]
std = []
@@ -0,0 +1,111 @@
// Copyright 2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use proc_macro2::{Span, TokenStream, Ident};
use syn::{
Data, Fields,
spanned::Spanned,
};
pub fn quote(data: &Data, type_name: &Ident, input: &TokenStream) -> TokenStream {
let call_site = Span::call_site();
match *data {
Data::Struct(ref data) => match data.fields {
Fields::Named(_) | Fields::Unnamed(_) => create_instance(
call_site,
quote! { #type_name },
input,
&data.fields,
),
Fields::Unit => {
quote_spanned! {call_site =>
drop(#input);
Some(#type_name)
}
},
},
Data::Enum(ref data) => {
assert!(data.variants.len() < 256, "Currently only enums with at most 256 variants are encodable.");
let recurse = data.variants.iter().enumerate().map(|(i, v)| {
let name = &v.ident;
let index = super::index(v, i);
let create = create_instance(
call_site,
quote! { #type_name :: #name },
input,
&v.fields,
);
quote_spanned! { v.span() =>
x if x == #index as u8 => {
#create
},
}
});
quote! {
match #input.read_byte()? {
#( #recurse )*
_ => None,
}
}
},
Data::Union(_) => panic!("Union types are not supported."),
}
}
fn create_instance(call_site: Span, name: TokenStream, input: &TokenStream, fields: &Fields) -> TokenStream {
match *fields {
Fields::Named(ref fields) => {
let recurse = fields.named.iter().map(|f| {
let name = &f.ident;
let field = quote_spanned!(call_site => #name);
quote_spanned! { f.span() =>
#field: ::codec::Decode::decode(#input)?
}
});
quote_spanned! {call_site =>
Some(#name {
#( #recurse, )*
})
}
},
Fields::Unnamed(ref fields) => {
let recurse = fields.unnamed.iter().map(|f| {
quote_spanned! { f.span() =>
::codec::Decode::decode(#input)?
}
});
quote_spanned! {call_site =>
Some(#name (
#( #recurse, )*
))
}
},
Fields::Unit => {
quote_spanned! {call_site =>
Some(#name)
}
},
}
}
@@ -0,0 +1,153 @@
// Copyright 2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
#[cfg(not(feature = "std"))]
use core::str::from_utf8;
#[cfg(feature = "std")]
use std::str::from_utf8;
use proc_macro2::{Span, TokenStream};
use syn::{
Data, Field, Fields, Ident, Index,
punctuated::Punctuated,
spanned::Spanned,
token::Comma,
};
type FieldsList = Punctuated<Field, Comma>;
fn encode_fields<F>(
dest: &TokenStream,
fields: &FieldsList,
field_name: F,
) -> TokenStream where
F: Fn(usize, &Option<Ident>) -> TokenStream,
{
let recurse = fields.iter().enumerate().map(|(i, f)| {
let field = field_name(i, &f.ident);
quote_spanned! { f.span() =>
#dest.push(#field);
}
});
quote! {
#( #recurse )*
}
}
pub fn quote(data: &Data, type_name: &Ident, self_: &TokenStream, dest: &TokenStream) -> TokenStream {
let call_site = Span::call_site();
match *data {
Data::Struct(ref data) => match data.fields {
Fields::Named(ref fields) => encode_fields(
dest,
&fields.named,
|_, name| quote_spanned!(call_site => &#self_.#name),
),
Fields::Unnamed(ref fields) => encode_fields(
dest,
&fields.unnamed,
|i, _| {
let index = Index { index: i as u32, span: call_site };
quote_spanned!(call_site => &#self_.#index)
},
),
Fields::Unit => quote_spanned! { call_site =>
drop(#dest);
},
},
Data::Enum(ref data) => {
assert!(data.variants.len() < 256, "Currently only enums with at most 256 variants are encodable.");
let recurse = data.variants.iter().enumerate().map(|(i, f)| {
let name = &f.ident;
let index = super::index(f, i);
match f.fields {
Fields::Named(ref fields) => {
let field_name = |_, ident: &Option<Ident>| quote_spanned!(call_site => #ident);
let names = fields.named
.iter()
.enumerate()
.map(|(i, f)| field_name(i, &f.ident));
let encode_fields = encode_fields(
dest,
&fields.named,
|a, b| field_name(a, b),
);
quote_spanned! { f.span() =>
#type_name :: #name { #( ref #names, )* } => {
#dest.push_byte(#index as u8);
#encode_fields
}
}
},
Fields::Unnamed(ref fields) => {
let field_name = |i, _: &Option<Ident>| {
let data = stringify(i as u8);
let ident = from_utf8(&data).expect("We never go beyond ASCII");
let ident = Ident::new(ident, call_site);
quote_spanned!(call_site => #ident)
};
let names = fields.unnamed
.iter()
.enumerate()
.map(|(i, f)| field_name(i, &f.ident));
let encode_fields = encode_fields(
dest,
&fields.unnamed,
|a, b| field_name(a, b),
);
quote_spanned! { f.span() =>
#type_name :: #name ( #( ref #names, )* ) => {
#dest.push_byte(#index as u8);
#encode_fields
}
}
},
Fields::Unit => {
quote_spanned! { f.span() =>
#type_name :: #name => {
#dest.push_byte(#index as u8);
}
}
},
}
});
quote! {
match *#self_ {
#( #recurse )*,
}
}
},
Data::Union(_) => panic!("Union types are not supported."),
}
}
pub fn stringify(id: u8) -> [u8; 2] {
const CHARS: &[u8] = b"abcdefghijklmnopqrstuvwxyz";
let len = CHARS.len() as u8;
let symbol = |id: u8| CHARS[(id % len) as usize];
let a = symbol(id);
let b = symbol(id / len);
[a, b]
}
+127
View File
@@ -0,0 +1,127 @@
// Copyright 2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Derives serialization and deserialization codec for complex structs for simple marshalling.
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]
extern crate proc_macro;
extern crate proc_macro2;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;
use proc_macro::TokenStream;
use syn::{DeriveInput, Generics, GenericParam, Ident};
mod decode;
mod encode;
const ENCODE_ERR: &str = "derive(Encode) failed";
#[proc_macro_derive(Encode, attributes(codec))]
pub fn encode_derive(input: TokenStream) -> TokenStream {
let input: DeriveInput = syn::parse(input).expect(ENCODE_ERR);
let name = &input.ident;
let generics = add_trait_bounds(input.generics, parse_quote!(::codec::Encode));
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let self_ = quote!(self);
let dest_ = quote!(dest);
let encoding = encode::quote(&input.data, name, &self_, &dest_);
let expanded = quote! {
impl #impl_generics ::codec::Encode for #name #ty_generics #where_clause {
fn encode_to<EncOut: ::codec::Output>(&#self_, #dest_: &mut EncOut) {
#encoding
}
}
};
expanded.into()
}
#[proc_macro_derive(Decode, attributes(codec))]
pub fn decode_derive(input: TokenStream) -> TokenStream {
let input: DeriveInput = syn::parse(input).expect(ENCODE_ERR);
let name = &input.ident;
let generics = add_trait_bounds(input.generics, parse_quote!(::codec::Decode));
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let input_ = quote!(input);
let decoding = decode::quote(&input.data, name, &input_);
let expanded = quote! {
impl #impl_generics ::codec::Decode for #name #ty_generics #where_clause {
fn decode<DecIn: ::codec::Input>(#input_: &mut DecIn) -> Option<Self> {
#decoding
}
}
};
expanded.into()
}
fn add_trait_bounds(mut generics: Generics, bounds: syn::TypeParamBound) -> Generics {
for param in &mut generics.params {
if let GenericParam::Type(ref mut type_param) = *param {
type_param.bounds.push(bounds.clone());
}
}
generics
}
fn index(v: &syn::Variant, i: usize) -> proc_macro2::TokenStream {
// look for an index in attributes
let index = v.attrs.iter().filter_map(|attr| {
let pair = attr.path.segments.first()?;
let seg = pair.value();
if seg.ident == Ident::new("codec", seg.ident.span()) {
assert_eq!(attr.path.segments.len(), 1);
let meta = attr.interpret_meta();
if let Some(syn::Meta::List(ref l)) = meta {
if let syn::NestedMeta::Meta(syn::Meta::NameValue(ref nv)) = l.nested.last().unwrap().value() {
assert_eq!(nv.ident, Ident::new("index", nv.ident.span()));
if let syn::Lit::Str(ref s) = nv.lit {
let byte: u8 = s.value().parse().expect("Numeric index expected.");
return Some(byte)
}
panic!("Invalid syntax for `codec` attribute: Expected string literal.")
}
}
panic!("Invalid syntax for `codec` attribute: Expected `name = value` pair.")
} else {
None
}
}).next();
// then fallback to discriminant or just index
index.map(|i| quote! { #i })
.unwrap_or_else(|| v.discriminant
.as_ref()
.map(|&(_, ref expr)| quote! { #expr })
.unwrap_or_else(|| quote! { #i })
)
}
@@ -0,0 +1,151 @@
// Copyright 2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
extern crate substrate_codec as codec;
#[macro_use]
extern crate substrate_codec_derive;
use codec::{Encode, Decode};
#[derive(Debug, PartialEq, Encode, Decode)]
struct Unit;
#[derive(Debug, PartialEq, Encode, Decode)]
struct Indexed(u32, u64);
#[derive(Debug, PartialEq, Encode, Decode)]
struct Struct<A, B, C> {
pub a: A,
pub b: B,
pub c: C,
}
type TestType = Struct<u32, u64, Vec<u8>>;
impl <A, B, C> Struct<A, B, C> {
fn new(a: A, b: B, c: C) -> Self {
Self { a, b, c }
}
}
#[derive(Debug, PartialEq, Encode, Decode)]
enum EnumType {
#[codec(index = "15")]
A,
B(u32, u64),
C {
a: u32,
b: u64,
},
}
#[derive(Debug, PartialEq, Encode, Decode)]
enum EnumWithDiscriminant {
A = 1,
B = 15,
C = 255,
}
#[test]
fn should_work_for_simple_enum() {
let a = EnumType::A;
let b = EnumType::B(1, 2);
let c = EnumType::C { a: 1, b: 2 };
a.using_encoded(|ref slice| {
assert_eq!(slice, &b"\x0f");
});
b.using_encoded(|ref slice| {
assert_eq!(slice, &b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0");
});
c.using_encoded(|ref slice| {
assert_eq!(slice, &b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0");
});
let mut da: &[u8] = b"\x0f";
assert_eq!(EnumType::decode(&mut da), Some(a));
let mut db: &[u8] = b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0";
assert_eq!(EnumType::decode(&mut db), Some(b));
let mut dc: &[u8] = b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0";
assert_eq!(EnumType::decode(&mut dc), Some(c));
let mut dz: &[u8] = &[0];
assert_eq!(EnumType::decode(&mut dz), None);
}
#[test]
fn should_work_for_enum_with_discriminant() {
EnumWithDiscriminant::A.using_encoded(|ref slice| {
assert_eq!(slice, &[1]);
});
EnumWithDiscriminant::B.using_encoded(|ref slice| {
assert_eq!(slice, &[15]);
});
EnumWithDiscriminant::C.using_encoded(|ref slice| {
assert_eq!(slice, &[255]);
});
let mut da: &[u8] = &[1];
assert_eq!(EnumWithDiscriminant::decode(&mut da), Some(EnumWithDiscriminant::A));
let mut db: &[u8] = &[15];
assert_eq!(EnumWithDiscriminant::decode(&mut db), Some(EnumWithDiscriminant::B));
let mut dc: &[u8] = &[255];
assert_eq!(EnumWithDiscriminant::decode(&mut dc), Some(EnumWithDiscriminant::C));
let mut dz: &[u8] = &[2];
assert_eq!(EnumWithDiscriminant::decode(&mut dz), None);
}
#[test]
fn should_derive_encode() {
let v = TestType::new(15, 9, b"Hello world".to_vec());
v.using_encoded(|ref slice| {
assert_eq!(slice, &b"\x0f\0\0\0\x09\0\0\0\0\0\0\0\x0b\0\0\0Hello world")
});
}
#[test]
fn should_derive_decode() {
let slice = b"\x0f\0\0\0\x09\0\0\0\0\0\0\0\x0b\0\0\0Hello world".to_vec();
let v = TestType::decode(&mut &*slice);
assert_eq!(v, Some(TestType::new(15, 9, b"Hello world".to_vec())));
}
#[test]
fn should_work_for_unit() {
let v = Unit;
v.using_encoded(|ref slice| {
assert_eq!(slice, &[]);
});
let mut a: &[u8] = &[];
assert_eq!(Unit::decode(&mut a), Some(Unit));
}
#[test]
fn should_work_for_indexed() {
let v = Indexed(1, 2);
v.using_encoded(|ref slice| {
assert_eq!(slice, &b"\x01\0\0\0\x02\0\0\0\0\0\0\0")
});
let mut v: &[u8] = b"\x01\0\0\0\x02\0\0\0\0\0\0\0";
assert_eq!(Indexed::decode(&mut v), Some(Indexed(1, 2)));
}
+36
View File
@@ -20,6 +20,7 @@ use alloc::vec::Vec;
use alloc::boxed::Box;
use core::{mem, slice};
use arrayvec::ArrayVec;
/// Trait that allows reading of data into a slice.
pub trait Input {
/// Read into the provided input slice. Returns the number of bytes read.
@@ -113,6 +114,7 @@ pub trait Decode: Sized {
/// Trait that allows zero-copy read/write of value-references to/from slices in LE format.
pub trait Codec: Decode + Encode {}
impl<S: Decode + Encode> Codec for S {}
impl<T: Encode, E: Encode> Encode for Result<T, E> {
@@ -252,6 +254,40 @@ impl Decode for Vec<u8> {
}
}
impl<'a> Encode for &'a str {
fn encode_to<W: Output>(&self, dest: &mut W) {
self.as_bytes().encode_to(dest)
}
}
#[cfg(feature = "std")]
impl<'a > Encode for ::std::borrow::Cow<'a, str> {
fn encode_to<W: Output>(&self, dest: &mut W) {
self.as_bytes().encode_to(dest)
}
}
#[cfg(feature = "std")]
impl<'a> Decode for ::std::borrow::Cow<'a, str> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(::std::borrow::Cow::Owned(String::from_utf8_lossy(&Vec::decode(input)?).into()))
}
}
#[cfg(feature = "std")]
impl Encode for String {
fn encode_to<W: Output>(&self, dest: &mut W) {
self.as_bytes().encode_to(dest)
}
}
#[cfg(feature = "std")]
impl Decode for String {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(Self::from_utf8_lossy(&Vec::decode(input)?).into())
}
}
impl<T: Encode> Encode for [T] {
fn encode_to<W: Output>(&self, dest: &mut W) {
let len = self.len();
+1 -1
View File
@@ -20,7 +20,7 @@ use Codec;
use core::iter::Extend;
use alloc::vec::Vec;
/// Trait to allow itselg to be serialised and prepended by a given slice.
/// Trait to allow itself to be serialised and prepended by a given slice.
pub trait KeyedVec {
fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec<u8>;
}
+48 -3
View File
@@ -26,6 +26,14 @@ name = "nodrop"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pwasm-alloc"
version = "0.1.0"
@@ -38,6 +46,14 @@ dependencies = [
name = "pwasm-libc"
version = "0.1.0"
[[package]]
name = "quote"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "runtime-test"
version = "0.1.0"
@@ -49,7 +65,7 @@ dependencies = [
[[package]]
name = "rustc-hex"
version = "2.0.0"
source = "git+https://github.com/rphmeier/rustc-hex.git#ee2ec40b9062ac7769ccb9dc891d6dc2cc9009d7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc_version"
@@ -84,6 +100,15 @@ dependencies = [
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-codec-derive"
version = "0.1.0"
dependencies = [
"proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-primitives"
version = "0.1.0"
@@ -91,9 +116,10 @@ dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
"rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)",
"rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-runtime-std 0.1.0",
"uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
]
@@ -128,6 +154,16 @@ dependencies = [
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "uint"
version = "0.1.2"
@@ -137,15 +173,24 @@ dependencies = [
"rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
"checksum fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "<none>"
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
"checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "<none>"
"checksum proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "cccdc7557a98fe98453030f077df7f3a042052fae465bb61d2c2c41435cfd9b6"
"checksum quote 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3372dc35766b36a99ce2352bd1b6ea0137c38d215cc0c8780bf6de6df7842ba9"
"checksum rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b03280c2813907a030785570c577fb27d3deec8da4c18566751ade94de0ace"
"checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69"
"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526"
"checksum syn 0.14.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e13df71f29f9440b50261a5882c86eac334f1badb3134ec26f0de2f1418e44"
"checksum uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "<none>"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
+1
View File
@@ -20,6 +20,7 @@ substrate-primitives = { path = "../../substrate/primitives" }
substrate-client = { path = "../../substrate/client" }
substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" }
substrate-codec = { path = "../../substrate/codec" }
substrate-codec-derive = { path = "../../substrate/codec/derive" }
substrate-network-libp2p = { path = "../../substrate/network-libp2p" }
[dev-dependencies]
+1
View File
@@ -33,6 +33,7 @@ extern crate ed25519;
#[macro_use] extern crate log;
#[macro_use] extern crate bitflags;
#[macro_use] extern crate error_chain;
#[macro_use] extern crate substrate_codec_derive;
#[cfg(test)] extern crate env_logger;
#[cfg(test)] extern crate substrate_keyring as keyring;
+29 -388
View File
@@ -102,7 +102,19 @@ bitflags! {
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
impl Encode for BlockAttributes {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push_byte(self.bits())
}
}
impl Decode for BlockAttributes {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Self::from_bits(input.read_byte()?)
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Encode, Decode)]
/// Block enumeration direction.
pub enum Direction {
/// Enumerate in ascending order (from child to parent).
@@ -112,7 +124,7 @@ pub enum Direction {
}
/// Remote call response.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct RemoteCallResponse {
/// Id of a request this response was made for.
pub id: RequestId,
@@ -120,26 +132,9 @@ pub struct RemoteCallResponse {
pub proof: Vec<Vec<u8>>,
}
impl Encode for RemoteCallResponse {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.id);
dest.push(&self.proof);
}
}
impl Decode for RemoteCallResponse {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(RemoteCallResponse {
id: Decode::decode(input)?,
proof: Decode::decode(input)?,
})
}
}
/// Generic types.
pub mod generic {
use primitives::AuthorityId;
use codec::{Decode, Encode, Input, Output};
use runtime_primitives::bft::Justification;
use ed25519;
use service::Roles;
@@ -147,7 +142,7 @@ pub mod generic {
/// Block data sent in the response.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct BlockData<Header, Hash, Extrinsic> {
/// Block header hash.
pub hash: Hash,
@@ -163,32 +158,8 @@ pub mod generic {
pub justification: Option<Justification<Hash>>,
}
impl<Header: Encode, Hash: Encode, Extrinsic: Encode> Encode for BlockData<Header, Hash, Extrinsic> {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.hash);
dest.push(&self.header);
dest.push(&self.body);
dest.push(&self.receipt);
dest.push(&self.message_queue);
dest.push(&self.justification);
}
}
impl<Header: Decode, Hash: Decode, Extrinsic: Decode> Decode for BlockData<Header, Hash, Extrinsic> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(BlockData {
hash: Decode::decode(input)?,
header: Decode::decode(input)?,
body: Decode::decode(input)?,
receipt: Decode::decode(input)?,
message_queue: Decode::decode(input)?,
justification: Decode::decode(input)?,
})
}
}
/// Identifies starting point of a block sequence.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub enum FromBlock<Hash, Number> {
/// Start with given hash.
Hash(Hash),
@@ -196,33 +167,8 @@ pub mod generic {
Number(Number),
}
impl<Hash: Encode, Number: Encode> Encode for FromBlock<Hash, Number> {
fn encode_to<T: Output>(&self, dest: &mut T) {
match *self {
FromBlock::Hash(ref h) => {
dest.push_byte(0);
dest.push(h);
}
FromBlock::Number(ref n) => {
dest.push_byte(1);
dest.push(n);
}
}
}
}
impl<Hash: Decode, Number: Decode> Decode for FromBlock<Hash, Number> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
match input.read_byte()? {
0 => Some(FromBlock::Hash(Decode::decode(input)?)),
1 => Some(FromBlock::Number(Decode::decode(input)?)),
_ => None,
}
}
}
/// Communication that can occur between participants in consensus.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub enum BftMessage<Block, Hash> {
/// A consensus message (proposal or vote)
Consensus(SignedConsensusMessage<Block, Hash>),
@@ -230,33 +176,8 @@ pub mod generic {
Auxiliary(Justification<Hash>),
}
impl<Block: Encode, Hash: Encode> Encode for BftMessage<Block, Hash> {
fn encode_to<T: Output>(&self, dest: &mut T) {
match *self {
BftMessage::Consensus(ref h) => {
dest.push_byte(0);
dest.push(h);
}
BftMessage::Auxiliary(ref n) => {
dest.push_byte(1);
dest.push(n);
}
}
}
}
impl<Block: Decode, Hash: Decode> Decode for BftMessage<Block, Hash> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
match input.read_byte()? {
0 => Some(BftMessage::Consensus(Decode::decode(input)?)),
1 => Some(BftMessage::Auxiliary(Decode::decode(input)?)),
_ => None,
}
}
}
/// BFT Consensus message with parent header hash attached to it.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct LocalizedBftMessage<Block, Hash> {
/// Consensus message.
pub message: BftMessage<Block, Hash>,
@@ -264,24 +185,8 @@ pub mod generic {
pub parent_hash: Hash,
}
impl<Block: Encode, Hash: Encode> Encode for LocalizedBftMessage<Block, Hash> {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.message);
dest.push(&self.parent_hash);
}
}
impl<Block: Decode, Hash: Decode> Decode for LocalizedBftMessage<Block, Hash> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(LocalizedBftMessage {
message: Decode::decode(input)?,
parent_hash: Decode::decode(input)?,
})
}
}
/// A localized proposal message. Contains two signed pieces of data.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct SignedConsensusProposal<Block, Hash> {
/// The round number.
pub round_number: u32,
@@ -297,32 +202,8 @@ pub mod generic {
pub full_signature: ed25519::Signature,
}
impl<Block: Encode, Hash: Encode> Encode for SignedConsensusProposal<Block, Hash> {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.round_number);
dest.push(&self.proposal);
dest.push(&self.digest);
dest.push(&self.sender);
dest.push(&self.digest_signature);
dest.push(&self.full_signature);
}
}
impl<Block: Decode, Hash: Decode> Decode for SignedConsensusProposal<Block, Hash> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(SignedConsensusProposal {
round_number: Decode::decode(input)?,
proposal: Decode::decode(input)?,
digest: Decode::decode(input)?,
sender: Decode::decode(input)?,
digest_signature: Decode::decode(input)?,
full_signature: Decode::decode(input)?,
})
}
}
/// A localized vote message, including the sender.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct SignedConsensusVote<H> {
/// The message sent.
pub vote: ConsensusVote<H>,
@@ -332,26 +213,8 @@ pub mod generic {
pub signature: ed25519::Signature,
}
impl<Hash: Encode> Encode for SignedConsensusVote<Hash> {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.vote);
dest.push(&self.sender);
dest.push(&self.signature);
}
}
impl<Hash: Decode> Decode for SignedConsensusVote<Hash> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(SignedConsensusVote {
vote: Decode::decode(input)?,
sender: Decode::decode(input)?,
signature: Decode::decode(input)?,
})
}
}
/// Votes during a consensus round.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub enum ConsensusVote<H> {
/// Prepare to vote for proposal with digest D.
Prepare(u32, H),
@@ -361,40 +224,8 @@ pub mod generic {
AdvanceRound(u32),
}
impl<Hash: Encode> Encode for ConsensusVote<Hash> {
fn encode_to<T: Output>(&self, dest: &mut T) {
match *self {
ConsensusVote::Prepare(ref r, ref h) => {
dest.push_byte(0);
dest.push(r);
dest.push(h);
}
ConsensusVote::Commit(ref r, ref h) => {
dest.push_byte(1);
dest.push(r);
dest.push(h);
}
ConsensusVote::AdvanceRound(ref r) => {
dest.push_byte(2);
dest.push(r);
}
}
}
}
impl<Hash: Decode> Decode for ConsensusVote<Hash> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
match input.read_byte()? {
0 => Some(ConsensusVote::Prepare(Decode::decode(input)?, Decode::decode(input)?)),
1 => Some(ConsensusVote::Commit(Decode::decode(input)?, Decode::decode(input)?)),
2 => Some(ConsensusVote::AdvanceRound(Decode::decode(input)?)),
_ => None,
}
}
}
/// A localized message.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub enum SignedConsensusMessage<Block, Hash> {
/// A proposal.
Propose(SignedConsensusProposal<Block, Hash>),
@@ -402,33 +233,8 @@ pub mod generic {
Vote(SignedConsensusVote<Hash>),
}
impl<Block: Encode, Hash: Encode> Encode for SignedConsensusMessage<Block, Hash> {
fn encode_to<T: Output>(&self, dest: &mut T) {
match *self {
SignedConsensusMessage::Propose(ref m) => {
dest.push_byte(0);
dest.push(m);
}
SignedConsensusMessage::Vote(ref m) => {
dest.push_byte(1);
dest.push(m);
}
}
}
}
impl<Block: Decode, Hash: Decode> Decode for SignedConsensusMessage<Block, Hash> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
match input.read_byte()? {
0 => Some(SignedConsensusMessage::Propose(Decode::decode(input)?)),
1 => Some(SignedConsensusMessage::Vote(Decode::decode(input)?)),
_ => None,
}
}
}
/// A network message.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub enum Message<Block, Header, Hash, Number, Extrinsic> {
/// Status packet.
Status(Status<Hash, Number>),
@@ -447,75 +253,12 @@ pub mod generic {
/// Remote method call response.
RemoteCallResponse(RemoteCallResponse),
/// Chain-specific message
#[codec(index = "255")]
ChainSpecific(Vec<u8>),
}
impl<Block: Encode, Header: Encode, Hash: Encode, Number: Encode, Extrinsic: Encode> Encode
for Message<Block, Header, Hash, Number, Extrinsic>
{
fn encode_to<T: Output>(&self, dest: &mut T) {
match *self {
Message::Status(ref m) => {
dest.push_byte(0);
dest.push(m);
}
Message::BlockRequest(ref m) => {
dest.push_byte(1);
dest.push(m);
}
Message::BlockResponse(ref m) => {
dest.push_byte(2);
dest.push(m);
}
Message::BlockAnnounce(ref m) => {
dest.push_byte(3);
dest.push(m);
}
Message::Transactions(ref m) => {
dest.push_byte(4);
dest.push(m);
}
Message::BftMessage(ref m) => {
dest.push_byte(5);
dest.push(m);
}
Message::RemoteCallRequest(ref m) => {
dest.push_byte(6);
dest.push(m);
}
Message::RemoteCallResponse(ref m) => {
dest.push_byte(7);
dest.push(m);
}
Message::ChainSpecific(ref m) => {
dest.push_byte(255);
dest.push(m);
}
}
}
}
impl<Block: Decode, Header: Decode, Hash: Decode, Number: Decode, Extrinsic: Decode> Decode
for Message<Block, Header, Hash, Number, Extrinsic>
{
fn decode<I: Input>(input: &mut I) -> Option<Self> {
match input.read_byte()? {
0 => Some(Message::Status(Decode::decode(input)?)),
1 => Some(Message::BlockRequest(Decode::decode(input)?)),
2 => Some(Message::BlockResponse(Decode::decode(input)?)),
3 => Some(Message::BlockAnnounce(Decode::decode(input)?)),
4 => Some(Message::Transactions(Decode::decode(input)?)),
5 => Some(Message::BftMessage(Decode::decode(input)?)),
6 => Some(Message::RemoteCallRequest(Decode::decode(input)?)),
7 => Some(Message::RemoteCallResponse(Decode::decode(input)?)),
255 => Some(Message::ChainSpecific(Decode::decode(input)?)),
_ => None,
}
}
}
/// Status sent on connection.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct Status<Hash, Number> {
/// Protocol version.
pub version: u32,
@@ -531,32 +274,8 @@ pub mod generic {
pub chain_status: Vec<u8>,
}
impl<Hash: Encode, Number: Encode> Encode for Status<Hash, Number> {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.version);
dest.push_byte(self.roles.bits());
dest.push(&self.best_number);
dest.push(&self.best_hash);
dest.push(&self.genesis_hash);
dest.push(&self.chain_status);
}
}
impl<Hash: Decode, Number: Decode> Decode for Status<Hash, Number> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(Status {
version: Decode::decode(input)?,
roles: Roles::from_bits(input.read_byte()?)?,
best_number: Decode::decode(input)?,
best_hash: Decode::decode(input)?,
genesis_hash: Decode::decode(input)?,
chain_status: Decode::decode(input)?,
})
}
}
/// Request block data from a peer.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct BlockRequest<Hash, Number> {
/// Unique request id.
pub id: RequestId,
@@ -572,36 +291,8 @@ pub mod generic {
pub max: Option<u32>,
}
impl<Hash: Encode, Number: Encode> Encode for BlockRequest<Hash, Number> {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.id);
dest.push_byte(self.fields.bits());
dest.push(&self.from);
dest.push(&self.to);
dest.push_byte(self.direction as u8);
dest.push(&self.max);
}
}
impl<Hash: Decode, Number: Decode> Decode for BlockRequest<Hash, Number> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(BlockRequest {
id: Decode::decode(input)?,
fields: BlockAttributes::from_bits(input.read_byte()?)?,
from: Decode::decode(input)?,
to: Decode::decode(input)?,
direction: match input.read_byte()? {
x if x == Direction::Ascending as u8 => Some(Direction::Ascending),
x if x == Direction::Descending as u8 => Some(Direction::Descending),
_ => None,
}?,
max: Decode::decode(input)?,
})
}
}
/// Response to `BlockRequest`
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct BlockResponse<Header, Hash, Extrinsic> {
/// Id of a request this response was made for.
pub id: RequestId,
@@ -609,44 +300,14 @@ pub mod generic {
pub blocks: Vec<BlockData<Header, Hash, Extrinsic>>,
}
impl<Header: Encode, Hash: Encode, Extrinsic: Encode> Encode for BlockResponse<Header, Hash, Extrinsic> {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.id);
dest.push(&self.blocks)
}
}
impl<Header: Decode, Hash: Decode, Extrinsic: Decode> Decode for BlockResponse<Header, Hash, Extrinsic> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(BlockResponse {
id: Decode::decode(input)?,
blocks: Decode::decode(input)?,
})
}
}
/// Announce a new complete relay chain block on the network.
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
pub struct BlockAnnounce<H> {
/// New block header.
pub header: H,
}
impl<Header: Encode> Encode for BlockAnnounce<Header> {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.header);
}
}
impl<Header: Decode> Decode for BlockAnnounce<Header> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(BlockAnnounce {
header: Decode::decode(input)?,
})
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
/// Remote call request.
pub struct RemoteCallRequest<H> {
/// Unique request id.
@@ -658,24 +319,4 @@ pub mod generic {
/// Call data.
pub data: Vec<u8>,
}
impl<Hash: Encode> Encode for RemoteCallRequest<Hash> {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.id);
dest.push(&self.block);
dest.push(self.method.as_bytes());
dest.push(&self.data);
}
}
impl<Hash: Decode> Decode for RemoteCallRequest<Hash> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(RemoteCallRequest {
id: Decode::decode(input)?,
block: Decode::decode(input)?,
method: String::from_utf8_lossy(&Vec::decode(input)?).into(),
data: Decode::decode(input)?,
})
}
}
}
@@ -59,6 +59,18 @@ bitflags! {
}
}
impl ::codec::Encode for Roles {
fn encode_to<T: ::codec::Output>(&self, dest: &mut T) {
dest.push_byte(self.bits())
}
}
impl ::codec::Decode for Roles {
fn decode<I: ::codec::Input>(input: &mut I) -> Option<Self> {
Self::from_bits(input.read_byte()?)
}
}
/// Sync status
pub trait SyncProvider<B: BlockT>: Send + Sync {
/// Get sync status
@@ -7,6 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
crunchy = "0.1"
substrate-runtime-std = { path = "../runtime-std", default_features = false }
substrate-codec = { path = "../codec", default_features = false }
substrate-codec-derive = { path = "../codec/derive", default_features = false }
fixed-hash = { git = "https://github.com/rphmeier/primitives.git", branch = "compile-for-wasm", default_features = false }
rustc-hex = { version = "2.0", default_features = false }
serde = { version = "1.0", default_features = false }
@@ -17,11 +17,10 @@
#[cfg(feature = "std")]
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use codec;
use H256;
/// An identifier for an authority in the consensus algorithm. The same size as ed25519::Public.
#[derive(Clone, Copy, PartialEq, Eq, Default)]
#[derive(Clone, Copy, PartialEq, Eq, Default, Encode, Decode)]
pub struct AuthorityId(pub [u8; 32]);
impl AuthorityId {
@@ -105,16 +104,3 @@ impl<'de> Deserialize<'de> for AuthorityId {
.map(|x| AuthorityId::from_slice(&x))
}
}
impl codec::Encode for AuthorityId {
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.0.using_encoded(f)
}
}
impl codec::Decode for AuthorityId {
fn decode<I: codec::Input>(input: &mut I) -> Option<Self> {
<[u8; 32] as codec::Decode>::decode(input).map(AuthorityId)
}
}
+5 -2
View File
@@ -21,14 +21,17 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]
extern crate rustc_hex;
extern crate byteorder;
#[macro_use]
extern crate crunchy;
#[macro_use]
extern crate fixed_hash;
#[macro_use]
extern crate uint as uint_crate;
#[macro_use]
extern crate substrate_codec_derive;
extern crate rustc_hex;
extern crate byteorder;
extern crate substrate_codec as codec;
#[cfg(feature = "std")]
+16 -172
View File
@@ -16,53 +16,33 @@
//! Definition of a sandbox environment.
use codec::{Encode, Decode, Input, Output};
#[cfg(test)]
use codec::Encode;
use rstd::vec::Vec;
/// Error error that can be returned from host function.
#[derive(Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct HostError;
impl Encode for HostError {
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
f(&[])
}
fn encode(&self) -> Vec<u8> {
Vec::new()
}
}
impl Decode for HostError {
fn decode<I: Input>(_: &mut I) -> Option<Self> {
Some(HostError)
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug))]
#[repr(i8)]
enum ValueType {
I32 = 1,
I64 = 2,
F32 = 3,
F64 = 4,
}
/// Representation of a typed wasm value.
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum TypedValue {
/// Value of 32-bit signed or unsigned integer.
#[codec(index = "1")]
I32(i32),
/// Value of 64-bit signed or unsigned integer.
#[codec(index = "2")]
I64(i64),
/// Value of 32-bit IEEE 754-2008 floating point number represented as a bit pattern.
#[codec(index = "3")]
F32(i32),
/// Value of 64-bit IEEE 754-2008 floating point number represented as a bit pattern.
#[codec(index = "4")]
F64(i64),
}
@@ -103,53 +83,16 @@ impl From<TypedValue> for ::wasmi::RuntimeValue {
}
}
impl Encode for TypedValue {
fn encode_to<T: Output>(&self, dest: &mut T) {
match *self {
TypedValue::I32(i) => {
dest.push_byte(ValueType::I32 as u8);
dest.push(&i);
}
TypedValue::I64(i) => {
dest.push_byte(ValueType::I64 as u8);
dest.push(&i);
}
TypedValue::F32(f_bits) => {
dest.push_byte(ValueType::F32 as u8);
dest.push(&f_bits);
}
TypedValue::F64(f_bits) => {
dest.push_byte(ValueType::F64 as u8);
dest.push(&f_bits);
}
}
}
}
impl Decode for TypedValue {
fn decode<I: Input>(value: &mut I) -> Option<Self> {
let typed_value = match i8::decode(value) {
Some(x) if x == ValueType::I32 as i8 => TypedValue::I32(i32::decode(value)?),
Some(x) if x == ValueType::I64 as i8 => TypedValue::I64(i64::decode(value)?),
Some(x) if x == ValueType::F32 as i8 => TypedValue::F32(i32::decode(value)?),
Some(x) if x == ValueType::F64 as i8 => TypedValue::F64(i64::decode(value)?),
_ => return None,
};
Some(typed_value)
}
}
/// Typed value that can be returned from a function.
///
/// Basically a `TypedValue` plus `Unit`, for functions which return nothing.
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum ReturnValue {
/// For returning some concrete value.
Value(TypedValue),
/// For returning nothing.
Unit,
/// For returning some concrete value.
Value(TypedValue),
}
impl From<TypedValue> for ReturnValue {
@@ -158,30 +101,6 @@ impl From<TypedValue> for ReturnValue {
}
}
impl Encode for ReturnValue {
fn encode_to<T: Output>(&self, dest: &mut T) {
match *self {
ReturnValue::Unit => {
dest.push_byte(0);
}
ReturnValue::Value(ref val) => {
dest.push_byte(1);
dest.push(val);
}
}
}
}
impl Decode for ReturnValue {
fn decode<I: Input>(value: &mut I) -> Option<Self> {
match i8::decode(value) {
Some(0) => Some(ReturnValue::Unit),
Some(1) => Some(ReturnValue::Value(TypedValue::decode(value)?)),
_ => return None,
}
}
}
impl ReturnValue {
/// Maximum number of bytes `ReturnValue` might occupy when serialized with
/// `Codec`.
@@ -199,63 +118,26 @@ fn return_value_encoded_max_size() {
assert_eq!(encoded.len(), ReturnValue::ENCODED_MAX_SIZE);
}
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug))]
#[repr(i8)]
enum ExternEntityKind {
Function = 1,
Memory = 2,
}
/// Describes an entity to define or import into the environment.
#[derive(Clone, PartialEq, Eq)]
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum ExternEntity {
/// Function that is specified by an index in a default table of
/// a module that creates the sandbox.
#[codec(index = "1")]
Function(u32),
/// Linear memory that is specified by some identifier returned by sandbox
/// module upon creation new sandboxed memory.
#[codec(index = "2")]
Memory(u32),
}
impl Encode for ExternEntity {
fn encode_to<T: Output>(&self, dest: &mut T) {
match *self {
ExternEntity::Function(ref index) => {
dest.push_byte(ExternEntityKind::Function as u8);
dest.push(index);
}
ExternEntity::Memory(ref mem_id) => {
dest.push_byte(ExternEntityKind::Memory as u8);
dest.push(mem_id);
}
}
}
}
impl Decode for ExternEntity {
fn decode<I: Input>(value: &mut I) -> Option<Self> {
match i8::decode(value) {
Some(x) if x == ExternEntityKind::Function as i8 => {
let idx = u32::decode(value)?;
Some(ExternEntity::Function(idx))
}
Some(x) if x == ExternEntityKind::Memory as i8 => {
let mem_id = u32::decode(value)?;
Some(ExternEntity::Memory(mem_id))
}
_ => None,
}
}
}
/// An entry in a environment definition table.
///
/// Each entry has a two-level name and description of an entity
/// being defined.
#[derive(Clone, PartialEq, Eq)]
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct Entry {
/// Module name of which corresponding entity being defined.
@@ -266,52 +148,14 @@ pub struct Entry {
pub entity: ExternEntity,
}
impl Encode for Entry {
fn encode_to<T: ::codec::Output>(&self, dest: &mut T) {
dest.push(&self.module_name);
dest.push(&self.field_name);
dest.push(&self.entity);
}
}
impl Decode for Entry {
fn decode<I: Input>(value: &mut I) -> Option<Self> {
let module_name = Vec::decode(value)?;
let field_name = Vec::decode(value)?;
let entity = ExternEntity::decode(value)?;
Some(Entry {
module_name,
field_name,
entity,
})
}
}
/// Definition of runtime that could be used by sandboxed code.
#[derive(Clone, PartialEq, Eq)]
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct EnvironmentDefinition {
/// Vector of all entries in the environment defintion.
pub entries: Vec<Entry>,
}
impl Encode for EnvironmentDefinition {
fn encode_to<T: Output>(&self, dest: &mut T) {
self.entries.encode_to(dest)
}
}
impl Decode for EnvironmentDefinition {
fn decode<I: Input>(value: &mut I) -> Option<Self> {
let entries = Vec::decode(value)?;
Some(EnvironmentDefinition {
entries,
})
}
}
/// Constant for specifying no limit when creating a sandboxed
/// memory instance. For FFI purposes.
pub const MEM_UNLIMITED: u32 = -1i32 as u32;
@@ -430,7 +430,6 @@ macro_rules! __decl_dispatch_module_common {
}
}
}
}
}
@@ -9,6 +9,7 @@ serde = { version = "1.0", default_features = false }
serde_derive = { version = "1.0", optional = true }
safe-mix = { path = "../../../safe-mix", default_features = false}
substrate-codec = { path = "../../codec", default_features = false }
substrate-codec-derive = { path = "../../codec/derive", default_features = false }
substrate-primitives = { path = "../../primitives", default_features = false }
substrate-runtime-std = { path = "../../runtime-std", default_features = false }
substrate-runtime-io = { path = "../../runtime-io", default_features = false }
@@ -21,18 +21,19 @@
#[cfg(feature = "std")]
extern crate serde;
#[cfg(feature = "std")]
extern crate substrate_primitives;
#[cfg(feature = "std")]
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate substrate_runtime_support;
#[cfg(feature = "std")]
extern crate substrate_primitives;
extern crate substrate_codec_derive;
#[macro_use]
extern crate substrate_runtime_std as rstd;
#[macro_use]
extern crate substrate_runtime_support;
extern crate substrate_codec as codec;
extern crate substrate_runtime_io as runtime_io;
@@ -17,11 +17,10 @@
//! Voting thresholds.
use primitives::traits::{Zero, IntegerSquareRoot};
use codec::{Decode, Encode, Input};
use rstd::ops::{Add, Mul, Div, Rem};
/// A means of determining if a vote is past pass threshold.
#[derive(Clone, Copy, PartialEq, Eq)]
#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub enum VoteThreshold {
/// A supermajority of approvals is needed to pass this vote.
@@ -32,27 +31,6 @@ pub enum VoteThreshold {
SimpleMajority,
}
impl Decode for VoteThreshold {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
input.read_byte().and_then(|v| match v {
0 => Some(VoteThreshold::SuperMajorityApprove),
1 => Some(VoteThreshold::SuperMajorityAgainst),
2 => Some(VoteThreshold::SimpleMajority),
_ => None,
})
}
}
impl Encode for VoteThreshold {
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
f(&[match *self {
VoteThreshold::SuperMajorityApprove => 0u8,
VoteThreshold::SuperMajorityAgainst => 1u8,
VoteThreshold::SimpleMajority => 2u8,
}])
}
}
pub trait Approved<Balance> {
/// Given `approve` votes for and `against` votes against from a total electorate size of
/// `electorate` (`electorate - (approve + against)` are abstainers), then returns true if the
@@ -9,6 +9,7 @@ integer-sqrt = { git = "https://github.com/paritytech/integer-sqrt-rs.git", bran
serde = { version = "1.0", optional = true }
serde_derive = { version = "1.0", optional = true }
substrate-codec = { path = "../../codec", default_features = false }
substrate-codec-derive = { path = "../../codec/derive", default_features = false }
substrate-primitives = { path = "../../primitives", default_features = false }
substrate-runtime-std = { path = "../../runtime-std", default_features = false }
substrate-runtime-io = { path = "../../runtime-io", default_features = false }
+27 -140
View File
@@ -20,100 +20,36 @@ use rstd::prelude::*;
use codec::{Decode, Encode, Input, Output};
use substrate_primitives::{AuthorityId, Signature};
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug))]
#[repr(i8)]
enum ActionKind {
Propose = 1,
ProposeHeader = 2,
Prepare = 3,
Commit = 4,
AdvanceRound = 5,
}
/// Type alias for extracting message type from block.
pub type ActionFor<B> = Action<B, <B as ::traits::Block>::Hash>;
/// Actions which can be taken during the BFT process.
#[derive(Clone, PartialEq, Eq)]
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub enum Action<Block, H> {
/// Proposal of a block candidate.
#[codec(index = "1")]
Propose(u32, Block),
/// Proposal header of a block candidate. Accompanies any proposal,
/// but is used for misbehavior reporting since blocks themselves are big.
#[codec(index = "2")]
ProposeHeader(u32, H),
/// Preparation to commit for a candidate.
#[codec(index = "3")]
Prepare(u32, H),
/// Vote to commit to a candidate.
#[codec(index = "4")]
Commit(u32, H),
/// Vote to advance round after inactive primary.
#[codec(index = "5")]
AdvanceRound(u32),
}
impl<Block: Encode, Hash: Encode> Encode for Action<Block, Hash> {
fn encode_to<T: Output>(&self, dest: &mut T) {
match *self {
Action::Propose(ref round, ref block) => {
dest.push_byte(ActionKind::Propose as u8);
dest.push(round);
dest.push(block);
}
Action::ProposeHeader(ref round, ref hash) => {
dest.push_byte(ActionKind::ProposeHeader as u8);
dest.push(round);
dest.push(hash);
}
Action::Prepare(ref round, ref hash) => {
dest.push_byte(ActionKind::Prepare as u8);
dest.push(round);
dest.push(hash);
}
Action::Commit(ref round, ref hash) => {
dest.push_byte(ActionKind::Commit as u8);
dest.push(round);
dest.push(hash);
}
Action::AdvanceRound(ref round) => {
dest.push_byte(ActionKind::AdvanceRound as u8);
dest.push(round);
}
}
}
}
impl<Block: Decode, Hash: Decode> Decode for Action<Block, Hash> {
fn decode<I: Input>(value: &mut I) -> Option<Self> {
match i8::decode(value) {
Some(x) if x == ActionKind::Propose as i8 => {
let (round, block) = Decode::decode(value)?;
Some(Action::Propose(round, block))
}
Some(x) if x == ActionKind::ProposeHeader as i8 => {
let (round, hash) = Decode::decode(value)?;
Some(Action::ProposeHeader(round, hash))
}
Some(x) if x == ActionKind::Prepare as i8 => {
let (round, hash) = Decode::decode(value)?;
Some(Action::Prepare(round, hash))
}
Some(x) if x == ActionKind::Commit as i8 => {
let (round, hash) = Decode::decode(value)?;
Some(Action::Commit(round, hash))
}
Some(x) if x == ActionKind::AdvanceRound as i8 => {
Decode::decode(value).map(Action::AdvanceRound)
}
_ => None,
}
}
}
/// Type alias for extracting message type from block.
pub type MessageFor<B> = Message<B, <B as ::traits::Block>::Hash>;
/// Messages exchanged between participants in the BFT consensus.
#[derive(Clone, PartialEq, Eq)]
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub struct Message<Block, Hash> {
/// The parent header hash this action is relative to.
@@ -122,24 +58,8 @@ pub struct Message<Block, Hash> {
pub action: Action<Block, Hash>,
}
impl<Block: Encode, Hash: Encode> Encode for Message<Block, Hash> {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.parent);
dest.push(&self.action);
}
}
impl<Block: Decode, Hash: Decode> Decode for Message<Block, Hash> {
fn decode<I: Input>(value: &mut I) -> Option<Self> {
Some(Message {
parent: Decode::decode(value)?,
action: Decode::decode(value)?,
})
}
}
/// Justification of a block.
#[derive(Clone, PartialEq, Eq)]
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub struct Justification<H> {
/// The round consensus was reached in.
@@ -150,24 +70,6 @@ pub struct Justification<H> {
pub signatures: Vec<(AuthorityId, Signature)>
}
impl<H: Encode> Encode for Justification<H> {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.round_number);
dest.push(&self.hash);
dest.push(&self.signatures);
}
}
impl<H: Decode> Decode for Justification<H> {
fn decode<I: Input>(value: &mut I) -> Option<Self> {
Some(Justification {
round_number: Decode::decode(value)?,
hash: Decode::decode(value)?,
signatures: Decode::decode(value)?,
})
}
}
// single-byte code to represent misbehavior kind.
#[repr(i8)]
enum MisbehaviorCode {
@@ -197,27 +99,9 @@ pub enum MisbehaviorKind<Hash> {
BftDoubleCommit(u32, (Hash, Signature), (Hash, Signature)),
}
/// A report of misbehavior by an authority.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub struct MisbehaviorReport<Hash, Number> {
/// The parent hash of the block where the misbehavior occurred.
pub parent_hash: Hash,
/// The parent number of the block where the misbehavior occurred.
pub parent_number: Number,
/// The authority who misbehavior.
pub target: AuthorityId,
/// The misbehavior kind.
pub misbehavior: MisbehaviorKind<Hash>,
}
impl<Hash: Encode, Number: Encode> Encode for MisbehaviorReport<Hash, Number> {
impl<Hash: Encode> Encode for MisbehaviorKind<Hash> {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.parent_hash);
dest.push(&self.parent_number);
dest.push(&self.target);
match self.misbehavior {
match *self {
MisbehaviorKind::BftDoublePrepare(ref round, (ref h_a, ref s_a), (ref h_b, ref s_b)) => {
dest.push(&(MisbehaviorCode::BftDoublePrepare as i8));
dest.push(round);
@@ -237,14 +121,9 @@ impl<Hash: Encode, Number: Encode> Encode for MisbehaviorReport<Hash, Number> {
}
}
}
impl<Hash: Decode, Number: Decode> Decode for MisbehaviorReport<Hash, Number> {
impl<Hash: Decode> Decode for MisbehaviorKind<Hash> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
let parent_hash = Hash::decode(input)?;
let parent_number = Number::decode(input)?;
let target = AuthorityId::decode(input)?;
let misbehavior = match i8::decode(input).and_then(MisbehaviorCode::from_i8)? {
Some(match i8::decode(input).and_then(MisbehaviorCode::from_i8)? {
MisbehaviorCode::BftDoublePrepare => {
MisbehaviorKind::BftDoublePrepare(
u32::decode(input)?,
@@ -259,17 +138,25 @@ impl<Hash: Decode, Number: Decode> Decode for MisbehaviorReport<Hash, Number> {
(Hash::decode(input)?, Signature::decode(input)?),
)
}
};
Some(MisbehaviorReport {
parent_hash,
parent_number,
target,
misbehavior,
})
}
}
/// A report of misbehavior by an authority.
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub struct MisbehaviorReport<Hash, Number> {
/// The parent hash of the block where the misbehavior occurred.
pub parent_hash: Hash,
/// The parent number of the block where the misbehavior occurred.
pub parent_number: Number,
/// The authority who misbehavior.
pub target: AuthorityId,
/// The misbehavior kind.
pub misbehavior: MisbehaviorKind<Hash>,
}
#[cfg(test)]
mod test {
use super::*;
@@ -31,7 +31,7 @@ use rstd::ops;
use bft::Justification;
/// Definition of something that the external world might want to say.
#[derive(PartialEq, Eq, Clone)]
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Extrinsic<Address, Index, Call> {
/// Who signed it (note this is not a signature).
@@ -42,32 +42,6 @@ pub struct Extrinsic<Address, Index, Call> {
pub function: Call,
}
impl<Address, Index, Call> Decode for Extrinsic<Address, Index, Call> where
Address: Decode,
Index: Decode,
Call: Decode,
{
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(Extrinsic {
signed: Decode::decode(input)?,
index: Decode::decode(input)?,
function: Decode::decode(input)?,
})
}
}
impl<Address, Index, Call> Encode for Extrinsic<Address, Index, Call> where
Address: Encode,
Index: Encode,
Call: Encode,
{
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.signed);
dest.push(&self.index);
dest.push(&self.function);
}
}
/// A extrinsic right from the external world. Unchecked.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
@@ -234,24 +208,12 @@ where
}
}
#[derive(Default, PartialEq, Eq, Clone)]
#[derive(Default, PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub struct Digest<Item> {
pub logs: Vec<Item>,
}
impl<Item: Decode> Decode for Digest<Item> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(Digest { logs: Decode::decode(input)? })
}
}
impl<Item: Encode> Encode for Digest<Item> {
fn encode_to<T: Output>(&self, dest: &mut T) {
self.logs.encode_to(dest)
}
}
impl<Item> traits::Digest for Digest<Item> where
Item: Member + Default + Codec
{
@@ -285,7 +247,7 @@ pub struct Header<Number, Hash: HashT, DigestItem> {
// dummy struct that uses the hash type directly.
// https://github.com/serde-rs/serde/issues/1296
#[cfg(feature = "std")]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[serde(rename_all = "camelCase")]
#[derive(Deserialize)]
struct DeserializeHeader<N, H, D> {
parent_hash: H,
@@ -319,6 +281,7 @@ impl<'a, Number: 'a, Hash: 'a + HashT, DigestItem: 'a> Deserialize<'a> for Heade
}
}
// TODO [ToDr] Issue with bounds
impl<Number, Hash, DigestItem> Decode for Header<Number, Hash, DigestItem> where
Number: Decode,
Hash: HashT,
@@ -437,7 +400,7 @@ impl<Block: BlockT> fmt::Display for BlockId<Block> {
}
/// Abstraction over a substrate block.
#[derive(PartialEq, Eq, Clone)]
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
@@ -448,22 +411,6 @@ pub struct Block<Header, Extrinsic> {
pub extrinsics: Vec<Extrinsic>,
}
impl<Header: Decode, Extrinsic: Decode> Decode for Block<Header, Extrinsic> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(Block {
header: Decode::decode(input)?,
extrinsics: Decode::decode(input)?,
})
}
}
impl<Header: Encode, Extrinsic: Encode> Encode for Block<Header, Extrinsic> {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.header);
dest.push(&self.extrinsics);
}
}
impl<Header, Extrinsic> traits::Block for Block<Header, Extrinsic>
where
Header: HeaderT,
@@ -488,7 +435,7 @@ where
}
/// Abstraction over a substrate block and justification.
#[derive(PartialEq, Eq, Clone)]
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
@@ -499,26 +446,6 @@ pub struct SignedBlock<Header, Extrinsic, Hash> {
pub justification: Justification<Hash>,
}
impl<Header: Decode, Extrinsic: Decode, Hash: Decode> Decode
for SignedBlock<Header, Extrinsic, Hash>
{
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(SignedBlock {
block: Decode::decode(input)?,
justification: Decode::decode(input)?,
})
}
}
impl<Header: Encode, Extrinsic: Encode, Hash: Encode> Encode
for SignedBlock<Header, Extrinsic, Hash>
{
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.block);
dest.push(&self.justification);
}
}
#[cfg(test)]
mod tests {
use codec::{Decode, Encode};
@@ -30,6 +30,9 @@ extern crate serde_derive;
#[macro_use]
extern crate log;
#[macro_use]
extern crate substrate_codec_derive;
extern crate num_traits;
extern crate integer_sqrt;
extern crate substrate_runtime_std as rstd;
@@ -82,7 +85,7 @@ impl BuildStorage for StorageMap {
}
/// Ed25519 signature verify.
#[derive(Eq, PartialEq, Clone, Default)]
#[derive(Eq, PartialEq, Clone, Default, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub struct Ed25519Signature(pub H512);
@@ -93,25 +96,13 @@ impl Verify for Ed25519Signature {
}
}
impl codec::Decode for Ed25519Signature {
fn decode<I: codec::Input>(input: &mut I) -> Option<Self> {
Some(Ed25519Signature(codec::Decode::decode(input)?,))
}
}
impl codec::Encode for Ed25519Signature {
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.0.using_encoded(f)
}
}
impl From<H512> for Ed25519Signature {
fn from(h: H512) -> Ed25519Signature {
Ed25519Signature(h)
}
}
#[derive(Eq, PartialEq, Clone, Copy)]
#[derive(Eq, PartialEq, Clone, Copy, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize))]
#[repr(u8)]
/// Outcome of a valid extrinsic application. Capable of being sliced.
@@ -121,22 +112,14 @@ pub enum ApplyOutcome {
/// Failed application (extrinsic was probably a no-op other than fees).
Fail = 1,
}
impl codec::Decode for ApplyOutcome {
fn decode<I: codec::Input>(input: &mut I) -> Option<Self> {
match input.read_byte()? {
x if x == ApplyOutcome::Success as u8 => Some(ApplyOutcome::Success),
x if x == ApplyOutcome::Fail as u8 => Some(ApplyOutcome::Fail),
_ => None,
}
}
}
impl codec::Encode for ApplyOutcome {
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
f(&[*self as u8])
}
}
#[derive(Eq, PartialEq, Clone, Copy)]
#[derive(Eq, PartialEq, Clone, Copy, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize))]
#[repr(u8)]
/// Reason why an extrinsic couldn't be applied (i.e. invalid extrinsic).
@@ -151,18 +134,6 @@ pub enum ApplyError {
CantPay = 3,
}
impl codec::Decode for ApplyError {
fn decode<I: codec::Input>(input: &mut I) -> Option<Self> {
match input.read_byte()? {
x if x == ApplyError::BadSignature as u8 => Some(ApplyError::BadSignature),
x if x == ApplyError::Stale as u8 => Some(ApplyError::Stale),
x if x == ApplyError::Future as u8 => Some(ApplyError::Future),
x if x == ApplyError::CantPay as u8 => Some(ApplyError::CantPay),
_ => None,
}
}
}
impl codec::Encode for ApplyError {
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
f(&[*self as u8])
@@ -173,7 +144,7 @@ impl codec::Encode for ApplyError {
pub type ApplyResult = Result<ApplyOutcome, ApplyError>;
/// Potentially "unsigned" signature verification.
#[derive(Eq, PartialEq, Clone, Default)]
#[derive(Eq, PartialEq, Clone, Default, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub struct MaybeUnsigned<T>(pub T);
@@ -204,18 +175,6 @@ impl<T: Verify> Verify for MaybeUnsigned<T> where
}
}
impl<T: codec::Decode> codec::Decode for MaybeUnsigned<T> {
fn decode<I: codec::Input>(input: &mut I) -> Option<Self> {
Some(MaybeUnsigned(codec::Decode::decode(input)?))
}
}
impl<T: codec::Encode> codec::Encode for MaybeUnsigned<T> {
fn encode_to<W: codec::Output>(&self, dest: &mut W) {
self.0.encode_to(dest)
}
}
impl<T> From<T> for MaybeUnsigned<T> {
fn from(t: T) -> Self {
MaybeUnsigned(t)
@@ -18,29 +18,17 @@
use serde::{Serialize, de::DeserializeOwned};
use std::fmt::Debug;
use codec::{Decode, Encode, Codec, Input, Output};
use codec::Codec;
use runtime_support::AuxDispatchable;
use traits::{self, Checkable, Applyable, BlakeTwo256};
pub use substrate_primitives::H256;
#[derive(Default, PartialEq, Eq, Clone, Serialize, Deserialize, Debug)]
#[derive(Default, PartialEq, Eq, Clone, Serialize, Deserialize, Debug, Encode, Decode)]
pub struct Digest {
pub logs: Vec<u64>,
}
impl Decode for Digest {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Vec::<u64>::decode(input).map(|logs| Digest { logs })
}
}
impl Encode for Digest {
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.logs.using_encoded(f)
}
}
impl traits::Digest for Digest {
type Item = u64;
fn push(&mut self, item: Self::Item) {
@@ -48,7 +36,7 @@ impl traits::Digest for Digest {
}
}
#[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug)]
#[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug, Encode, Decode)]
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
pub struct Header {
@@ -59,28 +47,6 @@ pub struct Header {
pub digest: Digest,
}
impl Decode for Header {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(Header {
parent_hash: Decode::decode(input)?,
number: Decode::decode(input)?,
state_root: Decode::decode(input)?,
extrinsics_root: Decode::decode(input)?,
digest: Decode::decode(input)?,
})
}
}
impl Encode for Header {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.parent_hash);
dest.push(&self.number);
dest.push(&self.state_root);
dest.push(&self.extrinsics_root);
dest.push(&self.digest);
}
}
impl traits::Header for Header {
type Number = u64;
type Hashing = BlakeTwo256;
@@ -115,25 +81,12 @@ impl traits::Header for Header {
}
}
#[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug)]
#[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug, Encode, Decode)]
pub struct Block<Xt> {
pub header: Header,
pub extrinsics: Vec<Xt>,
}
impl<Xt: Decode> Decode for Block<Xt> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(Block {
header: Decode::decode(input)?,
extrinsics: Decode::decode(input)?,
})
}
}
impl<Xt: Encode> Encode for Block<Xt> {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.header);
dest.push(&self.extrinsics);
}
}
impl<Xt: 'static + Codec + Sized + Send + Sync + Serialize + DeserializeOwned + Clone + Eq + Debug> traits::Block for Block<Xt> {
type Extrinsic = Xt;
type Header = Header;
@@ -153,21 +106,9 @@ impl<Xt: 'static + Codec + Sized + Send + Sync + Serialize + DeserializeOwned +
}
}
#[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug)]
#[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug, Encode, Decode)]
pub struct TestXt<Call>(pub (u64, u64, Call));
impl<Call: Decode> Decode for TestXt<Call> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(TestXt(Decode::decode(input)?))
}
}
impl<Call: Encode> Encode for TestXt<Call> {
fn encode_to<T: Output>(&self, dest: &mut T) {
self.0.encode_to(dest)
}
}
impl<Call: Codec + Sync + Send + Serialize + AuxDispatchable, Context> Checkable<Context> for TestXt<Call> {
type Checked = Self;
fn check_with(self, _: Context) -> Result<Self::Checked, &'static str> { Ok(self) }
@@ -7,6 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
serde = { version = "1.0", default_features = false }
serde_derive = { version = "1.0", optional = true }
substrate-codec = { path = "../../codec", default_features = false }
substrate-codec-derive = { path = "../../codec/derive", default_features = false }
substrate-runtime-std = { path = "../../runtime-std", default_features = false }
substrate-runtime-support = { path = "../../runtime-support", default_features = false }
+8 -33
View File
@@ -32,14 +32,12 @@ extern crate substrate_runtime_std as rstd;
#[macro_use]
extern crate substrate_runtime_support as runtime_support;
#[macro_use]
extern crate substrate_codec_derive;
extern crate substrate_codec as codec;
use rstd::prelude::*;
use codec::{Encode, Output};
#[cfg(feature = "std")]
use codec::{Decode, Input};
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(feature = "std")]
use std::fmt;
@@ -66,25 +64,25 @@ macro_rules! ver_str {
/// This triplet have different semantics and mis-interpretation could cause problems.
/// In particular: bug fixes should result in an increment of `spec_version` and possibly `authoring_version`,
/// absolutely not `impl_version` since they change the semantics of the runtime.
#[derive(Clone)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
#[derive(Clone, Encode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize, Decode))]
pub struct RuntimeVersion {
/// Identifies the different Substrate runtimes. There'll be at least polkadot and demo.
/// A different on-chain spec_name to that of the native runtime would normally result
/// in node not attempting to sync or author blocks.
pub spec_name: VersionString,
/// Name of the implementation of the spec. This is of little consequence for the node
/// and serves only to differentiate code of different implementation teams. For this
/// codebase, it will be parity-polkadot. If there were a non-Rust implementation of the
/// Polkadot runtime (e.g. C++), then it would identify itself with an accordingly different
/// `impl_name`.
pub impl_name: VersionString,
/// `authoring_version` is the version of the authorship interface. An authoring node
/// will not attempt to author blocks unless this is equal to its native runtime.
pub authoring_version: u32,
/// Version of the runtime specification. A full-node will not attempt to use its native
/// runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`,
/// `spec_version` and `authoring_version` are the same between Wasm and native.
@@ -136,29 +134,6 @@ impl RuntimeVersion {
}
}
impl Encode for RuntimeVersion {
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(self.spec_name.as_bytes());
dest.push(self.impl_name.as_bytes());
dest.push(&self.authoring_version);
dest.push(&self.spec_version);
dest.push(&self.impl_version);
}
}
#[cfg(feature = "std")]
impl Decode for RuntimeVersion {
fn decode<I: Input>(value: &mut I) -> Option<Self> {
Some(RuntimeVersion {
spec_name: Cow::Owned(String::from_utf8_lossy(&Vec::decode(value)?).into()),
impl_name: Cow::Owned(String::from_utf8_lossy(&Vec::decode(value)?).into()),
authoring_version: Decode::decode(value)?,
spec_version: Decode::decode(value)?,
impl_version: Decode::decode(value)?,
})
}
}
pub trait Trait {
const VERSION: RuntimeVersion;
}
+1
View File
@@ -8,6 +8,7 @@ parking_lot = "0.5"
log = "0.4"
substrate-primitives = { path = "../../substrate/primitives" }
substrate-codec = { path = "../../substrate/codec" }
substrate-codec-derive = { path = "../../substrate/codec/derive" }
[dev-dependencies]
env_logger = "0.4"
+1
View File
@@ -31,6 +31,7 @@
//!
#[macro_use] extern crate log;
#[macro_use] extern crate substrate_codec_derive;
extern crate parking_lot;
extern crate substrate_codec as codec;
extern crate substrate_primitives as primitives;
+2 -19
View File
@@ -23,7 +23,7 @@
//! The changes are journaled in the DB.
use std::collections::{HashMap, HashSet, VecDeque};
use codec::{Decode, Encode, self};
use codec::{Encode, Decode};
use {CommitSet, Error, MetaDb, to_meta_key, Hash};
const LAST_PRUNED: &[u8] = b"last_pruned";
@@ -43,30 +43,13 @@ struct DeathRow<BlockHash: Hash, Key: Hash> {
deleted: HashSet<Key>,
}
#[derive(Encode, Decode)]
struct JournalRecord<BlockHash: Hash, Key: Hash> {
hash: BlockHash,
inserted: Vec<Key>,
deleted: Vec<Key>,
}
impl<BlockHash: Hash, Key: Hash> Encode for JournalRecord<BlockHash, Key> {
fn encode_to<T: codec::Output>(&self, dest: &mut T) {
dest.push(&self.hash);
dest.push(&self.inserted);
dest.push(&self.deleted);
}
}
impl<BlockHash: Hash, Key: Hash> Decode for JournalRecord<BlockHash, Key> {
fn decode<I: codec::Input>(input: &mut I) -> Option<Self> {
Some(JournalRecord {
hash: Decode::decode(input)?,
inserted: Decode::decode(input)?,
deleted: Decode::decode(input)?,
})
}
}
fn to_journal_key(block: u64) -> Vec<u8> {
to_meta_key(PRUNING_JOURNAL, &block)
}
@@ -22,7 +22,7 @@
use std::collections::{HashMap, VecDeque};
use super::{Error, DBValue, ChangeSet, CommitSet, MetaDb, Hash, to_meta_key};
use codec::{self, Decode, Encode};
use codec::{Decode, Encode};
const UNFINALIZED_JOURNAL: &[u8] = b"unfinalized_journal";
const LAST_FINALIZED: &[u8] = b"last_finalized";
@@ -35,6 +35,7 @@ pub struct UnfinalizedOverlay<BlockHash: Hash, Key: Hash> {
last_finalized_overlay: HashMap<Key, DBValue>,
}
#[derive(Encode, Decode)]
struct JournalRecord<BlockHash: Hash, Key: Hash> {
hash: BlockHash,
parent_hash: BlockHash,
@@ -42,26 +43,6 @@ struct JournalRecord<BlockHash: Hash, Key: Hash> {
deleted: Vec<Key>,
}
impl<BlockHash: Hash, Key: Hash> Encode for JournalRecord<BlockHash, Key> {
fn encode_to<T: codec::Output>(&self, dest: &mut T) {
dest.push(&self.hash);
dest.push(&self.parent_hash);
dest.push(&self.inserted);
dest.push(&self.deleted);
}
}
impl<BlockHash: Hash, Key: Hash> Decode for JournalRecord<BlockHash, Key> {
fn decode<I: codec::Input>(input: &mut I) -> Option<Self> {
Some(JournalRecord {
hash: Decode::decode(input)?,
parent_hash: Decode::decode(input)?,
inserted: Decode::decode(input)?,
deleted: Decode::decode(input)?,
})
}
}
fn to_journal_key(block: u64, index: u64) -> Vec<u8> {
to_meta_key(UNFINALIZED_JOURNAL, &(block, index))
}
@@ -11,6 +11,7 @@ serde = { version = "1.0", optional = true }
serde_derive = { version = "1.0", optional = true }
substrate-keyring = { path = "../keyring", optional = true }
substrate-codec = { path = "../codec", default-features = false }
substrate-codec-derive = { path = "../codec/derive", default-features = false }
substrate-runtime-std = { path = "../runtime-std", default-features = false }
substrate-runtime-io = { path = "../runtime-io", default-features = false }
substrate-runtime-support = { path = "../runtime-support", default-features = false }
+9 -35
View File
@@ -31,6 +31,13 @@ extern crate serde_derive;
#[macro_use]
extern crate substrate_runtime_support as runtime_support;
#[macro_use]
extern crate substrate_codec_derive;
#[macro_use]
extern crate substrate_runtime_io as runtime_io;
#[macro_use]
extern crate substrate_runtime_version as runtime_version;
#[cfg(test)]
#[macro_use]
@@ -41,11 +48,6 @@ extern crate ed25519;
extern crate substrate_keyring as keyring;
#[cfg_attr(test, macro_use)]
extern crate substrate_primitives as primitives;
#[macro_use]
extern crate substrate_runtime_io as runtime_io;
#[macro_use]
extern crate substrate_runtime_version as runtime_version;
#[cfg(feature = "std")] pub mod genesismap;
pub mod system;
@@ -72,7 +74,7 @@ fn version() -> RuntimeVersion {
}
/// Calls in transactions.
#[derive(Clone, PartialEq, Eq)]
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub struct Transfer {
pub from: AccountId,
@@ -81,42 +83,14 @@ pub struct Transfer {
pub nonce: u64,
}
impl Encode for Transfer {
fn encode_to<T: ::codec::Output>(&self, dest: &mut T) {
self.from.encode_to(dest);
self.to.encode_to(dest);
self.amount.encode_to(dest);
self.nonce.encode_to(dest);
}
}
impl Decode for Transfer {
fn decode<I: ::codec::Input>(input: &mut I) -> Option<Self> {
Decode::decode(input).map(|(from, to, amount, nonce)| Transfer { from, to, amount, nonce })
}
}
/// Extrinsic for test-runtime.
#[derive(Clone, PartialEq, Eq)]
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub struct Extrinsic {
pub transfer: Transfer,
pub signature: Ed25519Signature,
}
impl Encode for Extrinsic {
fn encode_to<T: ::codec::Output>(&self, dest: &mut T) {
self.transfer.encode_to(dest);
self.signature.encode_to(dest);
}
}
impl Decode for Extrinsic {
fn decode<I: ::codec::Input>(input: &mut I) -> Option<Self> {
Decode::decode(input).map(|(transfer, signature)| Extrinsic { transfer, signature })
}
}
impl BlindCheckable for Extrinsic {
type Checked = Self;
+16 -3
View File
@@ -603,7 +603,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-hex"
version = "2.0.0"
source = "git+https://github.com/rphmeier/rustc-hex.git#ee2ec40b9062ac7769ccb9dc891d6dc2cc9009d7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc_version"
@@ -663,6 +663,15 @@ dependencies = [
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-codec-derive"
version = "0.1.0"
dependencies = [
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-primitives"
version = "0.1.0"
@@ -671,10 +680,11 @@ dependencies = [
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
"rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)",
"rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-runtime-std 0.1.0",
"twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
@@ -705,6 +715,7 @@ dependencies = [
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
"substrate-runtime-std 0.1.0",
@@ -741,6 +752,7 @@ dependencies = [
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-runtime-std 0.1.0",
"substrate-runtime-support 0.1.0",
]
@@ -769,6 +781,7 @@ dependencies = [
"hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-codec-derive 0.1.0",
"substrate-primitives 0.1.0",
"substrate-runtime-io 0.1.0",
"substrate-runtime-primitives 0.1.0",
@@ -1009,7 +1022,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rlp 0.2.1 (git+https://github.com/paritytech/parity.git)" = "<none>"
"checksum rlp 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "89db7f8dfdd5eb7ab3ac3ece7a07fd273a680b4b224cb231181280e8996f9f0b"
"checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e"
"checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "<none>"
"checksum rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b03280c2813907a030785570c577fb27d3deec8da4c18566751ade94de0ace"
"checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
@@ -8,6 +8,7 @@ log = { version = "0.3", optional = true }
hex-literal = { version = "0.1.0", optional = true }
ed25519 = { path = "../../ed25519", optional = true }
substrate-codec = { path = "../../codec", default-features = false }
substrate-codec-derive = { path = "../../codec/derive", default-features = false }
substrate-runtime-std = { path = "../../runtime-std", default-features = false }
substrate-runtime-io = { path = "../../runtime-io", default-features = false }
substrate-runtime-support = { path = "../../runtime-support", default-features = false }