Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

start compute block reward impl #37

Merged
73 changes: 72 additions & 1 deletion src/validation.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use super::state::{Block, ChainState, Transaction, UtreexoState};
use super::utils::{shl, shr};

const MAX_TARGET: u256 = 0x00000000FFFF0000000000000000000000000000000000000000000000000000;
pub const REWARD_INITIAL: u256 = 50; // 50 BTC in satoshis => 5000000000 SATS
pub const POW_SATS_AMOUNT: u256 = 8; // Pow to convert in SATS

#[generate_trait]
impl BlockValidatorImpl of BlockValidator {
Expand Down Expand Up @@ -206,9 +208,28 @@ fn validate_coinbase(block: @Block, total_fees: u256) -> Result<(), ByteArray> {
Result::Ok(())
}

// Return BTC reward in SATS
fn compute_block_reward(block_height: u32) -> u64 {
let number_halvings = block_height / 210_000;
match number_halvings {
0 => {
return shl(REWARD_INITIAL, POW_SATS_AMOUNT.try_into().unwrap()).try_into().unwrap();
}, // return REWARD_INITAL
_ => {}
}
// Calculate BTC to SATS amount
let sats_init_amount = shl(REWARD_INITIAL, POW_SATS_AMOUNT.try_into().unwrap());
// Shift right to divide by number_halvings
let current_reward = shr(sats_init_amount, number_halvings);
// Convert into a u64
(current_reward).try_into().unwrap()
}
#[cfg(test)]
mod tests {
use super::{validate_target, validate_timestamp, validate_proof_of_work};
use super::{
validate_target, validate_timestamp, validate_proof_of_work, compute_block_reward, shr, shl,
REWARD_INITIAL, POW_SATS_AMOUNT
};
use super::{Block, ChainState, UtreexoState};
use super::super::state::{Header, Transaction, TxIn, TxOut};

Expand Down Expand Up @@ -302,4 +323,54 @@ mod tests {
let result = validate_proof_of_work(@10_u256, @block);
assert!(result.is_ok(), "Expect prev block hash lt target");
}

// Ref implementation here:
// https://github.com/bitcoin/bitcoin/blob/0f68a05c084bef3e53e3f549c403bc90b1db319c/src/test/validation_tests.cpp#L24
#[test]
fn test_compute_block_reward() {
let max_halvings: u32 = 64;
let reward_initial: u256 = shl(
REWARD_INITIAL.try_into().unwrap(), POW_SATS_AMOUNT.try_into().unwrap()
);
let halving_block_range = 210_000; // every 210 000 blocks
let mut nprevious_subsidy: u256 = shl(
REWARD_INITIAL.try_into().unwrap() * 2, POW_SATS_AMOUNT.try_into().unwrap()
);
let mut halving_index: u32 = 0;
assert_eq!(nprevious_subsidy.try_into().unwrap(), reward_initial * 2);

// First halving block reward : initial supply in SATS
let first_halving_reward = compute_block_reward(halving_index * halving_block_range);
assert_eq!(first_halving_reward, reward_initial.try_into().unwrap());

// Second halving block reward : initial supply in SATS
let second_halving_reward = compute_block_reward((halving_index + 1) * halving_block_range);
assert_eq!(second_halving_reward, reward_initial.try_into().unwrap() / 2);

// Test the reward when we have 5 halvings
let five_halving_reward = compute_block_reward((halving_index + 5) * halving_block_range);
let five_reward_amount = shr(reward_initial.try_into().unwrap(), halving_index + 5)
.try_into()
.unwrap();
assert_eq!(five_halving_reward, five_reward_amount);

// Last halving block reward = 0
let last_reward = compute_block_reward(max_halvings * halving_block_range);
assert_eq!(last_reward, 0);

// Testing all halvings rewards possible
loop {
if halving_index == max_halvings {
break;
}
let block_height: u32 = halving_index * halving_block_range;
// Compute reward
let reward = compute_block_reward(block_height);
assert!(reward <= reward_initial.try_into().unwrap());
let cast_nprevious_subsidy: u64 = nprevious_subsidy.try_into().unwrap();
assert_eq!(reward, cast_nprevious_subsidy / 2);
nprevious_subsidy = reward.try_into().unwrap();
halving_index = halving_index + 1;
};
}
}