Skip to content

Commit aba1ae9

Browse files
Junha Yang0sgkim126
authored andcommitted
Add a new field 'validator set root' in the header
1 parent b20fe13 commit aba1ae9

File tree

21 files changed

+392
-972
lines changed

21 files changed

+392
-972
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/src/block.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use super::invoice::Invoice;
1818
use crate::client::{EngineInfo, TermInfo};
1919
use crate::consensus::CodeChainEngine;
2020
use crate::error::{BlockError, Error};
21+
use crate::stake;
2122
use crate::transaction::{SignedTransaction, UnverifiedTransaction};
2223
use crate::BlockId;
2324
use ccrypto::BLAKE_NULL_RLP;
@@ -232,6 +233,16 @@ impl<'x> OpenBlock<'x> {
232233
e
233234
})?;
234235
self.block.header.set_state_root(state_root);
236+
237+
/*
238+
FIXME: NextValidators entry doesn't exist in the state during static-validator-set-mode.
239+
It doesn't cause a direct error since we use unwrap_or_default() here, but should be aware of such problem.
240+
Remove this comment after we completely omit static-validator-set-mode.
241+
*/
242+
let vset_raw = stake::NextValidators::load_from_state(self.block.state())?;
243+
let vset = vset_raw.create_compact_validator_set();
244+
self.block.header.set_next_validator_set_hash(vset.hash());
245+
235246
Ok(())
236247
}
237248

core/src/consensus/stake/action_data.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2018-2019 Kodebox, Inc.
1+
// Copyright 2018-2020 Kodebox, Inc.
22
// This file is part of CodeChain.
33
//
44
// This program is free software: you can redistribute it and/or modify
@@ -18,6 +18,7 @@ use super::CUSTOM_ACTION_HANDLER_ID;
1818
use ckey::{public_to_address, Address, Public};
1919
use cstate::{ActionData, ActionDataKeyBuilder, StateResult, TopLevelState, TopState, TopStateView};
2020
use ctypes::errors::RuntimeError;
21+
use ctypes::CompactValidatorSet;
2122
use primitives::{Bytes, H256};
2223
use rlp::{decode_list, encode_list, Decodable, Encodable, Rlp, RlpStream};
2324
use std::cmp::Ordering;
@@ -287,6 +288,10 @@ impl NextValidators {
287288
Ok(Self(validators))
288289
}
289290

291+
pub fn create_compact_validator_set(&self) -> CompactValidatorSet {
292+
CompactValidatorSet(self.0.iter().map(|x| (*x.pubkey(), x.delegation())).collect())
293+
}
294+
290295
pub fn elect(state: &TopLevelState) -> StateResult<Self> {
291296
let (delegation_threshold, max_num_of_validators, min_num_of_validators, min_deposit) = {
292297
let metadata = state.metadata()?.expect("Metadata must exist");

core/src/encoded.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2018-2019 Kodebox, Inc.
1+
// Copyright 2018-2020 Kodebox, Inc.
22
// This file is part of CodeChain.
33
//
44
// This program is free software: you can redistribute it and/or modify
@@ -94,6 +94,11 @@ impl Header {
9494
self.view().transactions_root()
9595
}
9696

97+
/// Returns the transaction trie root.
98+
pub fn next_validator_set_hash(&self) -> H256 {
99+
self.view().next_validator_set_hash()
100+
}
101+
97102
/// Score of this block
98103
pub fn score(&self) -> U256 {
99104
self.view().score()

core/src/error.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ pub enum BlockError {
8484
InvalidStateRoot(Mismatch<H256>),
8585
/// Transactions root header field is invalid.
8686
InvalidTransactionsRoot(Mismatch<H256>),
87+
/// Next validator set hash header field is invalid.
88+
InvalidNextValidatorSetHash(Mismatch<H256>),
8789
/// Score is out of range; this can be used as an looser error prior to getting a definitive
8890
/// value for score. This error needs only provide bounds of which it is out.
8991
ScoreOutOfBounds(OutOfBounds<U256>),
@@ -139,6 +141,7 @@ impl fmt::Display for BlockError {
139141
InvalidSealArity(mis) => format!("Block seal in incorrect format: {}", mis),
140142
InvalidStateRoot(mis) => format!("Invalid state root in header: {}", mis),
141143
InvalidTransactionsRoot(mis) => format!("Invalid transactions root in header: {}", mis),
144+
InvalidNextValidatorSetHash(mis) => format!("Invalid next validator set hash in header: {}", mis),
142145
ScoreOutOfBounds(oob) => format!("Invalid block score: {}", oob),
143146
InvalidScore(oob) => format!("Invalid block score: {}", oob),
144147
InvalidProofOfWork => "Invalid proof of work.".into(),

core/src/scheme/genesis.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ pub struct Genesis {
3737
pub transactions_root: H256,
3838
/// State root.
3939
pub state_root: Option<H256>,
40+
/// Next validator set hash.
41+
pub next_validator_set_hash: Option<H256>,
4042
/// The genesis block's extra data field.
4143
pub extra_data: Bytes,
4244
}
@@ -51,6 +53,7 @@ impl From<cjson::scheme::Genesis> for Genesis {
5153
parent_hash: g.parent_hash.map_or_else(H256::zero, Into::into).into(),
5254
transactions_root: g.transactions_root.map_or_else(|| BLAKE_NULL_RLP, Into::into),
5355
state_root: g.state_root.map(Into::into),
56+
next_validator_set_hash: g.next_validator_set_hash.map(Into::into),
5457
extra_data: g.extra_data.map_or_else(Vec::new, Into::into),
5558
}
5659
}

core/src/scheme/scheme.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ impl Scheme {
266266
header.set_transactions_root(self.transactions_root);
267267
header.set_extra_data(blake256(&self.genesis_params().rlp_bytes()).to_vec());
268268
header.set_state_root(self.state_root());
269+
header.set_next_validator_set_hash(BLAKE_NULL_RLP /* This will be calculated from state after https://github.com/CodeChain-io/foundry/issues/142*/);
269270
header.set_score(self.score);
270271
header.set_seal({
271272
let r = Rlp::new(&self.seal_rlp);

core/src/verification/verification.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,5 +265,11 @@ pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error>
265265
found: *got.state_root(),
266266
})))
267267
}
268+
if expected.next_validator_set_hash() != got.next_validator_set_hash() {
269+
return Err(From::from(BlockError::InvalidNextValidatorSetHash(Mismatch {
270+
expected: *expected.next_validator_set_hash(),
271+
found: *got.next_validator_set_hash(),
272+
})))
273+
}
268274
Ok(())
269275
}

core/src/views/header.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2018-2019 Kodebox, Inc.
1+
// Copyright 2018-2020 Kodebox, Inc.
22
// This file is part of CodeChain.
33
//
44
// This program is free software: you can redistribute it and/or modify
@@ -70,29 +70,34 @@ impl<'a> HeaderView<'a> {
7070
self.rlp.val_at(3).unwrap()
7171
}
7272

73+
/// Returns next validator set hash
74+
pub fn next_validator_set_hash(&self) -> H256 {
75+
self.rlp.val_at(4).unwrap()
76+
}
77+
7378
/// Returns block score.
7479
pub fn score(&self) -> U256 {
75-
self.rlp.val_at(4).unwrap()
80+
self.rlp.val_at(5).unwrap()
7681
}
7782

7883
/// Returns block number.
7984
pub fn number(&self) -> BlockNumber {
80-
self.rlp.val_at(5).unwrap()
85+
self.rlp.val_at(6).unwrap()
8186
}
8287

8388
/// Returns timestamp.
8489
pub fn timestamp(&self) -> u64 {
85-
self.rlp.val_at(6).unwrap()
90+
self.rlp.val_at(7).unwrap()
8691
}
8792

8893
/// Returns block extra data.
8994
pub fn extra_data(&self) -> Bytes {
90-
self.rlp.val_at(7).unwrap()
95+
self.rlp.val_at(8).unwrap()
9196
}
9297

9398
/// Returns a vector of post-RLP-encoded seal fields.
9499
pub fn seal(&self) -> Vec<Bytes> {
95-
const SIZE_WITHOUT_SEAL: usize = 8;
100+
const SIZE_WITHOUT_SEAL: usize = 9;
96101

97102
let item_count = self.rlp.item_count().unwrap();
98103
let mut seal = Vec::with_capacity(item_count - SIZE_WITHOUT_SEAL);

json/src/scheme/genesis.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2018-2019 Kodebox, Inc.
1+
// Copyright 2018-2020 Kodebox, Inc.
22
// This file is part of CodeChain.
33
//
44
// This program is free software: you can redistribute it and/or modify
@@ -38,6 +38,8 @@ pub struct Genesis {
3838
pub transactions_root: Option<H256>,
3939
/// State root.
4040
pub state_root: Option<H256>,
41+
/// Next validator set hash.
42+
pub next_validator_set_hash: Option<H256>,
4143
/// Extra data.
4244
pub extra_data: Option<Bytes>,
4345
}
@@ -73,7 +75,8 @@ mod tests {
7375
"timestamp": "0x07",
7476
"parentHash": "0x9000000000000000000000000000000000000000000000000000000000000000",
7577
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
76-
"stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
78+
"stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544",
79+
"nextValidatorSetHash": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
7780
}"#;
7881
let deserialized: Genesis = serde_json::from_str(s).unwrap();
7982
assert_eq!(deserialized, Genesis {
@@ -90,6 +93,7 @@ mod tests {
9093
parent_hash: Some(H256(Core256::from("0x9000000000000000000000000000000000000000000000000000000000000000"))),
9194
transactions_root: None,
9295
state_root: Some(H256(Core256::from("0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"))),
96+
next_validator_set_hash: Some(H256(Core256::from("0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"))),
9397
extra_data: Some(Bytes::from_str("0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa").unwrap()),
9498
});
9599
}

0 commit comments

Comments
 (0)