mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 23:21:06 +00:00
Phase 1 of repo reorg (#719)
* Remove unneeded script * Rename Substrate Demo -> Substrate * Rename demo -> node * Build wasm from last rename. * Merge ed25519 into substrate-primitives * Minor tweak * Rename substrate -> core * Move substrate-runtime-support to core/runtime/support * Rename/move substrate-runtime-version * Move codec up a level * Rename substrate-codec -> parity-codec * Move environmental up a level * Move pwasm-* up to top, ready for removal * Remove requirement of s-r-support from s-r-primitives * Move core/runtime/primitives into core/runtime-primitives * Remove s-r-support dep from s-r-version * Remove dep of s-r-support from bft * Remove dep of s-r-support from node/consensus * Sever all other core deps from s-r-support * Forgot the no_std directive * Rename non-SRML modules to sr-* to avoid match clashes * Move runtime/* to srml/* * Rename substrate-runtime-* -> srml-* * Move srml to top-level
This commit is contained in:
committed by
Arkadiy Paronyan
parent
8fe5aa4c81
commit
1e01162505
@@ -0,0 +1,106 @@
|
||||
// Copyright 2017 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(feature = "std")]
|
||||
use serde::{Serialize, Serializer, Deserialize, Deserializer};
|
||||
use H256;
|
||||
|
||||
/// An identifier for an authority in the consensus algorithm. The same size as ed25519::Public.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Default, Encode, Decode)]
|
||||
pub struct AuthorityId(pub [u8; 32]);
|
||||
|
||||
impl AuthorityId {
|
||||
/// Create an id from a 32-byte slice. Panics with other lengths.
|
||||
#[cfg(feature = "std")]
|
||||
fn from_slice(data: &[u8]) -> Self {
|
||||
let mut r = [0u8; 32];
|
||||
r.copy_from_slice(data);
|
||||
AuthorityId(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl ::std::fmt::Display for AuthorityId {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
write!(f, "{}", ::hexdisplay::HexDisplay::from(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl ::std::fmt::Debug for AuthorityId {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
write!(f, "{}", ::hexdisplay::HexDisplay::from(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl ::std::hash::Hash for AuthorityId {
|
||||
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.0.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8; 32]> for AuthorityId {
|
||||
fn as_ref(&self) -> &[u8; 32] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for AuthorityId {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<[u8; 32]> for AuthorityId {
|
||||
fn into(self) -> [u8; 32] {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 32]> for AuthorityId {
|
||||
fn from(a: [u8; 32]) -> Self {
|
||||
AuthorityId(a)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<AuthorityId> for AuthorityId {
|
||||
fn as_ref(&self) -> &AuthorityId {
|
||||
&self
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<H256> for AuthorityId {
|
||||
fn into(self) -> H256 {
|
||||
self.0.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Serialize for AuthorityId {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
|
||||
::bytes::serialize(&self.0, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<'de> Deserialize<'de> for AuthorityId {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
|
||||
::bytes::deserialize_check_len(deserializer, ::bytes::ExpectedLen::Exact(32))
|
||||
.map(|x| AuthorityId::from_slice(&x))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
// Copyright 2017 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/>.
|
||||
|
||||
//! Simple type for representing Vec<u8> with regards to serde.
|
||||
|
||||
use core::fmt;
|
||||
|
||||
use serde::{de, Serializer, Deserializer};
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
mod alloc_types {
|
||||
pub use ::alloc::string::String;
|
||||
pub use ::alloc::vec::Vec;
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
mod alloc_types {
|
||||
pub use ::std::vec::Vec;
|
||||
pub use ::std::string::String;
|
||||
}
|
||||
|
||||
pub use self::alloc_types::*;
|
||||
|
||||
/// Serializes a slice of bytes.
|
||||
pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error> where
|
||||
S: Serializer,
|
||||
{
|
||||
let hex: String = ::rustc_hex::ToHex::to_hex(bytes);
|
||||
serializer.serialize_str(&format!("0x{}", hex))
|
||||
}
|
||||
|
||||
/// Serialize a slice of bytes as uint.
|
||||
///
|
||||
/// The representation will have all leading zeros trimmed.
|
||||
pub fn serialize_uint<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error> where
|
||||
S: Serializer,
|
||||
{
|
||||
let non_zero = bytes.iter().take_while(|b| **b == 0).count();
|
||||
let bytes = &bytes[non_zero..];
|
||||
if bytes.is_empty() {
|
||||
return serializer.serialize_str("0x0");
|
||||
}
|
||||
|
||||
let hex: String = ::rustc_hex::ToHex::to_hex(bytes);
|
||||
let has_leading_zero = !hex.is_empty() && &hex[0..1] == "0";
|
||||
serializer.serialize_str(
|
||||
&format!("0x{}", if has_leading_zero { &hex[1..] } else { &hex })
|
||||
)
|
||||
}
|
||||
|
||||
/// Expected length of bytes vector.
|
||||
#[derive(PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Debug))]
|
||||
pub enum ExpectedLen {
|
||||
/// Any length in bytes.
|
||||
#[cfg_attr(not(feature = "std"), allow(unused))]
|
||||
Any,
|
||||
/// Exact length in bytes.
|
||||
Exact(usize),
|
||||
/// A bytes length between (min; max].
|
||||
Between(usize, usize),
|
||||
}
|
||||
|
||||
impl fmt::Display for ExpectedLen {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
ExpectedLen::Any => write!(fmt, "even length"),
|
||||
ExpectedLen::Exact(v) => write!(fmt, "length of {}", v * 2),
|
||||
ExpectedLen::Between(min, max) => write!(fmt, "length between ({}; {}]", min * 2, max * 2),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Deserialize into vector of bytes.
|
||||
#[cfg(feature = "std")]
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error> where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserialize_check_len(deserializer, ExpectedLen::Any)
|
||||
}
|
||||
|
||||
/// Deserialize into vector of bytes with additional size check.
|
||||
pub fn deserialize_check_len<'de, D>(deserializer: D, len: ExpectedLen) -> Result<Vec<u8>, D::Error> where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct Visitor {
|
||||
len: ExpectedLen,
|
||||
}
|
||||
|
||||
impl<'a> de::Visitor<'a> for Visitor {
|
||||
type Value = Vec<u8>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "a 0x-prefixed hex string with {}", self.len)
|
||||
}
|
||||
|
||||
fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
|
||||
if v.len() < 2 || &v[0..2] != "0x" {
|
||||
return Err(E::custom("prefix is missing"))
|
||||
}
|
||||
|
||||
let is_len_valid = match self.len {
|
||||
// just make sure that we have all nibbles
|
||||
ExpectedLen::Any => v.len() % 2 == 0,
|
||||
ExpectedLen::Exact(len) => v.len() == 2 * len + 2,
|
||||
ExpectedLen::Between(min, max) => v.len() <= 2 * max + 2 && v.len() > 2 * min + 2,
|
||||
};
|
||||
|
||||
if !is_len_valid {
|
||||
return Err(E::invalid_length(v.len() - 2, &self))
|
||||
}
|
||||
|
||||
let bytes = match self.len {
|
||||
ExpectedLen::Between(..) if v.len() % 2 != 0 => {
|
||||
::rustc_hex::FromHex::from_hex(&*format!("0{}", &v[2..]))
|
||||
},
|
||||
_ => ::rustc_hex::FromHex::from_hex(&v[2..])
|
||||
};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
fn format_err(e: ::rustc_hex::FromHexError) -> String {
|
||||
format!("invalid hex value: {:?}", e)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
fn format_err(e: ::rustc_hex::FromHexError) -> String {
|
||||
match e {
|
||||
::rustc_hex::InvalidHexLength => format!("invalid hex value: invalid length"),
|
||||
::rustc_hex::InvalidHexCharacter(c, p) =>
|
||||
format!("invalid hex value: invalid character {} at position {}", c, p),
|
||||
}
|
||||
}
|
||||
|
||||
bytes.map_err(|e| E::custom(format_err(e)))
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
fn visit_string<E: de::Error>(self, v: String) -> Result<Self::Value, E> {
|
||||
self.visit_str(&v)
|
||||
}
|
||||
}
|
||||
// TODO [ToDr] Use raw bytes if we switch to RLP / binencoding
|
||||
// (visit_bytes, visit_bytes_buf)
|
||||
deserializer.deserialize_str(Visitor { len })
|
||||
}
|
||||
@@ -0,0 +1,352 @@
|
||||
// Copyright 2017 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/>.
|
||||
|
||||
// tag::description[]
|
||||
//! Simple Ed25519 API.
|
||||
// end::description[]
|
||||
|
||||
use untrusted;
|
||||
use blake2_rfc;
|
||||
use ring::{rand, signature};
|
||||
use {hash::H512, AuthorityId};
|
||||
use base58::{ToBase58, FromBase58};
|
||||
|
||||
/// Alias to 512-bit hash when used in the context of a signature on the relay chain.
|
||||
pub type Signature = H512;
|
||||
|
||||
/// Length of the PKCS#8 encoding of the key.
|
||||
pub const PKCS_LEN: usize = 85;
|
||||
|
||||
/// A localized signature also contains sender information.
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
pub struct LocalizedSignature {
|
||||
/// The signer of the signature.
|
||||
pub signer: Public,
|
||||
/// The signature itself.
|
||||
pub signature: Signature,
|
||||
}
|
||||
|
||||
/// Verify a message without type checking the parameters' types for the right size.
|
||||
pub fn verify<P: AsRef<[u8]>>(sig: &[u8], message: &[u8], public: P) -> bool {
|
||||
let public_key = untrusted::Input::from(public.as_ref());
|
||||
let msg = untrusted::Input::from(message);
|
||||
let sig = untrusted::Input::from(sig);
|
||||
|
||||
match signature::verify(&signature::ED25519, public_key, msg, sig) {
|
||||
Ok(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// A public key.
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct Public(pub [u8; 32]);
|
||||
|
||||
/// A key pair.
|
||||
pub struct Pair(signature::Ed25519KeyPair);
|
||||
|
||||
impl ::std::hash::Hash for Public {
|
||||
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.0.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// An error type for SS58 decoding.
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||
pub enum PublicError {
|
||||
/// Bad alphabet.
|
||||
BadBase58,
|
||||
/// Bad length.
|
||||
BadLength,
|
||||
/// Unknown version.
|
||||
UnknownVersion,
|
||||
/// Invalid checksum.
|
||||
InvalidChecksum,
|
||||
}
|
||||
|
||||
impl Public {
|
||||
/// A new instance from the given 32-byte `data`.
|
||||
pub fn from_raw(data: [u8; 32]) -> Self {
|
||||
Public(data)
|
||||
}
|
||||
|
||||
/// A new instance from the given slice that should be 32 bytes long.
|
||||
pub fn from_slice(data: &[u8]) -> Self {
|
||||
let mut r = [0u8; 32];
|
||||
r.copy_from_slice(data);
|
||||
Public(r)
|
||||
}
|
||||
|
||||
/// Some if the string is a properly encoded SS58Check address.
|
||||
pub fn from_ss58check(s: &str) -> Result<Self, PublicError> {
|
||||
let d = s.from_base58().map_err(|_| PublicError::BadBase58)?; // failure here would be invalid encoding.
|
||||
if d.len() != 35 {
|
||||
// Invalid length.
|
||||
return Err(PublicError::BadLength);
|
||||
}
|
||||
if d[0] != 42 {
|
||||
// Invalid version.
|
||||
return Err(PublicError::UnknownVersion);
|
||||
}
|
||||
if d[33..35] != blake2_rfc::blake2b::blake2b(64, &[], &d[0..33]).as_bytes()[0..2] {
|
||||
// Invalid checksum.
|
||||
return Err(PublicError::InvalidChecksum);
|
||||
}
|
||||
Ok(Self::from_slice(&d[1..33]))
|
||||
}
|
||||
|
||||
/// Return a `Vec<u8>` filled with raw data.
|
||||
pub fn to_raw_vec(self) -> Vec<u8> {
|
||||
let r: &[u8; 32] = self.as_ref();
|
||||
r.to_vec()
|
||||
}
|
||||
|
||||
/// Return a slice filled with raw data.
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
let r: &[u8; 32] = self.as_ref();
|
||||
&r[..]
|
||||
}
|
||||
|
||||
/// Return a slice filled with raw data.
|
||||
pub fn as_array_ref(&self) -> &[u8; 32] {
|
||||
self.as_ref()
|
||||
}
|
||||
|
||||
/// Return the ss58-check string for this key.
|
||||
pub fn to_ss58check(&self) -> String {
|
||||
let mut v = vec![42u8];
|
||||
v.extend(self.as_slice());
|
||||
let r = blake2_rfc::blake2b::blake2b(64, &[], &v);
|
||||
v.extend(&r.as_bytes()[0..2]);
|
||||
v.to_base58()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8; 32]> for Public {
|
||||
fn as_ref(&self) -> &[u8; 32] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Public {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<[u8; 32]> for Public {
|
||||
fn into(self) -> [u8; 32] {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Public> for Public {
|
||||
fn as_ref(&self) -> &Public {
|
||||
&self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Pair> for Pair {
|
||||
fn as_ref(&self) -> &Pair {
|
||||
&self
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<AuthorityId> for Public {
|
||||
fn into(self) -> AuthorityId {
|
||||
AuthorityId(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AuthorityId> for Public {
|
||||
fn from(id: AuthorityId) -> Self {
|
||||
Public(id.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for Public {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
write!(f, "{}", self.to_ss58check())
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Debug for Public {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
let s = self.to_ss58check();
|
||||
write!(f, "{} ({}...)", ::hexdisplay::HexDisplay::from(&self.0), &s[0..8])
|
||||
}
|
||||
}
|
||||
|
||||
impl Pair {
|
||||
/// Generate new secure (random) key pair, yielding it and the corresponding pkcs#8 bytes.
|
||||
pub fn generate_with_pkcs8() -> (Self, [u8; PKCS_LEN]) {
|
||||
let rng = rand::SystemRandom::new();
|
||||
let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).expect("system randomness is available; qed");
|
||||
let pair = Self::from_pkcs8(&pkcs8_bytes).expect("just-generated pkcs#8 data is valid; qed");
|
||||
|
||||
(pair, pkcs8_bytes)
|
||||
}
|
||||
|
||||
/// Generate new secure (random) key pair.
|
||||
pub fn generate() -> Pair {
|
||||
let (pair, _) = Self::generate_with_pkcs8();
|
||||
pair
|
||||
}
|
||||
|
||||
/// Generate from pkcs#8 bytes.
|
||||
pub fn from_pkcs8(pkcs8_bytes: &[u8]) -> Result<Self, ::ring::error::Unspecified> {
|
||||
signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).map(Pair)
|
||||
}
|
||||
|
||||
/// Make a new key pair from a seed phrase.
|
||||
/// NOTE: prefer pkcs#8 unless security doesn't matter -- this is used primarily for tests.
|
||||
pub fn from_seed(seed: &[u8; 32]) -> Pair {
|
||||
let key = signature::Ed25519KeyPair::from_seed_unchecked(untrusted::Input::from(&seed[..]))
|
||||
.expect("seed has valid length; qed");
|
||||
|
||||
Pair(key)
|
||||
}
|
||||
|
||||
/// Sign a message.
|
||||
pub fn sign(&self, message: &[u8]) -> Signature {
|
||||
let mut r = [0u8; 64];
|
||||
r.copy_from_slice(self.0.sign(message).as_ref());
|
||||
Signature::from(r)
|
||||
}
|
||||
|
||||
/// Get the public key.
|
||||
pub fn public(&self) -> Public {
|
||||
let mut r = [0u8; 32];
|
||||
let pk = self.0.public_key_bytes();
|
||||
r.copy_from_slice(pk);
|
||||
Public(r)
|
||||
}
|
||||
|
||||
/// Derive a child key. Probably unsafe and broken.
|
||||
// TODO: proper HD derivation https://cardanolaunch.com/assets/Ed25519_BIP.pdf
|
||||
pub fn derive_child_probably_bad(&self, chain_data: &[u8]) -> Pair {
|
||||
let sig = self.sign(chain_data);
|
||||
let mut seed = [0u8; 32];
|
||||
seed.copy_from_slice(&sig.0[..32]);
|
||||
|
||||
Pair::from_seed(&seed)
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify a signature on a message.
|
||||
pub fn verify_strong<P: AsRef<Public>>(sig: &Signature, message: &[u8], pubkey: P) -> bool {
|
||||
let public_key = untrusted::Input::from(&pubkey.as_ref().0[..]);
|
||||
let msg = untrusted::Input::from(message);
|
||||
let sig = untrusted::Input::from(&sig.0[..]);
|
||||
|
||||
match signature::verify(&signature::ED25519, public_key, msg, sig) {
|
||||
Ok(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Something that acts as a signature allowing a message to be verified.
|
||||
pub trait Verifiable {
|
||||
/// Verify something that acts like a signature.
|
||||
fn verify<P: AsRef<Public>>(&self, message: &[u8], pubkey: P) -> bool;
|
||||
}
|
||||
|
||||
impl Verifiable for Signature {
|
||||
/// Verify something that acts like a signature.
|
||||
fn verify<P: AsRef<Public>>(&self, message: &[u8], pubkey: P) -> bool {
|
||||
verify_strong(&self, message, pubkey)
|
||||
}
|
||||
}
|
||||
|
||||
impl Verifiable for LocalizedSignature {
|
||||
fn verify<P: AsRef<Public>>(&self, message: &[u8], pubkey: P) -> bool {
|
||||
pubkey.as_ref() == &self.signer && self.signature.verify(message, pubkey)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
fn _test_primitives_signature_and_local_the_same() {
|
||||
fn takes_two<T>(_: T, _: T) { }
|
||||
takes_two(Signature::default(), ::Signature::default())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vector_should_work() {
|
||||
let pair: Pair = Pair::from_seed(&hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"));
|
||||
let public = pair.public();
|
||||
assert_eq!(public, Public::from_raw(hex!("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a")));
|
||||
let message = b"";
|
||||
let signature: Signature = hex!("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b").into();
|
||||
assert!(&pair.sign(&message[..]) == &signature);
|
||||
assert!(verify_strong(&signature, &message[..], &public));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generated_pair_should_work() {
|
||||
let pair = Pair::generate();
|
||||
let public = pair.public();
|
||||
let message = b"Something important";
|
||||
let signature = pair.sign(&message[..]);
|
||||
assert!(verify_strong(&signature, &message[..], &public));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn seeded_pair_should_work() {
|
||||
use ::hexdisplay::HexDisplay;
|
||||
|
||||
let pair = Pair::from_seed(b"12345678901234567890123456789012");
|
||||
let public = pair.public();
|
||||
assert_eq!(public, Public::from_raw(hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee")));
|
||||
let message = hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000200d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000");
|
||||
let signature = pair.sign(&message[..]);
|
||||
println!("Correct signature: {}", HexDisplay::from(&signature.0));
|
||||
assert!(verify_strong(&signature, &message[..], &public));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generate_with_pkcs8_recovery_possible() {
|
||||
let (pair1, pkcs8) = Pair::generate_with_pkcs8();
|
||||
let pair2 = Pair::from_pkcs8(&pkcs8).unwrap();
|
||||
|
||||
assert_eq!(pair1.public(), pair2.public());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive_child() {
|
||||
let pair = Pair::generate();
|
||||
let _pair2 = pair.derive_child_probably_bad(b"session_1234");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ss58check_roundtrip_works() {
|
||||
let pair = Pair::from_seed(b"12345678901234567890123456789012");
|
||||
let public = pair.public();
|
||||
let s = public.to_ss58check();
|
||||
println!("Correct: {}", s);
|
||||
let cmp = Public::from_ss58check(&s).unwrap();
|
||||
assert_eq!(cmp, public);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ss58check_known_works() {
|
||||
let k = "5CGavy93sZgPPjHyziRohwVumxiHXMGmQLyuqQP4ZFx5vRU9";
|
||||
let enc = hex!["090fa15cb5b1666222fff584b4cc2b1761fe1e238346b340491b37e25ea183ff"];
|
||||
assert_eq!(Public::from_ss58check(k).unwrap(), Public::from_raw(enc));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
// Copyright 2017 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/>.
|
||||
|
||||
//! A fixed hash type.
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use serde::{Serialize, Serializer, Deserialize, Deserializer};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use bytes;
|
||||
#[cfg(feature = "std")]
|
||||
use core::cmp;
|
||||
#[cfg(feature = "std")]
|
||||
use rlp::{Rlp, RlpStream, DecoderError};
|
||||
|
||||
macro_rules! impl_rest {
|
||||
($name: ident, $len: expr) => {
|
||||
#[cfg(feature = "std")]
|
||||
impl Serialize for $name {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
|
||||
bytes::serialize(&self.0, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<'de> Deserialize<'de> for $name {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
|
||||
bytes::deserialize_check_len(deserializer, bytes::ExpectedLen::Exact($len))
|
||||
.map(|x| (&*x).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl ::codec::Encode for $name {
|
||||
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
|
||||
self.0.using_encoded(f)
|
||||
}
|
||||
}
|
||||
impl ::codec::Decode for $name {
|
||||
fn decode<I: ::codec::Input>(input: &mut I) -> Option<Self> {
|
||||
<[u8; $len] as ::codec::Decode>::decode(input).map($name)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl ::rlp::Encodable for $name {
|
||||
fn rlp_append(&self, s: &mut RlpStream) {
|
||||
s.encoder().encode_value(self);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl ::rlp::Decodable for $name {
|
||||
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
|
||||
rlp.decoder().decode_value(|bytes| match bytes.len().cmp(&$len) {
|
||||
cmp::Ordering::Less => Err(DecoderError::RlpIsTooShort),
|
||||
cmp::Ordering::Greater => Err(DecoderError::RlpIsTooBig),
|
||||
cmp::Ordering::Equal => {
|
||||
let mut t = [0u8; $len];
|
||||
t.copy_from_slice(bytes);
|
||||
Ok($name(t))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
construct_hash!(H160, 20);
|
||||
construct_hash!(H256, 32);
|
||||
construct_hash!(H512, 64);
|
||||
impl_rest!(H160, 20);
|
||||
impl_rest!(H256, 32);
|
||||
impl_rest!(H512, 64);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use substrate_serializer as ser;
|
||||
use rlp::{Encodable, RlpStream};
|
||||
|
||||
#[test]
|
||||
fn test_hash_is_encodable() {
|
||||
let h = H160::from(21);
|
||||
let mut s = RlpStream::new();
|
||||
h.rlp_append(&mut s);
|
||||
assert_eq!(s.drain().into_vec(), &[148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash_is_decodable() {
|
||||
let data = vec![148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123];
|
||||
let res = ::rlp::decode::<H160>(&data);
|
||||
assert!(res.is_ok());
|
||||
assert_eq!(res.unwrap(), H160::from(123));
|
||||
|
||||
let res = ::rlp::decode::<H256>(&data);
|
||||
assert!(res.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h160() {
|
||||
let tests = vec![
|
||||
(Default::default(), "0x0000000000000000000000000000000000000000"),
|
||||
(H160::from(2), "0x0000000000000000000000000000000000000002"),
|
||||
(H160::from(15), "0x000000000000000000000000000000000000000f"),
|
||||
(H160::from(16), "0x0000000000000000000000000000000000000010"),
|
||||
(H160::from(1_000), "0x00000000000000000000000000000000000003e8"),
|
||||
(H160::from(100_000), "0x00000000000000000000000000000000000186a0"),
|
||||
(H160::from(u64::max_value()), "0x000000000000000000000000ffffffffffffffff"),
|
||||
];
|
||||
|
||||
for (number, expected) in tests {
|
||||
assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number));
|
||||
assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_h256() {
|
||||
let tests = vec![
|
||||
(Default::default(), "0x0000000000000000000000000000000000000000000000000000000000000000"),
|
||||
(H256::from(2), "0x0000000000000000000000000000000000000000000000000000000000000002"),
|
||||
(H256::from(15), "0x000000000000000000000000000000000000000000000000000000000000000f"),
|
||||
(H256::from(16), "0x0000000000000000000000000000000000000000000000000000000000000010"),
|
||||
(H256::from(1_000), "0x00000000000000000000000000000000000000000000000000000000000003e8"),
|
||||
(H256::from(100_000), "0x00000000000000000000000000000000000000000000000000000000000186a0"),
|
||||
(H256::from(u64::max_value()), "0x000000000000000000000000000000000000000000000000ffffffffffffffff"),
|
||||
];
|
||||
|
||||
for (number, expected) in tests {
|
||||
assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number));
|
||||
assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid() {
|
||||
assert!(ser::from_str::<H256>("\"0x000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<H256>("\"0x000000000000000000000000000000000000000000000000000000000000000g\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<H256>("\"0x00000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<H256>("\"\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<H256>("\"0\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<H256>("\"10\"").unwrap_err().is_data());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_heapsizeof() {
|
||||
use heapsize::HeapSizeOf;
|
||||
let h = H256::new();
|
||||
assert_eq!(h.heap_size_of_children(), 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// 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/>.
|
||||
|
||||
//! Polkadot Blake2b Hasher implementation
|
||||
|
||||
use hashdb::Hasher;
|
||||
use plain_hasher::PlainHasher;
|
||||
use hash::H256;
|
||||
|
||||
pub mod blake2 {
|
||||
use super::{Hasher, PlainHasher, H256};
|
||||
#[cfg(feature = "std")]
|
||||
use hashing::blake2_256;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
extern "C" {
|
||||
fn ext_blake2_256(data: *const u8, len: u32, out: *mut u8);
|
||||
}
|
||||
#[cfg(not(feature = "std"))]
|
||||
fn blake2_256(data: &[u8]) -> [u8; 32] {
|
||||
let mut result: [u8; 32] = Default::default();
|
||||
unsafe {
|
||||
ext_blake2_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr());
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Concrete implementation of Hasher using Blake2b 256-bit hashes
|
||||
#[derive(Debug)]
|
||||
pub struct Blake2Hasher;
|
||||
|
||||
impl Hasher for Blake2Hasher {
|
||||
type Out = H256;
|
||||
type StdHasher = PlainHasher;
|
||||
const LENGTH:usize = 32;
|
||||
fn hash(x: &[u8]) -> Self::Out {
|
||||
blake2_256(x).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
// Copyright 2017 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/>.
|
||||
|
||||
//! Hashing functions.
|
||||
|
||||
use blake2_rfc;
|
||||
use twox_hash;
|
||||
|
||||
/// Do a Blake2 512-bit hash and place result in `dest`.
|
||||
pub fn blake2_512_into(data: &[u8], dest: &mut [u8; 64]) {
|
||||
dest.copy_from_slice(blake2_rfc::blake2b::blake2b(64, &[], data).as_bytes());
|
||||
}
|
||||
|
||||
/// Do a Blake2 512-bit hash and return result.
|
||||
pub fn blake2_512(data: &[u8]) -> [u8; 64] {
|
||||
let mut r = [0; 64];
|
||||
blake2_512_into(data, &mut r);
|
||||
r
|
||||
}
|
||||
|
||||
/// Do a Blake2 256-bit hash and place result in `dest`.
|
||||
pub fn blake2_256_into(data: &[u8], dest: &mut [u8; 32]) {
|
||||
dest.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes());
|
||||
}
|
||||
|
||||
/// Do a Blake2 256-bit hash and return result.
|
||||
pub fn blake2_256(data: &[u8]) -> [u8; 32] {
|
||||
let mut r = [0; 32];
|
||||
blake2_256_into(data, &mut r);
|
||||
r
|
||||
}
|
||||
|
||||
/// Do a Blake2 128-bit hash and place result in `dest`.
|
||||
pub fn blake2_128_into(data: &[u8], dest: &mut [u8; 16]) {
|
||||
dest.copy_from_slice(blake2_rfc::blake2b::blake2b(16, &[], data).as_bytes());
|
||||
}
|
||||
|
||||
/// Do a Blake2 128-bit hash and return result.
|
||||
pub fn blake2_128(data: &[u8]) -> [u8; 16] {
|
||||
let mut r = [0; 16];
|
||||
blake2_128_into(data, &mut r);
|
||||
r
|
||||
}
|
||||
|
||||
/// Do a XX 128-bit hash and place result in `dest`.
|
||||
pub fn twox_128_into(data: &[u8], dest: &mut [u8; 16]) {
|
||||
use ::core::hash::Hasher;
|
||||
let mut h0 = twox_hash::XxHash::with_seed(0);
|
||||
let mut h1 = twox_hash::XxHash::with_seed(1);
|
||||
h0.write(data);
|
||||
h1.write(data);
|
||||
let r0 = h0.finish();
|
||||
let r1 = h1.finish();
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
LittleEndian::write_u64(&mut dest[0..8], r0);
|
||||
LittleEndian::write_u64(&mut dest[8..16], r1);
|
||||
}
|
||||
|
||||
/// Do a XX 128-bit hash and return result.
|
||||
pub fn twox_128(data: &[u8]) -> [u8; 16] {
|
||||
let mut r: [u8; 16] = [0; 16];
|
||||
twox_128_into(data, &mut r);
|
||||
r
|
||||
}
|
||||
|
||||
/// Do a XX 256-bit hash and place result in `dest`.
|
||||
pub fn twox_256_into(data: &[u8], dest: &mut [u8; 32]) {
|
||||
use ::core::hash::Hasher;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
let mut h0 = twox_hash::XxHash::with_seed(0);
|
||||
let mut h1 = twox_hash::XxHash::with_seed(1);
|
||||
let mut h2 = twox_hash::XxHash::with_seed(2);
|
||||
let mut h3 = twox_hash::XxHash::with_seed(3);
|
||||
h0.write(data);
|
||||
h1.write(data);
|
||||
h2.write(data);
|
||||
h3.write(data);
|
||||
let r0 = h0.finish();
|
||||
let r1 = h1.finish();
|
||||
let r2 = h2.finish();
|
||||
let r3 = h3.finish();
|
||||
LittleEndian::write_u64(&mut dest[0..8], r0);
|
||||
LittleEndian::write_u64(&mut dest[8..16], r1);
|
||||
LittleEndian::write_u64(&mut dest[16..24], r2);
|
||||
LittleEndian::write_u64(&mut dest[24..32], r3);
|
||||
}
|
||||
|
||||
/// Do a XX 256-bit hash and return result.
|
||||
pub fn twox_256(data: &[u8]) -> [u8; 32] {
|
||||
let mut r: [u8; 32] = [0; 32];
|
||||
twox_256_into(data, &mut r);
|
||||
r
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// Copyright 2017 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/>.
|
||||
|
||||
//! Wrapper type for byte collections that outputs hex.
|
||||
|
||||
/// Simple wrapper to display hex representation of bytes.
|
||||
pub struct HexDisplay<'a>(&'a [u8]);
|
||||
|
||||
impl<'a> HexDisplay<'a> {
|
||||
/// Create new instance that will display `d` as a hex string when displayed.
|
||||
pub fn from(d: &'a AsBytesRef) -> Self { HexDisplay(d.as_bytes_ref()) }
|
||||
}
|
||||
|
||||
impl<'a> ::core::fmt::Display for HexDisplay<'a> {
|
||||
fn fmt(&self, fmtr: &mut ::core::fmt::Formatter) -> Result<(), ::core::fmt::Error> {
|
||||
if self.0.len() < 1027 {
|
||||
for byte in self.0 {
|
||||
fmtr.write_fmt(format_args!("{:02x}", byte))?;
|
||||
}
|
||||
} else {
|
||||
for byte in &self.0[0..512] {
|
||||
fmtr.write_fmt(format_args!("{:02x}", byte))?;
|
||||
}
|
||||
fmtr.write_str("...")?;
|
||||
for byte in &self.0[self.0.len() - 512..] {
|
||||
fmtr.write_fmt(format_args!("{:02x}", byte))?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Simple trait to transform various types to `&[u8]`
|
||||
pub trait AsBytesRef {
|
||||
/// Transform `self` into `&[u8]`.
|
||||
fn as_bytes_ref(&self) -> &[u8];
|
||||
}
|
||||
|
||||
impl<'a> AsBytesRef for &'a [u8] {
|
||||
fn as_bytes_ref(&self) -> &[u8] { self }
|
||||
}
|
||||
|
||||
impl AsBytesRef for [u8] {
|
||||
fn as_bytes_ref(&self) -> &[u8] { &self }
|
||||
}
|
||||
|
||||
impl AsBytesRef for ::bytes::Vec<u8> {
|
||||
fn as_bytes_ref(&self) -> &[u8] { &self }
|
||||
}
|
||||
|
||||
macro_rules! impl_non_endians {
|
||||
( $( $t:ty ),* ) => { $(
|
||||
impl AsBytesRef for $t {
|
||||
fn as_bytes_ref(&self) -> &[u8] { &self[..] }
|
||||
}
|
||||
)* }
|
||||
}
|
||||
|
||||
impl_non_endians!([u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8],
|
||||
[u8; 10], [u8; 12], [u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40],
|
||||
[u8; 48], [u8; 56], [u8; 64], [u8; 80], [u8; 96], [u8; 112], [u8; 128]);
|
||||
|
||||
/// Format into ASCII + # + hex, suitable for storage key preimages.
|
||||
pub fn ascii_format(asciish: &[u8]) -> String {
|
||||
let mut r = String::new();
|
||||
let mut latch = false;
|
||||
for c in asciish {
|
||||
match (latch, *c) {
|
||||
(false, 32...127) => r.push(*c as char),
|
||||
_ => {
|
||||
if !latch {
|
||||
r.push('#');
|
||||
latch = true;
|
||||
}
|
||||
r.push_str(&format!("{:02x}", *c));
|
||||
}
|
||||
}
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
// Copyright 2017 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/>.
|
||||
|
||||
// tag::description[]
|
||||
//! Shareable Polkadot types.
|
||||
// end::description[]
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![cfg_attr(not(feature = "std"), feature(alloc))]
|
||||
|
||||
#[macro_use]
|
||||
extern crate crunchy;
|
||||
#[macro_use]
|
||||
extern crate fixed_hash;
|
||||
#[macro_use]
|
||||
extern crate uint as uint_crate;
|
||||
#[macro_use]
|
||||
extern crate parity_codec_derive;
|
||||
|
||||
extern crate rustc_hex;
|
||||
extern crate byteorder;
|
||||
extern crate parity_codec as codec;
|
||||
#[cfg(feature = "std")]
|
||||
extern crate rlp;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate serde;
|
||||
#[cfg(feature = "std")]
|
||||
extern crate twox_hash;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate blake2_rfc;
|
||||
#[cfg(feature = "std")]
|
||||
extern crate ring;
|
||||
#[cfg(feature = "std")]
|
||||
extern crate base58;
|
||||
#[cfg(feature = "std")]
|
||||
extern crate untrusted;
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate hex_literal;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
#[cfg(feature = "std")]
|
||||
extern crate core;
|
||||
#[cfg(feature = "std")]
|
||||
extern crate wasmi;
|
||||
extern crate hashdb;
|
||||
extern crate plain_hasher;
|
||||
#[cfg(feature = "std")]
|
||||
extern crate patricia_trie;
|
||||
#[cfg(feature = "std")]
|
||||
extern crate elastic_array;
|
||||
|
||||
extern crate sr_std as rstd;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate substrate_serializer;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate heapsize;
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate pretty_assertions;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! map {
|
||||
($( $name:expr => $value:expr ),*) => (
|
||||
vec![ $( ( $name, $value ) ),* ].into_iter().collect()
|
||||
)
|
||||
}
|
||||
|
||||
use rstd::prelude::*;
|
||||
use rstd::ops::Deref;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub mod bytes;
|
||||
#[cfg(feature = "std")]
|
||||
pub mod hashing;
|
||||
#[cfg(feature = "std")]
|
||||
pub use hashing::{blake2_256, twox_128, twox_256};
|
||||
#[cfg(feature = "std")]
|
||||
pub mod hexdisplay;
|
||||
#[cfg(feature = "std")]
|
||||
pub mod ed25519;
|
||||
|
||||
pub mod u32_trait;
|
||||
|
||||
pub mod hash;
|
||||
mod hasher;
|
||||
pub mod sandbox;
|
||||
pub mod storage;
|
||||
pub mod uint;
|
||||
mod authority_id;
|
||||
#[cfg(feature = "std")]
|
||||
mod rlp_codec;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use self::hash::{H160, H256, H512};
|
||||
pub use self::uint::U256;
|
||||
pub use authority_id::AuthorityId;
|
||||
|
||||
// Switch back to Blake after PoC-3 is out
|
||||
// pub use self::hasher::blake::BlakeHasher;
|
||||
pub use self::hasher::blake2::Blake2Hasher;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use self::rlp_codec::RlpCodec;
|
||||
|
||||
/// A 512-bit value interpreted as a signature.
|
||||
pub type Signature = hash::H512;
|
||||
|
||||
/// Hex-serialised shim for `Vec<u8>`.
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Hash, PartialOrd, Ord))]
|
||||
pub struct Bytes(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
|
||||
|
||||
impl From<Vec<u8>> for Bytes {
|
||||
fn from(s: Vec<u8>) -> Self { Bytes(s) }
|
||||
}
|
||||
|
||||
impl Deref for Bytes {
|
||||
type Target = [u8];
|
||||
fn deref(&self) -> &[u8] { &self.0[..] }
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
// 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/>.
|
||||
|
||||
//! Polkadot Blake2b (trie) NodeCodec implementation
|
||||
|
||||
use elastic_array::{ElasticArray1024, ElasticArray128};
|
||||
use hashdb::Hasher;
|
||||
use rlp::{DecoderError, RlpStream, Rlp, Prototype};
|
||||
use core::marker::PhantomData;
|
||||
use patricia_trie::{NibbleSlice, NodeCodec, node::Node, ChildReference};
|
||||
|
||||
use hash::H256;
|
||||
use Blake2Hasher;
|
||||
|
||||
/// Concrete implementation of a `NodeCodec` with Rlp encoding, generic over the `Hasher`
|
||||
pub struct RlpNodeCodec<H: Hasher> {mark: PhantomData<H>}
|
||||
|
||||
/// Convenience type for a Blake2_256/Rlp flavoured NodeCodec
|
||||
pub type RlpCodec = RlpNodeCodec<Blake2Hasher>;
|
||||
|
||||
impl NodeCodec<Blake2Hasher> for RlpCodec {
|
||||
type Error = DecoderError;
|
||||
const HASHED_NULL_NODE : H256 = H256( [0x45, 0xb0, 0xcf, 0xc2, 0x20, 0xce, 0xec, 0x5b, 0x7c, 0x1c, 0x62, 0xc4, 0xd4, 0x19, 0x3d, 0x38, 0xe4, 0xeb, 0xa4, 0x8e, 0x88, 0x15, 0x72, 0x9c, 0xe7, 0x5f, 0x9c, 0xa, 0xb0, 0xe4, 0xc1, 0xc0] );
|
||||
fn decode(data: &[u8]) -> ::std::result::Result<Node, Self::Error> {
|
||||
let r = Rlp::new(data);
|
||||
match r.prototype()? {
|
||||
// either leaf or extension - decode first item with NibbleSlice::???
|
||||
// and use is_leaf return to figure out which.
|
||||
// if leaf, second item is a value (is_data())
|
||||
// if extension, second item is a node (either SHA3 to be looked up and
|
||||
// fed back into this function or inline RLP which can be fed back into this function).
|
||||
Prototype::List(2) => match NibbleSlice::from_encoded(r.at(0)?.data()?) {
|
||||
(slice, true) => Ok(Node::Leaf(slice, r.at(1)?.data()?)),
|
||||
(slice, false) => Ok(Node::Extension(slice, r.at(1)?.as_raw())),
|
||||
},
|
||||
// branch - first 16 are nodes, 17th is a value (or empty).
|
||||
Prototype::List(17) => {
|
||||
let mut nodes = [&[] as &[u8]; 16];
|
||||
for i in 0..16 {
|
||||
nodes[i] = r.at(i)?.as_raw();
|
||||
}
|
||||
Ok(Node::Branch(nodes, if r.at(16)?.is_empty() { None } else { Some(r.at(16)?.data()?) }))
|
||||
},
|
||||
// an empty branch index.
|
||||
Prototype::Data(0) => Ok(Node::Empty),
|
||||
// something went wrong.
|
||||
_ => Err(DecoderError::Custom("Rlp is not valid."))
|
||||
}
|
||||
}
|
||||
fn try_decode_hash(data: &[u8]) -> Option<<Blake2Hasher as Hasher>::Out> {
|
||||
let r = Rlp::new(data);
|
||||
if r.is_data() && r.size() == Blake2Hasher::LENGTH {
|
||||
Some(r.as_val().expect("Hash is the correct size; qed"))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn is_empty_node(data: &[u8]) -> bool {
|
||||
Rlp::new(data).is_empty()
|
||||
}
|
||||
fn empty_node() -> ElasticArray1024<u8> {
|
||||
let mut stream = RlpStream::new();
|
||||
stream.append_empty_data();
|
||||
stream.drain()
|
||||
}
|
||||
|
||||
fn leaf_node(partial: &[u8], value: &[u8]) -> ElasticArray1024<u8> {
|
||||
let mut stream = RlpStream::new_list(2);
|
||||
stream.append(&partial);
|
||||
stream.append(&value);
|
||||
stream.drain()
|
||||
}
|
||||
|
||||
fn ext_node(partial: &[u8], child_ref: ChildReference<<Blake2Hasher as Hasher>::Out>) -> ElasticArray1024<u8> {
|
||||
let mut stream = RlpStream::new_list(2);
|
||||
stream.append(&partial);
|
||||
match child_ref {
|
||||
ChildReference::Hash(h) => stream.append(&h),
|
||||
ChildReference::Inline(inline_data, len) => {
|
||||
let bytes = &AsRef::<[u8]>::as_ref(&inline_data)[..len];
|
||||
stream.append_raw(bytes, 1)
|
||||
},
|
||||
};
|
||||
stream.drain()
|
||||
}
|
||||
|
||||
fn branch_node<I>(children: I, value: Option<ElasticArray128<u8>>) -> ElasticArray1024<u8>
|
||||
where I: IntoIterator<Item=Option<ChildReference<<Blake2Hasher as Hasher>::Out>>>
|
||||
{
|
||||
let mut stream = RlpStream::new_list(17);
|
||||
for child_ref in children {
|
||||
match child_ref {
|
||||
Some(c) => match c {
|
||||
ChildReference::Hash(h) => stream.append(&h),
|
||||
ChildReference::Inline(inline_data, len) => {
|
||||
let bytes = &AsRef::<[u8]>::as_ref(&inline_data)[..len];
|
||||
stream.append_raw(bytes, 1)
|
||||
},
|
||||
},
|
||||
None => stream.append_empty_data()
|
||||
};
|
||||
}
|
||||
if let Some(value) = value {
|
||||
stream.append(&&*value);
|
||||
} else {
|
||||
stream.append_empty_data();
|
||||
}
|
||||
stream.drain()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
// 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/>.
|
||||
|
||||
//! Definition of a sandbox environment.
|
||||
|
||||
#[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;
|
||||
|
||||
/// Representation of a typed wasm value.
|
||||
#[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),
|
||||
}
|
||||
|
||||
impl TypedValue {
|
||||
/// Returns `Some` if this value of type `I32`.
|
||||
pub fn as_i32(&self) -> Option<i32> {
|
||||
match *self {
|
||||
TypedValue::I32(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl From<::wasmi::RuntimeValue> for TypedValue {
|
||||
fn from(val: ::wasmi::RuntimeValue) -> TypedValue {
|
||||
use ::wasmi::RuntimeValue;
|
||||
match val {
|
||||
RuntimeValue::I32(v) => TypedValue::I32(v),
|
||||
RuntimeValue::I64(v) => TypedValue::I64(v),
|
||||
RuntimeValue::F32(v) => TypedValue::F32(v.to_bits() as i32),
|
||||
RuntimeValue::F64(v) => TypedValue::F64(v.to_bits() as i64),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl From<TypedValue> for ::wasmi::RuntimeValue {
|
||||
fn from(val: TypedValue) -> ::wasmi::RuntimeValue {
|
||||
use ::wasmi::RuntimeValue;
|
||||
use ::wasmi::nan_preserving_float::{F32, F64};
|
||||
match val {
|
||||
TypedValue::I32(v) => RuntimeValue::I32(v),
|
||||
TypedValue::I64(v) => RuntimeValue::I64(v),
|
||||
TypedValue::F32(v_bits) => RuntimeValue::F32(F32::from_bits(v_bits as u32)),
|
||||
TypedValue::F64(v_bits) => RuntimeValue::F64(F64::from_bits(v_bits as u64)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Typed value that can be returned from a function.
|
||||
///
|
||||
/// Basically a `TypedValue` plus `Unit`, for functions which return nothing.
|
||||
#[derive(Clone, Copy, PartialEq, Encode, Decode)]
|
||||
#[cfg_attr(feature = "std", derive(Debug))]
|
||||
pub enum ReturnValue {
|
||||
/// For returning nothing.
|
||||
Unit,
|
||||
/// For returning some concrete value.
|
||||
Value(TypedValue),
|
||||
}
|
||||
|
||||
impl From<TypedValue> for ReturnValue {
|
||||
fn from(v: TypedValue) -> ReturnValue {
|
||||
ReturnValue::Value(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl ReturnValue {
|
||||
/// Maximum number of bytes `ReturnValue` might occupy when serialized with
|
||||
/// `Codec`.
|
||||
///
|
||||
/// Breakdown:
|
||||
/// 1 byte for encoding unit/value variant
|
||||
/// 1 byte for encoding value type
|
||||
/// 8 bytes for encoding the biggest value types available in wasm: f64, i64.
|
||||
pub const ENCODED_MAX_SIZE: usize = 10;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_value_encoded_max_size() {
|
||||
let encoded = ReturnValue::Value(TypedValue::I64(-1)).encode();
|
||||
assert_eq!(encoded.len(), ReturnValue::ENCODED_MAX_SIZE);
|
||||
}
|
||||
|
||||
/// Describes an entity to define or import into the environment.
|
||||
#[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),
|
||||
}
|
||||
|
||||
/// 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, Encode, Decode)]
|
||||
#[cfg_attr(feature = "std", derive(Debug))]
|
||||
pub struct Entry {
|
||||
/// Module name of which corresponding entity being defined.
|
||||
pub module_name: Vec<u8>,
|
||||
/// Field name in which corresponding entity being defined.
|
||||
pub field_name: Vec<u8>,
|
||||
/// External entity being defined.
|
||||
pub entity: ExternEntity,
|
||||
}
|
||||
|
||||
/// Definition of runtime that could be used by sandboxed code.
|
||||
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
|
||||
#[cfg_attr(feature = "std", derive(Debug))]
|
||||
pub struct EnvironmentDefinition {
|
||||
/// Vector of all entries in the environment definition.
|
||||
pub entries: Vec<Entry>,
|
||||
}
|
||||
|
||||
/// Constant for specifying no limit when creating a sandboxed
|
||||
/// memory instance. For FFI purposes.
|
||||
pub const MEM_UNLIMITED: u32 = -1i32 as u32;
|
||||
|
||||
/// No error happened.
|
||||
///
|
||||
/// For FFI purposes.
|
||||
pub const ERR_OK: u32 = 0;
|
||||
|
||||
/// Validation or instantiation error occured when creating new
|
||||
/// sandboxed module instance.
|
||||
///
|
||||
/// For FFI purposes.
|
||||
pub const ERR_MODULE: u32 = -1i32 as u32;
|
||||
|
||||
/// Out-of-bounds access attempted with memory or table.
|
||||
///
|
||||
/// For FFI purposes.
|
||||
pub const ERR_OUT_OF_BOUNDS: u32 = -2i32 as u32;
|
||||
|
||||
/// Execution error occurred (typically trap).
|
||||
///
|
||||
/// For FFI purposes.
|
||||
pub const ERR_EXECUTION: u32 = -3i32 as u32;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fmt;
|
||||
use codec::Codec;
|
||||
|
||||
fn roundtrip<S: Codec + PartialEq + fmt::Debug>(s: S) {
|
||||
let encoded = s.encode();
|
||||
assert_eq!(S::decode(&mut &encoded[..]).unwrap(), s);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn env_def_roundtrip() {
|
||||
roundtrip(EnvironmentDefinition {
|
||||
entries: vec![],
|
||||
});
|
||||
|
||||
roundtrip(EnvironmentDefinition {
|
||||
entries: vec![
|
||||
Entry {
|
||||
module_name: b"kernel"[..].into(),
|
||||
field_name: b"memory"[..].into(),
|
||||
entity: ExternEntity::Memory(1337),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
roundtrip(EnvironmentDefinition {
|
||||
entries: vec![
|
||||
Entry {
|
||||
module_name: b"env"[..].into(),
|
||||
field_name: b"abort"[..].into(),
|
||||
entity: ExternEntity::Function(228),
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2017 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/>.
|
||||
|
||||
//! Contract execution data.
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use bytes;
|
||||
use rstd::vec::Vec;
|
||||
|
||||
/// Contract storage key.
|
||||
#[derive(PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Hash, PartialOrd, Ord, Clone))]
|
||||
pub struct StorageKey(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
|
||||
|
||||
/// Contract storage entry data.
|
||||
#[derive(PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Hash, PartialOrd, Ord, Clone))]
|
||||
pub struct StorageData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
|
||||
|
||||
/// Storage change set
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, PartialEq, Eq))]
|
||||
pub struct StorageChangeSet<Hash> {
|
||||
/// Block hash
|
||||
pub block: Hash,
|
||||
/// A list of changes
|
||||
pub changes: Vec<(
|
||||
StorageKey,
|
||||
Option<StorageData>,
|
||||
)>,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2017 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/>.
|
||||
|
||||
//! Tests.
|
||||
@@ -0,0 +1,89 @@
|
||||
// Copyright 2017 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/>.
|
||||
|
||||
//! An u32 trait with "values" as impl'd types.
|
||||
|
||||
/// A u32 value, wrapped in a trait because we don't yet have const generics.
|
||||
pub trait Value {
|
||||
/// The actual value represented by the impl'ing type.
|
||||
const VALUE: u32;
|
||||
}
|
||||
/// Type representing the value 0 for the `Value` trait.
|
||||
pub struct _0; impl Value for _0 { const VALUE: u32 = 0; }
|
||||
/// Type representing the value 1 for the `Value` trait.
|
||||
pub struct _1; impl Value for _1 { const VALUE: u32 = 1; }
|
||||
/// Type representing the value 2 for the `Value` trait.
|
||||
pub struct _2; impl Value for _2 { const VALUE: u32 = 2; }
|
||||
/// Type representing the value 3 for the `Value` trait.
|
||||
pub struct _3; impl Value for _3 { const VALUE: u32 = 3; }
|
||||
/// Type representing the value 4 for the `Value` trait.
|
||||
pub struct _4; impl Value for _4 { const VALUE: u32 = 4; }
|
||||
/// Type representing the value 5 for the `Value` trait.
|
||||
pub struct _5; impl Value for _5 { const VALUE: u32 = 5; }
|
||||
/// Type representing the value 6 for the `Value` trait.
|
||||
pub struct _6; impl Value for _6 { const VALUE: u32 = 6; }
|
||||
/// Type representing the value 7 for the `Value` trait.
|
||||
pub struct _7; impl Value for _7 { const VALUE: u32 = 7; }
|
||||
/// Type representing the value 8 for the `Value` trait.
|
||||
pub struct _8; impl Value for _8 { const VALUE: u32 = 8; }
|
||||
/// Type representing the value 9 for the `Value` trait.
|
||||
pub struct _9; impl Value for _9 { const VALUE: u32 = 9; }
|
||||
/// Type representing the value 10 for the `Value` trait.
|
||||
pub struct _10; impl Value for _10 { const VALUE: u32 = 10; }
|
||||
/// Type representing the value 11 for the `Value` trait.
|
||||
pub struct _11; impl Value for _11 { const VALUE: u32 = 11; }
|
||||
/// Type representing the value 12 for the `Value` trait.
|
||||
pub struct _12; impl Value for _12 { const VALUE: u32 = 12; }
|
||||
/// Type representing the value 13 for the `Value` trait.
|
||||
pub struct _13; impl Value for _13 { const VALUE: u32 = 13; }
|
||||
/// Type representing the value 14 for the `Value` trait.
|
||||
pub struct _14; impl Value for _14 { const VALUE: u32 = 14; }
|
||||
/// Type representing the value 15 for the `Value` trait.
|
||||
pub struct _15; impl Value for _15 { const VALUE: u32 = 15; }
|
||||
/// Type representing the value 16 for the `Value` trait.
|
||||
pub struct _16; impl Value for _16 { const VALUE: u32 = 16; }
|
||||
/// Type representing the value 24 for the `Value` trait.
|
||||
pub struct _24; impl Value for _24 { const VALUE: u32 = 24; }
|
||||
/// Type representing the value 32 for the `Value` trait.
|
||||
pub struct _32; impl Value for _32 { const VALUE: u32 = 32; }
|
||||
/// Type representing the value 40 for the `Value` trait.
|
||||
pub struct _40; impl Value for _40 { const VALUE: u32 = 40; }
|
||||
/// Type representing the value 48 for the `Value` trait.
|
||||
pub struct _48; impl Value for _48 { const VALUE: u32 = 48; }
|
||||
/// Type representing the value 56 for the `Value` trait.
|
||||
pub struct _56; impl Value for _56 { const VALUE: u32 = 56; }
|
||||
/// Type representing the value 64 for the `Value` trait.
|
||||
pub struct _64; impl Value for _64 { const VALUE: u32 = 64; }
|
||||
/// Type representing the value 80 for the `Value` trait.
|
||||
pub struct _80; impl Value for _80 { const VALUE: u32 = 80; }
|
||||
/// Type representing the value 96 for the `Value` trait.
|
||||
pub struct _96; impl Value for _96 { const VALUE: u32 = 96; }
|
||||
/// Type representing the value 112 for the `Value` trait.
|
||||
pub struct _112; impl Value for _112 { const VALUE: u32 = 112; }
|
||||
/// Type representing the value 128 for the `Value` trait.
|
||||
pub struct _128; impl Value for _128 { const VALUE: u32 = 128; }
|
||||
/// Type representing the value 160 for the `Value` trait.
|
||||
pub struct _160; impl Value for _160 { const VALUE: u32 = 160; }
|
||||
/// Type representing the value 192 for the `Value` trait.
|
||||
pub struct _192; impl Value for _192 { const VALUE: u32 = 192; }
|
||||
/// Type representing the value 224 for the `Value` trait.
|
||||
pub struct _224; impl Value for _224 { const VALUE: u32 = 224; }
|
||||
/// Type representing the value 256 for the `Value` trait.
|
||||
pub struct _256; impl Value for _256 { const VALUE: u32 = 256; }
|
||||
/// Type representing the value 384 for the `Value` trait.
|
||||
pub struct _384; impl Value for _384 { const VALUE: u32 = 384; }
|
||||
/// Type representing the value 512 for the `Value` trait.
|
||||
pub struct _512; impl Value for _512 { const VALUE: u32 = 512; }
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright 2017 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/>.
|
||||
|
||||
//! An unsigned fixed-size integer.
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use serde::{Serialize, Serializer, Deserialize, Deserializer};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use bytes;
|
||||
|
||||
macro_rules! impl_serde {
|
||||
($name: ident, $len: expr) => {
|
||||
#[cfg(feature = "std")]
|
||||
impl Serialize for $name {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
|
||||
let mut bytes = [0u8; $len * 8];
|
||||
self.to_big_endian(&mut bytes);
|
||||
bytes::serialize_uint(&bytes, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<'de> Deserialize<'de> for $name {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
|
||||
bytes::deserialize_check_len(deserializer, bytes::ExpectedLen::Between(0, $len * 8))
|
||||
.map(|x| (&*x).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
construct_uint!(U256, 4);
|
||||
impl_serde!(U256, 4);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use substrate_serializer as ser;
|
||||
|
||||
macro_rules! test {
|
||||
($name: ident, $test_name: ident) => {
|
||||
#[test]
|
||||
fn $test_name() {
|
||||
let tests = vec![
|
||||
($name::from(0), "0x0"),
|
||||
($name::from(1), "0x1"),
|
||||
($name::from(2), "0x2"),
|
||||
($name::from(10), "0xa"),
|
||||
($name::from(15), "0xf"),
|
||||
($name::from(15), "0xf"),
|
||||
($name::from(16), "0x10"),
|
||||
($name::from(1_000), "0x3e8"),
|
||||
($name::from(100_000), "0x186a0"),
|
||||
($name::from(u64::max_value()), "0xffffffffffffffff"),
|
||||
($name::from(u64::max_value()) + $name::from(1), "0x10000000000000000"),
|
||||
];
|
||||
|
||||
for (number, expected) in tests {
|
||||
assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number));
|
||||
assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap());
|
||||
}
|
||||
|
||||
// Invalid examples
|
||||
assert!(ser::from_str::<$name>("\"0x\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<$name>("\"0xg\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<$name>("\"\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<$name>("\"10\"").unwrap_err().is_data());
|
||||
assert!(ser::from_str::<$name>("\"0\"").unwrap_err().is_data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test!(U256, test_u256);
|
||||
|
||||
#[test]
|
||||
fn test_large_values() {
|
||||
assert_eq!(
|
||||
ser::to_string_pretty(&!U256::zero()),
|
||||
"\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\""
|
||||
);
|
||||
assert!(
|
||||
ser::from_str::<U256>("\"0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"").unwrap_err().is_data()
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user