Skip to content

Commit

Permalink
Merge pull request #2408 from AleoHQ/testnet3-staging
Browse files Browse the repository at this point in the history
[Feb 10 Backport] Theoretical Hotfix for `testnet3` branch
  • Loading branch information
howardwu authored Mar 23, 2024
2 parents d23daa8 + 94d1135 commit 9ae59c8
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 17 deletions.
3 changes: 0 additions & 3 deletions ledger/block/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,6 @@ impl<N: Network> Block<N> {
transactions: Transactions<N>,
aborted_transaction_ids: Vec<N::TransactionID>,
) -> Result<Self> {
// Ensure the block contains transactions.
ensure!(!transactions.is_empty(), "Cannot create a block with zero transactions");

// Ensure the number of transactions is within the allowed range.
if transactions.len() > Transactions::<N>::MAX_TRANSACTIONS {
bail!(
Expand Down
25 changes: 12 additions & 13 deletions ledger/block/src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl<N: Network> Block<N> {
&self,
previous_block: &Block<N>,
current_state_root: N::StateRoot,
current_committee: &Committee<N>,
current_committee_lookback: &Committee<N>,
current_puzzle: &CoinbasePuzzle<N>,
current_epoch_challenge: &EpochChallenge<N>,
current_timestamp: i64,
Expand All @@ -41,7 +41,7 @@ impl<N: Network> Block<N> {

// Ensure the block authority is correct.
let (expected_round, expected_height, expected_timestamp, expected_existing_transaction_ids) =
self.verify_authority(previous_block.round(), previous_block.height(), current_committee)?;
self.verify_authority(previous_block.round(), previous_block.height(), current_committee_lookback)?;

// Ensure the block solutions are correct.
let (
Expand Down Expand Up @@ -138,8 +138,9 @@ impl<N: Network> Block<N> {
&self,
previous_round: u64,
previous_height: u32,
current_committee: &Committee<N>,
current_committee_lookback: &Committee<N>,
) -> Result<(u64, u32, i64, Vec<N::TransactionID>)> {
// Note: Do not remove this. This ensures that all blocks after genesis are quorum blocks.
#[cfg(not(any(test, feature = "test")))]
ensure!(self.authority.is_quorum(), "The next block must be a quorum block");

Expand All @@ -164,12 +165,13 @@ impl<N: Network> Block<N> {
subdag.anchor_round()
}
};
// Ensure the block round is at least the starting round of the committee.
// Ensure the block round minus the committee lookback range is at least the starting round of the committee lookback.
ensure!(
expected_round >= current_committee.starting_round(),
"Block {} has an invalid round (found '{expected_round}', expected at least '{}')",
expected_height,
current_committee.starting_round()
expected_round.saturating_sub(Committee::<N>::COMMITTEE_LOOKBACK_RANGE)
>= current_committee_lookback.starting_round(),
"Block {expected_height} has an invalid round (found '{}', expected at least '{}')",
expected_round.saturating_sub(Committee::<N>::COMMITTEE_LOOKBACK_RANGE),
current_committee_lookback.starting_round()
);

// Ensure the block authority is correct.
Expand All @@ -180,7 +182,7 @@ impl<N: Network> Block<N> {
let signer = signature.to_address();
// Ensure the block is signed by a committee member.
ensure!(
current_committee.members().contains_key(&signer),
current_committee_lookback.members().contains_key(&signer),
"Beacon block {expected_height} has a signer not in the committee (found '{signer}')",
);
// Ensure the signature is valid.
Expand All @@ -193,7 +195,7 @@ impl<N: Network> Block<N> {
}
Authority::Quorum(subdag) => {
// Compute the expected leader.
let expected_leader = current_committee.get_leader(expected_round)?;
let expected_leader = current_committee_lookback.get_leader(expected_round)?;
// Ensure the block is authored by the expected leader.
ensure!(
subdag.leader_address() == expected_leader,
Expand Down Expand Up @@ -387,9 +389,6 @@ impl<N: Network> Block<N> {
fn verify_transactions(&self) -> Result<()> {
let height = self.height();

// Ensure there are transactions.
ensure!(!self.transactions.is_empty(), "Block {height} must contain at least 1 transaction");

// Ensure the number of transactions is within the allowed range.
if self.transactions.len() > Transactions::<N>::MAX_TRANSACTIONS {
bail!(
Expand Down
2 changes: 2 additions & 0 deletions ledger/committee/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ pub struct Committee<N: Network> {
}

impl<N: Network> Committee<N> {
/// The committee lookback range.
pub const COMMITTEE_LOOKBACK_RANGE: u64 = 50;
/// The maximum number of members that may be in a committee.
pub const MAX_COMMITTEE_SIZE: u16 = 200;

Expand Down
15 changes: 14 additions & 1 deletion ledger/src/check_next_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,24 @@ impl<N: Network, C: ConsensusStorage<N>> Ledger<N, C> {
let ratified_finalize_operations =
self.vm.check_speculate(state, block.ratifications(), block.solutions(), block.transactions())?;

// Get the round number for the previous committee. Note, we subtract 2 from odd rounds,
// because committees are updated in even rounds.
let previous_round = match block.round() % 2 == 0 {
true => block.round().saturating_sub(1),
false => block.round().saturating_sub(2),
};
// Get the committee lookback round.
let committee_lookback_round = previous_round.saturating_sub(Committee::<N>::COMMITTEE_LOOKBACK_RANGE);
// Retrieve the committee lookback.
let committee_lookback = self
.get_committee_for_round(committee_lookback_round)?
.ok_or(anyhow!("Failed to fetch committee for round {committee_lookback_round}"))?;

// Ensure the block is correct.
let expected_existing_transaction_ids = block.verify(
&self.latest_block(),
self.latest_state_root(),
&self.latest_committee()?,
&committee_lookback,
self.coinbase_puzzle(),
&self.latest_epoch_challenge()?,
OffsetDateTime::now_utc().unix_timestamp(),
Expand Down

0 comments on commit 9ae59c8

Please sign in to comment.