Skip to content

Commit

Permalink
feat(data_structures): partially implement versioning for PoIs
Browse files Browse the repository at this point in the history
  • Loading branch information
aesedepece committed Oct 18, 2024
1 parent dc3d1b0 commit ebdb81c
Show file tree
Hide file tree
Showing 13 changed files with 262 additions and 131 deletions.
60 changes: 40 additions & 20 deletions data_structures/src/chain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ use crate::{
},
get_environment,
proto::{
versioning::{ProtocolVersion, Versioned},
versioning::{ProtocolVersion, Versioned, VersionedHashable},
ProtobufConvert,
},
staking::prelude::*,
Expand Down Expand Up @@ -756,13 +756,13 @@ pub struct BlockMerkleRoots {
}

/// Function to calculate a merkle tree from a transaction vector
pub fn merkle_tree_root<T>(transactions: &[T]) -> Hash
pub fn merkle_tree_root<T>(transactions: &[T], protocol_version: ProtocolVersion) -> Hash
where
T: Hashable,
T: VersionedHashable,
{
let transactions_hashes: Vec<Sha256> = transactions
.iter()
.map(|x| match x.hash() {
.map(|x| match x.versioned_hash(protocol_version) {
Hash::SHA256(x) => Sha256(x),
})
.collect();
Expand All @@ -773,16 +773,16 @@ where
}

impl BlockMerkleRoots {
pub fn from_transactions(txns: &BlockTransactions) -> Self {
pub fn from_transactions(txns: &BlockTransactions, protocol_version: ProtocolVersion) -> Self {
BlockMerkleRoots {
mint_hash: txns.mint.hash(),
vt_hash_merkle_root: merkle_tree_root(&txns.value_transfer_txns),
dr_hash_merkle_root: merkle_tree_root(&txns.data_request_txns),
commit_hash_merkle_root: merkle_tree_root(&txns.commit_txns),
reveal_hash_merkle_root: merkle_tree_root(&txns.reveal_txns),
tally_hash_merkle_root: merkle_tree_root(&txns.tally_txns),
stake_hash_merkle_root: merkle_tree_root(&txns.stake_txns),
unstake_hash_merkle_root: merkle_tree_root(&txns.unstake_txns),
mint_hash: txns.mint.versioned_hash(protocol_version),
vt_hash_merkle_root: merkle_tree_root(&txns.value_transfer_txns, protocol_version),
dr_hash_merkle_root: merkle_tree_root(&txns.data_request_txns, protocol_version),
commit_hash_merkle_root: merkle_tree_root(&txns.commit_txns, protocol_version),
reveal_hash_merkle_root: merkle_tree_root(&txns.reveal_txns, protocol_version),
tally_hash_merkle_root: merkle_tree_root(&txns.tally_txns, protocol_version),
stake_hash_merkle_root: merkle_tree_root(&txns.stake_txns, protocol_version),
unstake_hash_merkle_root: merkle_tree_root(&txns.unstake_txns, protocol_version),
}
}
}
Expand Down Expand Up @@ -901,13 +901,13 @@ impl SuperBlock {
&self,
blocks: &[Block],
tally_tx: &TallyTransaction,
protocol_version: ProtocolVersion,
) -> Option<TxInclusionProof> {
// Get the PoI for the block root, if the tally transaction is found on the list of blocks
// Obtain also the index of the tally root of the block containing the tally TX.
let (mut poi, tally_root_idx) = blocks
.iter()
.enumerate()
.find_map(|(idx, b)| Some((tally_tx.data_proof_of_inclusion(b)?, idx)))?;
let (mut poi, tally_root_idx) = blocks.iter().enumerate().find_map(|(idx, b)| {
Some((tally_tx.data_proof_of_inclusion(b, protocol_version)?, idx))
})?;

// Collect all tally roots from the blocks
let tally_roots = blocks
Expand Down Expand Up @@ -4726,10 +4726,11 @@ mod tests {
expected_lemma_lengths: Vec<usize>,
blocks: Vec<Block>,
tally_txs: Vec<TallyTransaction>,
protocol_version: ProtocolVersion,
) {
for index in 0..expected_indices.len() {
let result = sb
.tally_proof_of_inclusion(&blocks, &tally_txs[index])
.tally_proof_of_inclusion(&blocks, &tally_txs[index], protocol_version)
.unwrap();
assert_eq!(result.index, expected_indices[index]);
assert_eq!(result.lemma.len(), expected_lemma_lengths[index]);
Expand Down Expand Up @@ -6883,6 +6884,7 @@ mod tests {
1,
Hash::default(),
1,
ProtocolVersion::default(),
);

let expected_indices = vec![0, 2, 2];
Expand Down Expand Up @@ -6937,6 +6939,7 @@ mod tests {
1,
Hash::default(),
1,
ProtocolVersion::default(),
);

let expected_indices = vec![0, 2, 2, 8, 10, 6, 4, 6];
Expand Down Expand Up @@ -6972,6 +6975,7 @@ mod tests {
1,
Hash::default(),
1,
ProtocolVersion::default(),
);

let result = sb.dr_proof_of_inclusion(&[b1, b2], &dr_txs[2]);
Expand All @@ -6982,7 +6986,14 @@ mod tests {
fn test_dr_merkle_root_no_block() {
let dr_txs = build_test_dr_txs(3);

let sb = mining_build_superblock(&[], &[Hash::default()], 1, Hash::default(), 1);
let sb = mining_build_superblock(
&[],
&[Hash::default()],
1,
Hash::default(),
1,
ProtocolVersion::default(),
);

let result = sb.dr_proof_of_inclusion(&[], &dr_txs[2]);
assert!(result.is_none());
Expand All @@ -7008,6 +7019,7 @@ mod tests {
1,
Hash::default(),
1,
ProtocolVersion::default(),
);

let expected_indices = vec![0, 2];
Expand Down Expand Up @@ -7046,6 +7058,7 @@ mod tests {
1,
Hash::default(),
1,
ProtocolVersion::default(),
);

let expected_indices = vec![0, 2, 2];
Expand All @@ -7057,6 +7070,7 @@ mod tests {
expected_lemma_lengths,
vec![b1, b2],
tally_txs,
ProtocolVersion::default(),
);
}

Expand Down Expand Up @@ -7108,6 +7122,7 @@ mod tests {
1,
Hash::default(),
1,
ProtocolVersion::default(),
);

let expected_indices = vec![0, 2, 2, 8, 10, 6, 4, 6];
Expand All @@ -7119,12 +7134,14 @@ mod tests {
expected_lemma_lengths,
vec![b1, b2, b3],
tally_txs,
ProtocolVersion::default(),
);
}

#[test]
fn test_tally_merkle_root_none() {
let tally_txs = build_test_tally_txs(3);
let protocol_version = ProtocolVersion::default();

let mut b1 = block_example();
let mut b2 = block_example();
Expand All @@ -7143,9 +7160,10 @@ mod tests {
1,
Hash::default(),
1,
ProtocolVersion::default(),
);

let result = sb.tally_proof_of_inclusion(&[b1, b2], &tally_txs[2]);
let result = sb.tally_proof_of_inclusion(&[b1, b2], &tally_txs[2], protocol_version);
assert!(result.is_none());
}

Expand Down Expand Up @@ -7174,6 +7192,7 @@ mod tests {
1,
Hash::default(),
1,
ProtocolVersion::default(),
);

let expected_indices = vec![0, 2, 2];
Expand All @@ -7185,6 +7204,7 @@ mod tests {
expected_lemma_lengths,
vec![b1],
tally_txs,
ProtocolVersion::default(),
);
}

Expand Down
19 changes: 9 additions & 10 deletions data_structures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ use std::sync::RwLock;

use lazy_static::lazy_static;

use crate::proto::versioning::ProtocolInfo;
use crate::{
chain::{Environment, Epoch},
proto::versioning::ProtocolVersion,
proto::versioning::{ProtocolInfo, ProtocolVersion},
};

pub const DEFAULT_VALIDATOR_COUNT_FOR_TESTS: usize = 1000;
Expand Down Expand Up @@ -163,7 +162,7 @@ pub fn set_protocol_version(protocol_version: ProtocolVersion) {
/// Refresh the protocol version, i.e. derive the current version from the current epoch, and update `current_version`
/// accordingly.
pub fn refresh_protocol_version(current_epoch: Epoch) {
let current_version = get_protocol_version(Some(current_epoch));
let current_version = ProtocolVersion::from_epoch(current_epoch);
set_protocol_version(current_version)
}

Expand Down Expand Up @@ -200,7 +199,7 @@ mod tests {
// If this default changes before the transition to V2 is complete, almost everything will
// break because data structures change schema and, serialization changes and hash
// derivation breaks too
let protocol_version = get_protocol_version(None);
let protocol_version = ProtocolVersion::guess();
assert_eq!(protocol_version, ProtocolVersion::V1_7);

// Register the different protocol versions
Expand All @@ -209,23 +208,23 @@ mod tests {
register_protocol_version(ProtocolVersion::V2_0, 300, 20);

// The initial protocol version should be the default one
let version = get_protocol_version(Some(0));
let version = ProtocolVersion::from_epoch(0);
assert_eq!(version, ProtocolVersion::V1_7);

// Right after the
let version = get_protocol_version(Some(100));
let version = ProtocolVersion::from_epoch(100);
assert_eq!(version, ProtocolVersion::V1_7);
let version = get_protocol_version(Some(200));
let version = ProtocolVersion::from_epoch(200);
assert_eq!(version, ProtocolVersion::V1_8);
let version = get_protocol_version(Some(300));
let version = ProtocolVersion::from_epoch(300);
assert_eq!(version, ProtocolVersion::V2_0);

let version = get_protocol_version(None);
let version = ProtocolVersion::guess();
assert_eq!(version, ProtocolVersion::V1_7);

set_protocol_version(ProtocolVersion::V2_0);

let version = get_protocol_version(None);
let version = ProtocolVersion::guess();
assert_eq!(version, ProtocolVersion::V2_0);
}
}
4 changes: 4 additions & 0 deletions data_structures/src/proto/versioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ impl ProtocolVersion {
pub fn guess() -> Self {
get_protocol_version(None)
}

pub fn from_epoch(epoch: Epoch) -> Self {
get_protocol_version(Some(epoch))
}
}

impl PartialOrd for ProtocolVersion {
Expand Down
38 changes: 32 additions & 6 deletions data_structures/src/superblock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ impl SuperBlockState {
sync_superblock: Option<SuperBlock>,
block_epoch: Epoch,
) -> SuperBlock {
let protocol_version = ProtocolVersion::from_epoch(block_epoch);
let key_leaves = hash_key_leaves(&ars_identities.get_rep_ordered_bn256_list(alt_keys));

self.update_ars_identities(ars_identities);
Expand Down Expand Up @@ -474,6 +475,7 @@ impl SuperBlockState {
superblock_index,
last_block_in_previous_superblock,
self.signing_committee.len() as u32,
protocol_version,
)
};

Expand Down Expand Up @@ -679,6 +681,7 @@ pub fn mining_build_superblock(
index: u32,
last_block_in_previous_superblock: Hash,
signing_committee_length: u32,
protocol_version: ProtocolVersion,
) -> SuperBlock {
let last_block = block_headers.last();
match last_block {
Expand All @@ -704,7 +707,7 @@ pub fn mining_build_superblock(
)
}
Some(last_block_header) => {
let last_block_hash = last_block_header.versioned_hash(ProtocolVersion::guess());
let last_block_hash = last_block_header.versioned_hash(protocol_version);
let merkle_drs: Vec<Hash> = block_headers
.iter()
.map(|b| b.merkle_roots.dr_hash_merkle_root)
Expand All @@ -717,7 +720,13 @@ pub fn mining_build_superblock(
let ars_root = hash_merkle_tree_root(ars_ordered_hash_leaves);
let blocks: Vec<_> = block_headers
.iter()
.map(|b| format!("#{}: {}", b.beacon.checkpoint, b.hash()))
.map(|b| {
format!(
"#{}: {}",
b.beacon.checkpoint,
b.versioned_hash(protocol_version)
)
})
.collect();
log::trace!(
"Created superblock #{} with hash_prev_block {}, ARS {}, signing_committee_length: {}, blocks {:?}",
Expand Down Expand Up @@ -775,7 +784,8 @@ mod tests {
#[test]
fn test_superblock_creation_no_blocks() {
let default_hash = Hash::default();
let superblock = mining_build_superblock(&[], &[], 0, default_hash, 0);
let superblock =
mining_build_superblock(&[], &[], 0, default_hash, 0, ProtocolVersion::default());

let expected = SuperBlock::new(
0,
Expand Down Expand Up @@ -833,7 +843,14 @@ mod tests {
tally_merkle_root_1,
);

let superblock = mining_build_superblock(&[block], &[default_hash], 0, default_hash, 1);
let superblock = mining_build_superblock(
&[block],
&[default_hash],
0,
default_hash,
1,
ProtocolVersion::default(),
);
assert_eq!(superblock, expected_superblock);
}

Expand Down Expand Up @@ -901,8 +918,14 @@ mod tests {
expected_superblock_tally_root,
);

let superblock =
mining_build_superblock(&[block_1, block_2], &[default_hash], 0, default_hash, 1);
let superblock = mining_build_superblock(
&[block_1, block_2],
&[default_hash],
0,
default_hash,
1,
ProtocolVersion::default(),
);
assert_eq!(superblock, expected_superblock);
}

Expand Down Expand Up @@ -1917,6 +1940,7 @@ mod tests {
1,
genesis_hash,
3,
ProtocolVersion::default(),
);
let sb2_hash = expected_sb2.hash();

Expand Down Expand Up @@ -2018,6 +2042,7 @@ mod tests {
1,
genesis_hash,
2,
ProtocolVersion::default(),
);

assert_eq!(sb2, expected_sb2);
Expand Down Expand Up @@ -2178,6 +2203,7 @@ mod tests {
1,
genesis_hash,
2,
ProtocolVersion::default(),
);

assert_eq!(sb2, expected_sb2);
Expand Down
Loading

0 comments on commit ebdb81c

Please sign in to comment.