Skip to content

Commit 69d78b5

Browse files
celbalraiwagerr-builder
authored andcommitted
Introduce block time protocol V2 (15 second windows)
- Port and adapt PIVX commits on time protocol V2 (PR dashpay#1002) - Port PIVX commits on nTime offset warnings (PR dashpay#1138) - Adjust chain parameters - Add several copyright notices
1 parent d2b2c5f commit 69d78b5

19 files changed

+262
-98
lines changed

src/chain.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,38 @@ unsigned int CBlockIndex::GetStakeEntropyBit() const
124124
return ((UintToArith256(GetBlockHash()).GetLow64()) & 1);
125125
}
126126

127+
int CBlockIndex::FutureBlockTimeDrift(const int nHeight, const Consensus::Params& params) const
128+
{
129+
if (params.IsTimeProtocolV2(nHeight))
130+
// PoS (TimeV2): 14 seconds
131+
return params.nTimeSlotLength - 1;
132+
133+
// PoS (TimeV1): 3 minutes
134+
// PoW: 2 hours
135+
return (nHeight >= params.nPosStartHeight) ? MAX_FUTURE_BLOCK_TIME_POS : MAX_FUTURE_BLOCK_TIME_POW;
136+
}
137+
138+
int64_t CBlockIndex::MaxFutureBlockTime(int64_t nAdjustedTime, const Consensus::Params& params) const
139+
{
140+
return nAdjustedTime + FutureBlockTimeDrift(nHeight+1, params);
141+
}
142+
143+
int64_t CBlockIndex::MinPastBlockTime(const Consensus::Params& params) const
144+
{
145+
// Time Protocol v1: pindexPrev->MedianTimePast + 1
146+
if (!params.IsTimeProtocolV2(nHeight+1))
147+
return GetMedianTimePast();
148+
149+
// on the transition from Time Protocol v1 to v2
150+
// pindexPrev->nTime might be in the future (up to the allowed drift)
151+
// so we allow the nBlockTimeProtocolV2 to be at most (180-14) seconds earlier than previous block
152+
if (nHeight + 1 == params.nBlockTimeProtocolV2)
153+
return GetBlockTime() - FutureBlockTimeDrift(nHeight, params) + FutureBlockTimeDrift(nHeight + 1, params);
154+
155+
// Time Protocol v2: pindexPrev->nTime
156+
return GetBlockTime();
157+
}
158+
127159
arith_uint256 GetBlockProof(const CBlockIndex& block)
128160
{
129161
arith_uint256 bnTarget;

src/chain.h

+14-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
// Copyright (c) 2009-2010 Satoshi Nakamoto
22
// Copyright (c) 2009-2015 The Bitcoin Core developers
3+
// Copyright (c) 2011-2013 The PPCoin developers
4+
// Copyright (c) 2013-2014 The NovaCoin Developers
5+
// Copyright (c) 2014-2018 The BlackCoin Developers
6+
// Copyright (c) 2015-2019 The PIVX developers
37
// Distributed under the MIT software license, see the accompanying
48
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
59

@@ -18,15 +22,16 @@
1822
* Maximum amount of time that a block timestamp is allowed to exceed the
1923
* current network-adjusted time before the block will be accepted.
2024
*/
21-
static const int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60;
25+
static const int64_t MAX_FUTURE_BLOCK_TIME_POW = 2 * 60 * 60;
26+
static const int64_t MAX_FUTURE_BLOCK_TIME_POS = 3 * 60;
2227

2328
/**
2429
* Timestamp window used as a grace period by code that compares external
2530
* timestamps (such as timestamps passed to RPCs, or wallet key creation times)
2631
* to block timestamps. This should be set at least as high as
27-
* MAX_FUTURE_BLOCK_TIME.
32+
* MAX_FUTURE_BLOCK_TIME_POW.
2833
*/
29-
static const int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME;
34+
static const int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME_POW;
3035

3136
class CBlockFileInfo
3237
{
@@ -362,6 +367,12 @@ class CBlockIndex
362367
return pbegin[(pend - pbegin)/2];
363368
}
364369

370+
int FutureBlockTimeDrift(const int nHeight, const Consensus::Params& params) const;
371+
372+
int64_t MaxFutureBlockTime(int64_t nAdjustedTime, const Consensus::Params& params) const;
373+
374+
int64_t MinPastBlockTime(const Consensus::Params& params) const;
375+
365376
bool IsProofOfWork() const
366377
{
367378
return !(nFlags & BLOCK_PROOF_OF_STAKE);

src/chainparams.cpp

+31-11
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ class CMainParams : public CChainParams {
360360
consensus.nGovernanceMinQuorum = 10;
361361
consensus.nGovernanceFilterElements = 20000;
362362
consensus.nMasternodeMinimumConfirmations = 15;
363-
consensus.V16DeploymentHeight = 1600000;
363+
consensus.V16DeploymentHeight = std::numeric_limits<int64_t>::max();
364364
consensus.BIP34Height = 1;
365365
consensus.BIP34Hash = uint256S("000001364c4ed20f1b240810b5aa91fee23ae9b64b6e746b594b611cf6d8c87b");
366366
consensus.BIP65Height = consensus.V16DeploymentHeight;
@@ -379,14 +379,19 @@ class CMainParams : public CChainParams {
379379
// Wagerr specific parameters
380380
// Proof of Stake parameters
381381
consensus.nPosStartHeight = 201;
382-
consensus.nPivxProtocolV2StartHeight = std::numeric_limits<int>::max();
382+
consensus.nBlockTimeProtocolV2 = consensus.V16DeploymentHeight;
383383
consensus.posLimit = uint256S("000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 24
384+
consensus.posLimit_V2 = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 20
385+
consensus.nTimeSlotLength = 15;
384386
consensus.nPosTargetSpacing = 1 * 60; // 1 minute
387+
consensus.nPosTargetTimespan = 40 * 60; // 40 minutes
388+
consensus.nPosTargetTimespan_V2 = 2 * consensus.nTimeSlotLength * 60; // 30 minutes
385389
consensus.nStakeMinDepth = 600;
390+
consensus.nStakeMinAge = 60 * 60; // 1 hour
386391
consensus.nBlockStakeModifierV1A = 1000;
387-
consensus.nBlockStakeModifierV2 = std::numeric_limits<int>::max();
392+
consensus.nBlockStakeModifierV2 = consensus.V16DeploymentHeight;
388393
// ATP parameters
389-
consensus.ATPStartHeight = std::numeric_limits<int64_t>::max();
394+
consensus.ATPStartHeight = consensus.V16DeploymentHeight;
390395
consensus.WagerrAddrPrefix = "wagerr";
391396
consensus.strTokenManagementKey = "sYG1qGUtbTdNRYtFsKvnY3GvuauF3eVwhT";
392397
consensus.nOpGroupNewRequiredConfirmations = 1;
@@ -548,7 +553,7 @@ class CTestNetParams : public CChainParams {
548553
consensus.nGovernanceMinQuorum = 1;
549554
consensus.nGovernanceFilterElements = 500;
550555
consensus.nMasternodeMinimumConfirmations = 1;
551-
consensus.V16DeploymentHeight = 1600000;
556+
consensus.V16DeploymentHeight = std::numeric_limits<int>::max();
552557
consensus.BIP34Height = 1;
553558
consensus.BIP34Hash = uint256S("0000065432f43b3efb23bd0f63fe33d00d02a5f36233fe1b982c08274d58ef12");
554559
consensus.BIP65Height = consensus.V16DeploymentHeight;
@@ -567,10 +572,15 @@ class CTestNetParams : public CChainParams {
567572
// Wagerr specific parameters
568573
// Proof of Stake parameters
569574
consensus.nPosStartHeight = 201;
570-
consensus.nPivxProtocolV2StartHeight = std::numeric_limits<int>::max();
575+
consensus.nBlockTimeProtocolV2 = consensus.V16DeploymentHeight;
571576
consensus.posLimit = uint256S("000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 24
577+
consensus.posLimit_V2 = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 20
578+
consensus.nTimeSlotLength = 15;
572579
consensus.nPosTargetSpacing = 1 * 60; // 1 minute
580+
consensus.nPosTargetTimespan = 40 * 60; // 40 minutes
581+
consensus.nPosTargetTimespan_V2 = 2 * consensus.nTimeSlotLength * 60; // 30 minutes
573582
consensus.nStakeMinDepth = 100;
583+
consensus.nStakeMinAge = 60 * 60; // 1 hour
574584
consensus.nBlockStakeModifierV1A = 51197;
575585
consensus.nBlockStakeModifierV2 = std::numeric_limits<int>::max();
576586
// ATP parameters
@@ -739,12 +749,17 @@ class CDevNetParams : public CChainParams {
739749
// Wagerr specific parameters
740750
// Proof of Stake parameters
741751
consensus.nPosStartHeight = 201;
742-
consensus.nPivxProtocolV2StartHeight = 2000;
752+
consensus.nBlockTimeProtocolV2 = consensus.V16DeploymentHeight;
743753
consensus.posLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 1
754+
consensus.posLimit_V2 = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 1
755+
consensus.nTimeSlotLength = 15;
744756
consensus.nPosTargetSpacing = 1 * 60; // 1 minute
757+
consensus.nPosTargetTimespan = 40 * 60; // 40 minutes
758+
consensus.nPosTargetTimespan_V2 = 2 * consensus.nTimeSlotLength * 60; // 30 minutes
745759
consensus.nStakeMinDepth = 100;
760+
consensus.nStakeMinAge = 60 * 60; // 1 hour
746761
consensus.nBlockStakeModifierV1A = 1000;
747-
consensus.nBlockStakeModifierV2 = consensus.nPivxProtocolV2StartHeight;
762+
consensus.nBlockStakeModifierV2 = consensus.V16DeploymentHeight;
748763
// ATP parameters
749764
consensus.ATPStartHeight = std::numeric_limits<int64_t>::max();
750765
consensus.WagerrAddrPrefix = "wagerrtest";
@@ -889,7 +904,7 @@ class CRegTestParams : public CChainParams {
889904
consensus.nGovernanceMinQuorum = 1;
890905
consensus.nGovernanceFilterElements = 100;
891906
consensus.nMasternodeMinimumConfirmations = 1;
892-
consensus.V16DeploymentHeight = 1600000;
907+
consensus.V16DeploymentHeight = 300;
893908
consensus.BIP34Height = 100000000; // BIP34 has not activated on regtest (far in the future so block v1 are not rejected in tests)
894909
consensus.BIP34Hash = uint256();
895910
consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in rpc activation tests)
@@ -908,12 +923,17 @@ class CRegTestParams : public CChainParams {
908923
// Wagerr specific parameters
909924
// Proof of Stake parameters
910925
consensus.nPosStartHeight = 201;
911-
consensus.nPivxProtocolV2StartHeight = 2000;
926+
consensus.nBlockTimeProtocolV2 = consensus.V16DeploymentHeight;
912927
consensus.posLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 1
928+
consensus.posLimit_V2 = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 1
929+
consensus.nTimeSlotLength = 15;
913930
consensus.nPosTargetSpacing = 1 * 60; // 1 minute
931+
consensus.nPosTargetTimespan = 40 * 60; // 40 minutes
932+
consensus.nPosTargetTimespan_V2 = 2 * consensus.nTimeSlotLength * 60; // 30 minutes
914933
consensus.nStakeMinDepth = 100;
934+
consensus.nStakeMinAge = 0;
915935
consensus.nBlockStakeModifierV1A = 1000;
916-
consensus.nBlockStakeModifierV2 = consensus.nPivxProtocolV2StartHeight;
936+
consensus.nBlockStakeModifierV2 = consensus.V16DeploymentHeight;
917937
// ATP parameters
918938
consensus.ATPStartHeight = std::numeric_limits<int64_t>::max();
919939
consensus.WagerrAddrPrefix = "wagerrreg";

src/consensus/params.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,21 @@ struct Params {
190190

191191
/** Proof of stake parameters */
192192
int64_t nPosStartHeight;
193-
int64_t nPivxProtocolV2StartHeight;
194193
uint256 posLimit;
194+
uint256 posLimit_V2;
195195
int64_t nPosTargetSpacing;
196+
int64_t nPosTargetTimespan;
197+
int64_t nPosTargetTimespan_V2;
196198
int32_t nStakeMinDepth;
199+
int32_t nStakeMinAge;
197200
int64_t nBlockStakeModifierV1A;
198201
int64_t nBlockStakeModifierV2;
199202

203+
/** Time Protocol V2 **/
204+
int nBlockTimeProtocolV2;
205+
bool IsTimeProtocolV2(const int nHeight) const { return nHeight >= nBlockTimeProtocolV2; }
206+
int nTimeSlotLength;
207+
200208
/** ATP parameters */
201209
int64_t ATPStartHeight;
202210
std::string WagerrAddrPrefix;

src/miner.cpp

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
// Copyright (c) 2009-2010 Satoshi Nakamoto
22
// Copyright (c) 2009-2015 The Bitcoin Core developers
3+
// Copyright (c) 2011-2013 The PPCoin developers
4+
// Copyright (c) 2013-2014 The NovaCoin Developers
5+
// Copyright (c) 2014-2018 The BlackCoin Developers
6+
// Copyright (c) 2015-2019 The PIVX developers
37
// Copyright (c) 2014-2021 The Dash Core developers
48
// Distributed under the MIT software license, see the accompanying
59
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -61,7 +65,12 @@ uint64_t nLastBlockSize = 0;
6165
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
6266
{
6367
int64_t nOldTime = pblock->nTime;
64-
int64_t nNewTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
68+
int64_t nNewTime;
69+
if (consensusParams.IsTimeProtocolV2(pindexPrev->nHeight + 1)) {
70+
nNewTime = GetTimeSlot(GetAdjustedTime());
71+
} else {
72+
nNewTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
73+
}
6574

6675
if (nOldTime < nNewTime)
6776
pblock->nTime = nNewTime;
@@ -139,7 +148,7 @@ bool BlockAssembler::SplitCoinstakeVouts(std::shared_ptr<CMutableTransaction> co
139148
}
140149

141150
std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn,
142-
std::shared_ptr<CMutableTransaction> pCoinstakeTx, std::shared_ptr<CStakeInput> coinstakeInput, unsigned int nTxNewTime)
151+
std::shared_ptr<CMutableTransaction> pCoinstakeTx, std::shared_ptr<CStakeInput> coinstakeInput, uint64_t nTxNewTime)
143152
{
144153
CBasicKeyStore tempKeystore;
145154
#ifdef ENABLE_WALLET

src/miner.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ class BlockAssembler
162162

163163
/** Construct a new block template with coinbase to scriptPubKeyIn */
164164
std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn,
165-
std::shared_ptr<CMutableTransaction> pCoinstakeTx = nullptr, std::shared_ptr<CStakeInput> coinstakeInput = nullptr, unsigned int nTxNewTime = 0);
165+
std::shared_ptr<CMutableTransaction> pCoinstakeTx = nullptr, std::shared_ptr<CStakeInput> coinstakeInput = nullptr, uint64_t nTxNewTime = 0);
166166

167167
private:
168168
// utility functions

src/net.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -2338,6 +2338,32 @@ int CConnman::GetExtraOutboundCount()
23382338
return std::max(nOutbound - nMaxOutbound, 0);
23392339
}
23402340

2341+
void CConnman::CheckOffsetDisconnectedPeers(const CNetAddr& ip)
2342+
{
2343+
int nConnections = 0;
2344+
{
2345+
LOCK(cs_vNodes);
2346+
for (CNode* pnode : vNodes) {
2347+
if (pnode->fSuccessfullyConnected)
2348+
nConnections++;
2349+
if (nConnections == 2)
2350+
return;
2351+
}
2352+
}
2353+
2354+
// Not enough connections. Insert peer.
2355+
static std::set<CNetAddr> setOffsetDisconnectedPeers;
2356+
setOffsetDisconnectedPeers.insert(ip);
2357+
if (setOffsetDisconnectedPeers.size() >= 16) {
2358+
// clear the set
2359+
setOffsetDisconnectedPeers.clear();
2360+
// Trigger the warning
2361+
std::string strMessage = _("Warning: Peers are being disconnected due time differences. Please check that your computer's date and time are correct! If your clock is wrong Wagerr Core will not work properly.");
2362+
LogPrintf("*** %s\n", strMessage);
2363+
uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_ERROR);
2364+
}
2365+
}
2366+
23412367
void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
23422368
{
23432369
// Connect to specific addresses

src/net.h

+2
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,8 @@ friend class CNode;
414414
// not yet fully disconnected.
415415
int GetExtraOutboundCount();
416416

417+
void CheckOffsetDisconnectedPeers(const CNetAddr& ip);
418+
417419
bool AddNode(const std::string& node);
418420
bool RemoveAddedNode(const std::string& node);
419421
std::vector<AddedNodeInfo> GetAddedNodeInfo();

src/net_processing.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -2319,6 +2319,13 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
23192319

23202320
int64_t nTimeOffset = nTime - GetTime();
23212321
pfrom->nTimeOffset = nTimeOffset;
2322+
const int nTimeSlotLength = Params().GetConsensus().nTimeSlotLength;
2323+
if (abs64(nTimeOffset) > 2 * nTimeSlotLength) {
2324+
LogPrintf("timeOffset (%d seconds) too large. Disconnecting node %s\n",
2325+
nTimeOffset, pfrom->addr.ToString().c_str());
2326+
pfrom->fDisconnect = true;
2327+
connman->CheckOffsetDisconnectedPeers(pfrom->addr);
2328+
}
23222329
AddTimeData(pfrom->addr, nTimeOffset);
23232330

23242331
// Feeler connections exist only to verify if address is online.

src/pos/kernel.cpp

+15-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
// Copyright (c) 2012-2013 The PPCoin developers
2-
// Copyright (c) 2015-2018 The PIVX developers
1+
// Copyright (c) 2011-2013 The PPCoin developers
2+
// Copyright (c) 2013-2014 The NovaCoin Developers
3+
// Copyright (c) 2014-2018 The BlackCoin Developers
4+
// Copyright (c) 2015-2019 The PIVX developers
35
// Copyright (c) 2018-2019 The Ion developers
46
// Distributed under the MIT/X11 software license, see the accompanying
57
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -229,7 +231,7 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64_t& nStakeMod
229231

230232
// The stake modifier used to hash for a stake kernel is chosen as the stake
231233
// modifier about a selection interval later than the coin generating the kernel
232-
bool GetKernelStakeModifier(uint256 hashBlockFrom, uint64_t& nStakeModifier, int& nStakeModifierHeight, int64_t& nStakeModifierTime, bool fPrintProofOfStake)
234+
bool GetKernelStakeModifier(const uint256& hashBlockFrom, uint64_t& nStakeModifier, int& nStakeModifierHeight, int64_t& nStakeModifierTime, bool fPrintProofOfStake)
233235
{
234236
nStakeModifier = 0;
235237
if (!mapBlockIndex.count(hashBlockFrom))
@@ -316,7 +318,7 @@ bool HasStakeMinAgeOrDepth(const int contextHeight, const uint32_t contextTime,
316318
{
317319
// before stake modifier V2, the age required was 60 * 60 (1 hour) / not required on regtest
318320
if (contextHeight < Params().GetConsensus().nBlockStakeModifierV2)
319-
return (Params().NetworkIDString() == CBaseChainParams::REGTEST || (utxoFromBlockTime + 3600 <= contextTime));
321+
return (Params().NetworkIDString() == CBaseChainParams::REGTEST || (utxoFromBlockTime + Params().GetConsensus().nStakeMinAge <= contextTime));
320322

321323
// after stake modifier V2, we require the utxo to be nStakeMinDepth deep in the chain
322324
return (contextHeight - utxoFromBlockHeight >= Params().GetConsensus().nStakeMinDepth);
@@ -349,7 +351,7 @@ bool ContextualCheckZerocoinStake(int nPreviousBlockHeight, CStakeInput* stake)
349351
}
350352

351353
// Check kernel hash target and coinstake signature
352-
bool initStakeInput(const CBlock block, std::unique_ptr<CStake>& ionStake, std::unique_ptr<CZStake>& zStake, int nPreviousBlockHeight) {
354+
bool initStakeInput(const CBlock& block, std::unique_ptr<CStake>& ionStake, std::unique_ptr<CZStake>& zStake, int nPreviousBlockHeight) {
353355
const CTransaction tx = *block.vtx[1];
354356
if (!tx.IsCoinStake())
355357
return error("%s : called on non-coinstake %s", __func__, tx.GetHash().GetHex());
@@ -390,7 +392,7 @@ bool initStakeInput(const CBlock block, std::unique_ptr<CStake>& ionStake, std::
390392
}
391393

392394
// Check kernel hash target and coinstake signature
393-
bool CheckProofOfStake(const CBlock block, uint256& hashProofOfStake, const CBlockIndex* pindex)
395+
bool CheckProofOfStake(const CBlock& block, uint256& hashProofOfStake, const CBlockIndex* pindex)
394396
{
395397
std::unique_ptr<CStake> ionStake;
396398
std::unique_ptr<CZStake> zStake;
@@ -432,13 +434,6 @@ bool CheckProofOfStake(const CBlock block, uint256& hashProofOfStake, const CBlo
432434
return true;
433435
}
434436

435-
// Check whether the coinstake timestamp meets protocol
436-
bool CheckCoinStakeTimestamp(int64_t nTimeBlock, int64_t nTimeTx)
437-
{
438-
// v0.3 protocol
439-
return (nTimeBlock == nTimeTx);
440-
}
441-
442437
// Get stake modifier checksum
443438
unsigned int GetStakeModifierChecksum(const CBlockIndex* pindex)
444439
{
@@ -465,6 +460,13 @@ bool CheckStakeModifierCheckpoints(int nHeight, unsigned int nStakeModifierCheck
465460
return true;
466461
}
467462

463+
// Timestamp for time protocol V2: slot duration 15 seconds
464+
int64_t GetTimeSlot(const int64_t nTime)
465+
{
466+
const int slotLen = Params().GetConsensus().nTimeSlotLength;
467+
return (nTime / slotLen) * slotLen;
468+
}
469+
468470
bool SetPOSParameters(const CBlock& block, CValidationState& state, CBlockIndex* pindexNew) {
469471
AssertLockHeld(cs_main);
470472

0 commit comments

Comments
 (0)