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!: add validator mmr size #5873

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
2 changes: 2 additions & 0 deletions applications/minotari_app_grpc/proto/block.proto
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ message BlockHeader {
bytes total_script_offset = 15;
// Merkle root of validator nodes
bytes validator_node_mr = 16;
// Validator size
uint64 validator_node_size = 17;
}

// The proof of work data structure that is included in the block header.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ impl From<BlockHeader> for grpc::BlockHeader {
pow_data: h.pow.pow_data,
}),
validator_node_mr: h.validator_node_mr.to_vec(),
validator_node_size: h.validator_node_size,
}
}
}
Expand Down Expand Up @@ -83,6 +84,7 @@ impl TryFrom<grpc::BlockHeader> for BlockHeader {
nonce: header.nonce,
pow,
validator_node_mr: FixedHash::try_from(header.validator_node_mr).map_err(|err| err.to_string())?,
validator_node_size: header.validator_node_size,
})
}
}
6 changes: 6 additions & 0 deletions base_layer/core/src/blocks/block_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ pub struct BlockHeader {
pub total_script_offset: PrivateKey,
/// Merkle root of all active validator node.
pub validator_node_mr: FixedHash,
/// The number of validator node hashes
pub validator_node_size: u64,
/// Proof of work summary
pub pow: ProofOfWork,
/// Nonce increment used to mine this block.
Expand All @@ -137,6 +139,7 @@ impl BlockHeader {
nonce: 0,
pow: ProofOfWork::default(),
validator_node_mr: FixedHash::zero(),
validator_node_size: 0,
}
}

Expand Down Expand Up @@ -169,6 +172,7 @@ impl BlockHeader {
nonce: 0,
pow: ProofOfWork::default(),
validator_node_mr: FixedHash::zero(),
validator_node_size: prev.validator_node_size,
}
}

Expand Down Expand Up @@ -231,6 +235,7 @@ impl BlockHeader {
.chain(&self.total_kernel_offset)
.chain(&self.total_script_offset)
.chain(&self.validator_node_mr)
.chain(&self.validator_node_size)
.finalize()
.into()
}
Expand Down Expand Up @@ -277,6 +282,7 @@ impl From<NewBlockHeaderTemplate> for BlockHeader {
nonce: 0,
pow: header_template.pow,
validator_node_mr: FixedHash::zero(),
validator_node_size: 0,
}
}
}
Expand Down
1 change: 1 addition & 0 deletions base_layer/core/src/blocks/genesis_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ fn get_raw_block(genesis_timestamp: &DateTime<FixedOffset>, not_before_proof: &[
kernel_mmr_size: 0,
validator_node_mr: FixedHash::from_hex("277da65c40b2cf99db86baedb903a3f0a38540f3a94d40c826eecac7e27d5dfc")
.unwrap(),
validator_node_size: 0,
input_mr: FixedHash::zero(),
total_kernel_offset: PrivateKey::from_hex(
"0000000000000000000000000000000000000000000000000000000000000000",
Expand Down
12 changes: 9 additions & 3 deletions base_layer/core/src/chain_storage/blockchain_database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,7 @@ where B: BlockchainBackend
block.header.output_mr = roots.output_mr;
block.header.output_smt_size = roots.output_smt_size;
block.header.validator_node_mr = roots.validator_node_mr;
block.header.validator_node_size = roots.validator_node_size;
Ok(block)
}

Expand Down Expand Up @@ -1242,6 +1243,7 @@ pub struct MmrRoots {
pub output_mr: FixedHash,
pub output_smt_size: u64,
pub validator_node_mr: FixedHash,
pub validator_node_size: u64,
}

impl std::fmt::Display for MmrRoots {
Expand Down Expand Up @@ -1316,14 +1318,17 @@ pub fn calculate_mmr_roots<T: BlockchainBackend>(

let block_height = block.header.height;
let epoch_len = rules.consensus_constants(block_height).epoch_length();
let validator_node_mr = if block_height % epoch_len == 0 {
let (validator_node_mr, validator_node_size) = if block_height % epoch_len == 0 {
// At epoch boundary, the MR is rebuilt from the current validator set
let validator_nodes = db.fetch_active_validator_nodes(block_height)?;
FixedHash::try_from(calculate_validator_node_mr(&validator_nodes))?
(
FixedHash::try_from(calculate_validator_node_mr(&validator_nodes))?,
validator_nodes.len(),
)
} else {
// MR is unchanged except for epoch boundary
let tip_header = fetch_header(db, block_height - 1)?;
tip_header.validator_node_mr
(tip_header.validator_node_mr, 0)
};

let mmr_roots = MmrRoots {
Expand All @@ -1333,6 +1338,7 @@ pub fn calculate_mmr_roots<T: BlockchainBackend>(
output_mr: FixedHash::try_from(output_smt.hash().as_slice())?,
output_smt_size: output_smt.size(),
validator_node_mr,
validator_node_size: validator_node_size as u64,
};
Ok(mmr_roots)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ fn apply_mmr_to_block(db: &BlockchainDatabase<TempDatabase>, block: Block) -> Bl
block.header.kernel_mr = mmr_roots.kernel_mr;
block.header.kernel_mmr_size = mmr_roots.kernel_mmr_size;
block.header.validator_node_mr = mmr_roots.validator_node_mr;
block.header.validator_node_size = mmr_roots.validator_node_size;
block
}

Expand Down
11 changes: 10 additions & 1 deletion base_layer/core/src/proof_of_work/monero_rx/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ mod test {
nonce: 0,
pow: ProofOfWork::default(),
validator_node_mr: FixedHash::zero(),
validator_node_size: 0,
};
let hash = block_header.merge_mining_hash();
insert_merge_mining_tag_into_block(&mut block, hash).unwrap();
Expand Down Expand Up @@ -444,6 +445,7 @@ mod test {
nonce: 0,
pow: ProofOfWork::default(),
validator_node_mr: FixedHash::zero(),
validator_node_size: 0,
};
let hash = block_header.merge_mining_hash();
insert_merge_mining_tag_into_block(&mut block, hash).unwrap();
Expand Down Expand Up @@ -496,6 +498,7 @@ mod test {
nonce: 0,
pow: ProofOfWork::default(),
validator_node_mr: FixedHash::zero(),
validator_node_size: 0,
};
let count = 1 + (u16::try_from(block.tx_hashes.len()).unwrap());
let mut hashes = Vec::with_capacity(count as usize);
Expand Down Expand Up @@ -547,6 +550,7 @@ mod test {
nonce: 0,
pow: ProofOfWork::default(),
validator_node_mr: FixedHash::zero(),
validator_node_size: 0,
};
let hash = Hash::null();
insert_merge_mining_tag_into_block(&mut block, hash).unwrap();
Expand Down Expand Up @@ -602,6 +606,7 @@ mod test {
nonce: 0,
pow: ProofOfWork::default(),
validator_node_mr: FixedHash::zero(),
validator_node_size: 0,
};
let hash = block_header.merge_mining_hash();
insert_merge_mining_tag_into_block(&mut block, hash).unwrap();
Expand Down Expand Up @@ -669,7 +674,7 @@ mod test {
prev_hash: FixedHash::zero(),
timestamp: EpochTime::now(),
output_mr: FixedHash::zero(),
output_mmr_size: 0,
output_smt_size: 0,
kernel_mr: FixedHash::zero(),
kernel_mmr_size: 0,
input_mr: FixedHash::zero(),
Expand All @@ -678,6 +683,7 @@ mod test {
nonce: 0,
pow: ProofOfWork::default(),
validator_node_mr: FixedHash::zero(),
validator_node_size: 2,
};

// Let us manipulate the extra field to make it invalid
Expand Down Expand Up @@ -736,6 +742,7 @@ mod test {
nonce: 0,
pow: ProofOfWork::default(),
validator_node_mr: FixedHash::zero(),
validator_node_size: 0,
};
let hash = block_header.merge_mining_hash();
insert_merge_mining_tag_into_block(&mut block, hash).unwrap();
Expand Down Expand Up @@ -787,6 +794,7 @@ mod test {
nonce: 0,
pow: ProofOfWork::default(),
validator_node_mr: FixedHash::zero(),
validator_node_size: 0,
};
let monero_data = MoneroPowData {
header: Default::default(),
Expand Down Expand Up @@ -829,6 +837,7 @@ mod test {
nonce: 0,
pow: ProofOfWork::default(),
validator_node_mr: FixedHash::zero(),
validator_node_size: 0,
};
let hash = block_header.merge_mining_hash();
insert_merge_mining_tag_into_block(&mut block, hash).unwrap();
Expand Down
4 changes: 2 additions & 2 deletions base_layer/core/src/proof_of_work/sha3x_pow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ pub mod test {
#[test]
fn validate_max_target() {
let mut header = get_header();
header.nonce = 154;
header.nonce = 631;
println!("{:?}", header);
assert_eq!(sha3x_difficulty(&header).unwrap(), Difficulty::from_u64(6564).unwrap());
assert_eq!(sha3x_difficulty(&header).unwrap(), Difficulty::from_u64(3347).unwrap());
}
}
2 changes: 2 additions & 0 deletions base_layer/core/src/proto/block.proto
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ message BlockHeader {
bytes total_script_offset = 15;
// Merkle root of validator nodes
bytes validator_node_merkle_root = 16;
// Validator size
uint64 validator_node_size = 17;
}

// A Tari block. Blocks are linked together into a blockchain.
Expand Down
2 changes: 2 additions & 0 deletions base_layer/core/src/proto/block_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ impl TryFrom<proto::BlockHeader> for BlockHeader {
nonce: header.nonce,
pow,
validator_node_mr: FixedHash::try_from(header.validator_node_merkle_root).map_err(|err| err.to_string())?,
validator_node_size: header.validator_node_size,
})
}
}
Expand All @@ -83,6 +84,7 @@ impl From<BlockHeader> for proto::BlockHeader {
kernel_mmr_size: header.kernel_mmr_size,
output_mmr_size: header.output_smt_size,
validator_node_merkle_root: header.validator_node_mr.to_vec(),
validator_node_size: header.validator_node_size,
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions base_layer/core/src/validation/block_body/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ async fn it_passes_if_large_output_block_is_valid() {
block.header.kernel_mr = mmr_roots.kernel_mr;
block.header.kernel_mmr_size = mmr_roots.kernel_mmr_size;
block.header.validator_node_mr = mmr_roots.validator_node_mr;
block.header.validator_node_size = mmr_roots.validator_node_size;

let txn = blockchain.db().db_read_access().unwrap();
let start = Instant::now();
Expand Down Expand Up @@ -140,6 +141,7 @@ async fn it_passes_if_large_block_is_valid() {
block.header.kernel_mr = mmr_roots.kernel_mr;
block.header.kernel_mmr_size = mmr_roots.kernel_mmr_size;
block.header.validator_node_mr = mmr_roots.validator_node_mr;
block.header.validator_node_size = mmr_roots.validator_node_size;

let txn = blockchain.db().db_read_access().unwrap();
let start = Instant::now();
Expand Down Expand Up @@ -167,6 +169,7 @@ async fn it_passes_if_block_is_valid() {
block.header.kernel_mr = mmr_roots.kernel_mr;
block.header.kernel_mmr_size = mmr_roots.kernel_mmr_size;
block.header.validator_node_mr = mmr_roots.validator_node_mr;
block.header.validator_node_size = mmr_roots.validator_node_size;

let txn = blockchain.db().db_read_access().unwrap();
assert!(validator.validate_body(&*txn, &block).is_ok());
Expand Down
16 changes: 16 additions & 0 deletions base_layer/core/src/validation/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,22 @@ pub fn check_mmr_roots(header: &BlockHeader, mmr_roots: &MmrRoots) -> Result<(),
kind: "Validator Node",
}));
}

if header.validator_node_size != mmr_roots.validator_node_size {
warn!(
target: LOG_TARGET,
"Block header validator size in #{} {} does not match. Expected: {}, Actual:{}",
header.height,
header.hash().to_hex(),
header.validator_node_size,
mmr_roots.validator_node_size
);
return Err(ValidationError::BlockError(BlockValidationError::MismatchedMmrSize {
mmr_tree: "Validator_node".to_string(),
expected: mmr_roots.validator_node_size,
actual: header.validator_node_size,
}));
}
Ok(())
}

Expand Down
4 changes: 2 additions & 2 deletions base_layer/tari_mining_helper_ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,8 @@ mod tests {

#[test]
fn detect_change_in_consensus_encoding() {
const NONCE: u64 = 7688822913895845419;
let difficulty = Difficulty::from_u64(4881).expect("Failed to create difficulty");
const NONCE: u64 = 7597942135203888660;
let difficulty = Difficulty::from_u64(1490).expect("Failed to create difficulty");
unsafe {
let mut error = -1;
let error_ptr = &mut error as *mut c_int;
Expand Down
Loading