Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion codechain/run_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ pub fn run_node(matches: &ArgMatches) -> Result<(), String> {
let network_config = config.network_config()?;
// XXX: What should we do if the network id has been changed.
let c = client.client();
let network_id = c.common_params(BlockId::Latest).unwrap().network_id();
let network_id = c.common_params(BlockId::Number(0)).unwrap().network_id();
let routing_table = RoutingTable::new();
let service = network_start(network_id, timer_loop, &network_config, Arc::clone(&routing_table))?;

Expand Down
12 changes: 12 additions & 0 deletions core/src/blockchain/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,18 @@ impl BlockChain {
}
}

pub fn insert_bootstrap_header(&self, batch: &mut DBTransaction, header: &HeaderView) {
self.headerchain.insert_bootstrap_header(batch, header);

let hash = header.hash();

*self.pending_best_block_hash.write() = Some(hash);
batch.put(db::COL_EXTRA, BEST_BLOCK_KEY, &hash);

*self.pending_best_proposal_block_hash.write() = Some(hash);
batch.put(db::COL_EXTRA, BEST_PROPOSAL_BLOCK_KEY, &hash);
}

pub fn insert_header(
&self,
batch: &mut DBTransaction,
Expand Down
42 changes: 42 additions & 0 deletions core/src/blockchain/headerchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,48 @@ impl HeaderChain {
}
}

/// Inserts a bootstrap header into backing cache database.
/// Makes the imported header the best header.
/// Expects the header to be valid and already verified.
/// If the header is already known, does nothing.
// FIXME: Find better return type. Returning `None` at duplication is not natural
pub fn insert_bootstrap_header(&self, batch: &mut DBTransaction, header: &HeaderView) {
let hash = header.hash();

ctrace!(HEADERCHAIN, "Inserting bootstrap block header #{}({}) to the headerchain.", header.number(), hash);

if self.is_known_header(&hash) {
ctrace!(HEADERCHAIN, "Block header #{}({}) is already known.", header.number(), hash);
return
}

assert!(self.pending_best_header_hash.read().is_none());
assert!(self.pending_best_proposal_block_hash.read().is_none());

let compressed_header = compress(header.rlp().as_raw(), blocks_swapper());
batch.put(db::COL_HEADERS, &hash, &compressed_header);

let mut new_hashes = HashMap::new();
new_hashes.insert(header.number(), hash);
let mut new_details = HashMap::new();
new_details.insert(hash, BlockDetails {
number: header.number(),
total_score: 0.into(),
parent: header.parent_hash(),
});

batch.put(db::COL_EXTRA, BEST_HEADER_KEY, &hash);
*self.pending_best_header_hash.write() = Some(hash);
batch.put(db::COL_EXTRA, BEST_PROPOSAL_HEADER_KEY, &hash);
*self.pending_best_proposal_block_hash.write() = Some(hash);

let mut pending_hashes = self.pending_hashes.write();
let mut pending_details = self.pending_details.write();

batch.extend_with_cache(db::COL_EXTRA, &mut *pending_details, new_details, CacheUpdatePolicy::Overwrite);
batch.extend_with_cache(db::COL_EXTRA, &mut *pending_hashes, new_hashes, CacheUpdatePolicy::Overwrite);
}

/// Inserts the header into backing cache database.
/// Expects the header to be valid and already verified.
/// If the header is already known, does nothing.
Expand Down
11 changes: 10 additions & 1 deletion core/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use cstate::{
};
use ctimer::{TimeoutHandler, TimerApi, TimerScheduleError, TimerToken};
use ctypes::transaction::{AssetTransferInput, PartialHashing, ShardTransaction};
use ctypes::{BlockHash, BlockNumber, CommonParams, ShardId, Tracker, TxHash};
use ctypes::{BlockHash, BlockNumber, CommonParams, Header, ShardId, Tracker, TxHash};
use cvm::{decode, execute, ChainTimeInfo, ScriptResult, VMConfig};
use hashdb::AsHashDB;
use journaldb;
Expand Down Expand Up @@ -664,6 +664,15 @@ impl ImportBlock for Client {
Ok(self.importer.header_queue.import(unverified)?)
}

fn import_bootstrap_header(&self, header: &Header) -> Result<BlockHash, BlockImportError> {
if self.block_chain().is_known_header(&header.hash()) {
return Err(BlockImportError::Import(ImportError::AlreadyInChain))
}
let import_lock = self.importer.import_lock.lock();
self.importer.import_bootstrap_header(header, self, &import_lock);
Ok(header.hash())
}

fn import_sealed_block(&self, block: &SealedBlock) -> ImportResult {
let h = block.header().hash();
let start = Instant::now();
Expand Down
20 changes: 19 additions & 1 deletion core/src/client/importer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,13 @@ impl Importer {
}

{
let headers: Vec<&Header> = blocks.iter().map(|block| &block.header).collect();
let headers: Vec<_> = blocks.iter().map(|block| &block.header).collect();
self.import_headers(headers, client, &import_lock);
}

let start = Instant::now();

// NOTE: There are no situation importing "trusted block"s.
for block in blocks {
let header = &block.header;
ctrace!(CLIENT, "Importing block {}", header.number());
Expand Down Expand Up @@ -370,6 +371,23 @@ impl Importer {
imported.len()
}

pub fn import_bootstrap_header<'a>(&'a self, header: &'a Header, client: &Client, _importer_lock: &MutexGuard<()>) {
let hash = header.hash();
ctrace!(CLIENT, "Importing bootstrap header {}-{:?}", header.number(), hash);

{
let chain = client.block_chain();
let mut batch = DBTransaction::new();
chain.insert_bootstrap_header(&mut batch, &HeaderView::new(&header.rlp_bytes()));
client.db().write_buffered(batch);
chain.commit();
}

client.new_headers(&[hash], &[], &[hash], &[], &[], 0, Some(hash));

client.db().flush().expect("DB flush failed.");
}

fn check_header(&self, header: &Header, parent: &Header) -> bool {
// FIXME: self.verifier.verify_block_family
if let Err(e) = self.engine.verify_block_family(&header, &parent) {
Expand Down
6 changes: 5 additions & 1 deletion core/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use cmerkle::Result as TrieResult;
use cnetwork::NodeId;
use cstate::{AssetScheme, FindActionHandler, OwnedAsset, StateResult, Text, TopLevelState, TopStateView};
use ctypes::transaction::{AssetTransferInput, PartialHashing, ShardTransaction};
use ctypes::{BlockHash, BlockNumber, CommonParams, ShardId, Tracker, TxHash};
use ctypes::{BlockHash, BlockNumber, CommonParams, Header, ShardId, Tracker, TxHash};
use cvm::ChainTimeInfo;
use kvdb::KeyValueDB;
use primitives::{Bytes, H160, H256, U256};
Expand Down Expand Up @@ -200,6 +200,10 @@ pub trait ImportBlock {
/// Import a header into the blockchain
fn import_header(&self, bytes: Bytes) -> Result<BlockHash, BlockImportError>;

/// Import a trusted bootstrap header into the blockchain
/// Bootstrap headers don't execute any verifications
fn import_bootstrap_header(&self, bytes: &Header) -> Result<BlockHash, BlockImportError>;

/// Import sealed block. Skips all verifications.
fn import_sealed_block(&self, block: &SealedBlock) -> ImportResult;

Expand Down
4 changes: 4 additions & 0 deletions core/src/client/test_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,10 @@ impl ImportBlock for TestBlockChainClient {
unimplemented!()
}

fn import_bootstrap_header(&self, _header: &BlockHeader) -> Result<BlockHash, BlockImportError> {
unimplemented!()
}

fn import_sealed_block(&self, _block: &SealedBlock) -> ImportResult {
Ok(H256::default().into())
}
Expand Down
Loading