From 5b337e3a9c2160e633bf55cc7008b5b5f879a0a0 Mon Sep 17 00:00:00 2001 From: Gav Date: Sat, 27 Jan 2018 19:52:24 +0100 Subject: [PATCH] Repot and fix a ser/de bug. --- .../polkadot/src/codec/slicable.rs | 32 ++ substrate/wasm-runtime/polkadot/src/lib.rs | 3 +- .../polkadot/src/primitives/block.rs | 60 ++ .../polkadot/src/primitives/digest.rs | 27 + .../src/{support => primitives}/function.rs | 0 .../polkadot/src/primitives/header.rs | 74 +++ .../polkadot/src/primitives/misc.rs | 41 ++ .../polkadot/src/primitives/mod.rs | 38 ++ .../src/{support => primitives}/proposal.rs | 0 .../polkadot/src/primitives/tests.rs | 242 ++++++++ .../polkadot/src/primitives/transaction.rs | 69 +++ .../src/primitives/uncheckedtransaction.rs | 85 +++ .../polkadot/src/runtime/governance.rs | 3 +- .../polkadot/src/runtime/system.rs | 3 +- .../polkadot/src/support/hashable.rs | 38 ++ .../wasm-runtime/polkadot/src/support/mod.rs | 4 +- .../polkadot/src/support/primitives.rs | 525 ------------------ substrate/wasm-runtime/support/src/lib.rs | 2 +- .../release/runtime_polkadot.compact.wasm | Bin 62459 -> 62629 bytes .../release/runtime_polkadot.wasm | Bin 62508 -> 62678 bytes 20 files changed, 713 insertions(+), 533 deletions(-) create mode 100644 substrate/wasm-runtime/polkadot/src/primitives/block.rs create mode 100644 substrate/wasm-runtime/polkadot/src/primitives/digest.rs rename substrate/wasm-runtime/polkadot/src/{support => primitives}/function.rs (100%) create mode 100644 substrate/wasm-runtime/polkadot/src/primitives/header.rs create mode 100644 substrate/wasm-runtime/polkadot/src/primitives/misc.rs create mode 100644 substrate/wasm-runtime/polkadot/src/primitives/mod.rs rename substrate/wasm-runtime/polkadot/src/{support => primitives}/proposal.rs (100%) create mode 100644 substrate/wasm-runtime/polkadot/src/primitives/tests.rs create mode 100644 substrate/wasm-runtime/polkadot/src/primitives/transaction.rs create mode 100644 substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs create mode 100644 substrate/wasm-runtime/polkadot/src/support/hashable.rs delete mode 100644 substrate/wasm-runtime/polkadot/src/support/primitives.rs diff --git a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs index 002a506dc7..c702741ee3 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs +++ b/substrate/wasm-runtime/polkadot/src/codec/slicable.rs @@ -100,6 +100,38 @@ impl Slicable for Vec { } } +impl NonTrivialSlicable for Vec where Vec: Slicable {} + +impl Slicable for Vec { + fn from_slice(value: &[u8]) -> Option { + let len = Self::size_of(&value[0..4])?; + let mut off = 4; + let mut r = Vec::new(); + while off < len { + let element_len = T::size_of(&value[off..])?; + r.push(T::from_slice(&value[off..off + element_len])?); + off += element_len; + } + Some(r) + } + + fn set_as_slice bool>(_fill_slice: &F) -> Option { + unimplemented!(); + } + + fn to_vec(&self) -> Vec { + let vecs = self.iter().map(Slicable::to_vec).collect::>(); + let len = vecs.iter().fold(0, |mut a, v| {a += v.len(); a}); + let mut r = Vec::new().join(&(len as u32)); + vecs.iter().for_each(|v| r.extend_from_slice(v)); + r + } + + fn size_of(data: &[u8]) -> Option { + u32::from_slice(&data[0..4]).map(|i| (i + 4) as usize) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index c23622cec8..9389145843 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -28,9 +28,10 @@ extern crate rustc_hex; mod codec; #[macro_use] mod support; +pub mod primitives; pub mod runtime; pub use codec::{endiansensitive, streamreader, joiner, slicable, keyedvec}; -pub use support::{primitives, function, proposal, environment, storable}; +pub use support::{environment, storable, hashable}; #[cfg(feature = "with-std")] pub use support::{testing, statichex}; diff --git a/substrate/wasm-runtime/polkadot/src/primitives/block.rs b/substrate/wasm-runtime/polkadot/src/primitives/block.rs new file mode 100644 index 0000000000..2975286479 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives/block.rs @@ -0,0 +1,60 @@ +// 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 . + +//! Block type. + +use runtime_support::prelude::*; +use streamreader::StreamReader; +use joiner::Joiner; +use slicable::{Slicable, NonTrivialSlicable}; +use primitives::{Header, UncheckedTransaction}; + +/// A Polkadot relay chain block. +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +pub struct Block { + /// The header of the block. + pub header: Header, + /// All transactions. + pub transactions: Vec, +} + +impl Slicable for Block { + fn from_slice(value: &[u8]) -> Option { + let mut reader = StreamReader::new(value); + Some(Block { + header: reader.read()?, + transactions: reader.read()?, + }) + } + + fn set_as_slice bool>(_fill_slice: &F) -> Option { + unimplemented!(); + } + + fn to_vec(&self) -> Vec { + Vec::new() + .join(&self.header) + .join(&self.transactions) + } + + fn size_of(data: &[u8]) -> Option { + let first_part = Header::size_of(data)?; + let second_part = >::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + +impl NonTrivialSlicable for Block {} diff --git a/substrate/wasm-runtime/polkadot/src/primitives/digest.rs b/substrate/wasm-runtime/polkadot/src/primitives/digest.rs new file mode 100644 index 0000000000..b51bc8df54 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives/digest.rs @@ -0,0 +1,27 @@ +// 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 . + +//! Digest type. + +use runtime_support::prelude::*; + +#[derive(Clone, Default)] +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +/// The digest of a block, useful for light-clients. +pub struct Digest { + /// All logs that have happened in the block. + pub logs: Vec>, +} diff --git a/substrate/wasm-runtime/polkadot/src/support/function.rs b/substrate/wasm-runtime/polkadot/src/primitives/function.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/support/function.rs rename to substrate/wasm-runtime/polkadot/src/primitives/function.rs diff --git a/substrate/wasm-runtime/polkadot/src/primitives/header.rs b/substrate/wasm-runtime/polkadot/src/primitives/header.rs new file mode 100644 index 0000000000..76f3c012d1 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives/header.rs @@ -0,0 +1,74 @@ +// 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 . + +//! Block header type. + +use runtime_support::prelude::*; +use streamreader::StreamReader; +use joiner::Joiner; +use slicable::{Slicable, NonTrivialSlicable}; +use runtime_support::mem; +use primitives::{BlockNumber, Hash, Digest}; + +#[derive(Clone)] +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +/// The header for a block. +pub struct Header { + /// The parent block's "hash" (actually the Blake2-256 hash of its serialised header). + pub parent_hash: Hash, + /// The block's number (how many ancestors does it have?). + pub number: BlockNumber, + /// The root of the trie that represents this block's final storage map. + pub state_root: Hash, + /// The root of the trie that represents this block's transactions, indexed by a 32-bit integer. + pub transaction_root: Hash, + /// The digest for this block. + pub digest: Digest, +} + +impl Slicable for Header { + fn from_slice(value: &[u8]) -> Option { + let mut reader = StreamReader::new(value); + Some(Header { + parent_hash: reader.read()?, + number: reader.read()?, + state_root: reader.read()?, + transaction_root: reader.read()?, + digest: Digest { logs: reader.read()?, }, + }) + } + + fn set_as_slice bool>(_fill_slice: &F) -> Option { + unimplemented!(); + } + + fn to_vec(&self) -> Vec { + Vec::new() + .join(&self.parent_hash) + .join(&self.number) + .join(&self.state_root) + .join(&self.transaction_root) + .join(&self.digest.logs) + } + + fn size_of(data: &[u8]) -> Option { + let first_part = mem::size_of::() + mem::size_of::() + mem::size_of::() + mem::size_of::(); + let second_part = >>::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + +impl NonTrivialSlicable for Header {} diff --git a/substrate/wasm-runtime/polkadot/src/primitives/misc.rs b/substrate/wasm-runtime/polkadot/src/primitives/misc.rs new file mode 100644 index 0000000000..2d6954f9e7 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives/misc.rs @@ -0,0 +1,41 @@ +// 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 . + +//! Miscellaneous small types. + +/// The Ed25519 pubkey that identifies an account. +pub type AccountID = [u8; 32]; + +/// Virtual account ID that represents the idea of a dispatch/statement being signed by everybody +/// (who matters). Essentially this means that a majority of validators have decided it is +/// "correct". +pub const EVERYBODY: AccountID = [255u8; 32]; + +/// The Ed25519 pub key of an session that belongs to an authority. This is used as what the +/// external environment/consensus algorithm calls an "authority". +pub type SessionKey = AccountID; + +/// Indentifier for a chain. +pub type ChainID = u64; + +/// Index of a block in the chain. +pub type BlockNumber = u64; + +/// Index of a transaction. +pub type TxOrder = u64; + +/// A hash of some data. +pub type Hash = [u8; 32]; diff --git a/substrate/wasm-runtime/polkadot/src/primitives/mod.rs b/substrate/wasm-runtime/polkadot/src/primitives/mod.rs new file mode 100644 index 0000000000..51ce3d121a --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives/mod.rs @@ -0,0 +1,38 @@ +// 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 . + +//! Primitive types for the runtime. + +mod misc; +mod proposal; +mod function; +mod digest; +mod header; +mod transaction; +mod uncheckedtransaction; +mod block; + +#[cfg(test)] +mod tests; + +pub use self::misc::{AccountID, EVERYBODY, SessionKey, ChainID, BlockNumber, TxOrder, Hash}; +pub use self::proposal::{Proposal, InternalFunction}; +pub use self::function::Function; +pub use self::digest::Digest; +pub use self::header::Header; +pub use self::transaction::Transaction; +pub use self::uncheckedtransaction::UncheckedTransaction; +pub use self::block::Block; diff --git a/substrate/wasm-runtime/polkadot/src/support/proposal.rs b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/support/proposal.rs rename to substrate/wasm-runtime/polkadot/src/primitives/proposal.rs diff --git a/substrate/wasm-runtime/polkadot/src/primitives/tests.rs b/substrate/wasm-runtime/polkadot/src/primitives/tests.rs new file mode 100644 index 0000000000..76412c10b9 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives/tests.rs @@ -0,0 +1,242 @@ +// 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 . + +//! Tests. + +use super::*; +use runtime_support::prelude::*; +use joiner::Joiner; +use slicable::{Slicable, NonTrivialSlicable}; +use function::Function; + +#[test] +fn serialise_transaction_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + let tx = Transaction { + signed: one.clone(), + nonce: 69, + function: Function::StakingTransfer, + input_data: Vec::new().join(&two).join(&69u64), + }; + let serialised = tx.to_vec(); + assert_eq!(serialised, vec![ + 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 69, 0, 0, 0, 0, 0, 0, 0, + 2, + 40, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0 + ]); +} + +#[test] +fn deserialise_transaction_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + let tx = Transaction { + signed: one.clone(), + nonce: 69, + function: Function::StakingTransfer, + input_data: Vec::new().join(&two).join(&69u64), + }; + let data = [ + 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 69, 0, 0, 0, 0, 0, 0, 0, + 2, + 40, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0 + ]; + let deserialised = Transaction::from_slice(&data).unwrap(); + assert_eq!(deserialised, tx); +} + +#[test] +fn serialise_header_works() { + let h = Header { + parent_hash: [4u8; 32], + number: 42, + state_root: [5u8; 32], + transaction_root: [6u8; 32], + digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, + }; + let serialised = h.to_vec(); + assert_eq!(serialised, vec![ + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 26, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 + ]); +} + +#[test] +fn deserialise_header_works() { + let h = Header { + parent_hash: [4u8; 32], + number: 42, + state_root: [5u8; 32], + transaction_root: [6u8; 32], + digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, + }; + let data = [ + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 26, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 + ]; + let deserialised = Header::from_slice(&data).unwrap(); + assert_eq!(deserialised, h); +} + +#[test] +fn serialise_block_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + let tx1 = UncheckedTransaction { + transaction: Transaction { + signed: one.clone(), + nonce: 69, + function: Function::StakingTransfer, + input_data: Vec::new().join(&two).join(&69u64), + }, + signature: [1u8; 64], + }; + let tx2 = UncheckedTransaction { + transaction: Transaction { + signed: two.clone(), + nonce: 42, + function: Function::StakingStake, + input_data: Vec::new(), + }, + signature: [2u8; 64], + }; + let h = Header { + parent_hash: [4u8; 32], + number: 42, + state_root: [5u8; 32], + transaction_root: [6u8; 32], + digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, + }; + let b = Block { + header: h, + transactions: vec![tx1, tx2], + }; + let serialised = b.to_vec(); + assert_eq!(serialised, vec![ + // header + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 26, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, + // transactions + 2, 1, 0, 0, + // tx1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 69, 0, 0, 0, 0, 0, 0, 0, + 2, + 40, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0, + // tx2 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 42, 0, 0, 0, 0, 0, 0, 0, + 0, + 0, 0, 0, 0 + ]); +} + +#[test] +fn deserialise_block_works() { + let one: AccountID = [1u8; 32]; + let two: AccountID = [2u8; 32]; + let tx1 = UncheckedTransaction { + transaction: Transaction { + signed: one.clone(), + nonce: 69, + function: Function::StakingTransfer, + input_data: Vec::new().join(&two).join(&69u64), + }, + signature: [1u8; 64], + }; + let tx2 = UncheckedTransaction { + transaction: Transaction { + signed: two.clone(), + nonce: 42, + function: Function::StakingStake, + input_data: Vec::new(), + }, + signature: [2u8; 64], + }; + let h = Header { + parent_hash: [4u8; 32], + number: 42, + state_root: [5u8; 32], + transaction_root: [6u8; 32], + digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, + }; + let b = Block { + header: h, + transactions: vec![tx1, tx2], + }; + let data = [ + // header + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 26, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, + // transactions + 2, 1, 0, 0, + // tx1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 69, 0, 0, 0, 0, 0, 0, 0, + 2, + 40, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0, + // tx2 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 42, 0, 0, 0, 0, 0, 0, 0, + 0, + 0, 0, 0, 0 + ]; + let deserialised = Block::from_slice(&data).unwrap(); + assert_eq!(deserialised, b); +} diff --git a/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs b/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs new file mode 100644 index 0000000000..96dba4e6fb --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs @@ -0,0 +1,69 @@ +// 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 . + +//! Transaction type. + +use runtime_support::prelude::*; +use streamreader::StreamReader; +use joiner::Joiner; +use slicable::{Slicable, NonTrivialSlicable}; +use primitives::{AccountID, TxOrder, Function}; +use runtime_support::mem; + +/// A vetted and verified transaction from the external world. +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +pub struct Transaction { + /// Who signed it (note this is not a signature). + pub signed: AccountID, + /// The number of transactions have come before from the same signer. + pub nonce: TxOrder, + /// The function that should be called. + pub function: Function, + /// Serialised input data to the function. + pub input_data: Vec, +} + +impl Slicable for Transaction { + fn from_slice(value: &[u8]) -> Option { + let mut reader = StreamReader::new(value); + Some(Transaction { + signed: reader.read()?, + nonce: reader.read()?, + function: Function::from_u8(reader.read()?)?, + input_data: reader.read()?, + }) + } + + fn set_as_slice bool>(_fill_slice: &F) -> Option { + unimplemented!(); + } + + fn to_vec(&self) -> Vec { + Vec::new() + .join(&self.signed) + .join(&self.nonce) + .join(&(self.function as u8)) + .join(&self.input_data) + } + + fn size_of(data: &[u8]) -> Option { + let first_part = mem::size_of::() + mem::size_of::() + mem::size_of::(); + let second_part = >::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + +impl NonTrivialSlicable for Transaction {} diff --git a/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs b/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs new file mode 100644 index 0000000000..bf3669ec95 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs @@ -0,0 +1,85 @@ +// 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 . + +//! Unchecked Transaction type. + +use slicable::{Slicable, NonTrivialSlicable}; +use streamreader::StreamReader; +use joiner::Joiner; +use primitives::Transaction; +use runtime_support::{mem, ed25519_verify}; +use runtime_support::prelude::*; + +#[cfg(feature = "with-std")] +use std::fmt; + +/// A transactions right from the external world. Unchecked. +pub struct UncheckedTransaction { + /// The actual transaction information. + pub transaction: Transaction, + /// The signature; should be an Ed25519 signature applied to the serialised `transaction` field. + pub signature: [u8; 64], +} + +impl UncheckedTransaction { + /// Verify the signature. + pub fn ed25519_verify(&self) -> bool { + let msg = self.transaction.to_vec(); + ed25519_verify(&self.signature, &msg, &self.transaction.signed) + } +} + +#[cfg(feature = "with-std")] +impl PartialEq for UncheckedTransaction { + fn eq(&self, other: &Self) -> bool { + self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction + } +} + +#[cfg(feature = "with-std")] +impl fmt::Debug for UncheckedTransaction { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "UncheckedTransaction({:?})", self.transaction) + } +} + +impl Slicable for UncheckedTransaction { + fn from_slice(value: &[u8]) -> Option { + let mut reader = StreamReader::new(value); + Some(UncheckedTransaction { + signature: reader.read()?, + transaction: reader.read()?, + }) + } + + fn set_as_slice bool>(_fill_slice: &F) -> Option { + unimplemented!(); + } + + fn to_vec(&self) -> Vec { + Vec::new() + .join(&self.signature) + .join(&self.transaction) + } + + fn size_of(data: &[u8]) -> Option { + let first_part = mem::size_of::<[u8; 64]>(); + let second_part = ::size_of(&data[first_part..])?; + Some(first_part + second_part) + } +} + +impl NonTrivialSlicable for UncheckedTransaction {} diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index 4d944565a3..307e4bfa00 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -28,8 +28,7 @@ use runtime_support::prelude::*; use keyedvec::KeyedVec; use storable::{Storable, StorageVec, kill}; -use primitives::{AccountID, Hash, BlockNumber}; -use proposal::Proposal; +use primitives::{AccountID, Hash, BlockNumber, Proposal}; use runtime::{staking, system, session}; // TRANSACTION API diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index b3d4640e78..e37cc3cb32 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -17,10 +17,11 @@ //! System manager: Handles all of the top-level stuff; executing block/transaction, setting code //! and depositing logs. -use primitives::{Block, BlockNumber, Hash, UncheckedTransaction, TxOrder, Hashable}; +use primitives::{Block, BlockNumber, Hash, UncheckedTransaction, TxOrder}; use runtime_support::mem; use runtime_support::prelude::*; use runtime_support::print; +use hashable::Hashable; use storable::Storable; use keyedvec::KeyedVec; use environment::with_env; diff --git a/substrate/wasm-runtime/polkadot/src/support/hashable.rs b/substrate/wasm-runtime/polkadot/src/support/hashable.rs new file mode 100644 index 0000000000..31c133c3c3 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/support/hashable.rs @@ -0,0 +1,38 @@ +// 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 . + +//! Hashable trait. + +use slicable::Slicable; +use runtime_support::{blake2_256, twox_128, twox_256}; + +pub trait Hashable: Sized { + fn blake2_256(&self) -> [u8; 32]; + fn twox_128(&self) -> [u8; 16]; + fn twox_256(&self) -> [u8; 32]; +} + +impl Hashable for T { + fn blake2_256(&self) -> [u8; 32] { + blake2_256(&self.to_vec()) + } + fn twox_128(&self) -> [u8; 16] { + twox_128(&self.to_vec()) + } + fn twox_256(&self) -> [u8; 32] { + twox_256(&self.to_vec()) + } +} diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index 3730483b25..c2e034c527 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -16,11 +16,9 @@ //! Support code for the runtime. -pub mod primitives; -pub mod function; -pub mod proposal; pub mod environment; pub mod storable; +pub mod hashable; #[cfg(feature = "with-std")] pub mod statichex; diff --git a/substrate/wasm-runtime/polkadot/src/support/primitives.rs b/substrate/wasm-runtime/polkadot/src/support/primitives.rs deleted file mode 100644 index 48fa91dd79..0000000000 --- a/substrate/wasm-runtime/polkadot/src/support/primitives.rs +++ /dev/null @@ -1,525 +0,0 @@ -// 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 . - -//! Primitive types. - -use runtime_support::prelude::*; -use streamreader::StreamReader; -use joiner::Joiner; -use slicable::{Slicable, NonTrivialSlicable}; -use function::Function; -use runtime_support::{mem, blake2_256, twox_128, twox_256, ed25519_verify}; - -#[cfg(feature = "with-std")] -use std::fmt; - -/// The Ed25519 pubkey that identifies an account. -pub type AccountID = [u8; 32]; - -/// Virtual account ID that represents the idea of a dispatch/statement being signed by everybody -/// (who matters). Essentially this means that a majority of validators have decided it is -/// "correct". -pub const EVERYBODY: AccountID = [255u8; 32]; - -/// The Ed25519 pub key of an session that belongs to an authority. This is used as what the -/// external environment/consensus algorithm calls an "authority". -pub type SessionKey = AccountID; - -/// Indentifier for a chain. -pub type ChainID = u64; - -/// Index of a block in the chain. -pub type BlockNumber = u64; - -/// Index of a transaction. -pub type TxOrder = u64; - -/// A hash of some data. -pub type Hash = [u8; 32]; - -#[derive(Clone, Default)] -#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] -/// The digest of a block, useful for light-clients. -pub struct Digest { - /// All logs that have happened in the block. - pub logs: Vec>, -} - -#[derive(Clone)] -#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] -/// The header for a block. -pub struct Header { - /// The parent block's "hash" (actually the Blake2-256 hash of its serialised header). - pub parent_hash: Hash, - /// The block's number (how many ancestors does it have?). - pub number: BlockNumber, - /// The root of the trie that represents this block's final storage map. - pub state_root: Hash, - /// The root of the trie that represents this block's transactions, indexed by a 32-bit integer. - pub transaction_root: Hash, - /// The digest for this block. - pub digest: Digest, -} - -impl Slicable for Header { - fn from_slice(value: &[u8]) -> Option { - let mut reader = StreamReader::new(value); - Some(Header { - parent_hash: reader.read()?, - number: reader.read()?, - state_root: reader.read()?, - transaction_root: reader.read()?, - digest: Digest { logs: reader.read()?, }, - }) - } - - fn set_as_slice bool>(_fill_slice: &F) -> Option { - unimplemented!(); - } - - fn to_vec(&self) -> Vec { - Vec::new() - .join(&self.parent_hash) - .join(&self.number) - .join(&self.state_root) - .join(&self.transaction_root) - .join(&self.digest.logs) - } - - fn size_of(data: &[u8]) -> Option { - let first_part = mem::size_of::() + mem::size_of::() + mem::size_of::() + mem::size_of::(); - let second_part = >>::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -impl NonTrivialSlicable for Header {} - -/// A vetted and verified transaction from the external world. -#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] -pub struct Transaction { - /// Who signed it (note this is not a signature). - pub signed: AccountID, - /// The number of transactions have come before from the same signer. - pub nonce: TxOrder, - /// The function that should be called. - pub function: Function, - /// Serialised input data to the function. - pub input_data: Vec, -} - -impl Slicable for Transaction { - fn from_slice(value: &[u8]) -> Option { - let mut reader = StreamReader::new(value); - Some(Transaction { - signed: reader.read()?, - nonce: reader.read()?, - function: Function::from_u8(reader.read()?)?, - input_data: reader.read()?, - }) - } - - fn set_as_slice bool>(_fill_slice: &F) -> Option { - unimplemented!(); - } - - fn to_vec(&self) -> Vec { - Vec::new() - .join(&self.signed) - .join(&self.nonce) - .join(&(self.function as u8)) - .join(&self.input_data) - } - - fn size_of(data: &[u8]) -> Option { - let first_part = mem::size_of::() + mem::size_of::() + mem::size_of::(); - let second_part = >::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -pub trait Hashable: Sized { - fn blake2_256(&self) -> [u8; 32]; - fn twox_128(&self) -> [u8; 16]; - fn twox_256(&self) -> [u8; 32]; -} - -impl Hashable for T { - fn blake2_256(&self) -> [u8; 32] { - blake2_256(&self.to_vec()) - } - fn twox_128(&self) -> [u8; 16] { - twox_128(&self.to_vec()) - } - fn twox_256(&self) -> [u8; 32] { - twox_256(&self.to_vec()) - } -} - -impl NonTrivialSlicable for Transaction {} - -/// A transactions right from the external world. Unchecked. -pub struct UncheckedTransaction { - /// The actual transaction information. - pub transaction: Transaction, - /// The signature; should be an Ed25519 signature applied to the serialised `transaction` field. - pub signature: [u8; 64], -} - -impl UncheckedTransaction { - /// Verify the signature. - pub fn ed25519_verify(&self) -> bool { - let msg = self.transaction.to_vec(); - ed25519_verify(&self.signature, &msg, &self.transaction.signed) - } -} - -#[cfg(feature = "with-std")] -impl PartialEq for UncheckedTransaction { - fn eq(&self, other: &Self) -> bool { - self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction - } -} - -#[cfg(feature = "with-std")] -impl fmt::Debug for UncheckedTransaction { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "UncheckedTransaction({:?})", self.transaction) - } -} - -impl Slicable for UncheckedTransaction { - fn from_slice(value: &[u8]) -> Option { - let mut reader = StreamReader::new(value); - Some(UncheckedTransaction { - signature: reader.read()?, - transaction: reader.read()?, - }) - } - - fn set_as_slice bool>(_fill_slice: &F) -> Option { - unimplemented!(); - } - - fn to_vec(&self) -> Vec { - Vec::new() - .join(&self.signature) - .join(&self.transaction) - } - - fn size_of(data: &[u8]) -> Option { - let first_part = mem::size_of::<[u8; 64]>(); - let second_part = ::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -impl NonTrivialSlicable for UncheckedTransaction {} - -/// A Polkadot relay chain block. -#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] -pub struct Block { - /// The header of the block. - pub header: Header, - /// All transactions. - pub transactions: Vec, -} - -impl Slicable for Block { - fn from_slice(value: &[u8]) -> Option { - let mut reader = StreamReader::new(value); - Some(Block { - header: reader.read()?, - transactions: reader.read()?, - }) - } - - fn set_as_slice bool>(_fill_slice: &F) -> Option { - unimplemented!(); - } - - fn to_vec(&self) -> Vec { - Vec::new() - .join(&self.header) - .join(&self.transactions) - } - - fn size_of(data: &[u8]) -> Option { - let first_part = Header::size_of(data)?; - let second_part = >::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -impl NonTrivialSlicable for Block {} - -impl NonTrivialSlicable for Vec where Vec: Slicable {} - -impl Slicable for Vec { - fn from_slice(value: &[u8]) -> Option { - let len = Self::size_of(&value[0..4])?; - let mut off = 4; - let mut r = Vec::new(); - while off < len { - let element_len = T::size_of(&value[off..])?; - r.push(T::from_slice(&value[off..off + element_len])?); - off += element_len; - } - Some(r) - } - - fn set_as_slice bool>(_fill_slice: &F) -> Option { - unimplemented!(); - } - - fn to_vec(&self) -> Vec { - let vecs = self.iter().map(Slicable::to_vec).collect::>(); - let len = vecs.iter().fold(0, |mut a, v| {a += v.len(); a}); - let mut r = Vec::new().join(&(len as u32)); - vecs.iter().for_each(|v| r.extend_from_slice(v)); - r - } - - fn size_of(data: &[u8]) -> Option { - u32::from_slice(&data[0..4]).map(|i| (i + 4) as usize) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use joiner::Joiner; - use function::Function; - - #[test] - fn serialise_transaction_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - let tx = Transaction { - signed: one.clone(), - nonce: 69, - function: Function::StakingTransfer, - input_data: Vec::new().join(&two).join(&69u64), - }; - let serialised = tx.to_vec(); - assert_eq!(serialised, vec![ - 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 69, 0, 0, 0, 0, 0, 0, 0, - 2, - 40, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 69, 0, 0, 0, 0, 0, 0, 0 - ]); - } - - #[test] - fn deserialise_transaction_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - let tx = Transaction { - signed: one.clone(), - nonce: 69, - function: Function::StakingTransfer, - input_data: Vec::new().join(&two).join(&69u64), - }; - let data = [ - 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 69, 0, 0, 0, 0, 0, 0, 0, - 2, - 40, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 69, 0, 0, 0, 0, 0, 0, 0 - ]; - let deserialised = Transaction::from_slice(&data).unwrap(); - assert_eq!(deserialised, tx); - } - - #[test] - fn serialise_header_works() { - let h = Header { - parent_hash: [4u8; 32], - number: 42, - state_root: [5u8; 32], - transaction_root: [6u8; 32], - digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, - }; - let serialised = h.to_vec(); - assert_eq!(serialised, vec![ - 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 42, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 26, 0, 0, 0, - 7, 0, 0, 0, - 111, 110, 101, 32, 108, 111, 103, - 11, 0, 0, 0, - 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 - ]); - } - - #[test] - fn deserialise_header_works() { - let h = Header { - parent_hash: [4u8; 32], - number: 42, - state_root: [5u8; 32], - transaction_root: [6u8; 32], - digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, - }; - let data = [ - 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 42, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 26, 0, 0, 0, - 7, 0, 0, 0, - 111, 110, 101, 32, 108, 111, 103, - 11, 0, 0, 0, - 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 - ]; - let deserialised = Header::from_slice(&data).unwrap(); - assert_eq!(deserialised, h); - } - - #[test] - fn serialise_block_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - let tx1 = UncheckedTransaction { - transaction: Transaction { - signed: one.clone(), - nonce: 69, - function: Function::StakingTransfer, - input_data: Vec::new().join(&two).join(&69u64), - }, - signature: [1u8; 64], - }; - let tx2 = UncheckedTransaction { - transaction: Transaction { - signed: two.clone(), - nonce: 42, - function: Function::StakingStake, - input_data: Vec::new(), - }, - signature: [2u8; 64], - }; - let h = Header { - parent_hash: [4u8; 32], - number: 42, - state_root: [5u8; 32], - transaction_root: [6u8; 32], - digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, - }; - let b = Block { - header: h, - transactions: vec![tx1, tx2], - }; - let serialised = b.to_vec(); - assert_eq!(serialised, vec![ - // header - 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 42, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 26, 0, 0, 0, - 7, 0, 0, 0, - 111, 110, 101, 32, 108, 111, 103, - 11, 0, 0, 0, - 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, - // transactions - 2, 1, 0, 0, - // tx1 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 69, 0, 0, 0, 0, 0, 0, 0, - 2, - 40, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 69, 0, 0, 0, 0, 0, 0, 0, - // tx2 - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 42, 0, 0, 0, 0, 0, 0, 0, - 0, - 0, 0, 0, 0 - ]); - } - - #[test] - fn deserialise_block_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - let tx1 = UncheckedTransaction { - transaction: Transaction { - signed: one.clone(), - nonce: 69, - function: Function::StakingTransfer, - input_data: Vec::new().join(&two).join(&69u64), - }, - signature: [1u8; 64], - }; - let tx2 = UncheckedTransaction { - transaction: Transaction { - signed: two.clone(), - nonce: 42, - function: Function::StakingStake, - input_data: Vec::new(), - }, - signature: [2u8; 64], - }; - let h = Header { - parent_hash: [4u8; 32], - number: 42, - state_root: [5u8; 32], - transaction_root: [6u8; 32], - digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, - }; - let b = Block { - header: h, - transactions: vec![tx1, tx2], - }; - let data = [ - // header - 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 42, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 26, 0, 0, 0, - 7, 0, 0, 0, - 111, 110, 101, 32, 108, 111, 103, - 11, 0, 0, 0, - 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, - // transactions - 2, 1, 0, 0, - // tx1 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 69, 0, 0, 0, 0, 0, 0, 0, - 2, - 40, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 69, 0, 0, 0, 0, 0, 0, 0, - // tx2 - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 42, 0, 0, 0, 0, 0, 0, 0, - 0, - 0, 0, 0, 0 - ]; - let deserialised = Block::from_slice(&data).unwrap(); - assert_eq!(deserialised, b); - } -} diff --git a/substrate/wasm-runtime/support/src/lib.rs b/substrate/wasm-runtime/support/src/lib.rs index 878ef18ca0..82e34f3297 100644 --- a/substrate/wasm-runtime/support/src/lib.rs +++ b/substrate/wasm-runtime/support/src/lib.rs @@ -99,7 +99,7 @@ pub fn twox_256(data: &[u8]) -> [u8; 32] { result } -/// Conduct two XX hashes to give a 256-bit result. +/// Conduct two XX hashes to give a 128-bit result. pub fn twox_128(data: &[u8]) -> [u8; 16] { let mut result: [u8; 16] = Default::default(); // guaranteed to write into result. diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index 9bf101d73fd663a6ed67a0af89597d6b7273e4cd..63473ae445f0cf1d236ec0fc3f22f4d9baee3730 100644 GIT binary patch delta 16353 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 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index 6cbc2ef9b954b61a94ec459c330f44ab9975f50d..f2492b00ecb4b75e28bc85cbdcbc45b7138c0af6 100644 GIT binary patch delta 16399 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 delta 16041 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