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

refactor: remove chunk header signature verification from epoch manager #12462

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 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
9 changes: 5 additions & 4 deletions chain/chain/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::rayon_spawner::RayonAsyncComputationSpawner;
use crate::resharding::manager::ReshardingManager;
use crate::resharding::types::ReshardingSender;
use crate::sharding::shuffle_receipt_proofs;
use crate::signature_verification::verify_chunk_header_signature_with_epoch_manager;
use crate::state_request_tracker::StateRequestTracker;
use crate::state_snapshot_actor::SnapshotCallbacks;
use crate::stateless_validation::chunk_endorsement::{
Expand Down Expand Up @@ -881,10 +882,10 @@ impl Chain {
if chunk_header.shard_id() != shard_id {
return Err(Error::InvalidShardId(chunk_header.shard_id()));
}
if !epoch_manager.verify_chunk_header_signature(
&chunk_header.clone(),
block.header().epoch_id(),
block.header().prev_hash(),
if !verify_chunk_header_signature_with_epoch_manager(
epoch_manager,
&chunk_header,
&block.header().prev_hash(),
)? {
byzantine_assert!(false);
return Err(Error::InvalidChunk(format!(
Expand Down
1 change: 1 addition & 0 deletions chain/chain/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub mod missing_chunks;
pub mod orphan;
pub mod resharding;
pub mod runtime;
pub mod signature_verification;
mod state_request_tracker;
pub mod state_snapshot_actor;
mod state_sync;
Expand Down
48 changes: 48 additions & 0 deletions chain/chain/src/signature_verification.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use near_chain_primitives::Error;
use near_crypto::Signature;
use near_epoch_manager::EpochManagerAdapter;
use near_primitives::{
epoch_block_info::BlockInfo,
hash::CryptoHash,
sharding::{ChunkHash, ShardChunkHeader},
stateless_validation::ChunkProductionKey,
types::validator_stake::ValidatorStake,
};
use std::sync::Arc;

/// Verify chunk header signature.
/// return false if the header signature does not match the key for the assigned chunk producer
/// for this chunk, or if the chunk producer has been slashed
/// return `EpochError::NotAValidator` if cannot find chunk producer info for this chunk
pub fn verify_chunk_header_signature(
chunk_hash: &ChunkHash,
signature: &Signature,
chunk_producer: ValidatorStake,
block_info: Arc<BlockInfo>,
) -> Result<bool, Error> {
if block_info.slashed().contains_key(chunk_producer.account_id()) {
return Ok(false);
}
Ok(signature.verify(chunk_hash.as_ref(), chunk_producer.public_key()))
}

pub fn verify_chunk_header_signature_with_epoch_manager(
epoch_manager: &dyn EpochManagerAdapter,
chunk_header: &ShardChunkHeader,
parent_hash: &CryptoHash,
stedfn marked this conversation as resolved.
Show resolved Hide resolved
) -> Result<bool, Error> {
let epoch_id = epoch_manager.get_epoch_id_from_prev_block(parent_hash)?;
let key = ChunkProductionKey {
epoch_id,
height_created: chunk_header.height_created(),
shard_id: chunk_header.shard_id(),
};
let chunk_producer = epoch_manager.get_chunk_producer_info(&key)?;
let block_info = epoch_manager.get_block_info(&parent_hash)?;
verify_chunk_header_signature(
&chunk_header.chunk_hash(),
chunk_header.signature(),
chunk_producer,
block_info,
)
}
13 changes: 0 additions & 13 deletions chain/chain/src/test_utils/kv_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ use near_primitives::hash::{hash, CryptoHash};
use near_primitives::receipt::{ActionReceipt, Receipt, ReceiptEnum, ReceiptV0};
use near_primitives::shard_layout;
use near_primitives::shard_layout::{ShardLayout, ShardUId};
use near_primitives::sharding::ChunkHash;
use near_primitives::state_part::PartId;
use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsement;
use near_primitives::stateless_validation::contract_distribution::{
Expand Down Expand Up @@ -923,18 +922,6 @@ impl EpochManagerAdapter for MockEpochManager {
Ok(header.verify_block_producer(validator_stake.public_key()))
}

fn verify_chunk_signature_with_header_parts(
&self,
_chunk_hash: &ChunkHash,
_signature: &Signature,
_epoch_id: &EpochId,
_last_kown_hash: &CryptoHash,
_height_created: BlockHeight,
_shard_id: ShardId,
) -> Result<bool, Error> {
Ok(true)
}

fn verify_chunk_endorsement_signature(
&self,
_endorsement: &ChunkEndorsement,
Expand Down
10 changes: 6 additions & 4 deletions chain/chain/src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use near_primitives::transaction::SignedTransaction;
use near_primitives::types::chunk_extra::ChunkExtra;
use near_primitives::types::{AccountId, BlockHeight, EpochId, Nonce};

use crate::signature_verification::verify_chunk_header_signature_with_epoch_manager;
use crate::types::RuntimeAdapter;
use crate::{byzantine_assert, Chain};
use crate::{ChainStore, Error};
Expand Down Expand Up @@ -294,12 +295,13 @@ fn validate_chunk_authorship(
epoch_manager: &dyn EpochManagerAdapter,
chunk_header: &ShardChunkHeader,
) -> Result<AccountId, Error> {
let epoch_id = epoch_manager.get_epoch_id_from_prev_block(&chunk_header.prev_block_hash())?;
if epoch_manager.verify_chunk_header_signature(
if verify_chunk_header_signature_with_epoch_manager(
epoch_manager,
chunk_header,
&epoch_id,
&chunk_header.prev_block_hash(),
chunk_header.prev_block_hash(),
)? {
let epoch_id =
epoch_manager.get_epoch_id_from_prev_block(&chunk_header.prev_block_hash())?;
let chunk_producer = epoch_manager
.get_chunk_producer_info(&ChunkProductionKey {
epoch_id,
Expand Down
25 changes: 19 additions & 6 deletions chain/chunks/src/shards_manager_actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ use near_async::time::Duration;
use near_async::time::{self, Clock};
use near_chain::byzantine_assert;
use near_chain::near_chain_primitives::error::Error::DBNotFoundErr;
use near_chain::signature_verification::{
verify_chunk_header_signature, verify_chunk_header_signature_with_epoch_manager,
};
use near_chain::types::EpochManagerAdapter;
use near_chain_configs::MutableValidatorSigner;
pub use near_chunks_primitives::Error;
Expand Down Expand Up @@ -1219,13 +1222,19 @@ impl ShardsManagerActor {

// check signature
let epoch_id = self.epoch_manager.get_epoch_id_from_prev_block(&forward.prev_block_hash)?;
let valid_signature = self.epoch_manager.verify_chunk_signature_with_header_parts(
let key = ChunkProductionKey {
epoch_id,
height_created: forward.height_created,
shard_id: forward.shard_id,
};
let chunk_producer = self.epoch_manager.get_chunk_producer_info(&key)?;
let block_info = self.epoch_manager.get_block_info(&forward.prev_block_hash)?;

let valid_signature = verify_chunk_header_signature(
&forward.chunk_hash,
&forward.signature,
&epoch_id,
&forward.prev_block_hash,
forward.height_created,
forward.shard_id,
chunk_producer,
block_info,
)?;

if !valid_signature {
Expand Down Expand Up @@ -1385,7 +1394,11 @@ impl ShardsManagerActor {
}
};

if !self.epoch_manager.verify_chunk_header_signature(header, &epoch_id, &ancestor_hash)? {
if !verify_chunk_header_signature_with_epoch_manager(
self.epoch_manager.as_ref(),
&header,
&ancestor_hash,
)? {
return if epoch_id_confirmed {
byzantine_assert!(false);
Err(Error::InvalidChunkSignature)
Expand Down
54 changes: 0 additions & 54 deletions chain/epoch-manager/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use near_primitives::epoch_manager::{EpochConfig, ShardConfig};
use near_primitives::errors::EpochError;
use near_primitives::hash::CryptoHash;
use near_primitives::shard_layout::{account_id_to_shard_id, ShardLayout};
use near_primitives::sharding::{ChunkHash, ShardChunkHeader};
use near_primitives::stateless_validation::chunk_endorsement::ChunkEndorsement;
use near_primitives::stateless_validation::contract_distribution::{
ChunkContractAccesses, ContractCodeRequest,
Expand Down Expand Up @@ -358,39 +357,6 @@ pub trait EpochManagerAdapter: Send + Sync {
/// Verify header signature.
fn verify_header_signature(&self, header: &BlockHeader) -> Result<bool, Error>;

/// Verify chunk header signature.
/// return false if the header signature does not match the key for the assigned chunk producer
/// for this chunk, or if the chunk producer has been slashed
/// return `EpochError::NotAValidator` if cannot find chunk producer info for this chunk
/// `header`: chunk header
/// `epoch_id`: epoch_id that the chunk header belongs to
/// `last_known_hash`: used to determine the list of chunk producers that are slashed
fn verify_chunk_header_signature(
&self,
header: &ShardChunkHeader,
epoch_id: &EpochId,
last_known_hash: &CryptoHash,
) -> Result<bool, Error> {
self.verify_chunk_signature_with_header_parts(
&header.chunk_hash(),
header.signature(),
epoch_id,
last_known_hash,
header.height_created(),
header.shard_id(),
)
}

fn verify_chunk_signature_with_header_parts(
&self,
chunk_hash: &ChunkHash,
signature: &Signature,
epoch_id: &EpochId,
last_known_hash: &CryptoHash,
height_created: BlockHeight,
shard_id: ShardId,
) -> Result<bool, Error>;

fn verify_chunk_endorsement_signature(
&self,
endorsement: &ChunkEndorsement,
Expand Down Expand Up @@ -913,26 +879,6 @@ impl EpochManagerAdapter for EpochManagerHandle {
}
}

fn verify_chunk_signature_with_header_parts(
&self,
chunk_hash: &ChunkHash,
signature: &Signature,
epoch_id: &EpochId,
last_known_hash: &CryptoHash,
height_created: BlockHeight,
shard_id: ShardId,
) -> Result<bool, Error> {
let epoch_manager = self.read();
let key =
ChunkProductionKey { epoch_id: *epoch_id, height_created: height_created, shard_id };
let chunk_producer = epoch_manager.get_chunk_producer_info(&key)?;
let block_info = epoch_manager.get_block_info(last_known_hash)?;
if block_info.slashed().contains_key(chunk_producer.account_id()) {
return Ok(false);
}
Ok(signature.verify(chunk_hash.as_ref(), chunk_producer.public_key()))
}

fn verify_chunk_endorsement_signature(
&self,
endorsement: &ChunkEndorsement,
Expand Down
Loading