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

feat(optimistic_block): Introduce the optimistic block struct #12730

Merged
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
1 change: 1 addition & 0 deletions core/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod epoch_sync;
pub mod errors;
pub mod merkle;
pub mod network;
pub mod optimistic_block;
pub mod profile_data_v2;
pub mod profile_data_v3;
pub mod rand;
Expand Down
80 changes: 80 additions & 0 deletions core/primitives/src/optimistic_block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use borsh::{BorshDeserialize, BorshSerialize};
use near_crypto::Signature;
use near_schema_checker_lib::ProtocolSchema;

use crate::block::BlockHeader;
use crate::hash::{hash, CryptoHash};
use crate::types::{BlockHeight, SignatureDifferentiator};

#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq, ProtocolSchema)]
pub struct OptimisticBlockInner {
pub prev_block_hash: CryptoHash,
pub block_height: BlockHeight,
pub block_timestamp: u64,
// Data to confirm the correctness of randomness beacon output
pub random_value: CryptoHash,
pub vrf_value: near_crypto::vrf::Value,
pub vrf_proof: near_crypto::vrf::Proof,
signature_differentiator: SignatureDifferentiator,
}

/// An optimistic block is independent of specific chunks and can be generated
/// and distributed immediately after the previous block is processed.
/// This block is shared with the validators and used to optimistically process
/// chunks before they get included in the block.
#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq, ProtocolSchema)]
#[borsh(init=init)]
pub struct OptimisticBlock {
pub inner: OptimisticBlockInner,
/// Signature of the block producer.
pub signature: Signature,
#[borsh(skip)]
pub hash: CryptoHash,
VanBarbascu marked this conversation as resolved.
Show resolved Hide resolved
}

impl OptimisticBlock {
#[cfg(feature = "clock")]
pub fn produce(
prev_block_header: &BlockHeader,
height: BlockHeight,
signer: &crate::validator_signer::ValidatorSigner,
clock: near_time::Clock,
sandbox_delta_time: Option<near_time::Duration>,
) -> Self {
let prev_block_hash = *prev_block_header.hash();
let (vrf_value, vrf_proof) =
signer.compute_vrf_with_proof(prev_block_header.random_value().as_ref());
let random_value = hash(vrf_value.0.as_ref());

let now = clock.now_utc().unix_timestamp_nanos() as u64;
#[cfg(feature = "sandbox")]
let now = now + sandbox_delta_time.unwrap().whole_nanoseconds() as u64;
#[cfg(not(feature = "sandbox"))]
debug_assert!(sandbox_delta_time.is_none());
let time = if now <= prev_block_header.raw_timestamp() {
prev_block_header.raw_timestamp() + 1
} else {
now
};

let inner = OptimisticBlockInner {
prev_block_hash,
block_height: height,
block_timestamp: time,
random_value,
vrf_value,
vrf_proof,
signature_differentiator: "OptimisticBlock".to_owned(),
};

let hash = hash(&borsh::to_vec(&inner).expect("Failed to serialize"));
let signature = signer.sign_bytes(hash.as_ref());

Self { inner, signature, hash }
}

/// Recompute the hash after deserialization.
pub fn init(&mut self) {
self.hash = hash(&borsh::to_vec(&self.inner).expect("Failed to serialize"));
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use std::fmt::Debug;

use crate::sharding::{ChunkHash, ShardChunkHeader};
use crate::types::EpochId;
use crate::types::{EpochId, SignatureDifferentiator};
use crate::validator_signer::ValidatorSigner;
use borsh::{BorshDeserialize, BorshSerialize};
use near_crypto::{PublicKey, Signature};
use near_primitives_core::types::{AccountId, BlockHeight, ShardId};
use near_schema_checker_lib::ProtocolSchema;

use super::{ChunkProductionKey, SignatureDifferentiator};
use super::ChunkProductionKey;

/// The endorsement of a chunk by a chunk validator. By providing this, a
/// chunk validator has verified that the chunk state witness is correct.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ use near_primitives_core::hash::{hash, CryptoHash};
use near_primitives_core::types::{AccountId, ShardId};
use near_schema_checker_lib::ProtocolSchema;

use super::ChunkProductionKey;
#[cfg(feature = "solomon")]
use crate::reed_solomon::{ReedSolomonEncoderDeserialize, ReedSolomonEncoderSerialize};
use crate::types::SignatureDifferentiator;
use crate::{utils::compression::CompressedData, validator_signer::ValidatorSigner};

use super::{ChunkProductionKey, SignatureDifferentiator};

// Data structures for chunk producers to send accessesed contracts to chunk validators.

/// Contains contracts (as code-hashes) accessed during the application of a chunk.
Expand Down
8 changes: 0 additions & 8 deletions core/primitives/src/stateless_validation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,6 @@ pub mod state_witness;
pub mod stored_chunk_state_transition_data;
pub mod validator_assignment;

/// An arbitrary static string to make sure that this struct cannot be
/// serialized to look identical to another serialized struct. For chunk
/// production we are signing a chunk hash, so we need to make sure that
/// this signature means something different.
///
/// This is a messy workaround until we know what to do with NEP 483.
type SignatureDifferentiator = String;

/// This struct contains combination of fields that uniquely identify chunk production.
/// It means that for a given instance only one chunk could be produced.
#[derive(Debug, Hash, PartialEq, Eq, Clone, BorshSerialize, BorshDeserialize, ProtocolSchema)]
Expand Down
4 changes: 2 additions & 2 deletions core/primitives/src/stateless_validation/partial_witness.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::fmt::{Debug, Formatter};

use super::{ChunkProductionKey, SignatureDifferentiator};
use super::ChunkProductionKey;
use crate::sharding::ShardChunkHeader;
use crate::types::EpochId;
use crate::types::{EpochId, SignatureDifferentiator};
use crate::validator_signer::ValidatorSigner;
use borsh::{BorshDeserialize, BorshSerialize};
use bytesize::ByteSize;
Expand Down
4 changes: 2 additions & 2 deletions core/primitives/src/stateless_validation/state_witness.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use std::collections::HashMap;
use std::fmt::Debug;

use super::{ChunkProductionKey, SignatureDifferentiator};
use super::ChunkProductionKey;
use crate::bandwidth_scheduler::BandwidthRequests;
use crate::challenge::PartialState;
use crate::congestion_info::CongestionInfo;
#[cfg(feature = "solomon")]
use crate::reed_solomon::{ReedSolomonEncoderDeserialize, ReedSolomonEncoderSerialize};
use crate::sharding::{ChunkHash, ReceiptProof, ShardChunkHeader, ShardChunkHeaderV3};
use crate::transaction::SignedTransaction;
use crate::types::EpochId;
use crate::types::{EpochId, SignatureDifferentiator};
use crate::utils::compression::CompressedData;
use crate::validator_signer::EmptyValidatorSigner;
use borsh::{BorshDeserialize, BorshSerialize};
Expand Down
8 changes: 8 additions & 0 deletions core/primitives/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ pub use chunk_validator_stats::ChunkStats;
/// Hash used by to store state root.
pub type StateRoot = CryptoHash;

/// An arbitrary static string to make sure that this struct cannot be
/// serialized to look identical to another serialized struct. For chunk
/// production we are signing a chunk hash, so we need to make sure that
/// this signature means something different.
///
/// This is a messy workaround until we know what to do with NEP 483.
pub(crate) type SignatureDifferentiator = String;

/// Different types of finality.
#[derive(
serde::Serialize, serde::Deserialize, Default, Clone, Debug, PartialEq, Eq, arbitrary::Arbitrary,
Expand Down
2 changes: 2 additions & 0 deletions tools/protocol-schema-check/res/protocol_schema.toml
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ MethodResolveError = 1206790835
MissingTrieValueContext = 2666011379
NextEpochValidatorInfo = 3660299258
NonDelegateAction = 2970737551
OptimisticBlock = 1384126355
OptimisticBlockInner = 1534008891
ParentSplitParameters = 2945469052
PartialEdgeInfo = 1350359189
PartialEncodedChunk = 2321210648
Expand Down
Loading