1#![deny(unused_import_braces, unused_imports,
2 unused_comparisons, unused_must_use,
3 unused_variables, non_shorthand_field_patterns,
4 unreachable_code)]
5
6extern crate trie;
7extern crate sputnikvm;
8extern crate sha3;
9extern crate block;
10extern crate rlp;
11extern crate bigint;
12
13use bigint::{H256, U256, M256, Address};
14use sputnikvm::{ValidTransaction, HeaderParams, Memory, TransactionVM, VM,
15 AccountCommitment, Patch, AccountState, AccountChange};
16use sputnikvm::errors::{PreExecutionError, RequireError};
17use sha3::{Keccak256, Digest};
18use trie::{FixedSecureTrie, DatabaseGuard, MemoryDatabase, Database, DatabaseOwned};
19use block::{Account, Transaction};
20use std::collections::HashMap;
21use std::cmp::min;
22use std::rc::Rc;
23use std::ops::Deref;
24
25pub struct LiteralAccount {
26 pub nonce: U256,
27 pub balance: U256,
28 pub storage: HashMap<U256, M256>,
29 pub code: Vec<u8>,
30}
31
32#[derive(Debug)]
33pub struct Stateful<'a, D: 'a> {
34 database: &'a D,
35 root: H256,
36}
37
38impl<'a, D: 'a> Clone for Stateful<'a, D> {
39 fn clone(&self) -> Self {
40 Self {
41 database: self.database.clone(),
42 root: self.root.clone(),
43 }
44 }
45}
46
47impl<'a, D> Stateful<'a, D> {
48 pub fn new(database: &'a D, root: H256) -> Self {
49 Self {
50 database,
51 root
52 }
53 }
54
55 pub fn empty(database: &'a D) -> Self {
56 Self::new(database, MemoryDatabase::new().create_empty().root())
57 }
58}
59
60impl<'b, D: DatabaseOwned> Stateful<'b, D> {
61 fn is_empty_hash(hash: H256) -> bool {
62 hash == H256::from(Keccak256::digest(&[]).as_slice())
63 }
64
65 pub fn database(&self) -> &'b D {
66 self.database
67 }
68
69 pub fn code(&self, hash: H256) -> Option<Vec<u8>> {
70 let code_hashes = self.database.create_guard();
71
72 if Self::is_empty_hash(hash) {
73 Some(Vec::new())
74 } else {
75 code_hashes.get(hash)
76 }
77 }
78
79 pub fn step<V: VM>(
80 &self, vm: &mut V, block_number: U256, most_recent_block_hashes: &[H256]
81 ) {
82 assert!(U256::from(most_recent_block_hashes.len()) >=
83 min(block_number, U256::from(256)));
84
85 let state = self.database.create_fixed_secure_trie(self.root);
86 let code_hashes = self.database.create_guard();
87
88 loop {
89 match vm.step() {
90 Ok(()) => break,
91 Err(RequireError::Account(address)) => {
92 let account: Option<Account> = state.get(&address);
93
94 match account {
95 Some(account) => {
96 let code = if Self::is_empty_hash(account.code_hash) {
97 Vec::new()
98 } else {
99 code_hashes.get(account.code_hash).unwrap()
100 };
101
102 vm.commit_account(AccountCommitment::Full {
103 nonce: account.nonce,
104 address: address,
105 balance: account.balance,
106 code: Rc::new(code),
107 }).unwrap();
108 },
109 None => {
110 vm.commit_account(AccountCommitment::Nonexist(address)).unwrap();
111 },
112 }
113 },
114 Err(RequireError::AccountCode(address)) => {
115 let account: Option<Account> = state.get(&address);
116
117 match account {
118 Some(account) => {
119 let code = if Self::is_empty_hash(account.code_hash) {
120 Vec::new()
121 } else {
122 code_hashes.get(account.code_hash).unwrap()
123 };
124
125 vm.commit_account(AccountCommitment::Code {
126 address: address,
127 code: Rc::new(code),
128 }).unwrap();
129 },
130 None => {
131 vm.commit_account(AccountCommitment::Nonexist(address)).unwrap();
132 },
133 }
134 },
135 Err(RequireError::AccountStorage(address, index)) => {
136 let account: Option<Account> = state.get(&address);
137
138 match account {
139 Some(account) => {
140 let storage = self.database.create_fixed_secure_trie(account.storage_root);
141 let value = storage.get(&H256::from(index)).unwrap_or(M256::zero());
142
143 vm.commit_account(AccountCommitment::Storage {
144 address: address,
145 index, value
146 }).unwrap();
147 },
148 None => {
149 vm.commit_account(AccountCommitment::Nonexist(address)).unwrap();
150 },
151 }
152 },
153 Err(RequireError::Blockhash(number)) => {
154 let index = (block_number - number).as_usize();
155 vm.commit_blockhash(number, most_recent_block_hashes[index]).unwrap();
156 },
157 }
158 }
159 }
160
161 pub fn call<M: Memory + Default, P: Patch>(
162 &self, transaction: ValidTransaction, block: HeaderParams,
163 most_recent_block_hashes: &[H256]
164 ) -> TransactionVM<M, P> {
165 assert!(U256::from(most_recent_block_hashes.len()) >=
166 min(block.number, U256::from(256)));
167
168 let mut vm = TransactionVM::new(transaction, block.clone());
169 let state = self.database.create_fixed_secure_trie(self.root);
170 let code_hashes = self.database.create_guard();
171
172 loop {
173 match vm.fire() {
174 Ok(()) => break,
175 Err(RequireError::Account(address)) => {
176 let account: Option<Account> = state.get(&address);
177
178 match account {
179 Some(account) => {
180 let code = if Self::is_empty_hash(account.code_hash) {
181 Vec::new()
182 } else {
183 code_hashes.get(account.code_hash).unwrap()
184 };
185
186 vm.commit_account(AccountCommitment::Full {
187 nonce: account.nonce,
188 address: address,
189 balance: account.balance,
190 code: Rc::new(code),
191 }).unwrap();
192 },
193 None => {
194 vm.commit_account(AccountCommitment::Nonexist(address)).unwrap();
195 },
196 }
197 },
198 Err(RequireError::AccountCode(address)) => {
199 let account: Option<Account> = state.get(&address);
200
201 match account {
202 Some(account) => {
203 let code = if Self::is_empty_hash(account.code_hash) {
204 Vec::new()
205 } else {
206 code_hashes.get(account.code_hash).unwrap()
207 };
208
209 vm.commit_account(AccountCommitment::Code {
210 address: address,
211 code: Rc::new(code),
212 }).unwrap();
213 },
214 None => {
215 vm.commit_account(AccountCommitment::Nonexist(address)).unwrap();
216 },
217 }
218 },
219 Err(RequireError::AccountStorage(address, index)) => {
220 let account: Option<Account> = state.get(&address);
221
222 match account {
223 Some(account) => {
224 let storage = self.database.create_fixed_secure_trie(account.storage_root);
225 let value = storage.get(&H256::from(index)).unwrap_or(M256::zero());
226
227 vm.commit_account(AccountCommitment::Storage {
228 address: address,
229 index, value
230 }).unwrap();
231 },
232 None => {
233 vm.commit_account(AccountCommitment::Nonexist(address)).unwrap();
234 },
235 }
236 },
237 Err(RequireError::Blockhash(number)) => {
238 let index = (block.number - number).as_usize();
239 vm.commit_blockhash(number, most_recent_block_hashes[index]).unwrap();
240 },
241 }
242 }
243
244 vm
245 }
246
247 pub fn sets(
248 &mut self, accounts: &[(Address, LiteralAccount)]
249 ) {
250 let mut state = self.database.create_fixed_secure_trie(self.root);
251 let mut code_hashes = self.database.create_guard();
252
253 for &(address, ref account) in accounts {
254 let mut storage_trie = self.database.create_fixed_secure_empty();
255 for (key, value) in &account.storage {
256 if *value == M256::zero() {
257 storage_trie.remove(&H256::from(*key));
258 } else {
259 storage_trie.insert(H256::from(*key), *value);
260 }
261 }
262
263 let code_hash = H256::from(Keccak256::digest(&account.code).as_slice());
264 code_hashes.set(code_hash, account.code.clone());
265
266 let account = Account {
267 nonce: account.nonce,
268 balance: account.balance,
269 storage_root: storage_trie.root(),
270 code_hash
271 };
272
273 state.insert(address, account);
274 }
275
276 self.root = state.root();
277 }
278
279 pub fn transit(
280 &mut self, accounts: &[AccountChange]
281 ) {
282 let mut state = self.database.create_fixed_secure_trie(self.root);
283 let mut code_hashes = self.database.create_guard();
284
285 for account in accounts {
286 match account.clone() {
287 AccountChange::Full {
288 nonce, address, balance, changing_storage, code
289 } => {
290 let changing_storage: HashMap<U256, M256> = changing_storage.into();
291
292 let mut account: Account = state.get(&address).unwrap();
293
294 let mut storage_trie = self.database.create_fixed_secure_trie(account.storage_root);
295 for (key, value) in changing_storage {
296 if value == M256::zero() {
297 storage_trie.remove(&H256::from(key));
298 } else {
299 storage_trie.insert(H256::from(key), value);
300 }
301 }
302
303 account.balance = balance;
304 account.nonce = nonce;
305 account.storage_root = storage_trie.root();
306 assert!(account.code_hash == H256::from(Keccak256::digest(&code).as_slice()));
307
308 state.insert(address, account);
309 },
310 AccountChange::IncreaseBalance(address, value) => {
311 match state.get(&address) {
312 Some(mut account) => {
313 account.balance = account.balance + value;
314 state.insert(address, account);
315 },
316 None => {
317 let account = Account {
318 nonce: U256::zero(),
319 balance: value,
320 storage_root: self.database.create_empty().root(),
321 code_hash: H256::from(Keccak256::digest(&[]).as_slice())
322 };
323 state.insert(address, account);
324 }
325 }
326 },
327 AccountChange::Create {
328 nonce, address, balance, storage, code
329 } => {
330 let storage: HashMap<U256, M256> = storage.into();
331
332 let mut storage_trie = self.database.create_fixed_secure_empty();
333 for (key, value) in storage {
334 if value == M256::zero() {
335 storage_trie.remove(&H256::from(key));
336 } else {
337 storage_trie.insert(H256::from(key), value);
338 }
339 }
340
341 let code_hash = H256::from(Keccak256::digest(&code).as_slice());
342 code_hashes.set(code_hash, code.deref().clone());
343
344 let account = Account {
345 nonce: nonce,
346 balance: balance,
347 storage_root: storage_trie.root(),
348 code_hash
349 };
350
351 state.insert(address, account);
352 },
353 AccountChange::Nonexist(address) => {
354 state.remove(&address);
355 }
356 }
357 }
358
359 self.root = state.root();
360 }
361
362 pub fn execute<M: Memory + Default, P: Patch>(
363 &mut self, transaction: ValidTransaction, block: HeaderParams,
364 most_recent_block_hashes: &[H256]
365 ) -> TransactionVM<M, P> {
366 let vm = self.call::<_, P>(transaction, block, most_recent_block_hashes);
367 let mut accounts = Vec::new();
368 for account in vm.accounts() {
369 accounts.push(account.clone());
370 }
371 self.transit(&accounts);
372 vm
373 }
374
375 pub fn to_valid<P: Patch>(
376 &self, transaction: Transaction,
377 ) -> Result<ValidTransaction, PreExecutionError> {
378 let state = self.database.create_fixed_secure_trie(self.root);
379 let code_hashes = self.database.create_guard();
380 let mut account_state = AccountState::default();
381
382 loop {
383 match ValidTransaction::from_transaction::<P>(&transaction, &account_state) {
384 Ok(val) => return val,
385 Err(RequireError::Account(address)) => {
386 let account: Option<Account> = state.get(&address);
387
388 match account {
389 Some(account) => {
390 let code = if Self::is_empty_hash(account.code_hash) {
391 Vec::new()
392 } else {
393 code_hashes.get(account.code_hash).unwrap()
394 };
395
396 account_state.commit(AccountCommitment::Full {
397 nonce: account.nonce,
398 address: address,
399 balance: account.balance,
400 code: Rc::new(code),
401 }).unwrap();
402 },
403 None => {
404 account_state.commit(AccountCommitment::Nonexist(address)).unwrap();
405 },
406 }
407 },
408 Err(RequireError::AccountCode(address)) => {
409 let account: Option<Account> = state.get(&address);
410
411 match account {
412 Some(account) => {
413 let code = if Self::is_empty_hash(account.code_hash) {
414 Vec::new()
415 } else {
416 code_hashes.get(account.code_hash).unwrap()
417 };
418
419 account_state.commit(AccountCommitment::Code {
420 address: address,
421 code: Rc::new(code),
422 }).unwrap();
423 },
424 None => {
425 account_state.commit(AccountCommitment::Nonexist(address)).unwrap();
426 },
427 }
428 },
429 Err(RequireError::AccountStorage(address, index)) => {
430 let account: Option<Account> = state.get(&address);
431
432 match account {
433 Some(account) => {
434 let storage = self.database.create_fixed_secure_trie(account.storage_root);
435 let value = storage.get(&H256::from(index)).unwrap_or(M256::zero());
436
437 account_state.commit(AccountCommitment::Storage {
438 address: address,
439 index, value
440 }).unwrap();
441 },
442 None => {
443 account_state.commit(AccountCommitment::Nonexist(address)).unwrap();
444 },
445 }
446 },
447 Err(RequireError::Blockhash(_)) => {
448 panic!()
449 },
450 }
451 }
452 }
453
454 pub fn root(&self) -> H256 {
455 self.root
456 }
457
458 pub fn state_of<'a>(&'a self, root: H256) -> FixedSecureTrie<<D as Database<'a>>::Guard, Address, Account> {
459 self.database.create_fixed_secure_trie::<Address, Account>(root)
460 }
461
462 pub fn state<'a>(&'a self) -> FixedSecureTrie<<D as Database<'a>>::Guard, Address, Account> {
463 self.state_of(self.root())
464 }
465
466 pub fn storage_state_of<'a>(&'a self, root: H256) -> FixedSecureTrie<<D as Database<'a>>::Guard, H256, M256> {
467 self.database.create_fixed_secure_trie::<H256, M256>(root)
468 }
469
470 pub fn storage_state<'a>(&'a self, address: Address) -> Option<FixedSecureTrie<<D as Database<'a>>::Guard, H256, M256>> {
471 let state = self.state();
472 let account = state.get(&address);
473
474 match account {
475 Some(account) => {
476 Some(self.storage_state_of(account.storage_root))
477 },
478 None => None,
479 }
480 }
481}
482
483pub type MemoryStateful<'a> = Stateful<'a, MemoryDatabase>;