Last active
November 2, 2021 20:51
-
-
Save vital-edu/3099119f8c847c396dbfe2bc08bc7dfe to your computer and use it in GitHub Desktop.
Bitcoin max supply simulation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ####################################### | |
// ----- bin/bitcoin_simulation.dart ----- | |
// ####################################### | |
import 'dart:math'; | |
import 'package:intl/intl.dart'; | |
// import 'package:bitcoin_ssimulation/chain_params.dart'; | |
// import 'package:bitcoin_simulation/consensus/params.dart'; | |
// import 'package:bitcoin_simulation/validation.dart'; | |
// import 'package:bitcoin_simulation/consensus/amount.dart'; | |
typedef BlockSubsidyFunction = CAmount Function(int, Params); | |
/// This programm will simulate the max number of bitcoin that will be mined | |
/// by the Bitcoin Network. | |
/// | |
/// Excute with `new` as the first argument to run a modified algorithm that | |
/// would produce exactly 21 millions of satoshis: | |
/// ```shell | |
/// dart bin/bitcoin_simulation.dart new | |
/// ``` | |
/// | |
/// Without any args, it will be executed the simulation based on the current | |
/// Bitcoin Core implementation, which will mine 20999999.97690000 bitcoins | |
/// or less: | |
/// ```shell | |
/// dart bin/bitcoin_simulation.dart | |
/// ``` | |
int main(List<String> args) { | |
// Uncomment the code below to run the modified version on dartpad. | |
// args = ["new"]; | |
BlockSubsidyFunction blockSubsidy = args.isNotEmpty && args.first == 'new' | |
? modifiedGetBlockSubsidy | |
: getBlockSubsidy; | |
CAmount satoshis = CAmount.zero; | |
int blocksMined = 0; | |
final Params consensusParams = CMainParams().consensus; | |
while (satoshis < MAX_MONEY) { | |
CAmount subsidy = blockSubsidy(blocksMined, consensusParams); | |
if (subsidy == CAmount.zero) break; | |
satoshis += (subsidy * CAmount.from(consensusParams.nSubsidyHalvingInterval)); | |
blocksMined += consensusParams.nSubsidyHalvingInterval; | |
} | |
final lastSubsidizedBlock = blocksMined - 1; | |
final btc = satoshis / COIN; | |
final maxHalvings = | |
lastSubsidizedBlock ~/ consensusParams.nSubsidyHalvingInterval; | |
final lastSubsidizedBlockMinedAt = | |
approximateYearOfMinedBlock(lastSubsidizedBlock); | |
print('Last subsidized block: $lastSubsidizedBlock'); | |
print('Last subsidized block mined on the year: $lastSubsidizedBlockMinedAt'); | |
print('Max quantity of satoshis to be created: ${satoshis.toInt()}'); | |
print('Max quantity of BTC to be created: ${btc.toStringAsFixed(8)}'); | |
print('Max quantity of halvings that will happen: $maxHalvings'); | |
return 0; | |
} | |
int approximateYearOfMinedBlock(int blocksMined) { | |
const firstBlockDate = "January 09, 2009 02:54 AM UTC"; | |
const dateFormat = "MMMM d, yyyy hh:mm a UTC"; | |
const approximateMinutesToMineBlock = 10; | |
final firstBlockMiningDate = | |
DateFormat(dateFormat).parse(firstBlockDate, true); | |
final blockMinedDate = firstBlockMiningDate.add( | |
Duration(minutes: approximateMinutesToMineBlock * blocksMined), | |
); | |
return blockMinedDate.year; | |
} | |
CAmount modifiedGetBlockSubsidy(int nHeight, Params consensusParams) { | |
int halvings = nHeight ~/ consensusParams.nSubsidyHalvingInterval; | |
// Force block reward to zero when right shift is undefined. | |
if (halvings >= 64) return CAmount.zero; | |
double nSubsidy = 50.0 * COIN.toInt(); | |
// Subsidy is cut in half every 210,000 blocks which will occur approximately every 4 years. | |
nSubsidy /= pow(2, halvings); | |
return nSubsidy >= 1 | |
? CAmount.from(nSubsidy.floor()) | |
: CAmount.from(nSubsidy.ceil()); | |
} | |
// ##################################### | |
// ----- lib/consensus/amount.dart ----- | |
// ##################################### | |
/// This file contains fragments of the source code of the Bitcoin Core rewritten with dart-lang. | |
/// [See original implementation](https://github.com/bitcoin/bitcoin/blob/816e15ee81a2029cde6b4f9fe6fb93e75478c903/src/consensus/amount.h) | |
// ignore_for_file: constant_identifier_names, non_constant_identifier_names | |
/// Amount in satoshis (Can be negative) | |
/// --- | |
/// [Original implementation](https://github.com/bitcoin/bitcoin/blob/816e15ee81a2029cde6b4f9fe6fb93e75478c903/src/consensus/amount.h#L11-L12): | |
/// ```cpp | |
/// typedef int CAmount; | |
/// ``` | |
/// | |
/// CAmount is defined as BigInt to allow compatibility with dart for web. | |
typedef CAmount = BigInt; | |
/// --- | |
/// [Original implementation](https://github.com/bitcoin/bitcoin/blob/816e15ee81a2029cde6b4f9fe6fb93e75478c903/src/consensus/amount.h#L14): | |
/// ```cpp | |
/// static constexpr CAmount COIN = 100000000; | |
/// ``` | |
final CAmount COIN = CAmount.from(100000000); | |
/// No amount larger than this (in satoshi) is valid. | |
/// | |
/// Note that this constant is *not* the total money supply, which in Bitcoin | |
/// currently happens to be less than 21,000,000 BTC for various reasons, but | |
/// rather a sanity check. As this sanity check is used by consensus-critical | |
/// validation code, the exact value of the MAX_MONEY constant is consensus | |
/// critical; in unusual circumstances like a(nother) overflow bug that allowed | |
/// for the creation of coins out of thin air modification could lead to a fork. | |
/// --- | |
/// [Original implementation](https://github.com/bitcoin/bitcoin/blob/816e15ee81a2029cde6b4f9fe6fb93e75478c903/src/consensus/amount.h#L16-L25): | |
/// ```cpp | |
/// static constexpr CAmount MAX_MONEY = 21000000 * COIN;; | |
/// ``` | |
final CAmount MAX_MONEY = CAmount.from(21000000) * COIN; | |
// ################################# | |
// ----- lib/chain_params.dart ----- | |
// ################################# | |
/// This file contains fragments of the source code of the Bitcoin Core rewritten with dart-lang. | |
/// [See original header definition](https://github.com/bitcoin/bitcoin/blob/feedb9c84e72e4fff489810a2bbeec09bcda5763/src/chainparams.h) | |
/// [See original implementation](https://github.com/bitcoin/bitcoin/blob/feedb9c84e72e4fff489810a2bbeec09bcda5763/src/chainparams.cpp) | |
// import 'consensus/params.dart'; | |
/// CChainParams defines various tweakable parameters of a given instance of the | |
/// Bitcoin system. | |
/// --- | |
/// Only the param `consensus` was keep. | |
/// [See original implementation](https://github.com/bitcoin/bitcoin/blob/7fcf53f7b4524572d1d0c9a5fdc388e87eb02416/src/chainparams.h#L60-L133) | |
abstract class CChainParams { | |
final Params consensus; | |
CChainParams({ | |
required this.consensus, | |
}); | |
} | |
/// Main network on which people trade goods and services. | |
/// --- | |
/// [See original implementation](https://github.com/bitcoin/bitcoin/blob/feedb9c84e72e4fff489810a2bbeec09bcda5763/src/chainparams.cpp#L58-L175) | |
class CMainParams implements CChainParams { | |
/// --- | |
/// The consensus params with the `nSubsidyHalvingInterval` definition. | |
/// [See original implementation](https://github.com/bitcoin/bitcoin/blob/feedb9c84e72e4fff489810a2bbeec09bcda5763/src/chainparams.cpp#L67) | |
const CMainParams() | |
: consensus = const Params(210000), | |
super(); | |
@override | |
final Params consensus; | |
} | |
// ########################################## | |
// ----- lib/consensus/params.dart.dart ----- | |
// ########################################## | |
/// This file contains fragments of the source code of the Bitcoin Core rewritten with dart-lang. | |
/// [See original implementation](https://github.com/bitcoin/bitcoin/blob/7fcf53f7b4524572d1d0c9a5fdc388e87eb02416/src/consensus/params.h) | |
/// Parameters that influence chain consensus. | |
/// --- | |
/// Only the param `nSubsidyHalvingInterval` was keep. | |
/// [See original implementation](https://github.com/bitcoin/bitcoin/blob/7fcf53f7b4524572d1d0c9a5fdc388e87eb02416/src/consensus/params.h#L46-L93) | |
class Params { | |
/// --- | |
/// This is used to determine when the halving will happen. | |
/// Every `nSubsidyHalvingInterval` block mined, happens a new halving. | |
/// [See original implementation](https://github.com/bitcoin/bitcoin/blob/7fcf53f7b4524572d1d0c9a5fdc388e87eb02416/src/consensus/params.h#L48) | |
final int nSubsidyHalvingInterval; | |
const Params(this.nSubsidyHalvingInterval); | |
} | |
// ############################### | |
// ----- lib/validation.dart ----- | |
// ############################### | |
/// This file contains fragments of the source code of the Bitcoin Core rewritten with dart-lang. | |
/// [See original implementation](https://github.com/bitcoin/bitcoin/blob/816e15ee81a2029cde6b4f9fe6fb93e75478c903/src/consensus/amount.h) | |
// import 'consensus/amount.dart'; | |
// import 'consensus/params.dart'; | |
/// Function defined on Bitcoin Core rewritten with dart-lang. | |
/// | |
/// [See original implementation](https://github.com/bitcoin/bitcoin/blob/1847ce2d49e13f76824bb6b52985e8ef5fbcd1db/src/validation.cpp#L1068-L1079): | |
/// ```cpp | |
/// CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) | |
/// { | |
/// int halvings = nHeight / consensusParams.nSubsidyHalvingInterval; | |
/// // Force block reward to zero when right shift is undefined. | |
/// if (halvings >= 64) | |
/// return 0; | |
/// | |
/// CAmount nSubsidy = 50 * COIN; | |
/// // Subsidy is cut in half every 210,000 blocks which will occur approximately every 4 years. | |
/// nSubsidy >>= halvings; | |
/// return nSubsidy; | |
/// } | |
/// ``` | |
CAmount getBlockSubsidy(int nHeight, Params consensusParams) { | |
int halvings = nHeight ~/ consensusParams.nSubsidyHalvingInterval; | |
// Force block reward to zero when right shift is undefined. | |
if (halvings >= 64) return CAmount.zero; | |
CAmount nSubsidy = CAmount.from(50) * COIN; | |
// Subsidy is cut in half every 210,000 blocks which will occur approximately every 4 years. | |
nSubsidy >>= halvings; | |
return nSubsidy; | |
} | |
// ######################## | |
// ----- pubspec.yaml ----- | |
// ######################## | |
// ```yaml | |
// name: bitcoin_simulation | |
// description: Bitcoin max supply simulation | |
// version: 1.0.0 | |
// | |
// environment: | |
// sdk: '>=2.14.2 <3.0.0' | |
// | |
// dev_dependencies: | |
// lints: ^1.0.0 | |
// dependencies: | |
// intl: ^0.17.0 | |
// ``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment