use super::ChunkProductionKey;
#[cfg(feature = "solomon")]
use crate::reed_solomon::{ReedSolomonEncoderDeserialize, ReedSolomonEncoderSerialize};
use crate::sharding::{ChunkHash, ReceiptProof, ShardChunkHeader};
use crate::state::PartialState;
use crate::transaction::SignedTransaction;
use crate::types::EpochId;
use crate::utils::compression::CompressedData;
use borsh::{BorshDeserialize, BorshSerialize};
use bytesize::ByteSize;
use near_primitives_core::hash::CryptoHash;
use near_primitives_core::types::{BlockHeight, ShardId};
use near_schema_checker_lib::ProtocolSchema;
use std::collections::HashMap;
use std::fmt::Debug;
pub const MAX_UNCOMPRESSED_STATE_WITNESS_SIZE: u64 =
ByteSize::mib(if cfg!(feature = "test_features") { 512 } else { 64 }).0;
pub const STATE_WITNESS_COMPRESSION_LEVEL: i32 = 1;
pub const STATE_WITNESS_COMPRESSION_NUM_WORKERS: u32 = 4;
#[derive(
Debug,
Clone,
PartialEq,
Eq,
BorshSerialize,
BorshDeserialize,
ProtocolSchema,
derive_more::From,
derive_more::AsRef,
)]
pub struct EncodedChunkStateWitness(Box<[u8]>);
impl
CompressedData<
ChunkStateWitness,
MAX_UNCOMPRESSED_STATE_WITNESS_SIZE,
STATE_WITNESS_COMPRESSION_LEVEL,
STATE_WITNESS_COMPRESSION_NUM_WORKERS,
> for EncodedChunkStateWitness
{
}
#[cfg(feature = "solomon")]
impl ReedSolomonEncoderSerialize for EncodedChunkStateWitness {
fn serialize_single_part(&self) -> std::io::Result<Vec<u8>> {
Ok(self.0.to_vec())
}
}
#[cfg(feature = "solomon")]
impl ReedSolomonEncoderDeserialize for EncodedChunkStateWitness {
fn deserialize_single_part(data: &[u8]) -> std::io::Result<Self> {
Ok(EncodedChunkStateWitness(data.to_vec().into_boxed_slice()))
}
}
impl EncodedChunkStateWitness {
pub fn size_bytes(&self) -> usize {
self.0.len()
}
}
pub type ChunkStateWitnessSize = usize;
#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, ProtocolSchema)]
pub struct ChunkStateWitnessAck {
pub chunk_hash: ChunkHash,
}
impl ChunkStateWitnessAck {
pub fn new(witness: &ChunkStateWitness) -> Self {
Self { chunk_hash: witness.chunk_header().chunk_hash().clone() }
}
}
#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, ProtocolSchema)]
#[borsh(use_discriminant = true)]
#[repr(u8)]
pub enum ChunkStateWitness {
V2(Box<ChunkStateWitnessV2>) = 1,
}
#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, ProtocolSchema)]
pub struct ChunkStateWitnessV2 {
pub epoch_id: EpochId,
pub chunk_header: ShardChunkHeader,
pub main_state_transition: ChunkStateTransition,
pub source_receipt_proofs: HashMap<ChunkHash, ReceiptProof>,
pub applied_receipts_hash: CryptoHash,
pub transactions: Vec<SignedTransaction>,
pub implicit_transitions: Vec<ChunkStateTransition>,
pub new_transactions: Vec<SignedTransaction>,
}
impl ChunkStateWitness {
pub fn new(
epoch_id: EpochId,
chunk_header: ShardChunkHeader,
main_state_transition: ChunkStateTransition,
source_receipt_proofs: HashMap<ChunkHash, ReceiptProof>,
applied_receipts_hash: CryptoHash,
transactions: Vec<SignedTransaction>,
implicit_transitions: Vec<ChunkStateTransition>,
new_transactions: Vec<SignedTransaction>,
) -> Self {
Self::V2(Box::new(ChunkStateWitnessV2 {
epoch_id,
chunk_header,
main_state_transition,
source_receipt_proofs,
applied_receipts_hash,
transactions,
implicit_transitions,
new_transactions,
}))
}
pub fn new_dummy(height: BlockHeight, shard_id: ShardId, prev_block_hash: CryptoHash) -> Self {
let header = ShardChunkHeader::new_dummy(height, shard_id, prev_block_hash);
Self::new(
EpochId::default(),
header,
Default::default(),
Default::default(),
Default::default(),
Default::default(),
Default::default(),
Default::default(),
)
}
pub fn chunk_production_key(&self) -> ChunkProductionKey {
match self {
ChunkStateWitness::V2(witness) => witness.chunk_production_key(),
}
}
pub fn epoch_id(&self) -> &EpochId {
match self {
ChunkStateWitness::V2(witness) => &witness.epoch_id,
}
}
pub fn chunk_header(&self) -> &ShardChunkHeader {
match self {
ChunkStateWitness::V2(witness) => &witness.chunk_header,
}
}
pub fn main_state_transition(&self) -> &ChunkStateTransition {
match self {
ChunkStateWitness::V2(witness) => &witness.main_state_transition,
}
}
pub fn mut_main_state_transition(&mut self) -> &mut ChunkStateTransition {
match self {
ChunkStateWitness::V2(witness) => &mut witness.main_state_transition,
}
}
pub fn source_receipt_proofs(&self) -> &HashMap<ChunkHash, ReceiptProof> {
match self {
ChunkStateWitness::V2(witness) => &witness.source_receipt_proofs,
}
}
pub fn applied_receipts_hash(&self) -> &CryptoHash {
match self {
ChunkStateWitness::V2(witness) => &witness.applied_receipts_hash,
}
}
pub fn transactions(&self) -> &Vec<SignedTransaction> {
match self {
ChunkStateWitness::V2(witness) => &witness.transactions,
}
}
pub fn implicit_transitions(&self) -> &Vec<ChunkStateTransition> {
match self {
ChunkStateWitness::V2(witness) => &witness.implicit_transitions,
}
}
pub fn new_transactions(&self) -> &Vec<SignedTransaction> {
match self {
ChunkStateWitness::V2(witness) => &witness.new_transactions,
}
}
}
impl ChunkStateWitnessV2 {
pub fn chunk_production_key(&self) -> ChunkProductionKey {
ChunkProductionKey {
shard_id: self.chunk_header.shard_id(),
epoch_id: self.epoch_id,
height_created: self.chunk_header.height_created(),
}
}
}
#[derive(
Debug, Default, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, ProtocolSchema,
)]
pub struct ChunkStateTransition {
pub block_hash: CryptoHash,
pub base_state: PartialState,
pub post_state_root: CryptoHash,
}