subcoin_runtime_primitives/
lib.rs

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