consensus/state/SlotCheckpoint: renamed eta to previous eta and introduced fork hashes vector

This commit is contained in:
aggstam
2023-06-07 15:57:39 +03:00
parent 1035ca4ce5
commit e436e6d069
7 changed files with 63 additions and 27 deletions

View File

@@ -156,11 +156,16 @@ impl ConsensusState {
}
/// Generate current slot checkpoint
fn generate_slot_checkpoint(&mut self, sigma1: pallas::Base, sigma2: pallas::Base) {
fn generate_slot_checkpoint(
&mut self,
fork_hashes: Vec<blake3::Hash>,
sigma1: pallas::Base,
sigma2: pallas::Base,
) {
let slot = self.time_keeper.current_slot();
let eta = self.get_eta();
info!(target: "consensus::state", "generate_slot_checkpoint: slot: {:?}, eta: {:?}", slot, eta);
let checkpoint = SlotCheckpoint { slot, eta, sigma1, sigma2 };
let previous_eta = self.get_previous_eta();
let checkpoint = SlotCheckpoint { slot, previous_eta, fork_hashes, sigma1, sigma2 };
info!(target: "consensus::state", "generate_slot_checkpoint: {:?}", checkpoint);
self.slot_checkpoints.push(checkpoint);
}
@@ -176,10 +181,11 @@ impl ConsensusState {
/// Returns flag to signify if epoch has changed.
pub async fn epoch_changed(
&mut self,
fork_hashes: Vec<blake3::Hash>,
sigma1: pallas::Base,
sigma2: pallas::Base,
) -> Result<bool> {
self.generate_slot_checkpoint(sigma1, sigma2);
self.generate_slot_checkpoint(fork_hashes, sigma1, sigma2);
let epoch = self.time_keeper.current_epoch();
if epoch <= self.epoch {
return Ok(false)
@@ -423,7 +429,7 @@ impl ConsensusState {
let first_winning = coin.is_leader(
sigma1,
sigma2,
self.get_eta(),
self.get_previous_eta(),
pallas::Base::from(self.time_keeper.current_slot()),
);
@@ -534,7 +540,7 @@ impl ConsensusState {
/// Utility function to extract leader selection lottery randomness(eta),
/// defined as the hash of the last block, converted to pallas base.
pub fn get_eta(&self) -> pallas::Base {
pub fn get_previous_eta(&self) -> pallas::Base {
let (_, hash) = self.blockchain.last().unwrap();
let mut bytes: [u8; 32] = *hash.as_bytes();
// Read first 254 bits
@@ -584,6 +590,22 @@ impl ConsensusState {
}
}
/// Retrieve current forks last proposal hashes.
/// If node holds no fork, retrieve last canonical hash.
pub fn fork_hashes(&self) -> Vec<blake3::Hash> {
let mut hashes = vec![];
for fork in &self.forks {
hashes.push(fork.sequence.last().unwrap().proposal.hash);
}
if hashes.is_empty() {
let (_, hash) = self.blockchain.last().unwrap();
hashes.push(hash);
}
hashes
}
/// Auxiliary structure to reset consensus state for a resync
pub fn reset(&mut self) {
self.participating = None;
@@ -668,10 +690,11 @@ impl net::Message for ConsensusSlotCheckpointsResponse {
pub struct SlotCheckpoint {
/// Slot UID
pub slot: u64,
/// Slot eta
// TODO: this should be renamed to previous_eta,
// corresponding to previous block eta.
pub eta: pallas::Base,
/// Previous slot eta
pub previous_eta: pallas::Base,
/// Previous slot forks last proposal/block hashes,
/// as observed by the validator
pub fork_hashes: Vec<blake3::Hash>,
/// Slot sigma1
pub sigma1: pallas::Base,
/// Slot sigma2
@@ -679,17 +702,24 @@ pub struct SlotCheckpoint {
}
impl SlotCheckpoint {
pub fn new(slot: u64, eta: pallas::Base, sigma1: pallas::Base, sigma2: pallas::Base) -> Self {
Self { slot, eta, sigma1, sigma2 }
pub fn new(
slot: u64,
previous_eta: pallas::Base,
fork_hashes: Vec<blake3::Hash>,
sigma1: pallas::Base,
sigma2: pallas::Base,
) -> Self {
Self { slot, previous_eta, fork_hashes, sigma1, sigma2 }
}
/// Generate the genesis slot checkpoint.
pub fn genesis_slot_checkpoint() -> Self {
let eta = pallas::Base::zero();
let previous_eta = pallas::Base::zero();
let fork_hashes = vec![];
let sigma1 = pallas::Base::zero();
let sigma2 = pallas::Base::zero();
Self::new(0, eta, sigma1, sigma2)
Self::new(0, previous_eta, fork_hashes, sigma1, sigma2)
}
}

View File

@@ -186,10 +186,14 @@ async fn propose_period(consensus_p2p: P2pPtr, state: ValidatorStatePtr) -> bool
// Keep a record of slot to verify if next slot got skipped during processing
let processing_slot = state.read().await.consensus.time_keeper.current_slot();
// Retrieve current forks last hash
let fork_hashes = state.read().await.consensus.fork_hashes();
// Retrieve slot sigmas
let (sigma1, sigma2) = state.write().await.consensus.sigmas();
// Node checks if epoch has changed and generate slot checkpoint
let epoch_changed = state.write().await.consensus.epoch_changed(sigma1, sigma2).await;
let epoch_changed =
state.write().await.consensus.epoch_changed(fork_hashes, sigma1, sigma2).await;
match epoch_changed {
Ok(changed) => {
if changed {

View File

@@ -362,7 +362,7 @@ impl ValidatorState {
sigma1: pallas::Base,
sigma2: pallas::Base,
) -> Result<Option<(BlockProposal, LeadCoin, pallas::Scalar)>> {
let eta = self.consensus.get_eta();
let eta = self.consensus.get_previous_eta();
// Check if node can produce proposals
if !self.consensus.proposing {
return Ok(None)
@@ -576,7 +576,7 @@ impl ValidatorState {
// Validate proposal public value against coin creation slot checkpoint
let (mu_y, mu_rho) = LeadCoin::election_seeds_u64(
self.consensus.get_eta(),
self.consensus.get_previous_eta(),
self.consensus.time_keeper.current_slot(),
);
// y

View File

@@ -278,10 +278,8 @@ pub fn create_proposal_proof(
let slot_pallas = pallas::Base::from(slot_checkpoint.slot);
let seed = poseidon_hash([SEED_PREFIX, input.note.serial]);
// NOTE: slot checkpoint eta to be renamed to previous_eta,
// corresponding to previous block eta.
let mut vrf_input = Vec::with_capacity(32 + 32);
vrf_input.extend_from_slice(&slot_checkpoint.eta.to_repr());
vrf_input.extend_from_slice(&slot_checkpoint.previous_eta.to_repr());
vrf_input.extend_from_slice(&slot_pallas.to_repr());
let vrf_proof = VrfProof::prove(input.secret, &vrf_input, &mut OsRng);
let mut eta = [0u8; 64];

View File

@@ -97,10 +97,8 @@ pub(crate) fn consensus_proposal_get_metadata_v1(
// Verify eta VRF proof
let slot_pallas = pallas::Base::from(slot_checkpoint.slot);
// NOTE: slot checkpoint eta to be renamed to previous_eta,
// corresponding to previous block eta.
let mut vrf_input = Vec::with_capacity(32 + 32);
vrf_input.extend_from_slice(&slot_checkpoint.eta.to_repr());
vrf_input.extend_from_slice(&slot_checkpoint.previous_eta.to_repr());
vrf_input.extend_from_slice(&slot_pallas.to_repr());
let vrf_proof = &params.vrf_proof;
if !vrf_proof.verify(params.input.signature_public, &vrf_input) {

View File

@@ -113,8 +113,11 @@ pub const HEADSTART: pallas::Base = pallas::Base::from_raw([
pub struct SlotCheckpoint {
/// Slot UID
pub slot: u64,
/// Slot eta
pub eta: pallas::Base,
/// Previous slot eta
pub previous_eta: pallas::Base,
/// Previous slot forks last proposal/block hashes,
/// as observed by the validator
pub fork_hashes: Vec<blake3::Hash>,
/// Slot sigma1
pub sigma1: pallas::Base,
/// Slot sigma2

View File

@@ -850,10 +850,13 @@ impl ConsensusTestHarness {
pub async fn generate_slot_checkpoint(&self, slot: u64) -> Result<SlotCheckpoint> {
// We grab the genesis slot to generate slot checkpoint
// using same consensus parameters
let faucet = self.holders.get(&Holder::Faucet).unwrap();
let fork_hashes = vec![faucet.state.read().await.consensus.genesis_block];
let genesis_slot = self.get_slot_checkpoint_by_slot(0).await?;
let slot_checkpoint = SlotCheckpoint {
slot,
eta: genesis_slot.eta,
previous_eta: genesis_slot.previous_eta,
fork_hashes,
sigma1: genesis_slot.sigma1,
sigma2: genesis_slot.sigma2,
};