Skip to content

Commit

Permalink
Implement and enforce CbTx with correct block height and deprecate BIP34
Browse files Browse the repository at this point in the history
  • Loading branch information
codablock committed Sep 3, 2018
1 parent 11df4f2 commit 0a08689
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 5 deletions.
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ BITCOIN_CORE_H = \
evo/specialtx.h \
evo/providertx.h \
evo/deterministicmns.h \
evo/cbtx.h \
privatesend.h \
privatesend-client.h \
privatesend-server.h \
Expand Down Expand Up @@ -224,6 +225,7 @@ libdash_server_a_SOURCES = \
evo/specialtx.cpp \
evo/providertx.cpp \
evo/deterministicmns.cpp \
evo/cbtx.cpp \
httprpc.cpp \
httpserver.cpp \
init.cpp \
Expand Down
47 changes: 47 additions & 0 deletions src/evo/cbtx.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) 2017 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "cbtx.h"
#include "specialtx.h"
#include "deterministicmns.h"

#include "validation.h"
#include "univalue.h"

bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state)
{
AssertLockHeld(cs_main);

if (!tx.IsCoinBase())
return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-invalid");

CCbTx cbTx;
if (!GetTxPayload(tx, cbTx))
return state.DoS(100, false, REJECT_INVALID, "bad-tx-payload");

if (cbTx.nVersion > CCbTx::CURRENT_VERSION)
return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-version");

if (pindexPrev) {
if (pindexPrev->nHeight + 1 != cbTx.nHeight)
return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-height");
}

return true;
}

std::string CCbTx::ToString() const
{
return strprintf("CCbTx(nHeight=%d, nVersion=%d, merkleRootMNList=%s)",
nVersion, nHeight, merkleRootMNList.ToString());
}

void CCbTx::ToJson(UniValue& obj) const
{
obj.clear();
obj.setObject();
obj.push_back(Pair("version", (int)nVersion));
obj.push_back(Pair("height", (int)nHeight));
obj.push_back(Pair("merkleRootMNList", merkleRootMNList.ToString()));
}
42 changes: 42 additions & 0 deletions src/evo/cbtx.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) 2017 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef DASH_CBTX_H
#define DASH_CBTX_H

#include "primitives/transaction.h"
#include "consensus/validation.h"

class CBlockIndex;
class UniValue;

// coinbase transaction
class CCbTx
{
public:
static const uint16_t CURRENT_VERSION = 1;

public:
uint16_t nVersion{CURRENT_VERSION};
int32_t nHeight{0};
uint256 merkleRootMNList;

public:
ADD_SERIALIZE_METHODS;

template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(nVersion);
READWRITE(nHeight);
READWRITE(merkleRootMNList);
}

std::string ToString() const;
void ToJson(UniValue& obj) const;
};

bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state);

#endif//DASH_CBTX_H
7 changes: 7 additions & 0 deletions src/evo/specialtx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "specialtx.h"
#include "deterministicmns.h"
#include "cbtx.h"

bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state)
{
Expand All @@ -33,6 +34,8 @@ bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVali
return CheckProUpRegTx(tx, pindexPrev, state);
case TRANSACTION_PROVIDER_UPDATE_REVOKE:
return CheckProUpRevTx(tx, pindexPrev, state);
case TRANSACTION_COINBASE:
return CheckCbTx(tx, pindexPrev, state);
}

return state.DoS(10, false, REJECT_INVALID, "bad-tx-type");
Expand All @@ -49,6 +52,8 @@ bool ProcessSpecialTx(const CTransaction& tx, const CBlockIndex* pindex, CValida
case TRANSACTION_PROVIDER_UPDATE_REGISTRAR:
case TRANSACTION_PROVIDER_UPDATE_REVOKE:
return true; // handled in batches per block
case TRANSACTION_COINBASE:
return true; // nothing to do
}

return state.DoS(100, false, REJECT_INVALID, "bad-tx-type");
Expand All @@ -65,6 +70,8 @@ bool UndoSpecialTx(const CTransaction& tx, const CBlockIndex* pindex)
case TRANSACTION_PROVIDER_UPDATE_REGISTRAR:
case TRANSACTION_PROVIDER_UPDATE_REVOKE:
return true; // handled in batches per block
case TRANSACTION_COINBASE:
return true; // nothing to do
}

return false;
Expand Down
20 changes: 19 additions & 1 deletion src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
#include "masternode-sync.h"
#include "validationinterface.h"

#include "evo/specialtx.h"
#include "evo/cbtx.h"

#include <algorithm>
#include <boost/thread.hpp>
#include <boost/tuple/tuple.hpp>
Expand Down Expand Up @@ -126,6 +129,9 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
pblocktemplate->vTxSigOps.push_back(-1); // updated at end

LOCK2(cs_main, mempool.cs);

bool fDIP0003Active_context = VersionBitsState(chainActive.Tip(), chainparams.GetConsensus(), Consensus::DEPLOYMENT_DIP0003, versionbitscache) == THRESHOLD_ACTIVE;

CBlockIndex* pindexPrev = chainActive.Tip();
nHeight = pindexPrev->nHeight + 1;

Expand Down Expand Up @@ -166,7 +172,19 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc

// Compute regular coinbase transaction.
coinbaseTx.vout[0].nValue = blockReward;
coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0;

if (!fDIP0003Active_context) {
coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0;
} else {
coinbaseTx.vin[0].scriptSig = CScript() << OP_RETURN;

coinbaseTx.nVersion = 3;
coinbaseTx.nType = TRANSACTION_COINBASE;

CCbTx cbTx;
cbTx.nHeight = nHeight;
SetTxPayload(coinbaseTx, cbTx);
}

// Update coinbase transaction with additional info about masternode and governance payments,
// get some info back to pass to getblocktemplate
Expand Down
1 change: 1 addition & 0 deletions src/primitives/transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ enum {
TRANSACTION_PROVIDER_UPDATE_SERVICE = 2,
TRANSACTION_PROVIDER_UPDATE_REGISTRAR = 3,
TRANSACTION_PROVIDER_UPDATE_REVOKE = 4,
TRANSACTION_COINBASE = 5,
};

/** An outpoint - a combination of a transaction hash and an index n into its vout */
Expand Down
8 changes: 8 additions & 0 deletions src/rpc/rawtransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include "evo/specialtx.h"
#include "evo/providertx.h"
#include "evo/cbtx.h"

#include <stdint.h>

Expand Down Expand Up @@ -158,6 +159,13 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
proTx.ToJson(proTxObj);
entry.push_back(Pair("proUpRevTx", proTxObj));
}
} else if (tx.nType == TRANSACTION_COINBASE) {
CCbTx cbTx;
if (GetTxPayload(tx, cbTx)) {
UniValue proTxObj;
cbTx.ToJson(proTxObj);
entry.push_back(Pair("cbTx", proTxObj));
}
}

if (!hashBlock.IsNull()) {
Expand Down
24 changes: 20 additions & 4 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "evo/specialtx.h"
#include "evo/providertx.h"
#include "evo/deterministicmns.h"
#include "evo/cbtx.h"

#include <atomic>
#include <sstream>
Expand Down Expand Up @@ -550,7 +551,12 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fChe

if (tx.IsCoinBase())
{
if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
int minCbSize = 2;
if (tx.nType == TRANSACTION_COINBASE) {
// With the introduction of CbTx, coinbase scripts are not required anymore to hold a valid block height
minCbSize = 1;
}
if (tx.vin[0].scriptSig.size() < minCbSize || tx.vin[0].scriptSig.size() > 100)
return state.DoS(100, false, REJECT_INVALID, "bad-cb-length");
}
else
Expand All @@ -576,10 +582,11 @@ bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state,
tx.nType != TRANSACTION_PROVIDER_REGISTER &&
tx.nType != TRANSACTION_PROVIDER_UPDATE_SERVICE &&
tx.nType != TRANSACTION_PROVIDER_UPDATE_REGISTRAR &&
tx.nType != TRANSACTION_PROVIDER_UPDATE_REVOKE) {
tx.nType != TRANSACTION_PROVIDER_UPDATE_REVOKE &&
tx.nType != TRANSACTION_COINBASE) {
return state.DoS(100, false, REJECT_INVALID, "bad-txns-type");
}
if (tx.IsCoinBase() && tx.nType != TRANSACTION_NORMAL)
if (tx.IsCoinBase() && tx.nType != TRANSACTION_COINBASE)
return state.DoS(100, false, REJECT_INVALID, "bad-txns-cb-type");
} else if (tx.nType != TRANSACTION_NORMAL) {
return state.DoS(100, false, REJECT_INVALID, "bad-txns-type");
Expand Down Expand Up @@ -3513,6 +3520,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co
: block.GetBlockTime();

bool fDIP0001Active_context = nHeight >= Params().GetConsensus().DIP0001Height;
bool fDIP0003Active_context = VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_DIP0003, versionbitscache) == THRESHOLD_ACTIVE;

// Size limits
unsigned int nMaxBlockSize = MaxBlockSize(fDIP0001Active_context);
Expand All @@ -3537,7 +3545,9 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co
return state.DoS(10, false, REJECT_INVALID, "bad-blk-sigops", false, "out-of-bounds SigOpCount");

// Enforce rule that the coinbase starts with serialized block height
if (nHeight >= consensusParams.BIP34Height)
// After DIP3/DIP4 activation, we don't enforce the height in the input script anymore.
// The CbTx special transaction payload will then contain the height, which is checked in CheckCbTx
if (nHeight >= consensusParams.BIP34Height && !fDIP0003Active_context)
{
CScript expect = CScript() << nHeight;
if (block.vtx[0]->vin[0].scriptSig.size() < expect.size() ||
Expand All @@ -3546,6 +3556,12 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co
}
}

if (fDIP0003Active_context) {
if (block.vtx[0]->nType != TRANSACTION_COINBASE) {
return state.DoS(100, false, REJECT_INVALID, "bad-cb-type", false, "coinbase is not a CbTx");
}
}

return true;
}

Expand Down

0 comments on commit 0a08689

Please sign in to comment.