Skip to content

Commit 70baf90

Browse files
author
Joon-Mo Yang
committed
Execute custom actions
1 parent fb9f455 commit 70baf90

File tree

10 files changed

+52
-14
lines changed

10 files changed

+52
-14
lines changed

core/src/client/client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ impl Client {
9999
let trie_factory = TrieFactory::new(trie_spec);
100100

101101
let journal_db = journaldb::new(db.clone(), journaldb::Algorithm::Archive, ::db::COL_STATE);
102-
let mut state_db = StateDB::new(journal_db, config.state_cache_size);
102+
let mut state_db = StateDB::new(journal_db, config.state_cache_size, spec.custom_handlers.clone());
103103
if !spec.check_genesis_root(state_db.as_hashdb()) {
104104
return Err(SpecError::InvalidState.into())
105105
}

core/src/client/test_client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ impl TestBlockChainClient {
288288
pub fn get_temp_state_db() -> StateDB {
289289
let db = kvdb_memorydb::create(NUM_COLUMNS.unwrap_or(0));
290290
let journal_db = journaldb::new(Arc::new(db), journaldb::Algorithm::Archive, COL_STATE);
291-
StateDB::new(journal_db, 1024 * 1024)
291+
StateDB::new(journal_db, 1024 * 1024, Vec::new())
292292
}
293293

294294
impl ReopenBlock for TestBlockChainClient {

core/src/spec/spec.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ pub struct Spec {
106106
genesis_accounts: PodAccounts,
107107
genesis_shards: PodShards,
108108

109-
custom_handlers: Vec<Arc<ActionHandler>>,
109+
pub custom_handlers: Vec<Arc<ActionHandler>>,
110110
}
111111

112112
// helper for formatting errors.
@@ -402,7 +402,7 @@ fn load_from(s: cjson::spec::Spec, handlers: Vec<Arc<ActionHandler>>) -> Result<
402402
match g.state_root {
403403
Some(root) => *s.state_root_memo.get_mut() = root,
404404
None => {
405-
let db = StateDB::new_with_memorydb(0);
405+
let db = StateDB::new_with_memorydb(0, s.custom_handlers.clone());
406406
let trie_factory = TrieFactory::new(Default::default());
407407
let _ = s.initialize_state(&trie_factory, db)?;
408408
}

core/src/tests/helpers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,5 @@ pub fn get_good_dummy_block_hash() -> (H256, Bytes) {
6161
}
6262

6363
pub fn get_temp_state_db() -> StateDB {
64-
StateDB::new_with_memorydb(5 * 1024 * 1024)
64+
StateDB::new_with_memorydb(5 * 1024 * 1024, Vec::new())
6565
}

state/src/action_handler/hit.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ impl Decodable for HitAction {
4444
}
4545
}
4646

47+
#[derive(Clone)]
4748
pub struct HitHandler {}
4849

4950
impl HitHandler {
@@ -60,7 +61,7 @@ impl HitHandler {
6061

6162
impl ActionHandler for HitHandler {
6263
fn init(&self, state: &mut TrieMut) -> StateResult<()> {
63-
let r = state.insert(&self.address(), &0u32.rlp_bytes());
64+
let r = state.insert(&self.address(), &1u32.rlp_bytes());
6465
debug_assert_eq!(Ok(None), r);
6566
r?;
6667
Ok(())

state/src/backend.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,15 @@
3737
//! should become general over time to the point where not even a
3838
//! merkle trie is strictly necessary.
3939
40+
use std::sync::Arc;
41+
4042
use ckey::Address;
4143
use hashdb::HashDB;
4244
use primitives::{Bytes, H256};
4345

4446
use super::{
45-
Account, Asset, AssetAddress, AssetScheme, AssetSchemeAddress, Metadata, MetadataAddress, Shard, ShardAddress,
47+
Account, ActionHandler, Asset, AssetAddress, AssetScheme, AssetSchemeAddress, Metadata, MetadataAddress, Shard,
48+
ShardAddress,
4649
};
4750

4851

@@ -76,6 +79,8 @@ pub trait TopBackend: Send {
7679
fn get_cached_account_with<F, U>(&self, a: &Address, f: F) -> Option<U>
7780
where
7881
F: FnOnce(Option<&mut Account>) -> U;
82+
83+
fn custom_handlers(&self) -> &[Arc<ActionHandler>];
7984
}
8085

8186
pub trait ShardBackend: Send {

state/src/db.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ use primitives::{Bytes, H256};
3131
use util_error::UtilError;
3232

3333
use super::{
34-
Account, Asset, AssetAddress, AssetScheme, AssetSchemeAddress, Backend, CacheableItem, Metadata, MetadataAddress,
35-
Shard, ShardAddress, ShardBackend, TopBackend,
34+
Account, ActionHandler, Asset, AssetAddress, AssetScheme, AssetSchemeAddress, Backend, CacheableItem, Metadata,
35+
MetadataAddress, Shard, ShardAddress, ShardBackend, TopBackend,
3636
};
3737

3838
const STATE_CACHE_BLOCKS: usize = 12;
@@ -125,14 +125,16 @@ pub struct StateDB {
125125
commit_hash: Option<H256>,
126126
/// Number of the committing block or `None` if not committed yet.
127127
commit_number: Option<BlockNumber>,
128+
129+
custom_handlers: Vec<Arc<ActionHandler>>,
128130
}
129131

130132
impl StateDB {
131133
/// Create a new instance wrapping `JournalDB` and the maximum allowed size
132134
/// of the LRU cache in bytes. Actual used memory may (read: will) be higher due to bookkeeping.
133135
// TODO: make the cache size actually accurate by moving the account storage cache
134136
// into the `AccountCache` structure as its own `LruCache<(Address, H256), H256>`.
135-
pub fn new(db: Box<JournalDB>, cache_size: usize) -> StateDB {
137+
pub fn new(db: Box<JournalDB>, cache_size: usize, custom_handlers: Vec<Arc<ActionHandler>>) -> StateDB {
136138
assert_eq!(
137139
100,
138140
ACCOUNT_CACHE_RATIO
@@ -197,12 +199,13 @@ impl StateDB {
197199
parent_hash: None,
198200
commit_hash: None,
199201
commit_number: None,
202+
custom_handlers,
200203
}
201204
}
202205

203-
pub fn new_with_memorydb(cache_size: usize) -> Self {
206+
pub fn new_with_memorydb(cache_size: usize, custom_handlers: Vec<Arc<ActionHandler>>) -> Self {
204207
let memorydb = Arc::new(kvdb_memorydb::create(0));
205-
StateDB::new(journaldb::new(memorydb, Algorithm::Archive, None), cache_size)
208+
StateDB::new(journaldb::new(memorydb, Algorithm::Archive, None), cache_size, custom_handlers)
206209
}
207210

208211
/// Journal all recent operations under the given era and ID.
@@ -427,6 +430,7 @@ impl StateDB {
427430
parent_hash: Some(parent.clone()),
428431
commit_hash: None,
429432
commit_number: None,
433+
custom_handlers: self.custom_handlers.clone(),
430434
}
431435
}
432436

@@ -541,6 +545,8 @@ impl Clone for StateDB {
541545
parent_hash: None,
542546
commit_hash: None,
543547
commit_number: None,
548+
549+
custom_handlers: self.custom_handlers.clone(),
544550
}
545551
}
546552
}
@@ -609,6 +615,10 @@ impl TopBackend for StateDB {
609615
F: FnOnce(Option<&mut Account>) -> U, {
610616
self.get_cached_with(a, f, &self.account_cache)
611617
}
618+
619+
fn custom_handlers(&self) -> &[Arc<ActionHandler>] {
620+
&self.custom_handlers
621+
}
612622
}
613623

614624
impl ShardBackend for StateDB {

state/src/impls/top_level.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,15 @@ impl TopLevelState {
410410
error: None,
411411
})
412412
}
413+
Action::Custom(bytes) => {
414+
let handlers = self.db.custom_handlers().to_vec();
415+
for h in handlers {
416+
if h.is_target(bytes) {
417+
return h.execute(bytes, self)
418+
}
419+
}
420+
panic!("Unknown custom parcel accepted!")
421+
}
413422
}
414423
}
415424

state/src/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub mod helpers {
1919
use super::super::StateDB;
2020

2121
pub fn get_temp_state_db() -> StateDB {
22-
StateDB::new_with_memorydb(5 * 1024 * 1024)
22+
StateDB::new_with_memorydb(5 * 1024 * 1024, Vec::new())
2323
}
2424

2525
pub fn get_temp_state() -> TopLevelState {

types/src/parcel/action.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// along with this program. If not, see <https://www.gnu.org/licenses/>.
1616

1717
use ckey::{Address, Public};
18-
use primitives::{H256, U256};
18+
use primitives::{Bytes, H256, U256};
1919
use rlp::{Decodable, DecoderError, Encodable, RlpStream, UntrustedRlp};
2020

2121
use super::super::transaction::Transaction;
@@ -25,6 +25,7 @@ const CHANGE_SHARD_STATE: u8 = 1;
2525
const PAYMENT: u8 = 2;
2626
const SET_REGULAR_KEY: u8 = 3;
2727
const CREATE_SHARD: u8 = 4;
28+
const CUSTOM: u8 = 5;
2829

2930
#[derive(Debug, Clone, PartialEq, Eq, Serialize, RlpDecodable, RlpEncodable)]
3031
#[serde(rename_all = "camelCase")]
@@ -51,6 +52,7 @@ pub enum Action {
5152
key: Public,
5253
},
5354
CreateShard,
55+
Custom(Bytes),
5456
}
5557

5658
impl Encodable for Action {
@@ -85,6 +87,11 @@ impl Encodable for Action {
8587
s.begin_list(1);
8688
s.append(&CREATE_SHARD);
8789
}
90+
Action::Custom(bytes) => {
91+
s.begin_list(2);
92+
s.append(&CUSTOM);
93+
s.append(bytes);
94+
}
8895
}
8996
}
9097
}
@@ -124,6 +131,12 @@ impl Decodable for Action {
124131
}
125132
Ok(Action::CreateShard)
126133
}
134+
CUSTOM => {
135+
if rlp.item_count()? != 2 {
136+
return Err(DecoderError::RlpIncorrectListLen)
137+
}
138+
Ok(Action::Custom(rlp.val_at(1)?))
139+
}
127140
_ => Err(DecoderError::Custom("Unexpected action prefix")),
128141
}
129142
}

0 commit comments

Comments
 (0)