Skip to content

Commit

Permalink
Merge pull request #2569 from ProvableHQ/feat/block_reward_v2
Browse files Browse the repository at this point in the history
[ARC-0042] Adjust reward algorithms to utilize timestamps
  • Loading branch information
zosorock authored Nov 13, 2024
2 parents 60a0aa5 + 44740f0 commit 5443685
Show file tree
Hide file tree
Showing 12 changed files with 1,004 additions and 58 deletions.
7 changes: 7 additions & 0 deletions console/network/src/canary_v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ impl Network for CanaryV0 {
/// The transmission checksum type.
type TransmissionChecksum = u128;

/// The block height from which consensus V2 rules apply.
#[cfg(not(any(test, feature = "test")))]
const CONSENSUS_V2_HEIGHT: u32 = 2_900_000;
// TODO (raychu86): Update this value based on the desired canary height.
/// The block height from which consensus V2 rules apply.
#[cfg(any(test, feature = "test"))]
const CONSENSUS_V2_HEIGHT: u32 = 0;
/// The network edition.
const EDITION: u16 = 0;
/// The genesis block coinbase target.
Expand Down
3 changes: 3 additions & 0 deletions console/network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ pub trait Network:
/// The network edition.
const EDITION: u16;

/// The block height from which consensus V2 rules apply.
const CONSENSUS_V2_HEIGHT: u32;

/// The function name for the inclusion circuit.
const INCLUSION_FUNCTION_NAME: &'static str;

Expand Down
7 changes: 7 additions & 0 deletions console/network/src/mainnet_v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,13 @@ impl Network for MainnetV0 {
/// The transmission checksum type.
type TransmissionChecksum = u128;

/// The block height from which consensus V2 rules apply.
#[cfg(not(any(test, feature = "test")))]
const CONSENSUS_V2_HEIGHT: u32 = 2_800_000;
// TODO (raychu86): Update this value based on the desired mainnet height.
/// The block height from which consensus V2 rules apply.
#[cfg(any(test, feature = "test"))]
const CONSENSUS_V2_HEIGHT: u32 = 0;
/// The network edition.
const EDITION: u16 = 0;
/// The genesis block coinbase target.
Expand Down
7 changes: 7 additions & 0 deletions console/network/src/testnet_v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ impl Network for TestnetV0 {
/// The transmission checksum type.
type TransmissionChecksum = u128;

/// The block height from which consensus V2 rules apply.
#[cfg(not(any(test, feature = "test")))]
const CONSENSUS_V2_HEIGHT: u32 = 2_950_000;
// TODO (raychu86): Update this value based on the desired testnet height.
/// The block height from which consensus V2 rules apply.
#[cfg(any(test, feature = "test"))]
const CONSENSUS_V2_HEIGHT: u32 = 10;
/// The network edition.
const EDITION: u16 = 0;
/// The genesis block coinbase target.
Expand Down
848 changes: 819 additions & 29 deletions ledger/block/src/helpers/target.rs

Large diffs are not rendered by default.

17 changes: 14 additions & 3 deletions ledger/block/src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,12 @@ impl<N: Network> Block<N> {
)?;

// Calculate the expected coinbase reward.
let expected_coinbase_reward = coinbase_reward(
let expected_coinbase_reward = coinbase_reward::<N>(
height,
timestamp,
N::GENESIS_TIMESTAMP,
N::STARTING_SUPPLY,
N::ANCHOR_TIME,
N::ANCHOR_HEIGHT,
N::BLOCK_TIME,
combined_proof_target,
Expand All @@ -402,9 +405,17 @@ impl<N: Network> Block<N> {
let expected_transaction_fees =
self.transactions.iter().map(|tx| Ok(*tx.priority_fee_amount()?)).sum::<Result<u64>>()?;

// Calculate the time since last block.
let time_since_last_block = timestamp.saturating_sub(previous_block.timestamp());
// Compute the expected block reward.
let expected_block_reward =
block_reward(N::STARTING_SUPPLY, N::BLOCK_TIME, expected_coinbase_reward, expected_transaction_fees);
let expected_block_reward = block_reward::<N>(
height,
N::STARTING_SUPPLY,
N::BLOCK_TIME,
time_since_last_block,
expected_coinbase_reward,
expected_transaction_fees,
);
// Compute the expected puzzle reward.
let expected_puzzle_reward = puzzle_reward(expected_coinbase_reward);

Expand Down
6 changes: 5 additions & 1 deletion ledger/src/advance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,9 +295,12 @@ impl<N: Network, C: ConsensusStorage<N>> Ledger<N, C> {
)?;

// Calculate the coinbase reward.
let coinbase_reward = coinbase_reward(
let coinbase_reward = coinbase_reward::<N>(
next_height,
next_timestamp,
N::GENESIS_TIMESTAMP,
N::STARTING_SUPPLY,
N::ANCHOR_TIME,
N::ANCHOR_HEIGHT,
N::BLOCK_TIME,
combined_proof_target,
Expand All @@ -316,6 +319,7 @@ impl<N: Network, C: ConsensusStorage<N>> Ledger<N, C> {
// Speculate over the ratifications, solutions, and transactions.
let (ratifications, transactions, aborted_transaction_ids, ratified_finalize_operations) = self.vm.speculate(
state,
next_timestamp.saturating_sub(previous_block.timestamp()),
Some(coinbase_reward),
candidate_ratifications,
&solutions,
Expand Down
11 changes: 9 additions & 2 deletions ledger/src/check_next_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,15 @@ impl<N: Network, C: ConsensusStorage<N>> Ledger<N, C> {
)?;

// Ensure speculation over the unconfirmed transactions is correct and ensure each transaction is well-formed and unique.
let ratified_finalize_operations =
self.vm.check_speculate(state, block.ratifications(), block.solutions(), block.transactions(), rng)?;
let time_since_last_block = block.timestamp().saturating_sub(self.latest_timestamp());
let ratified_finalize_operations = self.vm.check_speculate(
state,
time_since_last_block,
block.ratifications(),
block.solutions(),
block.transactions(),
rng,
)?;

// Retrieve the committee lookback.
let committee_lookback = {
Expand Down
102 changes: 87 additions & 15 deletions synthesizer/src/vm/finalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
/// `Ratify::BlockReward(block_reward)` and `Ratify::PuzzleReward(puzzle_reward)`
/// to the front of the `ratifications` list.
#[inline]
#[allow(clippy::too_many_arguments)]
pub fn speculate<'a, R: Rng + CryptoRng>(
&self,
state: FinalizeGlobalState,
time_since_last_block: i64, // TODO (raychu86): Consider moving this value into `FinalizeGlobalState`.
coinbase_reward: Option<u64>,
candidate_ratifications: Vec<Ratify<N>>,
candidate_solutions: &Solutions<N>,
Expand Down Expand Up @@ -62,6 +64,7 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
let (ratifications, confirmed_transactions, speculation_aborted_transactions, ratified_finalize_operations) =
self.atomic_speculate(
state,
time_since_last_block,
coinbase_reward,
candidate_ratifications,
candidate_solutions,
Expand Down Expand Up @@ -104,6 +107,7 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
pub fn check_speculate<R: Rng + CryptoRng>(
&self,
state: FinalizeGlobalState,
time_since_last_block: i64,
ratifications: &Ratifications<N>,
solutions: &Solutions<N>,
transactions: &Transactions<N>,
Expand All @@ -129,7 +133,14 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {

// Performs a **dry-run** over the list of ratifications, solutions, and transactions.
let (speculate_ratifications, confirmed_transactions, aborted_transactions, ratified_finalize_operations) =
self.atomic_speculate(state, None, candidate_ratifications, solutions, candidate_transactions.iter())?;
self.atomic_speculate(
state,
time_since_last_block,
None,
candidate_ratifications,
solutions,
candidate_transactions.iter(),
)?;

// Ensure the ratifications after speculation match.
if ratifications != &speculate_ratifications {
Expand Down Expand Up @@ -193,6 +204,7 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
fn atomic_speculate<'a>(
&self,
state: FinalizeGlobalState,
time_since_last_block: i64,
coinbase_reward: Option<u64>,
ratifications: Vec<Ratify<N>>,
solutions: &Solutions<N>,
Expand Down Expand Up @@ -478,9 +490,11 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
};

// Compute the block reward.
let block_reward = ledger_block::block_reward(
let block_reward = ledger_block::block_reward::<N>(
state.block_height(),
N::STARTING_SUPPLY,
N::BLOCK_TIME,
time_since_last_block,
coinbase_reward,
transaction_fees,
);
Expand Down Expand Up @@ -1458,8 +1472,10 @@ finalize transfer_public:
rng: &mut R,
) -> Result<Block<CurrentNetwork>> {
// Speculate on the candidate ratifications, solutions, and transactions.
let time_since_last_block = CurrentNetwork::BLOCK_TIME as i64;
let (ratifications, transactions, aborted_transaction_ids, ratified_finalize_operations) = vm.speculate(
sample_finalize_state(previous_block.height() + 1),
time_since_last_block,
None,
vec![],
&None.into(),
Expand All @@ -1478,7 +1494,7 @@ finalize transfer_public:
CurrentNetwork::GENESIS_PROOF_TARGET,
previous_block.last_coinbase_target(),
previous_block.last_coinbase_timestamp(),
CurrentNetwork::GENESIS_TIMESTAMP + 1,
previous_block.timestamp().saturating_add(time_since_last_block),
)?;

// Construct the new block header.
Expand Down Expand Up @@ -1736,6 +1752,7 @@ finalize transfer_public:
let (ratifications, confirmed_transactions, aborted_transaction_ids, _) = vm
.speculate(
sample_finalize_state(1),
CurrentNetwork::BLOCK_TIME as i64,
None,
vec![],
&None.into(),
Expand Down Expand Up @@ -1763,7 +1780,14 @@ finalize transfer_public:

// Ensure the dry run of the redeployment will cause a reject transaction to be created.
let (_, candidate_transactions, aborted_transaction_ids, _) = vm
.atomic_speculate(sample_finalize_state(1), None, vec![], &None.into(), [deployment_transaction].iter())
.atomic_speculate(
sample_finalize_state(1),
CurrentNetwork::BLOCK_TIME as i64,
None,
vec![],
&None.into(),
[deployment_transaction].iter(),
)
.unwrap();
assert_eq!(candidate_transactions.len(), 1);
assert!(matches!(candidate_transactions[0], ConfirmedTransaction::RejectedDeploy(..)));
Expand Down Expand Up @@ -1849,8 +1873,16 @@ finalize transfer_public:

// Speculate on the transactions.
let transactions = [bond_validator_transaction.clone()];
let (_, confirmed_transactions, _, _) =
vm.atomic_speculate(sample_finalize_state(1), None, vec![], &None.into(), transactions.iter()).unwrap();
let (_, confirmed_transactions, _, _) = vm
.atomic_speculate(
sample_finalize_state(1),
CurrentNetwork::BLOCK_TIME as i64,
None,
vec![],
&None.into(),
transactions.iter(),
)
.unwrap();

// Assert that the transaction is rejected.
assert_eq!(confirmed_transactions.len(), 1);
Expand Down Expand Up @@ -1952,8 +1984,16 @@ finalize transfer_public:
// Transfer_20 -> Balance = 20 - 20 = 0
{
let transactions = [mint_10.clone(), transfer_10.clone(), transfer_20.clone()];
let (_, confirmed_transactions, aborted_transaction_ids, _) =
vm.atomic_speculate(sample_finalize_state(1), None, vec![], &None.into(), transactions.iter()).unwrap();
let (_, confirmed_transactions, aborted_transaction_ids, _) = vm
.atomic_speculate(
sample_finalize_state(1),
CurrentNetwork::BLOCK_TIME as i64,
None,
vec![],
&None.into(),
transactions.iter(),
)
.unwrap();

// Assert that all the transactions are accepted.
assert_eq!(confirmed_transactions.len(), 3);
Expand All @@ -1972,8 +2012,16 @@ finalize transfer_public:
// Transfer_30 -> Balance = 30 - 30 = 0
{
let transactions = [transfer_20.clone(), mint_10.clone(), mint_20.clone(), transfer_30.clone()];
let (_, confirmed_transactions, aborted_transaction_ids, _) =
vm.atomic_speculate(sample_finalize_state(1), None, vec![], &None.into(), transactions.iter()).unwrap();
let (_, confirmed_transactions, aborted_transaction_ids, _) = vm
.atomic_speculate(
sample_finalize_state(1),
CurrentNetwork::BLOCK_TIME as i64,
None,
vec![],
&None.into(),
transactions.iter(),
)
.unwrap();

// Assert that all the transactions are accepted.
assert_eq!(confirmed_transactions.len(), 4);
Expand All @@ -1992,8 +2040,16 @@ finalize transfer_public:
// Transfer_10 -> Balance = 0 - 10 = -10 (should be rejected)
{
let transactions = [transfer_20.clone(), transfer_10.clone()];
let (_, confirmed_transactions, aborted_transaction_ids, _) =
vm.atomic_speculate(sample_finalize_state(1), None, vec![], &None.into(), transactions.iter()).unwrap();
let (_, confirmed_transactions, aborted_transaction_ids, _) = vm
.atomic_speculate(
sample_finalize_state(1),
CurrentNetwork::BLOCK_TIME as i64,
None,
vec![],
&None.into(),
transactions.iter(),
)
.unwrap();

// Assert that the accepted and rejected transactions are correct.
assert_eq!(confirmed_transactions.len(), 2);
Expand All @@ -2016,8 +2072,16 @@ finalize transfer_public:
// Transfer_10 -> Balance = 10 - 10 = 0
{
let transactions = [mint_20.clone(), transfer_30.clone(), transfer_20.clone(), transfer_10.clone()];
let (_, confirmed_transactions, aborted_transaction_ids, _) =
vm.atomic_speculate(sample_finalize_state(1), None, vec![], &None.into(), transactions.iter()).unwrap();
let (_, confirmed_transactions, aborted_transaction_ids, _) = vm
.atomic_speculate(
sample_finalize_state(1),
CurrentNetwork::BLOCK_TIME as i64,
None,
vec![],
&None.into(),
transactions.iter(),
)
.unwrap();

// Assert that the accepted and rejected transactions are correct.
assert_eq!(confirmed_transactions.len(), 4);
Expand Down Expand Up @@ -2116,7 +2180,15 @@ function ped_hash:

// Speculatively execute the transaction. Ensure that this call does not panic and returns a rejected transaction.
let (_, confirmed_transactions, aborted_transaction_ids, _) = vm
.speculate(sample_finalize_state(1), None, vec![], &None.into(), [transaction.clone()].iter(), rng)
.speculate(
sample_finalize_state(1),
CurrentNetwork::BLOCK_TIME as i64,
None,
vec![],
&None.into(),
[transaction.clone()].iter(),
rng,
)
.unwrap();
assert!(aborted_transaction_ids.is_empty());

Expand Down
16 changes: 12 additions & 4 deletions synthesizer/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
let state = FinalizeGlobalState::new_genesis::<N>()?;
// Speculate on the ratifications, solutions, and transactions.
let (ratifications, transactions, aborted_transaction_ids, ratified_finalize_operations) =
self.speculate(state, None, ratifications, &solutions, transactions.iter(), rng)?;
self.speculate(state, 0, None, ratifications, &solutions, transactions.iter(), rng)?;
ensure!(
aborted_transaction_ids.is_empty(),
"Failed to initialize a genesis block - found aborted transaction IDs"
Expand Down Expand Up @@ -686,8 +686,16 @@ function compute:
let previous_block = vm.block_store().get_block(&block_hash).unwrap().unwrap();

// Construct the new block header.
let (ratifications, transactions, aborted_transaction_ids, ratified_finalize_operations) =
vm.speculate(sample_finalize_state(1), None, vec![], &None.into(), transactions.iter(), rng)?;
let time_since_last_block = MainnetV0::BLOCK_TIME as i64;
let (ratifications, transactions, aborted_transaction_ids, ratified_finalize_operations) = vm.speculate(
sample_finalize_state(1),
time_since_last_block,
None,
vec![],
&None.into(),
transactions.iter(),
rng,
)?;

// Construct the metadata associated with the block.
let metadata = Metadata::new(
Expand All @@ -700,7 +708,7 @@ function compute:
MainnetV0::GENESIS_PROOF_TARGET,
previous_block.last_coinbase_target(),
previous_block.last_coinbase_timestamp(),
MainnetV0::GENESIS_TIMESTAMP + 1,
previous_block.timestamp().saturating_add(time_since_last_block),
)?;

let header = Header::from(
Expand Down
Loading

0 comments on commit 5443685

Please sign in to comment.