diff --git a/src/Makefile.am b/src/Makefile.am index 8fc7f61d4b..24ae008afc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -167,6 +167,8 @@ BITCOIN_CORE_H = \ policy/policy.h \ policy/rbf.h \ policy/settings.h \ + pos.h \ + pos_kernel.h \ pow.h \ protocol.h \ psbt.h \ @@ -286,6 +288,8 @@ libbitcoin_server_a_SOURCES = \ policy/fees.cpp \ policy/rbf.cpp \ policy/settings.cpp \ + pos.cpp \ + pos_kernel.cpp \ pow.cpp \ rest.cpp \ rpc/blockchain.cpp \ diff --git a/src/chain.h b/src/chain.h index 1b67ebbe41..26c303c38d 100644 --- a/src/chain.h +++ b/src/chain.h @@ -14,6 +14,7 @@ #include #include +#include /** * Maximum amount of time that a block timestamp is allowed to exceed the @@ -181,6 +182,10 @@ class CBlockIndex uint32_t nTime; uint32_t nBits; uint32_t nNonce; + boost::optional proofOfStakeBody; + + // proof-of-stake specific fields + uint256 stakeModifier; // hash modifier for proof-of-stake //! (memory only) Sequential id assigned to distinguish order in which blocks are received. int32_t nSequenceId; @@ -204,6 +209,10 @@ class CBlockIndex nSequenceId = 0; nTimeMax = 0; + // PoS + proofOfStakeBody = boost::optional{}; + stakeModifier = uint256{}; + nVersion = 0; hashMerkleRoot = uint256(); nTime = 0; @@ -225,6 +234,8 @@ class CBlockIndex nTime = block.nTime; nBits = block.nBits; nNonce = block.nNonce; + stakeModifier = block.stakeModifier; + proofOfStakeBody = block.proofOfStakeBody; } FlatFilePos GetBlockPos() const { @@ -255,6 +266,8 @@ class CBlockIndex block.nTime = nTime; block.nBits = nBits; block.nNonce = nNonce; + block.stakeModifier = stakeModifier; + block.proofOfStakeBody = proofOfStakeBody; return block; } @@ -300,8 +313,9 @@ class CBlockIndex std::string ToString() const { - return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)", + return strprintf("CBlockIndex(pprev=%p, nHeight=%d, stakeModifier=(%s), merkle=%s, hashBlock=%s)", pprev, nHeight, + stakeModifier.ToString(), hashMerkleRoot.ToString(), GetBlockHash().ToString()); } @@ -329,6 +343,11 @@ class CBlockIndex return false; } + bool IsProofOfStake() const + { + return (bool) proofOfStakeBody; + } + //! Build the skiplist pointer for this entry. void BuildSkip(); @@ -376,6 +395,11 @@ class CDiskBlockIndex : public CBlockIndex if (nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(nUndoPos)); + //PoS serialization + CBlockHeader::PoS loc_proofOfStake = proofOfStakeBody ? *proofOfStakeBody : CBlockHeader::PoS{}; + READWRITE(loc_proofOfStake); + proofOfStakeBody = loc_proofOfStake; + // block header READWRITE(this->nVersion); READWRITE(hashPrev); @@ -394,6 +418,8 @@ class CDiskBlockIndex : public CBlockIndex block.nTime = nTime; block.nBits = nBits; block.nNonce = nNonce; + block.stakeModifier = stakeModifier; + block.proofOfStakeBody = proofOfStakeBody; return block.GetHash(); } diff --git a/src/chainparams.cpp b/src/chainparams.cpp index f511be2e68..ec66a23226 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -69,6 +69,17 @@ class CMainParams : public CChainParams { consensus.BIP34Hash = uint256S("0x000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8"); consensus.BIP65Height = 388381; // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0 consensus.BIP66Height = 363725; // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931 + + consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.pos.nTargetTimespan = 14 * 24 * 60 * 60; // two weeks + consensus.pos.nTargetSpacing = 10 * 60; // 10 minutes + consensus.pos.fAllowMinDifficultyBlocks = false; // only for regtest + consensus.pos.fNoRetargeting = false; // only for regtest + + consensus.pos.coinstakeMaturity = 100; + + consensus.pos.allowMintingWithoutPeers = false; // don't mint if no peers connected + consensus.CSVHeight = 419328; // 000000000000000004a1b34462cb8aeebd5799177f7a29cf28f2d1961716b5b5 consensus.SegwitHeight = 481824; // 0000000000000000001c8018d9cb3b742ef25114f27563e3fc4a1902167f9893 consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); @@ -175,6 +186,17 @@ class CTestNetParams : public CChainParams { consensus.BIP34Hash = uint256S("0x0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8"); consensus.BIP65Height = 581885; // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6 consensus.BIP66Height = 330776; // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182 + + consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.pos.nTargetTimespan = 14 * 24 * 60 * 60; // two weeks + consensus.pos.nTargetSpacing = 10 * 60; // 10 minutes + consensus.pos.fAllowMinDifficultyBlocks = false; // only for regtest + consensus.pos.fNoRetargeting = false; // only for regtest + + consensus.pos.coinstakeMaturity = 100; + + consensus.pos.allowMintingWithoutPeers = false; // don't mint if no peers connected + consensus.CSVHeight = 770112; // 00000000025e930139bac5c6c31a403776da130831ab85be56578f3fa75369bb consensus.SegwitHeight = 834624; // 00000000002b980fcd729daaa248fd9316a5200e9b367f4ff2c42453e84201ca consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); @@ -259,6 +281,16 @@ class CRegTestParams : public CChainParams { consensus.BIP34Hash = uint256(); consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in functional tests) consensus.BIP66Height = 1251; // BIP66 activated on regtest (Used in functional tests) + consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.pos.nTargetTimespan = 14 * 24 * 60 * 60; // two weeks + consensus.pos.nTargetSpacing = 10 * 60; // 10 minutes + consensus.pos.fAllowMinDifficultyBlocks = false; // only for regtest + consensus.pos.fNoRetargeting = false; // only for regtest + + consensus.pos.coinstakeMaturity = 100; + + consensus.pos.allowMintingWithoutPeers = false; // don't mint if no peers connected + consensus.CSVHeight = 432; // CSV activated on regtest (Used in rpc activation tests) consensus.SegwitHeight = 0; // SEGWIT is always activated on regtest unless overridden consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); diff --git a/src/consensus/params.h b/src/consensus/params.h index 8263b0fef4..c903b48a1d 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -10,6 +10,7 @@ #include #include #include +#include namespace Consensus { @@ -62,6 +63,22 @@ struct Params { * Note that segwit v0 script rules are enforced on all blocks except the * BIP 16 exception blocks. */ int SegwitHeight; + + struct PoS { + uint256 diffLimit; + int64_t nTargetTimespan; + int64_t nTargetSpacing; + bool fAllowMinDifficultyBlocks; + bool fNoRetargeting; + + int64_t DifficultyAdjustmentInterval() const { return nTargetTimespan / nTargetSpacing; } + + arith_uint256 interestAtoms = arith_uint256{10000000000000000ull}; + bool allowMintingWithoutPeers; + int coinstakeMaturity = 500; + }; + PoS pos; + /** * Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period, * (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments. diff --git a/src/miner.cpp b/src/miner.cpp index 015645c9c6..63ed457ca2 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include