From e1ce43df71b751e84886ae5b8f4e4a88cf1aa76a Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Sun, 20 Apr 2014 11:39:21 +0100 Subject: [PATCH 1/3] Corrected block maturity test. --- src/main.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index b5302a9bf..dac145148 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -936,7 +936,11 @@ int CMerkleTx::GetBlocksToMaturity() const { if (!IsCoinBase()) return 0; - return max(0, (COINBASE_MATURITY+1) - GetDepthInMainChain()); + + if(GetDepthInMainChain() >= COINBASE_MATURITY_SWITCH) + return max(0, (COINBASE_MATURITY_NEW+20) - GetDepthInMainChain()); + else + return max(0, (COINBASE_MATURITY+20) - GetDepthInMainChain()); } From 85392ed8bbcb6bd2d199f9f78b8657b719401404 Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Sun, 20 Apr 2014 12:12:03 +0100 Subject: [PATCH 2/3] Added GetHeightInMainChain() method. Corrected call to GetDepthInMainChain() with GetHeightInMainChain() when checking coin maturity. --- src/main.cpp | 7 ++++++- src/main.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index dac145148..3210a7875 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -932,12 +932,17 @@ int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const return nResult; } +int CMerkleTx::GetHeightInMainChain(CBlockIndex* &pindexRet) const +{ + return chainActive.Height() - GetDepthInMainChain(pindexRet) + 1; +} + int CMerkleTx::GetBlocksToMaturity() const { if (!IsCoinBase()) return 0; - if(GetDepthInMainChain() >= COINBASE_MATURITY_SWITCH) + if(GetHeightInMainChain() >= COINBASE_MATURITY_SWITCH) return max(0, (COINBASE_MATURITY_NEW+20) - GetDepthInMainChain()); else return max(0, (COINBASE_MATURITY+20) - GetDepthInMainChain()); diff --git a/src/main.h b/src/main.h index 155ad413d..6c150e472 100644 --- a/src/main.h +++ b/src/main.h @@ -476,6 +476,8 @@ public: // >=1 : this many blocks deep in the main chain int GetDepthInMainChain(CBlockIndex* &pindexRet) const; int GetDepthInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); } + int GetHeightInMainChain(CBlockIndex* &pindexRet) const; + int GetHeightInMainChain() const { CBlockIndex *pindexRet; return GetHeightInMainChain(pindexRet); } bool IsInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; } int GetBlocksToMaturity() const; bool AcceptToMemoryPool(bool fLimitFree=true); From d0957dc745d5e822a62d5fd036501643f30ec637 Mon Sep 17 00:00:00 2001 From: Patrick Lodder Date: Sun, 20 Apr 2014 17:14:13 +0400 Subject: [PATCH 3/3] DRY calculation for required maturity depth Having this defined in multiple places is suboptimal and may lead to porting issues, so I extracted it into it's own function and let both implementations call that instead. --- src/main.cpp | 30 ++++++++++++++++++++++-------- src/main.h | 7 +++++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 3210a7875..38f567661 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -941,11 +941,12 @@ int CMerkleTx::GetBlocksToMaturity() const { if (!IsCoinBase()) return 0; - - if(GetHeightInMainChain() >= COINBASE_MATURITY_SWITCH) - return max(0, (COINBASE_MATURITY_NEW+20) - GetDepthInMainChain()); - else - return max(0, (COINBASE_MATURITY+20) - GetDepthInMainChain()); + + int nHeight = GetHeightInMainChain(); + int nMaturity = GetRequiredMaturityDepth(nHeight); + + return max(0, (nMaturity+20) - GetDepthInMainChain()); + } @@ -1539,6 +1540,19 @@ bool VerifySignature(const CCoins& txFrom, const CTransaction& txTo, unsigned in return CScriptCheck(txFrom, txTo, nIn, flags, nHashType)(); } +int GetRequiredMaturityDepth(int nHeight) +{ + + if (nHeight >= COINBASE_MATURITY_SWITCH) + { + return COINBASE_MATURITY_NEW; + } + else + { + return COINBASE_MATURITY; + } +} + bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, std::vector *pvChecks) { if (!tx.IsCoinBase()) @@ -1564,9 +1578,9 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach // If prev is coinbase, check that it's matured if (coins.IsCoinBase()) { - int minDepth = COINBASE_MATURITY; - if(coins.nHeight >= COINBASE_MATURITY_SWITCH) - minDepth = COINBASE_MATURITY_NEW; + + int minDepth = GetRequiredMaturityDepth(coins.nHeight); + if (nSpendHeight - coins.nHeight < minDepth) return state.Invalid( error("CheckInputs() : tried to spend coinbase at depth %d", nSpendHeight - coins.nHeight), diff --git a/src/main.h b/src/main.h index 6c150e472..542252051 100644 --- a/src/main.h +++ b/src/main.h @@ -307,6 +307,13 @@ inline bool AllowFree(double dPriority) return dPriority > 100 * COIN * 1440 / 250; // Dogecoin: 1440 blocks found a day. Priority cutoff is 100 dogecoin day / 250 bytes. } +/** Get the maturity depth for coinbase transactions at a given height. + @param[in] nHeight The height at which to check maturity for + @return the depth at which the coinbase transaction matures + */ +// Dogecoin specific implementation, standardizes checks for the hard maturity change at block 145k +int GetRequiredMaturityDepth(int nHeight); + // Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts) // This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it // instead of being performed inline.