Skip to content

Commit

Permalink
[stateless_validation] Introduce versioned BlockBody (#10411)
Browse files Browse the repository at this point in the history
This PR introduces versioned BlockBody struct which would be a part of
BlockV4. Note that this isn't being used with the current protocol
version.

Eventually with stateless validation, we are going to have chunk
endorsements as part of the BlockBody, the structure of which would look
something like this or equivalent (still undecided if we need
`Vec<Vec<ChunkEndorsement>>` or `Vec<ChunkEndorsement>`)

```
pub struct BlockBodyV2 {
    pub chunks: Vec<ShardChunkHeader>,
    pub challenges: Challenges,

    // Data to confirm the correctness of randomness beacon output
    pub vrf_value: Value,
    pub vrf_proof: Proof,
    
    // Chunk Endorsements
    pub chunk_endorsements: Vec<ChunkEndorsement>,
}
```
  • Loading branch information
Shreyan Gupta authored Jan 12, 2024
1 parent ac967f6 commit 12bfdda
Show file tree
Hide file tree
Showing 7 changed files with 222 additions and 70 deletions.
2 changes: 1 addition & 1 deletion chain/client/src/tests/process_blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ fn test_bad_block_content_vrf() {
env.process_block(0, prev_block, Provenance::PRODUCED);
let block = env.clients[0].produce_block(2).unwrap().unwrap();
let mut bad_block = block.clone();
bad_block.get_mut().body.vrf_value = Value([0u8; 32]);
bad_block.set_vrf_value(Value([0u8; 32]));

let err = env.clients[0]
.receive_block_impl(
Expand Down
88 changes: 48 additions & 40 deletions core/primitives/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::block::BlockValidityError::{
InvalidChallengeRoot, InvalidChunkHeaderRoot, InvalidChunkMask, InvalidReceiptRoot,
InvalidStateRoot, InvalidTransactionRoot,
};
use crate::block_body::{BlockBody, BlockBodyV1};
pub use crate::block_header::*;
use crate::challenge::{Challenges, ChallengesResult};
use crate::checked_feature;
Expand Down Expand Up @@ -65,21 +66,18 @@ pub struct BlockV2 {
pub vrf_proof: near_crypto::vrf::Proof,
}

/// V2 -> V3: added BlockBody
/// V2 -> V3: added BlockBodyV1
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, Eq, PartialEq)]
pub struct BlockV3 {
pub header: BlockHeader,
pub body: BlockBody,
pub body: BlockBodyV1,
}

/// V3 -> V4: use versioned BlockBody
#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, Eq, PartialEq)]
pub struct BlockBody {
pub chunks: Vec<ShardChunkHeader>,
pub challenges: Challenges,

// Data to confirm the correctness of randomness beacon output
pub vrf_value: near_crypto::vrf::Value,
pub vrf_proof: near_crypto::vrf::Proof,
pub struct BlockV4 {
pub header: BlockHeader,
pub body: BlockBody,
}

/// Versioned Block data structure.
Expand All @@ -89,6 +87,7 @@ pub enum Block {
BlockV1(Arc<BlockV1>),
BlockV2(Arc<BlockV2>),
BlockV3(Arc<BlockV3>),
BlockV4(Arc<BlockV4>),
}

pub fn genesis_chunks(
Expand Down Expand Up @@ -145,8 +144,9 @@ impl Block {
) -> Block {
if next_epoch_protocol_version < SHARD_CHUNK_HEADER_UPGRADE_VERSION {
let legacy_chunks = body
.chunks
.into_iter()
.chunks()
.iter()
.cloned()
.map(|chunk| match chunk {
ShardChunkHeader::V1(header) => header,
ShardChunkHeader::V2(_) => panic!(
Expand All @@ -161,20 +161,24 @@ impl Block {
Block::BlockV1(Arc::new(BlockV1 {
header,
chunks: legacy_chunks,
challenges: body.challenges,
vrf_value: body.vrf_value,
vrf_proof: body.vrf_proof,
challenges: body.challenges().to_vec(),
vrf_value: *body.vrf_value(),
vrf_proof: *body.vrf_proof(),
}))
} else if !checked_feature!("stable", BlockHeaderV4, this_epoch_protocol_version) {
Block::BlockV2(Arc::new(BlockV2 {
header,
chunks: body.chunks,
challenges: body.challenges,
vrf_value: body.vrf_value,
vrf_proof: body.vrf_proof,
chunks: body.chunks().to_vec(),
challenges: body.challenges().to_vec(),
vrf_value: *body.vrf_value(),
vrf_proof: *body.vrf_proof(),
}))
} else if !checked_feature!("stable", ChunkValidation, this_epoch_protocol_version) {
match body {
BlockBody::V1(body) => Block::BlockV3(Arc::new(BlockV3 { header, body })),
}
} else {
Block::BlockV3(Arc::new(BlockV3 { header, body }))
Block::BlockV4(Arc::new(BlockV4 { header, body }))
}
}

Expand All @@ -194,17 +198,18 @@ impl Block {
}
let vrf_value = near_crypto::vrf::Value([0; 32]);
let vrf_proof = near_crypto::vrf::Proof([0; 64]);
let body = BlockBody { chunks, challenges, vrf_value, vrf_proof };
let body =
BlockBody::new(genesis_protocol_version, chunks, challenges, vrf_value, vrf_proof);
let header = BlockHeader::genesis(
genesis_protocol_version,
height,
Block::compute_state_root(&body.chunks),
Block::compute_block_body_hash_impl(&body),
Block::compute_chunk_prev_outgoing_receipts_root(&body.chunks),
Block::compute_chunk_headers_root(&body.chunks).0,
Block::compute_chunk_tx_root(&body.chunks),
body.chunks.len() as u64,
Block::compute_challenges_root(&body.challenges),
Block::compute_state_root(body.chunks()),
body.compute_hash(),
Block::compute_chunk_prev_outgoing_receipts_root(body.chunks()),
Block::compute_chunk_headers_root(body.chunks()).0,
Block::compute_chunk_tx_root(body.chunks()),
body.chunks().len() as u64,
Block::compute_challenges_root(body.challenges()),
timestamp,
initial_gas_price,
initial_total_supply,
Expand Down Expand Up @@ -297,20 +302,21 @@ impl Block {
}
};

let body = BlockBody { chunks, challenges, vrf_value, vrf_proof };
let body =
BlockBody::new(this_epoch_protocol_version, chunks, challenges, vrf_value, vrf_proof);
let header = BlockHeader::new(
this_epoch_protocol_version,
next_epoch_protocol_version,
height,
*prev.hash(),
Block::compute_block_body_hash_impl(&body),
Block::compute_state_root(&body.chunks),
Block::compute_chunk_prev_outgoing_receipts_root(&body.chunks),
Block::compute_chunk_headers_root(&body.chunks).0,
Block::compute_chunk_tx_root(&body.chunks),
Block::compute_outcome_root(&body.chunks),
body.compute_hash(),
Block::compute_state_root(body.chunks()),
Block::compute_chunk_prev_outgoing_receipts_root(body.chunks()),
Block::compute_chunk_headers_root(body.chunks()).0,
Block::compute_chunk_tx_root(body.chunks()),
Block::compute_outcome_root(body.chunks()),
time,
Block::compute_challenges_root(&body.challenges),
Block::compute_challenges_root(body.challenges()),
random_value,
prev_validator_proposals,
chunk_mask,
Expand Down Expand Up @@ -417,10 +423,6 @@ impl Block {
.0
}

pub fn compute_block_body_hash_impl(body: &BlockBody) -> CryptoHash {
CryptoHash::hash_borsh(body)
}

pub fn compute_chunk_prev_outgoing_receipts_root<
'a,
T: IntoIterator<Item = &'a ShardChunkHeader>,
Expand Down Expand Up @@ -510,6 +512,7 @@ impl Block {
Block::BlockV1(block) => &block.header,
Block::BlockV2(block) => &block.header,
Block::BlockV3(block) => &block.header,
Block::BlockV4(block) => &block.header,
}
}

Expand All @@ -520,6 +523,7 @@ impl Block {
),
Block::BlockV2(block) => ChunksCollection::V2(&block.chunks),
Block::BlockV3(block) => ChunksCollection::V2(&block.body.chunks),
Block::BlockV4(block) => ChunksCollection::V2(&block.body.chunks()),
}
}

Expand All @@ -529,6 +533,7 @@ impl Block {
Block::BlockV1(block) => &block.challenges,
Block::BlockV2(block) => &block.challenges,
Block::BlockV3(block) => &block.body.challenges,
Block::BlockV4(block) => block.body.challenges(),
}
}

Expand All @@ -538,6 +543,7 @@ impl Block {
Block::BlockV1(block) => &block.vrf_value,
Block::BlockV2(block) => &block.vrf_value,
Block::BlockV3(block) => &block.body.vrf_value,
Block::BlockV4(block) => &block.body.vrf_value(),
}
}

Expand All @@ -547,6 +553,7 @@ impl Block {
Block::BlockV1(block) => &block.vrf_proof,
Block::BlockV2(block) => &block.vrf_proof,
Block::BlockV3(block) => &block.body.vrf_proof,
Block::BlockV4(block) => &block.body.vrf_proof(),
}
}

Expand All @@ -558,7 +565,8 @@ impl Block {
match self {
Block::BlockV1(_) => None,
Block::BlockV2(_) => None,
Block::BlockV3(block) => Some(Self::compute_block_body_hash_impl(&block.body)),
Block::BlockV3(block) => Some(block.body.compute_hash()),
Block::BlockV4(block) => Some(block.body.compute_hash()),
}
}

Expand Down
77 changes: 77 additions & 0 deletions core/primitives/src/block_body.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use borsh::{BorshDeserialize, BorshSerialize};
use near_crypto::vrf::{Proof, Value};
use near_primitives_core::hash::CryptoHash;
use near_primitives_core::types::ProtocolVersion;

use crate::challenge::Challenges;
use crate::sharding::ShardChunkHeader;

#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, Eq, PartialEq)]
pub struct BlockBodyV1 {
pub chunks: Vec<ShardChunkHeader>,
pub challenges: Challenges,

// Data to confirm the correctness of randomness beacon output
pub vrf_value: Value,
pub vrf_proof: Proof,
}

impl BlockBodyV1 {
pub fn compute_hash(&self) -> CryptoHash {
CryptoHash::hash_borsh(self)
}
}

// For now, we only have one version of block body.
// Eventually with ChunkValidation, we would include ChunkEndorsement in BlockBodyV2
#[derive(BorshSerialize, BorshDeserialize, Clone, PartialEq, Eq, Debug)]
pub enum BlockBody {
V1(BlockBodyV1),
}

impl BlockBody {
pub fn new(
_protocol_version: ProtocolVersion,
chunks: Vec<ShardChunkHeader>,
challenges: Challenges,
vrf_value: Value,
vrf_proof: Proof,
) -> Self {
// Eventually we will have different versions of block body, but for now we only have V1.
BlockBody::V1(BlockBodyV1 { chunks, challenges, vrf_value, vrf_proof })
}

#[inline]
pub fn chunks(&self) -> &[ShardChunkHeader] {
match self {
BlockBody::V1(body) => &body.chunks,
}
}

#[inline]
pub fn challenges(&self) -> &Challenges {
match self {
BlockBody::V1(body) => &body.challenges,
}
}

#[inline]
pub fn vrf_value(&self) -> &Value {
match self {
BlockBody::V1(body) => &body.vrf_value,
}
}

#[inline]
pub fn vrf_proof(&self) -> &Proof {
match self {
BlockBody::V1(body) => &body.vrf_proof,
}
}

pub fn compute_hash(&self) -> CryptoHash {
match self {
BlockBody::V1(body) => body.compute_hash(),
}
}
}
1 change: 1 addition & 0 deletions core/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub use near_primitives_core::serialize;

pub mod action;
pub mod block;
pub mod block_body;
pub mod block_header;
pub mod challenge;
pub mod chunk_validation;
Expand Down
Loading

0 comments on commit 12bfdda

Please sign in to comment.