mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
validator: check if proposal already exists when looking ofr its fork index
This also solves the bug where when appending a dublicated proposal, a new duplicate fork being created, resulting in never finalizing, as forks of same height existed
This commit is contained in:
@@ -336,6 +336,9 @@ pub enum Error {
|
||||
#[error("Proposal task stopped")]
|
||||
ProposalTaskStopped,
|
||||
|
||||
#[error("Proposal already exists")]
|
||||
ProposalAlreadyExists,
|
||||
|
||||
#[error("Miner task stopped")]
|
||||
MinerTaskStopped,
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@ impl Consensus {
|
||||
/// Given a proposal, the node verifys it and finds which fork it extends.
|
||||
/// If the proposal extends the canonical blockchain, a new fork chain is created.
|
||||
pub async fn append_proposal(&self, proposal: &Proposal) -> Result<()> {
|
||||
info!(target: "validator::consensus::append_proposal", "Appending proposal {}", proposal.hash);
|
||||
debug!(target: "validator::consensus::append_proposal", "Appending proposal {}", proposal.hash);
|
||||
|
||||
// Verify proposal and grab corresponding fork
|
||||
let (mut fork, index) = verify_proposal(self, proposal).await?;
|
||||
@@ -244,6 +244,8 @@ impl Consensus {
|
||||
}
|
||||
drop(lock);
|
||||
|
||||
info!(target: "validator::consensus::append_proposal", "Appended proposal {}", proposal.hash);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -259,6 +261,10 @@ impl Consensus {
|
||||
// Check if proposal extends any fork
|
||||
let found = find_extended_fork_index(&forks, proposal);
|
||||
if found.is_err() {
|
||||
if let Err(Error::ProposalAlreadyExists) = found {
|
||||
return Err(Error::ProposalAlreadyExists)
|
||||
}
|
||||
|
||||
// Check if proposal extends canonical
|
||||
let (last_slot, last_block) = self.blockchain.last()?;
|
||||
if proposal.block.header.previous != last_block ||
|
||||
|
||||
@@ -254,17 +254,39 @@ pub fn previous_slot_info(
|
||||
}
|
||||
|
||||
/// Given a proposal, find the index of the fork chain it extends, along with the specific
|
||||
/// extended proposal index.
|
||||
/// extended proposal index. Additionally, check that proposal doesn't already exists in any
|
||||
/// fork chain.
|
||||
pub fn find_extended_fork_index(forks: &[Fork], proposal: &Proposal) -> Result<(usize, usize)> {
|
||||
// Grab provided proposal hash
|
||||
let proposal_hash = proposal.block.hash()?;
|
||||
|
||||
// Keep track of fork and proposal indexes
|
||||
let (mut fork_index, mut proposal_index) = (None, None);
|
||||
|
||||
// Loop through all the forks
|
||||
for (f_index, fork) in forks.iter().enumerate() {
|
||||
// Traverse fork proposals sequence in reverse
|
||||
for (p_index, p_hash) in fork.proposals.iter().enumerate().rev() {
|
||||
// Check we haven't already seen that proposal
|
||||
if &proposal_hash == p_hash {
|
||||
return Err(Error::ProposalAlreadyExists)
|
||||
}
|
||||
|
||||
// Check if proposal extends this fork
|
||||
if &proposal.block.header.previous == p_hash {
|
||||
return Ok((f_index, p_index))
|
||||
// Proposal must only extend a single fork
|
||||
if fork_index.is_some() {
|
||||
return Err(Error::ProposalAlreadyExists)
|
||||
}
|
||||
(fork_index, proposal_index) = (Some(f_index), Some(p_index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let (Some(f_index), Some(p_index)) = (fork_index, proposal_index) {
|
||||
return Ok((f_index, p_index))
|
||||
}
|
||||
|
||||
Err(Error::ExtendedChainIndexNotFound)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user