Skip to content

Commit

Permalink
Feature/xsystem xsupport (paritytech#158)
Browse files Browse the repository at this point in the history
* add xsystem module

* add xsupport
  • Loading branch information
Aton authored Dec 18, 2018
1 parent 3bcbc6b commit 74bcd90
Show file tree
Hide file tree
Showing 16 changed files with 1,218 additions and 76 deletions.
33 changes: 33 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,9 @@ members = [
"executor",
"runtime",
"cli",

# xrml
"xrml/xsystem",
"xrml/xsupport",
"xrml/xexecutive",
]
68 changes: 0 additions & 68 deletions cxrml/system/src/lib.rs

This file was deleted.

2 changes: 2 additions & 0 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,8 @@ impl_runtime_apis! {
.map(|v| (v.0, UncheckedExtrinsic::new_unsigned(Call::Consensus(v.1))))
);

// TODO add blockproducer

inherent.as_mut_slice().sort_unstable_by_key(|v| v.0);
inherent.into_iter().map(|v| v.1).collect()
}
Expand Down
Empty file removed xrml/xsupport/.gitkeep
Empty file.
31 changes: 31 additions & 0 deletions xrml/xsupport/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[package]
name = "xrml-xsupport"
version = "0.3.0"
authors = ["Chainpool <https://www.chainx.org>"]

[dependencies]
hex-literal = "0.1.0"
serde = { version = "1.0", default_features = false }
serde_derive = { version = "1.0", optional = true }
parity-codec = { version = "2.0", default-features = false }
parity-codec-derive = { version = "2.0", default-features = false }
sr-std = { git = "https://github.com/chainpool/substrate", default_features = false }
sr-io = { git = "https://github.com/chainpool/substrate", default_features = false }
sr-primitives = { git = "https://github.com/chainpool/substrate", default_features = false }
srml-support = { git = "https://github.com/chainpool/substrate", default_features = false }
substrate-primitives = { git = "https://github.com/chainpool/substrate", default_features = false }


[features]
default = ["std"]
std=[
"serde/std",
"serde_derive",
"parity-codec/std",
"parity-codec-derive/std",
"substrate-primitives/std",
"sr-std/std",
"sr-io/std",
"sr-primitives/std",
"srml-support/std",
]
16 changes: 16 additions & 0 deletions xrml/xsupport/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2018 Chainpool.

#![cfg_attr(not(feature = "std"), no_std)]

extern crate parity_codec as codec;
#[macro_use]
extern crate parity_codec_derive;
extern crate sr_io as runtime_io;
extern crate sr_primitives as primitives;
extern crate sr_std as rstd;

extern crate srml_support as runtime_support;

pub use storage::double_map::StorageDoubleMap;

pub mod storage;
35 changes: 35 additions & 0 deletions xrml/xsupport/src/storage/btree_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2018 Chainpool.

use codec::{Decode, Encode, Input, Output};
use rstd::collections::btree_map::BTreeMap;

#[derive(Default)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct CodecBTreeMap<K: Ord, V>(pub BTreeMap<K, V>);

impl<K: Encode + Ord, V: Encode> Encode for CodecBTreeMap<K, V> {
fn encode_to<W: Output>(&self, dest: &mut W) {
let len = self.0.len();
assert!(
len <= u32::max_value() as usize,
"Attempted to serialize a collection with too many elements."
);
(len as u32).encode_to(dest);
for i in self.0.iter() {
i.encode_to(dest);
}
}
}

impl<K: Decode + Ord, V: Decode> Decode for CodecBTreeMap<K, V> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
u32::decode(input).and_then(move |len| {
let mut r: BTreeMap<K, V> = BTreeMap::new(); // with_capacity(len as usize);
for _ in 0..len {
let (key, v) = <(K, V)>::decode(input)?;
r.insert(key, v);
}
Some(CodecBTreeMap::<K, V>(r))
})
}
}
104 changes: 104 additions & 0 deletions xrml/xsupport/src/storage/double_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// 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 implementation of double map backed by storage.
//!
//! This implementation is somewhat specialized to the tracking of the storage of accounts.
use codec::{Codec, Encode};
use rstd::prelude::*;
use runtime_io::{blake2_256, twox_128};
use runtime_support::storage::unhashed;

/// Returns only a first part of the storage key.
///
/// Hashed by XX.
#[allow(dead_code)]
fn first_part_of_key<M: StorageDoubleMap + ?Sized>(k1: M::Key1) -> [u8; 16] {
let mut raw_prefix = Vec::new();
raw_prefix.extend(M::PREFIX);
raw_prefix.extend(Encode::encode(&k1));
twox_128(&raw_prefix)
}

/// Returns a compound key that consist of the two parts: (prefix, `k1`) and `k2`.
///
/// The first part is hased by XX and then concatenated with a blake2 hash of `k2`.
#[allow(dead_code)]
fn full_key<M: StorageDoubleMap + ?Sized>(k1: M::Key1, k2: M::Key2) -> Vec<u8> {
let first_part = first_part_of_key::<M>(k1);
let second_part = blake2_256(&Encode::encode(&k2));

let mut k = Vec::new();
k.extend(&first_part);
k.extend(&second_part);
k
}

/// An implementation of a map with a two keys.
///
/// It provides an important ability to efficiently remove all entries
/// that have a common first key.
///
/// # Mapping of keys to a storage path
///
/// The storage key (i.e. the key under which the `Value` will be stored) is created from two parts.
/// The first part is a XX hash of a concatenation of the `PREFIX` and `Key1`. And the second part
/// is a blake2 hash of a `Key2`.
///
/// Blake2 is used for `Key2` is because it will be used as a key for contract's storage and
/// thus will be susceptible for a untrusted input.
pub trait StorageDoubleMap {
type Key1: Codec;
type Key2: Codec;
type Value: Codec + Default;

const PREFIX: &'static [u8];

/// Insert an entry into this map.
fn insert(k1: Self::Key1, k2: Self::Key2, val: Self::Value) {
unhashed::put(&full_key::<Self>(k1, k2)[..], &val);
}

/// Remove an entry from this map.
fn remove(k1: Self::Key1, k2: Self::Key2) {
unhashed::kill(&full_key::<Self>(k1, k2)[..]);
}

/// Get an entry from this map.
///
/// If there is entry stored under the given keys, returns `None`.
fn get(k1: Self::Key1, k2: Self::Key2) -> Option<Self::Value> {
unhashed::get(&full_key::<Self>(k1, k2)[..])
}

/// Get an entry from this map.
///
/// If there is entry stored under the given keys, returns default value.
fn get_or_default(k1: Self::Key1, k2: Self::Key2) -> Self::Value {
unhashed::get_or_default(&full_key::<Self>(k1, k2)[..])
}

/// Removes all entries that shares the `k1` as the first key.
fn remove_prefix(k1: Self::Key1) {
unhashed::kill_prefix(&first_part_of_key::<Self>(k1))
}

/// Remove and return the value, None for the value not exist.
fn take(k1: Self::Key1, k2: Self::Key2) -> Option<Self::Value> {
unhashed::take(&full_key::<Self>(k1, k2)[..])
}
}
Loading

0 comments on commit 74bcd90

Please sign in to comment.