1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
#![cfg_attr(not(feature = "std"), no_std)]
// TODO: This originates from `sp_api::decl_runtime_apis`.
#![allow(clippy::multiple_bound_locations)]
extern crate alloc;
use alloc::vec::Vec;
use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_runtime::ConsensusEngineId;
/// The `ConsensusEngineId` of Bitcoin block hash.
pub const NAKAMOTO_HASH_ENGINE_ID: ConsensusEngineId = *b"hash";
/// The `ConsensusEngineId` of Bitcoin block header.
pub const NAKAMOTO_HEADER_ENGINE_ID: ConsensusEngineId = *b"hedr";
/// 1 BTC in satoshis
const COIN: u64 = 100_000_000;
/// Initial block reward
const INITIAL_SUBSIDY: u64 = 50 * COIN;
const HALVING_INTERVAL: u32 = 210_000;
const MAX_SCRIPT_SIZE: usize = 10_000;
/// Unspent transaction output.
#[derive(Debug, TypeInfo, Encode, Decode)]
pub struct Coin {
/// Whether the coin is from a coinbase transaction.
pub is_coinbase: bool,
/// Transfer value in satoshis.
pub amount: u64,
// Block height at which this containing transaction was included.
pub height: u32,
/// Spending condition of the output.
pub script_pubkey: Vec<u8>,
}
impl MaxEncodedLen for Coin {
fn max_encoded_len() -> usize {
bool::max_encoded_len() + u64::max_encoded_len() + MAX_SCRIPT_SIZE
}
}
/// Returns the amount of subsidy in satoshis at given height.
pub fn bitcoin_block_subsidy(height: u32) -> u64 {
block_subsidy(height, HALVING_INTERVAL)
}
/// Returns the block subsidy at given height and halving interval.
fn block_subsidy(height: u32, subsidy_halving_interval: u32) -> u64 {
let halvings = height / subsidy_halving_interval;
// Force block reward to zero when right shift is undefined.
if halvings >= 64 {
return 0;
}
let mut subsidy = INITIAL_SUBSIDY;
// Subsidy is cut in half every 210,000 blocks which will occur
// approximately every 4 years.
subsidy >>= halvings;
subsidy
}
sp_api::decl_runtime_apis! {
/// Subcoin API.
pub trait Subcoin {
/// Same as the original `execute_block()` with the removal
/// of `state_root` check in the `final_checks()`.
fn execute_block_without_state_root_check(block: Block);
/// Finalize block without checking the extrinsics_root and state_root.
fn finalize_block_without_checks(header: Block::Header);
}
}