Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chunks + Validators #1118

Merged
merged 12 commits into from
Jul 31, 2019
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
82 changes: 6 additions & 76 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@ Checkout the [Running Locally](https://docs.nearprotocol.com/running-a-node#runn

## Developing

Checkout the [Developing NEARCore](https://docs.nearprotocol.com/contribution/nearcore) section of documentation. You can see the most recently pushed code running at [neartest.com](https://neartest.com). Disclaimer: *Do not publish critical contracts on neartest.com.* This has a very high likelihood of being broken.
Checkout the [Developing NEARCore](https://docs.nearprotocol.com/contribution/nearcore) section of documentation.

83 changes: 58 additions & 25 deletions chain/chain/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ use chrono::Duration;
use log::{debug, info};

use near_primitives::hash::CryptoHash;
use near_primitives::sharding::{ChunkHash, ShardChunk, ShardChunkHeader};
use near_primitives::transaction::{ReceiptTransaction, TransactionResult};
use near_primitives::types::{AccountId, BlockIndex, MerkleHash, ShardId};
use near_primitives::types::{AccountId, BlockIndex, GasUsage, ShardId};
use near_store::Store;

use crate::error::{Error, ErrorKind};
use crate::store::{ChainStore, ChainStoreAccess, ChainStoreUpdate, StateSyncInfo};
use crate::store::{ChainStore, ChainStoreAccess, ChainStoreUpdate, ChunkExtra, StateSyncInfo};
use crate::types::{
Block, BlockHeader, BlockStatus, Provenance, RuntimeAdapter, ShardFullChunkOrOnePart, Tip,
};
use near_primitives::sharding::{ChunkHash, ShardChunk, ShardChunkHeader};

/// Maximum number of orphans chain can store.
pub const MAX_ORPHAN_SIZE: usize = 1024;
Expand Down Expand Up @@ -104,6 +104,19 @@ impl OrphanBlockPool {
}
}

/// Chain genesis configuration.
#[derive(Clone)]
pub struct ChainGenesis {
pub time: DateTime<Utc>,
pub gas_limit: GasUsage,
}

impl ChainGenesis {
pub fn new(time: DateTime<Utc>, gas_limit: GasUsage) -> Self {
Self { time, gas_limit }
}
}

/// Facade to the blockchain block processing and storage.
/// Provides current view on the state according to the chain state.
pub struct Chain {
Expand All @@ -118,14 +131,18 @@ impl Chain {
pub fn new(
store: Arc<Store>,
runtime_adapter: Arc<dyn RuntimeAdapter>,
genesis_time: DateTime<Utc>,
chain_genesis: ChainGenesis,
) -> Result<Chain, Error> {
let mut store = ChainStore::new(store);

// Get runtime initial state and create genesis block out of it.
let (state_store_update, state_roots) = runtime_adapter.genesis_state();
let genesis =
Block::genesis(state_roots.clone(), genesis_time, runtime_adapter.num_shards());
let genesis = Block::genesis(
state_roots.clone(),
chain_genesis.time,
runtime_adapter.num_shards(),
chain_genesis.gas_limit,
);

// Check if we have a head in the store, otherwise pick genesis block.
let mut store_update = store.store_update();
Expand Down Expand Up @@ -174,7 +191,10 @@ impl Chain {

for (chunk_header, state_root) in genesis.chunks.iter().zip(state_roots.iter())
{
store_update.save_post_state_root(&chunk_header.chunk_hash(), state_root);
store_update.save_chunk_extra(
&chunk_header.chunk_hash(),
ChunkExtra::new(state_root, vec![], 0, chain_genesis.gas_limit),
);
}

head = Tip::from_header(&genesis.header);
Expand Down Expand Up @@ -815,10 +835,18 @@ impl Chain {
self.store.block_exists(hash)
}

/// Get state root hash after applying header with given hash.
/// Get chunk extra that was computed after applying chunk with given hash.
#[inline]
pub fn get_chunk_extra(&mut self, hash: &ChunkHash) -> Result<&ChunkExtra, Error> {
self.store.get_chunk_extra(hash)
}

/// Helper to return latest chunk extra for given shard.
#[inline]
pub fn get_post_state_root(&mut self, hash: &ChunkHash) -> Result<&MerkleHash, Error> {
self.store.get_post_state_root(hash)
pub fn get_latest_chunk_extra(&mut self, shard_id: ShardId) -> Result<&ChunkExtra, Error> {
let chunk_hash =
self.get_block(&self.head()?.last_block_hash)?.chunks[shard_id as usize].chunk_hash();
self.store.get_chunk_extra(&chunk_hash)
}

/// Get transaction result for given hash of transaction.
Expand Down Expand Up @@ -1001,6 +1029,7 @@ impl<'a> ChainUpdate<'a> {
let receipt_hashes = receipts.iter().map(|r| r.get_hash()).collect::<Vec<_>>();
let transaction_hashes =
chunk.transactions.iter().map(|t| t.get_hash()).collect::<Vec<_>>();
let gas_limit = chunk.header.gas_limit;

// Apply block to runtime.
let (
Expand All @@ -1022,20 +1051,14 @@ impl<'a> ChainUpdate<'a> {
)
.map_err(|e| ErrorKind::Other(e.to_string()))?;

// If block checks out, record validator proposals for given block.
self.runtime_adapter
.add_validator_proposals(
block.header.prev_hash,
block.hash(),
block.header.height,
validator_proposals,
vec![],
)
.map_err(|err| ErrorKind::Other(err.to_string()))?;

self.chain_store_update.save_trie_changes(trie_changes);
// Save state root after applying transactions.
self.chain_store_update.save_post_state_root(&chunk_hash, &state_root);
// XXX: gas used return.
let gas_used = 0;
self.chain_store_update.save_chunk_extra(
&chunk_hash,
ChunkExtra::new(&state_root, validator_proposals, gas_used, gas_limit),
);
// Save resulting receipts.
for (_receipt_shard_id, receipts) in new_receipts.drain() {
// The receipts in store are indexed by the SOURCE shard_id, not destination,
Expand Down Expand Up @@ -1163,11 +1186,10 @@ impl<'a> ChainUpdate<'a> {
} else {
if prev_chunk_header != chunk_header {
info!(
"MOO {:?} != {:?}, DEF: {}, GEN: {}",
"MOO {:?} != {:?}, DEF: {}",
prev_chunk_header,
chunk_header,
CryptoHash::default(),
Block::chunk_genesis_hash()
);
return Err(ErrorKind::InvalidChunk.into());
}
Expand All @@ -1185,6 +1207,17 @@ impl<'a> ChainUpdate<'a> {
self.chain_store_update.add_block_to_catchup(prev_hash, block.hash());
}

// If block checks out, record validator proposals for given block.
self.runtime_adapter
.add_validator_proposals(
block.header.prev_hash,
block.hash(),
block.header.height,
block.header.validator_proposal.clone(),
vec![],
)
.map_err(|err| ErrorKind::Other(err.to_string()))?;

// Update the chain head if total weight has increased.
let res = self.update_head(block)?;
Ok((res, needs_to_start_fetching_state))
Expand Down Expand Up @@ -1304,7 +1337,7 @@ impl<'a> ChainUpdate<'a> {
.runtime_adapter
.get_block_proposer(header.epoch_hash, header.height)
.map_err(|e| Error::from(ErrorKind::Other(e.to_string())))?;
if self.runtime_adapter.check_validator_signature(
if self.runtime_adapter.verify_validator_signature(
&header.epoch_hash,
&validator,
header.hash().as_ref(),
Expand Down
4 changes: 4 additions & 0 deletions chain/chain/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ pub enum ErrorKind {
/// Invalid Signature
#[fail(display = "Invalid Signature")]
InvalidSignature,
/// Validator error.
#[fail(display = "Validator Error")]
ValidatorError(String),
/// IO Error.
#[fail(display = "IO Error: {}", _0)]
IOErr(String),
Expand Down Expand Up @@ -106,6 +109,7 @@ impl Error {
| ErrorKind::ChunksMissing(_)
| ErrorKind::IOErr(_)
| ErrorKind::Other(_)
| ErrorKind::ValidatorError(_)
| ErrorKind::DBNotFoundErr(_) => false,
ErrorKind::InvalidBlockPastTime(_, _)
| ErrorKind::InvalidBlockFutureTime(_)
Expand Down
Loading