mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 04:41:02 +00:00
Merge branch 'master' into author-relay-block
This commit is contained in:
@@ -40,6 +40,9 @@ pub trait Backend {
|
||||
/// Commit updates to the backend and get new state.
|
||||
fn commit<I>(&mut self, changes: I) -> Committed
|
||||
where I: IntoIterator<Item=Update>;
|
||||
|
||||
/// Get all key/value pairs into a Vec.
|
||||
fn pairs(&self) -> Vec<(&[u8], &[u8])>;
|
||||
}
|
||||
|
||||
/// Error impossible.
|
||||
@@ -59,15 +62,27 @@ impl error::Error for Void {
|
||||
|
||||
/// In-memory backend. Fully recomputes tries on each commit but useful for
|
||||
/// tests.
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Clone)]
|
||||
pub struct InMemory {
|
||||
inner: MemoryState, // keeps all the state in memory.
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl InMemory {
|
||||
/// Create a new instance from a given storage map.
|
||||
pub fn from(storage: ::std::collections::HashMap<Vec<u8>, Vec<u8>>) -> Self {
|
||||
InMemory {
|
||||
inner: MemoryState {
|
||||
storage
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Backend for InMemory {
|
||||
type Error = Void;
|
||||
|
||||
fn storage(&self, key: &[u8]) -> Result<&[u8], Void> {
|
||||
fn storage(&self, key: &[u8]) -> Result<&[u8], Self::Error> {
|
||||
Ok(self.inner.storage(key).unwrap_or(&[]))
|
||||
}
|
||||
|
||||
@@ -87,6 +102,10 @@ impl Backend for InMemory {
|
||||
storage_tree_root,
|
||||
}
|
||||
}
|
||||
|
||||
fn pairs(&self) -> Vec<(&[u8], &[u8])> {
|
||||
self.inner.storage.iter().map(|(k, v)| (&k[..], &v[..])).collect()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: DB-based backend
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
//! Conrete externalities implementation.
|
||||
|
||||
use std::{error, fmt};
|
||||
|
||||
use triehash::trie_root;
|
||||
use backend::Backend;
|
||||
use {Externalities, ExternalitiesError, OverlayedChanges};
|
||||
|
||||
@@ -75,4 +75,15 @@ impl<'a, B: 'a> Externalities for Ext<'a, B>
|
||||
fn chain_id(&self) -> u64 {
|
||||
42
|
||||
}
|
||||
|
||||
fn storage_root(&self) -> [u8; 32] {
|
||||
let mut all_pairs = self.backend.pairs();
|
||||
all_pairs.extend(
|
||||
self.overlay.committed.storage.iter()
|
||||
.chain(self.overlay.prospective.storage.iter())
|
||||
.map(|(k, v)| (&k[..], &v[..]))
|
||||
);
|
||||
|
||||
trie_root(all_pairs.into_iter().map(|(k, v)| (k.to_vec(), v.to_vec()))).0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#![warn(missing_docs)]
|
||||
|
||||
extern crate polkadot_primitives as primitives;
|
||||
#[macro_use]
|
||||
extern crate hex_literal;
|
||||
|
||||
extern crate hashdb;
|
||||
extern crate memorydb;
|
||||
@@ -35,6 +37,9 @@ use primitives::contract::{CallData};
|
||||
|
||||
pub mod backend;
|
||||
mod ext;
|
||||
mod testing;
|
||||
|
||||
pub use testing::TestExternalities;
|
||||
|
||||
/// Updates to be committed to the state.
|
||||
pub enum Update {
|
||||
@@ -43,7 +48,7 @@ pub enum Update {
|
||||
}
|
||||
|
||||
// in-memory section of the state.
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Clone)]
|
||||
struct MemoryState {
|
||||
storage: HashMap<Vec<u8>, Vec<u8>>,
|
||||
}
|
||||
@@ -141,6 +146,9 @@ pub trait Externalities {
|
||||
/// Get the identity of the chain.
|
||||
fn chain_id(&self) -> u64;
|
||||
|
||||
/// Get the trie root of the current storage map.
|
||||
fn storage_root(&self) -> [u8; 32];
|
||||
|
||||
/// Get the current set of authorities from storage.
|
||||
fn authorities(&self) -> Result<Vec<&[u8]>, ExternalitiesError> {
|
||||
(0..self.storage(b"con:aut:len")?.into_iter()
|
||||
@@ -152,7 +160,7 @@ pub trait Externalities {
|
||||
}
|
||||
|
||||
/// Code execution engine.
|
||||
pub trait CodeExecutor: Sized {
|
||||
pub trait CodeExecutor: Sized + Send + Sync {
|
||||
/// Externalities error type.
|
||||
type Error: Error;
|
||||
|
||||
@@ -210,8 +218,9 @@ pub fn execute<B: backend::Backend, Exec: CodeExecutor>(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::HashMap;
|
||||
use super::{OverlayedChanges, Externalities, ExternalitiesError};
|
||||
use super::*;
|
||||
use super::backend::InMemory;
|
||||
use super::ext::Ext;
|
||||
|
||||
#[test]
|
||||
fn overlayed_storage_works() {
|
||||
@@ -238,22 +247,6 @@ mod tests {
|
||||
assert!(overlayed.storage(&key).is_none());
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct TestExternalities {
|
||||
storage: HashMap<Vec<u8>, Vec<u8>>,
|
||||
}
|
||||
impl Externalities for TestExternalities {
|
||||
fn storage(&self, key: &[u8]) -> Result<&[u8], ExternalitiesError> {
|
||||
Ok(self.storage.get(&key.to_vec()).map_or(&[] as &[u8], Vec::as_slice))
|
||||
}
|
||||
|
||||
fn set_storage(&mut self, key: Vec<u8>, value: Vec<u8>) {
|
||||
self.storage.insert(key, value);
|
||||
}
|
||||
|
||||
fn chain_id(&self) -> u64 { 42 }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn authorities_call_works() {
|
||||
let mut ext = TestExternalities::default();
|
||||
@@ -273,4 +266,34 @@ mod tests {
|
||||
ext.set_storage(b"con:aut:\x01\0\0\0".to_vec(), b"second".to_vec());
|
||||
assert_eq!(ext.authorities(), Ok(vec![&b"first"[..], &b"second"[..]]));
|
||||
}
|
||||
|
||||
macro_rules! map {
|
||||
($( $name:expr => $value:expr ),*) => (
|
||||
vec![ $( ( $name, $value ) ),* ].into_iter().collect()
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overlayed_storage_root_works() {
|
||||
let mut backend = InMemory::from(map![
|
||||
b"doe".to_vec() => b"reindeer".to_vec(),
|
||||
b"dog".to_vec() => b"puppyXXX".to_vec(),
|
||||
b"dogglesworth".to_vec() => b"catXXX".to_vec()
|
||||
]);
|
||||
let mut overlay = OverlayedChanges {
|
||||
committed: MemoryState { storage: map![
|
||||
b"dog".to_vec() => b"puppy".to_vec(),
|
||||
b"dogglesworth".to_vec() => b"catYYY".to_vec()
|
||||
], },
|
||||
prospective: MemoryState { storage: map![
|
||||
b"dogglesworth".to_vec() => b"cat".to_vec()
|
||||
], },
|
||||
};
|
||||
let ext = Ext {
|
||||
backend: &mut backend,
|
||||
overlay: &mut overlay,
|
||||
};
|
||||
const ROOT: [u8; 32] = hex!("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3");
|
||||
assert_eq!(ext.storage_root(), ROOT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Test implementation for Externalities.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use super::{Externalities, ExternalitiesError};
|
||||
use triehash::trie_root;
|
||||
|
||||
/// Simple HashMap based Externalities impl.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TestExternalities {
|
||||
/// The storage.
|
||||
pub storage: HashMap<Vec<u8>, Vec<u8>>,
|
||||
}
|
||||
|
||||
impl TestExternalities {
|
||||
/// Create a new instance with empty storage.
|
||||
pub fn new() -> Self {
|
||||
TestExternalities {
|
||||
storage: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Externalities for TestExternalities {
|
||||
fn storage(&self, key: &[u8]) -> Result<&[u8], ExternalitiesError> {
|
||||
Ok(self.storage.get(&key.to_vec()).map_or(&[] as &[u8], Vec::as_slice))
|
||||
}
|
||||
|
||||
fn set_storage(&mut self, key: Vec<u8>, value: Vec<u8>) {
|
||||
self.storage.insert(key, value);
|
||||
}
|
||||
|
||||
fn chain_id(&self) -> u64 { 42 }
|
||||
|
||||
fn storage_root(&self) -> [u8; 32] {
|
||||
trie_root(self.storage.clone()).0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn commit_should_work() {
|
||||
let mut ext = TestExternalities::new();
|
||||
ext.set_storage(b"doe".to_vec(), b"reindeer".to_vec());
|
||||
ext.set_storage(b"dog".to_vec(), b"puppy".to_vec());
|
||||
ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec());
|
||||
const ROOT: [u8; 32] = hex!("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3");
|
||||
assert_eq!(ext.storage_root(), ROOT);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user