Introduce UncheckedTransaction & test.

This commit is contained in:
Gav
2018-01-18 15:14:01 +01:00
parent 712becb205
commit 92d8712b2b
8 changed files with 143 additions and 71 deletions
@@ -26,4 +26,6 @@ macro_rules! impl_non_endians {
} }
impl_endians!(u16, u32, u64, usize, i16, i32, i64, isize); impl_endians!(u16, u32, u64, usize, i16, i32, i64, isize);
impl_non_endians!(u8, i8, [u8; 20], [u8; 32]); impl_non_endians!(u8, i8, [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]);
+4 -3
View File
@@ -11,11 +11,12 @@ pub use codec::{endiansensitive, streamreader, joiner, slicable, keyedvec};
pub use support::{primitives, function, environment, storage}; pub use support::{primitives, function, environment, storage};
#[cfg(test)] #[cfg(test)]
pub use support::testing; pub use support::testing;
#[allow(unused_imports)] // TODO: remove in due course
#[allow(unused_imports)] // TODO: remove in due course
use runtime_support::Vec; use runtime_support::Vec;
use slicable::Slicable; use slicable::Slicable;
use primitives::{Block, Transaction}; use primitives::{Block, UncheckedTransaction};
// TODO: add externals for: // TODO: add externals for:
// - keccak256 (or some better hashing scheme) // - keccak256 (or some better hashing scheme)
@@ -27,7 +28,7 @@ pub fn execute_block(input: Vec<u8>) -> Vec<u8> {
} }
pub fn execute_transaction(input: Vec<u8>) -> Vec<u8> { pub fn execute_transaction(input: Vec<u8>) -> Vec<u8> {
runtime::system::execute_transaction(&Transaction::from_slice(&input).unwrap()) runtime::system::execute_transaction(&UncheckedTransaction::from_slice(&input).unwrap())
} }
impl_stubs!(execute_block, execute_transaction); impl_stubs!(execute_block, execute_transaction);
@@ -2,14 +2,13 @@ use runtime_support::Vec;
use keyedvec::KeyedVec; use keyedvec::KeyedVec;
use storage::Storage; use storage::Storage;
use primitives::{AccountID, SessionKey, BlockNumber}; use primitives::{AccountID, SessionKey, BlockNumber};
use storage::storage_into;
pub fn set_authority(index: u32, authority: AccountID) { pub fn set_authority(index: u32, authority: AccountID) {
authority.store(&index.to_keyed_vec(b"con\0aut\0")); authority.store(&index.to_keyed_vec(b"con\0aut\0"));
} }
fn authority(index: u32) -> AccountID { fn authority(index: u32) -> AccountID {
storage_into(&index.to_keyed_vec(b"con\0aut\0")) Storage::into(&index.to_keyed_vec(b"con\0aut\0"))
} }
pub fn set_authority_count(count: u32) { pub fn set_authority_count(count: u32) {
@@ -18,7 +17,7 @@ pub fn set_authority_count(count: u32) {
} }
fn authority_count() -> u32 { fn authority_count() -> u32 {
storage_into(b"con\0aut\0len") Storage::into(b"con\0aut\0len")
} }
/// Get the current set of authorities. These are the session keys. /// Get the current set of authorities. These are the session keys.
@@ -49,7 +48,7 @@ pub fn set_validators(_new: &[AccountID]) {
/// The number of blocks in each session. /// The number of blocks in each session.
pub fn session_length() -> BlockNumber { pub fn session_length() -> BlockNumber {
storage_into(b"con\0bps") Storage::into(b"con\0bps")
} }
/// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next /// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next
@@ -1,5 +1,5 @@
use keyedvec::KeyedVec; use keyedvec::KeyedVec;
use storage::{Storage, storage_into}; use storage::Storage;
use primitives::{BlockNumber, Balance, AccountID}; use primitives::{BlockNumber, Balance, AccountID};
use runtime::consensus; use runtime::consensus;
@@ -10,7 +10,7 @@ pub fn era_length() -> BlockNumber {
/// The length of a staking era in sessions. /// The length of a staking era in sessions.
pub fn sessions_per_era() -> BlockNumber { pub fn sessions_per_era() -> BlockNumber {
storage_into(b"sta\0spe") Storage::into(b"sta\0spe")
} }
/// The era has changed - enact new staking set. /// The era has changed - enact new staking set.
@@ -22,16 +22,16 @@ pub fn next_era() {
/// The balance of a given account. /// The balance of a given account.
pub fn balance(who: &AccountID) -> Balance { pub fn balance(who: &AccountID) -> Balance {
storage_into(&who.to_keyed_vec(b"sta\0bal\0")) Storage::into(&who.to_keyed_vec(b"sta\0bal\0"))
} }
/// Transfer some unlocked staking balance to another staker. /// Transfer some unlocked staking balance to another staker.
pub fn transfer_stake(transactor: &AccountID, dest: &AccountID, value: Balance) { pub fn transfer_stake(transactor: &AccountID, dest: &AccountID, value: Balance) {
let from_key = transactor.to_keyed_vec(b"sta\0bal\0"); let from_key = transactor.to_keyed_vec(b"sta\0bal\0");
let from_balance: Balance = storage_into(&from_key); let from_balance: Balance = Storage::into(&from_key);
assert!(from_balance >= value); assert!(from_balance >= value);
let to_key = dest.to_keyed_vec(b"sta\0bal\0"); let to_key = dest.to_keyed_vec(b"sta\0bal\0");
let to_balance: Balance = storage_into(&to_key); let to_balance: Balance = Storage::into(&to_key);
assert!(to_balance + value > to_balance); // no overflow assert!(to_balance + value > to_balance); // no overflow
(from_balance - value).store(&from_key); (from_balance - value).store(&from_key);
(to_balance + value).store(&to_key); (to_balance + value).store(&to_key);
@@ -1,4 +1,4 @@
use primitives::{Block, BlockNumber, Hash, Transaction}; use primitives::{Block, BlockNumber, Hash, UncheckedTransaction};
use runtime_support::{Vec, swap}; use runtime_support::{Vec, swap};
use environment::with_env; use environment::with_env;
use runtime_support; use runtime_support;
@@ -53,7 +53,7 @@ fn final_checks(_block: &Block) {
} }
/// Execute a given transaction. /// Execute a given transaction.
pub fn execute_transaction(_tx: &Transaction) -> Vec<u8> { pub fn execute_transaction(_tx: &UncheckedTransaction) -> Vec<u8> {
// TODO: decode data and ensure valid // TODO: decode data and ensure valid
// TODO: ensure signature valid and recover id (use authentication::authenticate) // TODO: ensure signature valid and recover id (use authentication::authenticate)
// TODO: check nonce // TODO: check nonce
@@ -61,7 +61,7 @@ pub fn execute_transaction(_tx: &Transaction) -> Vec<u8> {
// TODO: ensure target_function valid // TODO: ensure target_function valid
// TODO: decode parameters // TODO: decode parameters
_tx.function.dispatch(&_tx.signed, &_tx.input_data); _tx.transaction.function.dispatch(&_tx.transaction.signed, &_tx.transaction.input_data);
// TODO: encode any return // TODO: encode any return
Vec::new() Vec::new()
@@ -78,7 +78,7 @@ mod tests {
use function::Function; use function::Function;
use std::collections::HashMap; use std::collections::HashMap;
use runtime_support::{NoError, with_externalities, Externalities}; use runtime_support::{NoError, with_externalities, Externalities};
use primitives::{AccountID, Transaction}; use primitives::{AccountID, UncheckedTransaction, Transaction};
use runtime::{system, staking}; use runtime::{system, staking};
#[derive(Debug, Default)] #[derive(Debug, Default)]
@@ -114,11 +114,14 @@ mod tests {
{ let mut r = b"sta\0bal\0".to_vec(); r.extend_from_slice(&one); r } => vec![111u8, 0, 0, 0, 0, 0, 0, 0] { let mut r = b"sta\0bal\0".to_vec(); r.extend_from_slice(&one); r } => vec![111u8, 0, 0, 0, 0, 0, 0, 0]
], }; ], };
let tx = Transaction { let tx = UncheckedTransaction {
signed: one.clone(), transaction: Transaction {
function: Function::StakingTransferStake, signed: one.clone(),
input_data: vec![].join(&two).join(&69u64), nonce: 0,
nonce: 0, function: Function::StakingTransferStake,
input_data: vec![].join(&two).join(&69u64),
},
signature: [1u8; 64],
}; };
with_externalities(&mut t, || { with_externalities(&mut t, || {
@@ -1,9 +1,10 @@
use primitives::Timestamp; use primitives::Timestamp;
use storage::Storage;
pub fn timestamp() -> Timestamp { pub fn timestamp() -> Timestamp {
unimplemented!() Storage::into(b"tim\0val")
} }
pub fn set_timestamp(_now: Timestamp) { pub fn set_timestamp(now: Timestamp) {
unimplemented!() now.store(b"tim\0val")
} }
@@ -5,10 +5,13 @@ use slicable::{Slicable, NonTrivialSlicable};
use function::Function; use function::Function;
use runtime_support::size_of; use runtime_support::size_of;
/// The hash of an ECDSA pub key which is used to identify an external transactor. #[cfg(test)]
use std::fmt;
/// The Ed25519 pubkey that identifies an account.
pub type AccountID = [u8; 32]; pub type AccountID = [u8; 32];
/// The ECDSA pub key of an authority. This is what the external environment/consensus algorithm /// The Ed25519 pub key of an session that belongs to an authority. This is used as what the
/// refers to as a "authority". /// external environment/consensus algorithm calls an "authority".
pub type SessionKey = AccountID; pub type SessionKey = AccountID;
pub type Balance = u64; pub type Balance = u64;
pub type ChainID = u64; pub type ChainID = u64;
@@ -36,15 +39,9 @@ pub struct Header {
#[cfg_attr(test, derive(PartialEq, Debug))] #[cfg_attr(test, derive(PartialEq, Debug))]
pub struct Transaction { pub struct Transaction {
pub signed: AccountID, pub signed: AccountID,
pub nonce: TxOrder,
pub function: Function, pub function: Function,
pub input_data: Vec<u8>, pub input_data: Vec<u8>,
pub nonce: TxOrder,
}
#[cfg_attr(test, derive(PartialEq, Debug))]
pub struct Block {
pub header: Header,
pub transactions: Vec<Transaction>,
} }
impl Slicable for Transaction { impl Slicable for Transaction {
@@ -52,8 +49,8 @@ impl Slicable for Transaction {
let mut reader = StreamReader::new(value); let mut reader = StreamReader::new(value);
Some(Transaction { Some(Transaction {
signed: reader.read()?, signed: reader.read()?,
function: Function::from_u8(reader.read()?)?,
nonce: reader.read()?, nonce: reader.read()?,
function: Function::from_u8(reader.read()?)?,
input_data: reader.read()?, input_data: reader.read()?,
}) })
} }
@@ -65,13 +62,13 @@ impl Slicable for Transaction {
fn to_vec(&self) -> Vec<u8> { fn to_vec(&self) -> Vec<u8> {
Vec::new() Vec::new()
.join(&self.signed) .join(&self.signed)
.join(&(self.function as u8))
.join(&self.nonce) .join(&self.nonce)
.join(&(self.function as u8))
.join(&self.input_data) .join(&self.input_data)
} }
fn size_of(data: &[u8]) -> Option<usize> { fn size_of(data: &[u8]) -> Option<usize> {
let first_part = size_of::<AccountID>() + size_of::<u8>() + size_of::<TxOrder>(); let first_part = size_of::<AccountID>() + size_of::<TxOrder>() + size_of::<u8>();
let second_part = <Vec<u8>>::size_of(&data[first_part..])?; let second_part = <Vec<u8>>::size_of(&data[first_part..])?;
Some(first_part + second_part) Some(first_part + second_part)
} }
@@ -79,6 +76,59 @@ impl Slicable for Transaction {
impl NonTrivialSlicable for Transaction {} impl NonTrivialSlicable for Transaction {}
pub struct UncheckedTransaction {
pub transaction: Transaction,
pub signature: [u8; 64],
}
#[cfg(test)]
impl PartialEq for UncheckedTransaction {
fn eq(&self, other: &Self) -> bool {
self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction
}
}
#[cfg(test)]
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<Self> {
let mut reader = StreamReader::new(value);
Some(UncheckedTransaction {
signature: reader.read()?,
transaction: reader.read()?,
})
}
fn set_as_slice<F: FnOnce(&mut[u8]) -> bool>(_fill_slice: F) -> Option<Self> {
unimplemented!();
}
fn to_vec(&self) -> Vec<u8> {
Vec::new()
.join(&self.signature)
.join(&self.transaction)
}
fn size_of(data: &[u8]) -> Option<usize> {
let first_part = size_of::<[u8; 64]>();
let second_part = <Transaction>::size_of(&data[first_part..])?;
Some(first_part + second_part)
}
}
impl NonTrivialSlicable for UncheckedTransaction {}
#[cfg_attr(test, derive(PartialEq, Debug))]
pub struct Block {
pub header: Header,
pub transactions: Vec<UncheckedTransaction>,
}
impl<T: Slicable> NonTrivialSlicable for Vec<T> where Vec<T>: Slicable {} impl<T: Slicable> NonTrivialSlicable for Vec<T> where Vec<T>: Slicable {}
impl<T: NonTrivialSlicable> Slicable for Vec<T> { impl<T: NonTrivialSlicable> Slicable for Vec<T> {
@@ -181,15 +231,15 @@ mod tests {
let two: AccountID = [2u8; 32]; let two: AccountID = [2u8; 32];
let tx = Transaction { let tx = Transaction {
signed: one.clone(), signed: one.clone(),
nonce: 69,
function: Function::StakingTransferStake, function: Function::StakingTransferStake,
input_data: Vec::new().join(&two).join(&69u64), input_data: Vec::new().join(&two).join(&69u64),
nonce: 69,
}; };
let serialised = tx.to_vec(); let serialised = tx.to_vec();
assert_eq!(serialised, 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, 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,
2,
69, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0,
2,
40, 0, 0, 0, 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, 2, 2, 2, 2, 2, 2, 2, 2, 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 69, 0, 0, 0, 0, 0, 0, 0
@@ -202,14 +252,14 @@ mod tests {
let two: AccountID = [2u8; 32]; let two: AccountID = [2u8; 32];
let tx = Transaction { let tx = Transaction {
signed: one.clone(), signed: one.clone(),
nonce: 69,
function: Function::StakingTransferStake, function: Function::StakingTransferStake,
input_data: Vec::new().join(&two).join(&69u64), input_data: Vec::new().join(&two).join(&69u64),
nonce: 69,
}; };
let data = [ 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, 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,
2,
69, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0,
2,
40, 0, 0, 0, 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, 2, 2, 2, 2, 2, 2, 2, 2, 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 69, 0, 0, 0, 0, 0, 0, 0
@@ -269,17 +319,23 @@ mod tests {
fn serialise_block_works() { fn serialise_block_works() {
let one: AccountID = [1u8; 32]; let one: AccountID = [1u8; 32];
let two: AccountID = [2u8; 32]; let two: AccountID = [2u8; 32];
let tx1 = Transaction { let tx1 = UncheckedTransaction {
signed: one.clone(), transaction: Transaction {
function: Function::StakingTransferStake, signed: one.clone(),
input_data: Vec::new().join(&two).join(&69u64), nonce: 69,
nonce: 69, function: Function::StakingTransferStake,
input_data: Vec::new().join(&two).join(&69u64),
},
signature: [1u8; 64],
}; };
let tx2 = Transaction { let tx2 = UncheckedTransaction {
signed: two.clone(), transaction: Transaction {
function: Function::StakingStake, signed: two.clone(),
input_data: Vec::new(), nonce: 42,
nonce: 42, function: Function::StakingStake,
input_data: Vec::new(),
},
signature: [2u8; 64],
}; };
let h = Header { let h = Header {
parent_hash: [4u8; 32], parent_hash: [4u8; 32],
@@ -305,18 +361,20 @@ mod tests {
11, 0, 0, 0, 11, 0, 0, 0,
97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103,
// transactions // transactions
130, 0, 0, 0, 2, 1, 0, 0,
// tx1 // 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2,
69, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0,
2,
40, 0, 0, 0, 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, 2, 2, 2, 2, 2, 2, 2, 2, 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, 69, 0, 0, 0, 0, 0, 0, 0,
// tx2 // 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, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
0,
42, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 0 0, 0, 0, 0
]); ]);
} }
@@ -325,17 +383,23 @@ mod tests {
fn deserialise_block_works() { fn deserialise_block_works() {
let one: AccountID = [1u8; 32]; let one: AccountID = [1u8; 32];
let two: AccountID = [2u8; 32]; let two: AccountID = [2u8; 32];
let tx1 = Transaction { let tx1 = UncheckedTransaction {
signed: one.clone(), transaction: Transaction {
function: Function::StakingTransferStake, signed: one.clone(),
input_data: Vec::new().join(&two).join(&69u64), nonce: 69,
nonce: 69, function: Function::StakingTransferStake,
input_data: Vec::new().join(&two).join(&69u64),
},
signature: [1u8; 64],
}; };
let tx2 = Transaction { let tx2 = UncheckedTransaction {
signed: two.clone(), transaction: Transaction {
function: Function::StakingStake, signed: two.clone(),
input_data: Vec::new(), nonce: 42,
nonce: 42, function: Function::StakingStake,
input_data: Vec::new(),
},
signature: [2u8; 64],
}; };
let h = Header { let h = Header {
parent_hash: [4u8; 32], parent_hash: [4u8; 32],
@@ -360,18 +424,20 @@ mod tests {
11, 0, 0, 0, 11, 0, 0, 0,
97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103,
// transactions // transactions
130, 0, 0, 0, 2, 1, 0, 0,
// tx1 // 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2,
69, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0,
2,
40, 0, 0, 0, 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, 2, 2, 2, 2, 2, 2, 2, 2, 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, 69, 0, 0, 0, 0, 0, 0, 0,
// tx2 // 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, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
0,
42, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 0 0, 0, 0, 0
]; ];
let deserialised = Block::from_slice(&data).unwrap(); let deserialised = Block::from_slice(&data).unwrap();
@@ -3,12 +3,12 @@ use endiansensitive::EndianSensitive;
use runtime_support; use runtime_support;
pub trait Storage { pub trait Storage {
fn storage_into(key: &[u8]) -> Self; fn into(key: &[u8]) -> Self;
fn store(&self, key: &[u8]); fn store(&self, key: &[u8]);
} }
impl<T: Default + Sized + EndianSensitive> Storage for T { impl<T: Default + Sized + EndianSensitive> Storage for T {
fn storage_into(key: &[u8]) -> Self { fn into(key: &[u8]) -> Self {
Slicable::set_as_slice(|out| runtime_support::read_storage(key, out) == out.len()) Slicable::set_as_slice(|out| runtime_support::read_storage(key, out) == out.len())
.unwrap_or_else(Default::default) .unwrap_or_else(Default::default)
} }
@@ -19,5 +19,5 @@ impl<T: Default + Sized + EndianSensitive> Storage for T {
} }
pub fn storage_into<T: Storage>(key: &[u8]) -> T { pub fn storage_into<T: Storage>(key: &[u8]) -> T {
T::storage_into(key) T::into(key)
} }