Skip to content
This repository was archived by the owner on Feb 6, 2025. It is now read-only.

Commit 39bb96b

Browse files
Merge pull request #3 from abailly/abailly/test-header-validation
Provide partial test suite for header validation
2 parents 77e329d + 3f39398 commit 39bb96b

File tree

7 files changed

+321
-27
lines changed

7 files changed

+321
-27
lines changed

ouroboros-praos/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ mockall = "0.13"
2020
pallas-traverse = "0.31.0"
2121
tracing-subscriber = "0.3"
2222
criterion = "0.5.1"
23+
serde = { version = "1.0", features = ["derive"] }
24+
serde_json = "1.0.128"
2325

2426
[[bench]]
2527
harness = false

ouroboros-praos/benches/benchmark.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ fn validate_conway_block() {
2727

2828
let active_slots_coeff: FixedDecimal =
2929
FixedDecimal::from(5u64) / FixedDecimal::from(100u64);
30-
let c = (FixedDecimal::from(1u64) - active_slots_coeff).ln();
3130
let conway_block_tag: u8 = 6;
3231
let multi_era_header = MultiEraHeader::decode(conway_block_tag, None, test_block).unwrap();
3332
let babbage_header = multi_era_header.as_babbage().expect("Infallible");
@@ -57,7 +56,7 @@ fn validate_conway_block() {
5756
.expect_latest_opcert_sequence_number()
5857
.returning(|_| None);
5958

60-
let block_validator = BlockValidator::new(babbage_header, &ledger_state, &epoch_nonce, &c);
59+
let block_validator = BlockValidator::new(babbage_header, &ledger_state, &epoch_nonce, &active_slots_coeff);
6160
assert_eq!(block_validator.validate().is_ok(), expected);
6261
}
6362
}

ouroboros-praos/src/consensus/mod.rs

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,21 @@ pub struct BlockValidator<'b> {
2828
header: &'b babbage::MintedHeader<'b>,
2929
ledger_state: &'b dyn LedgerState,
3030
epoch_nonce: &'b Hash<32>,
31-
// c is the ln(1-active_slots_coeff). Usually ln(1-0.05)
32-
c: &'b FixedDecimal,
31+
active_slots_coeff: &'b FixedDecimal,
3332
}
3433

3534
impl<'b> BlockValidator<'b> {
3635
pub fn new(
3736
header: &'b babbage::MintedHeader,
3837
ledger_state: &'b dyn LedgerState,
3938
epoch_nonce: &'b Hash<32>,
40-
c: &'b FixedDecimal,
39+
active_slots_coeff: &'b FixedDecimal,
4140
) -> Self {
4241
Self {
4342
header,
4443
ledger_state,
4544
epoch_nonce,
46-
c,
45+
active_slots_coeff,
4746
}
4847
}
4948

@@ -103,7 +102,7 @@ impl<'b> BlockValidator<'b> {
103102
&block_vrf_proof,
104103
)
105104
}),
106-
Box::new(|| self.validate_operational_certificate(issuer_vkey.as_slice())),
105+
Box::new(|| self.validate_operational_certificate(issuer_vkey.as_slice(), &pool_id)),
107106
Box::new(|| self.validate_kes_signature(absolute_slot, kes_signature)),
108107
];
109108

@@ -138,10 +137,10 @@ impl<'b> BlockValidator<'b> {
138137
.operational_cert_kes_period;
139138

140139
if opcert_kes_period > slot_kes_period {
141-
return Err(ValidationError::KesVerificationError(
142-
"Operational Certificate KES period is greater than the block slot KES period!"
143-
.to_string(),
144-
));
140+
return Err(ValidationError::OpCertKesPeriodTooLarge {
141+
opcert_kes_period,
142+
slot_kes_period,
143+
});
145144
}
146145
if slot_kes_period >= opcert_kes_period + self.ledger_state.max_kes_evolutions() {
147146
return Err(ValidationError::KesVerificationError(
@@ -168,7 +167,7 @@ impl<'b> BlockValidator<'b> {
168167
})
169168
}
170169

171-
fn validate_operational_certificate(&self, issuer_vkey: &[u8]) -> Result<(), ValidationError> {
170+
fn validate_operational_certificate(&self, issuer_vkey: &[u8], pool_id: &PoolId) -> Result<(), ValidationError> {
172171
// Verify the Operational Certificate signature
173172
let opcert_signature = Signature::try_from(
174173
self.header
@@ -191,12 +190,12 @@ impl<'b> BlockValidator<'b> {
191190

192191
// Check the sequence number of the operational certificate. It should either be the same
193192
// as the latest known sequence number for the issuer_vkey or one greater.
194-
match self.ledger_state.latest_opcert_sequence_number(issuer_vkey) {
193+
match self.ledger_state.latest_opcert_sequence_number(pool_id) {
195194
Some(latest_opcert_sequence_number) => {
196-
if (opcert_sequence_number - latest_opcert_sequence_number) > 1 {
197-
return Err(ValidationError::InvalidOpcertSequenceNumber("Operational Certificate sequence number is too far ahead of the latest known sequence number!".to_string()));
198-
} else if opcert_sequence_number < latest_opcert_sequence_number {
195+
if opcert_sequence_number < latest_opcert_sequence_number {
199196
return Err(ValidationError::InvalidOpcertSequenceNumber("Operational Certificate sequence number is less than the latest known sequence number!".to_string()));
197+
} else if (opcert_sequence_number - latest_opcert_sequence_number) > 1 {
198+
return Err(ValidationError::InvalidOpcertSequenceNumber("Operational Certificate sequence number is too far ahead of the latest known sequence number!".to_string()));
200199
}
201200
trace!("Operational Certificate sequence number is ok.")
202201
}
@@ -289,15 +288,22 @@ impl<'b> BlockValidator<'b> {
289288
absolute_slot: u64,
290289
leader_vrf_output: &[u8],
291290
) -> Result<(), ValidationError> {
291+
// special case for testing purposes
292+
if self.active_slots_coeff == &FixedDecimal::from(1u64) {
293+
return Ok(());
294+
}
295+
292296
let certified_leader_vrf: FixedDecimal = leader_vrf_output.into();
293297
let denominator = CERTIFIED_NATURAL_MAX.deref() - &certified_leader_vrf;
294298
let recip_q = CERTIFIED_NATURAL_MAX.deref() / &denominator;
295-
let x = -(sigma * self.c);
299+
let c = (FixedDecimal::from(1u64) - self.active_slots_coeff.clone()).ln();
300+
let x = -(sigma * &c);
296301

302+
trace!("leader_vrf_output: {}", hex::encode(leader_vrf_output));
297303
trace!("certified_leader_vrf: {}", certified_leader_vrf);
298304
trace!("denominator: {}", denominator);
299305
trace!("recip_q: {}", recip_q);
300-
trace!("c: {}", self.c);
306+
trace!("active_slots_coeff: {}", self.active_slots_coeff);
301307
trace!("x: {}", x);
302308

303309
let ordering = x.exp_cmp(1000, 3, &recip_q);
@@ -333,10 +339,10 @@ impl<'b> BlockValidator<'b> {
333339
trace!("block vrf_vkey_hash: {}", hex::encode(vrf_vkey_hash));
334340
let ledger_vrf_vkey_hash = self.ledger_state.vrf_vkey_hash(pool_id)?;
335341
if vrf_vkey_hash != ledger_vrf_vkey_hash {
336-
return Err(ValidationError::InvalidVrfKeyForPool(
337-
hex::encode(ledger_vrf_vkey_hash),
338-
hex::encode(vrf_vkey),
339-
));
342+
return Err(ValidationError::InvalidVrfKeyForPool {
343+
key_hash_from_ledger: hex::encode(ledger_vrf_vkey_hash),
344+
key_hash_from_block: hex::encode(vrf_vkey),
345+
});
340346
}
341347
Ok(())
342348
}
@@ -409,7 +415,6 @@ mod tests {
409415

410416
let active_slots_coeff: FixedDecimal =
411417
FixedDecimal::from(5u64) / FixedDecimal::from(100u64);
412-
let c = (FixedDecimal::from(1u64) - active_slots_coeff).ln();
413418
let conway_block_tag: u8 = 6;
414419
let multi_era_header =
415420
MultiEraHeader::decode(conway_block_tag, None, test_block).unwrap();
@@ -441,7 +446,7 @@ mod tests {
441446
.returning(|_| None);
442447

443448
let block_validator =
444-
BlockValidator::new(babbage_header, &ledger_state, &epoch_nonce, &c);
449+
BlockValidator::new(babbage_header, &ledger_state, &epoch_nonce, &active_slots_coeff);
445450
assert_eq!(block_validator.validate().is_ok(), expected);
446451
}
447452
}

ouroboros-praos/tests/data/test-vector.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)