diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 3af622b751..43de6e25e0 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -1,11 +1,3 @@ -[root] -name = "polkadot-serializer" -version = "0.1.0" -dependencies = [ - "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "aho-corasick" version = "0.6.3" @@ -30,6 +22,29 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "backtrace" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "0.7.0" @@ -45,6 +60,16 @@ name = "byteorder" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cc" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "clap" version = "2.27.1" @@ -65,6 +90,15 @@ name = "crunchy" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "dbghelp-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "difference" version = "1.0.0" @@ -84,6 +118,14 @@ dependencies = [ "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "error-chain" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fixed-hash" version = "0.1.0" @@ -179,9 +221,28 @@ dependencies = [ "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "uint 0.1.0 (git+https://github.com/paritytech/primitives.git)", ] +[[package]] +name = "polkadot-serializer" +version = "0.1.0" +dependencies = [ + "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "polkadot-validator" +version = "0.1.0" +dependencies = [ + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "polkadot-primitives 0.1.0", + "polkadot-serializer 0.1.0", + "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pretty_assertions" version = "0.4.0" @@ -235,6 +296,11 @@ name = "regex-syntax" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc-demangle" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc-hex" version = "1.0.0" @@ -346,6 +412,11 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tiny-keccak" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "uint" version = "0.1.0" @@ -408,14 +479,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" "checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860" +"checksum backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99f2ce94e22b8e664d95c57fff45b98a966c2252b60691d0b7aeeccd88d70983" +"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d" +"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719" +"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b8c532887f1a292d17de05ae858a8fe50a301e196f9ef0ddb7ccd0d1d00f180" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" +"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" "checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" +"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum fixed-hash 0.1.0 (git+https://github.com/paritytech/primitives.git)" = "" "checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159" "checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82" @@ -433,6 +510,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" +"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" "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" @@ -447,6 +525,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" "checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" +"checksum tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d52d12ad79e4063e0cb0ca5efa202ed7244b6ce4d25f4d3abe410b2a66128292" "checksum uint 0.1.0 (git+https://github.com/paritytech/primitives.git)" = "" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" diff --git a/substrate/Cargo.toml b/substrate/Cargo.toml index d506a38ffa..14a08ae612 100644 --- a/substrate/Cargo.toml +++ b/substrate/Cargo.toml @@ -4,10 +4,11 @@ version = "0.1.0" authors = ["Parity Team "] [dependencies] -polkadot-cli = { path = "cli" } +polkadot-cli = { path = "cli", version = "0.1" } [workspace] members = [ "primitives", - "serializer" + "serializer", + "validator", ] diff --git a/substrate/primitives/Cargo.toml b/substrate/primitives/Cargo.toml index 36352ad157..709a8d0566 100644 --- a/substrate/primitives/Cargo.toml +++ b/substrate/primitives/Cargo.toml @@ -4,11 +4,12 @@ version = "0.1.0" authors = ["Parity Team "] [dependencies] -crunchy = "0.1.5" +crunchy = "0.1" fixed-hash = { git = "https://github.com/paritytech/primitives.git" } rustc-hex = "1.0" serde = "1.0" serde_derive = "1.0" +tiny-keccak = "1.3" uint = { git = "https://github.com/paritytech/primitives.git" } [dev-dependencies] diff --git a/substrate/primitives/src/block.rs b/substrate/primitives/src/block.rs index 8e36366f2c..41d684f70d 100644 --- a/substrate/primitives/src/block.rs +++ b/substrate/primitives/src/block.rs @@ -16,50 +16,23 @@ //! Block and header type definitions. -use bytes; use hash::H256; +use parachain; /// Hash used to refer to a block hash. pub type HeaderHash = H256; -/// Hash used to refer to proof of block header. -pub type ProofHash = H256; - -/// Unique identifier of a parachain. -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Serialize, Deserialize)] -pub struct ParachainId(u64); - -impl From for u64 { - fn from(x: ParachainId) -> Self { x.0 } -} - -impl From for ParachainId { - fn from(x: u64) -> Self { ParachainId(x) } -} - -/// A wrapper type for parachain block header raw bytes. -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct ParachainBlockHeader(#[serde(with="bytes")] pub Vec); - -/// A parachain block proposal. -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct ParachainProposal { - /// The ID of the parachain this is a proposal for. - pub parachain: ParachainId, - /// Parachain block header bytes. - pub header: ParachainBlockHeader, - /// Hash of data necessary to prove validity of the header. - pub proof_hash: ProofHash, -} /// A relay chain block header. #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Header { /// Block parent's hash. - pub parent_hash: HeaderHash, + #[serde(rename="parentHash")] + pub parent_hash: HeaderHash, /// State root after this transition. - pub state_root: H256, + #[serde(rename="stateRoot")] + pub state_root: H256, /// Unix time at which this header was produced. - pub timestamp: u64, + pub timestamp: u64, /// Block number. pub number: u64, } @@ -71,7 +44,8 @@ pub struct Header { #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Body { /// Parachain proposal blocks. - pub para_blocks: Vec, + #[serde(rename="paraBlocks")] + pub para_blocks: Vec, } @@ -88,8 +62,8 @@ mod tests { timestamp: 10, number: 67, }), r#"{ - "parent_hash": "0x0000000000000000000000000000000000000000000000000000000000000005", - "state_root": "0x0000000000000000000000000000000000000000000000000000000000000003", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000005", + "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000003", "timestamp": 10, "number": 67 }"#); @@ -99,18 +73,18 @@ mod tests { fn test_body_serialization() { assert_eq!(ser::to_string_pretty(&Body { para_blocks: vec![ - ParachainProposal { + parachain::Proposal { parachain: 5.into(), - header: ParachainBlockHeader(vec![1, 2, 3, 4]), + header: parachain::Header(vec![1, 2, 3, 4]), proof_hash: 5.into(), } ], }), r#"{ - "para_blocks": [ + "paraBlocks": [ { "parachain": 5, "header": "0x01020304", - "proof_hash": "0x0000000000000000000000000000000000000000000000000000000000000005" + "proofHash": "0x0000000000000000000000000000000000000000000000000000000000000005" } ] }"#); diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index 596c13f4ac..08079e42fb 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -18,8 +18,9 @@ #![warn(missing_docs)] -extern crate serde; extern crate rustc_hex; +extern crate serde; +extern crate tiny_keccak; #[macro_use] extern crate crunchy; @@ -41,7 +42,14 @@ extern crate pretty_assertions; mod bytes; pub mod block; pub mod hash; +pub mod parachain; pub mod uint; +pub mod validator; /// Alias to 160-bit hash when used in the context of an account address. pub type Address = hash::H160; + +/// A hash function. +pub fn hash(data: &[u8]) -> hash::H256 { + tiny_keccak::keccak256(data).into() +} diff --git a/substrate/primitives/src/parachain.rs b/substrate/primitives/src/parachain.rs new file mode 100644 index 0000000000..567225acfe --- /dev/null +++ b/substrate/primitives/src/parachain.rs @@ -0,0 +1,100 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Parachain data types. + +use bytes; + +/// Unique identifier of a parachain. +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Serialize, Deserialize)] +pub struct Id(u64); + +impl From for u64 { + fn from(x: Id) -> Self { x.0 } +} + +impl From for Id { + fn from(x: u64) -> Self { Id(x) } +} + +/// A parachain block proposal. +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct Proposal { + /// The ID of the parachain this is a proposal for. + pub parachain: Id, + /// Parachain block header bytes. + pub header: Header, + /// Hash of data necessary to prove validity of the header. + #[serde(rename="proofHash")] + pub proof_hash: ProofHash, +} + +/// Parachain header raw bytes wrapper type. +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct Header(#[serde(with="bytes")] pub Vec); + +/// Hash used to refer to proof of block header. +pub type ProofHash = ::hash::H256; + +/// Raw proof data. +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct RawProof(#[serde(with="bytes")] pub Vec); + +impl RawProof { + /// Compute and store the hash of the proof. + pub fn into_proof(self) -> Proof { + let hash = ::hash(&self.0); + Proof(self, hash) + } +} + +/// Parachain proof data. +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct Proof(RawProof, ProofHash); + +impl Proof { + /// Get raw proof data. + pub fn raw(&self) -> &RawProof { &self.0 } + + /// Get hash of proof data. + pub fn hash(&self) -> &ProofHash { &self.1 } + + /// Decompose the proof back into raw data and hash. + pub fn into_inner(self) -> (RawProof, ProofHash) { + (self.0, self.1) + } +} + +/// Parachain validation code. +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct ValidationCode(#[serde(with="bytes")] pub Vec); + +#[cfg(test)] +mod tests { + use super::*; + use polkadot_serializer as ser; + + #[test] + fn test_proof_serialization() { + assert_eq!( + ser::to_string_pretty(&Proof(RawProof(vec![1,2,3]), 5.into())), + r#"[ + "0x010203", + "0x0000000000000000000000000000000000000000000000000000000000000005" +]"# + ) + } +} diff --git a/substrate/primitives/src/validator.rs b/substrate/primitives/src/validator.rs new file mode 100644 index 0000000000..3ae18fe270 --- /dev/null +++ b/substrate/primitives/src/validator.rs @@ -0,0 +1,104 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Validator primitives. + +use bytes; + +/// Parachain incoming messages. +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct IngressPosts(#[serde(with="bytes")] pub Vec); + +/// Parachain incoming messages delta. +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct IngressPostsDelta(#[serde(with="bytes")] pub Vec); + +/// Parachain outgoing messages. +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct EgressPosts(#[serde(with="bytes")] pub Vec); + +/// Validity result of particular proof and ingress queue. +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(tag="type", content="data")] +pub enum ProofValidity { + /// The proof is invalid. + #[serde(rename="invalid")] + Invalid, + #[serde(rename="valid")] + /// The proof is processed and new egress queue is created. + /// Also includes current ingress queue delta. + Valid(IngressPostsDelta, EgressPosts), +} + +impl ProofValidity { + /// The proof is valid. + pub fn is_valid(&self) -> bool { + match *self { + ProofValidity::Invalid => false, + ProofValidity::Valid(..) => true, + } + } +} + +impl From> for ProofValidity { + fn from(posts: Option<(IngressPostsDelta, EgressPosts)>) -> Self { + match posts { + Some((delta, posts)) => ProofValidity::Valid(delta, posts), + None => ProofValidity::Invalid, + } + } +} + +// TODO [ToDr] This shouldn't be here! +/// Validator logic. +pub trait Validator { + /// Validation error. + type Error: ::std::error::Error; + + /// Validates if the provided proof holds given a current ingress queue. + /// + /// In case of success produces egress posts. + fn validate( + &self, + messages: &IngressPosts, + proof: &::parachain::Proof, + code: &[u8], + ) -> Result; +} + +#[cfg(test)] +mod tests { + use super::*; + use polkadot_serializer as ser; + + #[test] + fn test_proof_validity_serialization() { + assert_eq!( + ser::to_string_pretty(&ProofValidity::Invalid), + r#"{ + "type": "invalid" +}"#); + assert_eq!( + ser::to_string_pretty(&ProofValidity::Valid(IngressPostsDelta(vec![1]), EgressPosts(vec![1, 2, 3]))), + r#"{ + "type": "valid", + "data": [ + "0x01", + "0x010203" + ] +}"#); + } +} diff --git a/substrate/validator/Cargo.toml b/substrate/validator/Cargo.toml new file mode 100644 index 0000000000..00b0d14c89 --- /dev/null +++ b/substrate/validator/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "polkadot-validator" +version = "0.1.0" +authors = ["Parity Team "] + +[dependencies] +error-chain = "0.11" +polkadot-primitives = { path = "../primitives", version = "0.1" } +polkadot-serializer = { path = "../serializer", version = "0.1" } +serde = "1.0" diff --git a/substrate/validator/src/error.rs b/substrate/validator/src/error.rs new file mode 100644 index 0000000000..1c8caf739f --- /dev/null +++ b/substrate/validator/src/error.rs @@ -0,0 +1,33 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +use serializer; + +error_chain! { + foreign_links { + Serialization(serializer::Error); + } + errors { + Timeout { + description("Validation task has timed-out."), + display("Validation timeout."), + } + InvalidCode(details: String) { + description("The code is invalid."), + display("invalid code: '{}'", details), + } + } +} diff --git a/substrate/validator/src/lib.rs b/substrate/validator/src/lib.rs new file mode 100644 index 0000000000..131a4861aa --- /dev/null +++ b/substrate/validator/src/lib.rs @@ -0,0 +1,33 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Validator implementation. + +#[warn(missing_docs)] + +extern crate polkadot_primitives as primitives; +extern crate polkadot_serializer as serializer; +extern crate serde; + +#[macro_use] +extern crate error_chain; + +mod error; +mod parachains; +mod validator; + +pub use error::{Error, ErrorKind, Result}; +pub use validator::Validator; diff --git a/substrate/validator/src/parachains.rs b/substrate/validator/src/parachains.rs new file mode 100644 index 0000000000..7c73ffabae --- /dev/null +++ b/substrate/validator/src/parachains.rs @@ -0,0 +1,46 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +use std::fmt; + +use primitives::validator; +use serde::de::DeserializeOwned; + +/// Parachain code implementation. +pub trait ParachainCode: fmt::Debug { + /// Deserialized messages type. + type Messages: DeserializeOwned; + /// Deserialized proof type. + type Proof: DeserializeOwned; + + /// Given decoded messages and proof validate it and return egress posts. + fn check(&self, messages: Self::Messages, proof: Self::Proof) -> + Option<(validator::IngressPostsDelta, validator::EgressPosts)>; +} + +/// Dummy implementation of the first parachain validation. +#[derive(Debug)] +pub struct ParaChain1; + +impl ParachainCode for ParaChain1 { + type Messages = (); + type Proof = (); + + fn check(&self, _messages: Self::Messages, _proof: Self::Proof) + -> Option<(validator::IngressPostsDelta, validator::EgressPosts)> { + None + } +} diff --git a/substrate/validator/src/validator.rs b/substrate/validator/src/validator.rs new file mode 100644 index 0000000000..fcacc23d07 --- /dev/null +++ b/substrate/validator/src/validator.rs @@ -0,0 +1,79 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +use std::fmt; + +use primitives::{validator, parachain}; +use serde::de::DeserializeOwned; +use serializer; + +use error::{Error, ErrorKind, Result}; +use parachains::{ParachainCode, ParaChain1}; + +/// A dummy validator implementation. +#[derive(Debug)] +pub struct Validator { + codes: Vec>, +} + +impl Validator { + /// Create a new validator. + pub fn new() -> Self { + Validator { + codes: vec![ + Box::new(ParaChain1) as Box + ], + } + } +} + +impl validator::Validator for Validator { + type Error = Error; + + fn validate( + &self, + messages: &validator::IngressPosts, + proof: ¶chain::Proof, + code: &[u8], + ) -> Result { + ensure!(code.len() == 1, ErrorKind::InvalidCode(format!("The code should be a single byte."))); + + match self.codes.get(code[0] as usize) { + Some(code) => code.check(messages, proof), + None => bail!(ErrorKind::InvalidCode(format!("Unknown parachain code."))), + } + } +} + +/// Simplified parachain code verification +trait Code: fmt::Debug { + /// Given bytes of messages and proof determine if the proof is valid and return egress posts. + fn check(&self, messages: &validator::IngressPosts, proof: ¶chain::Proof) -> Result; +} + +impl Code for T where + M: DeserializeOwned, + P: DeserializeOwned, + T: ParachainCode, +{ + fn check(&self, messages: &validator::IngressPosts, proof: ¶chain::Proof) -> Result { + let messages = serializer::from_slice(&messages.0)?; + let proof = serializer::from_slice(&proof.raw().0)?; + + Ok(self.check(messages, proof).into()) + } +} +