1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#![feature(box_syntax)]
mod block;
mod output;
mod pending_transaction;
use std::{borrow::Cow, collections::HashMap, convert::TryInto};
use blockchain_traits::Blockchain;
use oasis_types::{AccountMeta, Address};
use block::Block;
type State<'bc> = HashMap<Address, Cow<'bc, Account>>;
pub type PtxPtr = *const *mut dyn blockchain_traits::PendingTransaction<
Address = Address,
AccountMeta = AccountMeta,
>;
pub type AccountMain = extern "C" fn(PtxPtr) -> u16;
#[derive(Debug)]
pub struct Memchain<'bc> {
name: String,
blocks: Vec<Block<'bc>>,
base_gas: u64,
}
impl<'bc> Memchain<'bc> {
pub fn new<S: AsRef<str>>(name: S, genesis_state: State<'bc>, base_gas: u64) -> Self {
let mut bc = Self {
name: name.as_ref().to_string(),
blocks: Vec::new(),
base_gas,
};
bc.create_block_with_state(genesis_state);
bc
}
pub fn create_block(&mut self) -> &mut Block<'bc> {
self.create_block_with_state(self.blocks.last().unwrap().state.clone())
}
fn create_block_with_state(&mut self, state: State<'bc>) -> &mut Block<'bc> {
self.blocks.push(Block::new(
self.blocks.len().try_into().unwrap(),
state,
self.base_gas,
));
self.blocks.last_mut().unwrap()
}
}
impl<'bc> Blockchain for Memchain<'bc> {
type Address = Address;
type AccountMeta = AccountMeta;
fn name(&self) -> &str {
&self.name
}
fn block(
&self,
height: usize,
) -> Option<
&dyn blockchain_traits::Block<Address = Self::Address, AccountMeta = Self::AccountMeta>,
> {
self.blocks.get(height).map(|b| {
b as &dyn blockchain_traits::Block<
Address = Self::Address,
AccountMeta = Self::AccountMeta,
>
})
}
fn last_block(
&self,
) -> &dyn blockchain_traits::Block<Address = Self::Address, AccountMeta = Self::AccountMeta>
{
self.blocks.last().unwrap()
}
fn last_block_mut(
&mut self,
) -> &mut dyn blockchain_traits::Block<Address = Self::Address, AccountMeta = Self::AccountMeta>
{
self.blocks.last_mut().unwrap()
}
}
#[derive(Clone, Default, Debug)]
pub struct Account {
pub balance: u64,
pub code: Vec<u8>,
pub storage: HashMap<Vec<u8>, Vec<u8>>,
pub expiry: Option<std::time::Duration>,
pub main: Option<AccountMain>,
}
impl blockchain_traits::KVStore for Account {
fn contains(&self, key: &[u8]) -> bool {
self.storage.contains_key(key)
}
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
self.storage.get(key).map(Vec::to_owned)
}
}
impl blockchain_traits::KVStoreMut for Account {
fn set(&mut self, key: &[u8], value: &[u8]) {
self.storage.insert(key.to_vec(), value.to_vec());
}
fn remove(&mut self, key: &[u8]) {
self.storage.remove(key);
}
}
#[cfg(test)]
mod tests;