Skip to content

Commit 1955025

Browse files
Seulgi Kimsgkim126
authored andcommitted
Add World
1 parent a68ff1f commit 1955025

File tree

4 files changed

+225
-2
lines changed

4 files changed

+225
-2
lines changed

state/src/item/address.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,38 @@ macro_rules! define_address_constructor {
4141

4242
hash[4..6].clone_from_slice(&[0, 0]); // world id
4343

44+
$name(hash)
45+
}
46+
};
47+
(WORLD, $name:ident, $prefix:expr) => {
48+
fn from_transaction_hash_with_shard_and_world_id(
49+
transaction_hash: ::primitives::H256,
50+
index: u64,
51+
shard_id: ::ctypes::ShardId,
52+
world_id: ::ctypes::WorldId,
53+
) -> Self {
54+
let mut hash: ::primitives::H256 =
55+
::ccrypto::Blake::blake_with_key(&transaction_hash, &::primitives::H128::from(index));
56+
hash[0..2].clone_from_slice(&[$prefix, 0]);
57+
58+
let mut shard_id_bytes = Vec::<u8>::new();
59+
debug_assert_eq!(::std::mem::size_of::<u16>(), ::std::mem::size_of::<::ctypes::ShardId>());
60+
::byteorder::WriteBytesExt::write_u16::<::byteorder::BigEndian>(&mut shard_id_bytes, shard_id).unwrap();
61+
assert_eq!(2, shard_id_bytes.len());
62+
hash[2..4].clone_from_slice(&shard_id_bytes);
63+
64+
let mut world_id_bytes = Vec::<u8>::new();
65+
debug_assert_eq!(::std::mem::size_of::<u16>(), ::std::mem::size_of::<::ctypes::WorldId>());
66+
::byteorder::WriteBytesExt::write_u16::<::byteorder::BigEndian>(&mut world_id_bytes, world_id).unwrap();
67+
assert_eq!(2, world_id_bytes.len());
68+
hash[4..6].clone_from_slice(&world_id_bytes);
69+
4470
$name(hash)
4571
}
4672
};
4773
}
4874

49-
macro_rules! define_shard_id {
75+
macro_rules! define_id_getter {
5076
(TOP) => {
5177
};
5278
(SHARD) => {
@@ -56,14 +82,23 @@ macro_rules! define_shard_id {
5682
::std::io::Cursor::new(&self.0[2..4]).read_u16::<::byteorder::BigEndian>().unwrap()
5783
}
5884
};
85+
(WORLD) => {
86+
define_id_getter!(SHARD);
87+
88+
pub fn world_id(&self) -> ::ctypes::WorldId {
89+
debug_assert_eq!(::std::mem::size_of::<u16>(), ::std::mem::size_of::<ShardId>());
90+
use byteorder::ReadBytesExt;
91+
::std::io::Cursor::new(&self.0[4..6]).read_u16::<::byteorder::BigEndian>().unwrap()
92+
}
93+
};
5994
}
6095

6196
macro_rules! impl_address {
6297
($type:ident, $name:ident, $prefix:expr) => {
6398
impl $name {
6499
define_address_constructor!($type, $name, $prefix);
65100

66-
define_shard_id!($type);
101+
define_id_getter!($type);
67102

68103
pub fn from_hash(hash: ::primitives::H256) -> Option<Self> {
69104
if Self::is_valid_format(&hash) {

state/src/item/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub mod metadata;
2525
pub mod regular_account;
2626
pub mod shard;
2727
pub mod shard_metadata;
28+
pub mod world;
2829

2930
const ASSET_PREFIX: u8 = 'A' as u8;
3031
const ADDRESS_PREFIX: u8 = 'C' as u8;
@@ -33,3 +34,4 @@ const SHARD_PREFIX: u8 = 'H' as u8;
3334
const METADATA_PREFIX: u8 = 'M' as u8;
3435
const REGULAR_ACCOUNT_PREFIX: u8 = 'R' as u8;
3536
const ASSET_SCHEME_PREFIX: u8 = 'S' as u8;
37+
const WORLD_PREFIX: u8 = 'W' as u8;

state/src/item/world.rs

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
// Copyright 2018 Kodebox, Inc.
2+
// This file is part of CodeChain.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as
6+
// published by the Free Software Foundation, either version 3 of the
7+
// License, or (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
use ckey::Address;
18+
use ctypes::{ShardId, WorldId};
19+
use primitives::H256;
20+
use rlp::{Decodable, DecoderError, Encodable, RlpStream, UntrustedRlp};
21+
22+
use super::cache::CacheableItem;
23+
24+
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
25+
pub struct World {
26+
world_owners: Vec<Address>,
27+
nonce: u64,
28+
}
29+
30+
impl World {
31+
pub fn new(world_owners: Vec<Address>) -> Self {
32+
Self {
33+
world_owners,
34+
nonce: 0,
35+
}
36+
}
37+
38+
pub fn new_with_nonce(world_owners: Vec<Address>, nonce: u64) -> Self {
39+
Self {
40+
world_owners,
41+
nonce,
42+
}
43+
}
44+
45+
pub fn world_owners(&self) -> &[Address] {
46+
&self.world_owners
47+
}
48+
49+
pub fn nonce(&self) -> &u64 {
50+
&self.nonce
51+
}
52+
}
53+
54+
impl CacheableItem for World {
55+
type Address = WorldAddress;
56+
57+
fn is_null(&self) -> bool {
58+
self.world_owners.is_empty() && self.nonce == 0
59+
}
60+
}
61+
62+
const PREFIX: u8 = super::WORLD_PREFIX;
63+
64+
impl Encodable for World {
65+
fn rlp_append(&self, s: &mut RlpStream) {
66+
s.begin_list(3).append(&PREFIX).append_list(self.world_owners()).append(self.nonce());
67+
}
68+
}
69+
70+
impl Decodable for World {
71+
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
72+
let prefix = rlp.val_at::<u8>(0)?;
73+
if PREFIX != prefix {
74+
cdebug!(STATE, "{} is not an expected prefix for world", prefix);
75+
return Err(DecoderError::Custom("Unexpected prefix"))
76+
}
77+
Ok(Self {
78+
world_owners: rlp.list_at(1)?,
79+
nonce: rlp.val_at(2)?,
80+
})
81+
}
82+
}
83+
84+
#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
85+
pub struct WorldAddress(H256);
86+
87+
impl_address!(WORLD, WorldAddress, PREFIX);
88+
89+
impl WorldAddress {
90+
pub fn new(shard_id: ShardId, world_id: WorldId) -> Self {
91+
Self::from_transaction_hash_with_shard_and_world_id(H256::from_slice(b"world"), 0, shard_id, world_id)
92+
}
93+
}
94+
95+
#[cfg(test)]
96+
mod tests {
97+
use super::*;
98+
99+
#[test]
100+
fn address() {
101+
let shard_id = 0xBeef;
102+
let world_id = 0xCafe;
103+
let address = WorldAddress::new(shard_id, world_id);
104+
assert_eq!(address[0..2], [PREFIX, 0]);
105+
assert_eq!(address[2..4], [0xBE, 0xEF]); // shard id
106+
assert_eq!(address[4..6], [0xCA, 0xFE]); // world id
107+
}
108+
109+
#[test]
110+
fn parse_fail_return_none() {
111+
let hash = {
112+
let mut hash;
113+
loop {
114+
hash = H256::random();
115+
if hash[0] == PREFIX {
116+
continue
117+
}
118+
for i in 1..6 {
119+
if hash[i] == 0 {
120+
continue
121+
}
122+
}
123+
break
124+
}
125+
hash
126+
};
127+
let address = WorldAddress::from_hash(hash);
128+
assert_eq!(None, address);
129+
}
130+
131+
#[test]
132+
fn parse_return_some() {
133+
let hash = {
134+
let mut hash = H256::random();
135+
hash[0..6].clone_from_slice(&[PREFIX, 0, 0, 0, 0, 0]);
136+
hash
137+
};
138+
let address = WorldAddress::from_hash(hash.clone());
139+
assert_eq!(Some(WorldAddress(hash)), address);
140+
}
141+
142+
#[test]
143+
fn shard_id() {
144+
let shard_id = 0xCAA;
145+
let world_id = 0xBEE;
146+
let world_address = WorldAddress::new(shard_id, world_id);
147+
assert_eq!(shard_id, world_address.shard_id());
148+
}
149+
150+
#[test]
151+
fn world_id() {
152+
let world_id = 0xCAA;
153+
let shard_id = 0xBEE;
154+
let world_address = WorldAddress::new(shard_id, world_id);
155+
assert_eq!(world_id, world_address.world_id());
156+
}
157+
158+
#[test]
159+
fn shard_id_from_hash() {
160+
let hash = {
161+
let mut hash = H256::random();
162+
hash[0] = PREFIX;
163+
hash[1] = 0;
164+
hash
165+
};
166+
assert_eq!(::std::mem::size_of::<u16>(), ::std::mem::size_of::<ShardId>());
167+
let shard_id = ((hash[2] as ShardId) << 8) + (hash[3] as ShardId);
168+
let world_address = WorldAddress::from_hash(hash).unwrap();
169+
assert_eq!(shard_id, world_address.shard_id());
170+
}
171+
172+
#[test]
173+
fn world_id_from_hash() {
174+
let hash = {
175+
let mut hash = H256::random();
176+
hash[0] = PREFIX;
177+
hash[1] = 0;
178+
hash
179+
};
180+
assert_eq!(::std::mem::size_of::<u16>(), ::std::mem::size_of::<WorldId>());
181+
let world_id = ((hash[4] as WorldId) << 8) + (hash[5] as WorldId);
182+
let world_address = WorldAddress::from_hash(hash).unwrap();
183+
assert_eq!(world_id, world_address.world_id());
184+
}
185+
}

state/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ pub use item::metadata::{Metadata, MetadataAddress};
6565
pub use item::regular_account::{RegularAccount, RegularAccountAddress};
6666
pub use item::shard::{Shard, ShardAddress};
6767
pub use item::shard_metadata::{ShardMetadata, ShardMetadataAddress};
68+
pub use item::world::{World, WorldAddress};
6869
pub use traits::{ShardState, ShardStateInfo, StateWithCache, TopState, TopStateInfo};
6970

7071
pub type StateResult<T> = Result<T, StateError>;

0 commit comments

Comments
 (0)