mirror of
https://github.com/dashpay/dash.git
synced 2024-12-27 04:52:59 +01:00
Merge pull request #2239 from codablock/pr_dip2
DIP2 / Special Transactions base implementation
This commit is contained in:
commit
28ba2ad0fb
@ -357,33 +357,44 @@ class CTransaction(object):
|
|||||||
def __init__(self, tx=None):
|
def __init__(self, tx=None):
|
||||||
if tx is None:
|
if tx is None:
|
||||||
self.nVersion = 1
|
self.nVersion = 1
|
||||||
|
self.nType = 0
|
||||||
self.vin = []
|
self.vin = []
|
||||||
self.vout = []
|
self.vout = []
|
||||||
self.nLockTime = 0
|
self.nLockTime = 0
|
||||||
|
self.vExtraPayload = None
|
||||||
self.sha256 = None
|
self.sha256 = None
|
||||||
self.hash = None
|
self.hash = None
|
||||||
else:
|
else:
|
||||||
self.nVersion = tx.nVersion
|
self.nVersion = tx.nVersion
|
||||||
|
self.nType = tx.nType
|
||||||
self.vin = copy.deepcopy(tx.vin)
|
self.vin = copy.deepcopy(tx.vin)
|
||||||
self.vout = copy.deepcopy(tx.vout)
|
self.vout = copy.deepcopy(tx.vout)
|
||||||
self.nLockTime = tx.nLockTime
|
self.nLockTime = tx.nLockTime
|
||||||
|
self.vExtraPayload = tx.vExtraPayload
|
||||||
self.sha256 = tx.sha256
|
self.sha256 = tx.sha256
|
||||||
self.hash = tx.hash
|
self.hash = tx.hash
|
||||||
|
|
||||||
def deserialize(self, f):
|
def deserialize(self, f):
|
||||||
self.nVersion = struct.unpack("<i", f.read(4))[0]
|
ver32bit = struct.unpack("<i", f.read(4))[0]
|
||||||
|
self.nVersion = ver32bit & 0xffff
|
||||||
|
self.nType = (ver32bit >> 16) & 0xffff
|
||||||
self.vin = deser_vector(f, CTxIn)
|
self.vin = deser_vector(f, CTxIn)
|
||||||
self.vout = deser_vector(f, CTxOut)
|
self.vout = deser_vector(f, CTxOut)
|
||||||
self.nLockTime = struct.unpack("<I", f.read(4))[0]
|
self.nLockTime = struct.unpack("<I", f.read(4))[0]
|
||||||
|
if self.nType != 0:
|
||||||
|
self.vExtraPayload = deser_string(f)
|
||||||
self.sha256 = None
|
self.sha256 = None
|
||||||
self.hash = None
|
self.hash = None
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
r = b""
|
r = b""
|
||||||
r += struct.pack("<i", self.nVersion)
|
ver32bit = int(self.nVersion | (self.nType << 16))
|
||||||
|
r += struct.pack("<i", ver32bit)
|
||||||
r += ser_vector(self.vin)
|
r += ser_vector(self.vin)
|
||||||
r += ser_vector(self.vout)
|
r += ser_vector(self.vout)
|
||||||
r += struct.pack("<I", self.nLockTime)
|
r += struct.pack("<I", self.nLockTime)
|
||||||
|
if self.nType != 0:
|
||||||
|
r += ser_string(self.vExtraPayload)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def rehash(self):
|
def rehash(self):
|
||||||
|
@ -106,6 +106,7 @@ BITCOIN_CORE_H = \
|
|||||||
core_io.h \
|
core_io.h \
|
||||||
core_memusage.h \
|
core_memusage.h \
|
||||||
cuckoocache.h \
|
cuckoocache.h \
|
||||||
|
evo/specialtx.h \
|
||||||
privatesend.h \
|
privatesend.h \
|
||||||
privatesend-client.h \
|
privatesend-client.h \
|
||||||
privatesend-server.h \
|
privatesend-server.h \
|
||||||
@ -216,6 +217,7 @@ libdash_server_a_SOURCES = \
|
|||||||
chain.cpp \
|
chain.cpp \
|
||||||
checkpoints.cpp \
|
checkpoints.cpp \
|
||||||
dsnotificationinterface.cpp \
|
dsnotificationinterface.cpp \
|
||||||
|
evo/specialtx.cpp \
|
||||||
httprpc.cpp \
|
httprpc.cpp \
|
||||||
httpserver.cpp \
|
httpserver.cpp \
|
||||||
init.cpp \
|
init.cpp \
|
||||||
|
@ -457,6 +457,13 @@ public:
|
|||||||
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nWindowSize = 100;
|
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nWindowSize = 100;
|
||||||
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nThreshold = 50; // 50% of 100
|
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nThreshold = 50; // 50% of 100
|
||||||
|
|
||||||
|
// Deployment of DIP0003
|
||||||
|
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].bit = 3;
|
||||||
|
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nStartTime = 1535752800; // Sep 1st, 2018
|
||||||
|
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nTimeout = 1567288800; // Sep 1st, 2019
|
||||||
|
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nWindowSize = 100;
|
||||||
|
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nThreshold = 50; // 50% of 100
|
||||||
|
|
||||||
// The best chain should have at least this much work.
|
// The best chain should have at least this much work.
|
||||||
consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000000000000000000000");
|
consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000000000000000000000");
|
||||||
|
|
||||||
@ -573,6 +580,9 @@ public:
|
|||||||
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].bit = 2;
|
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].bit = 2;
|
||||||
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nStartTime = 0;
|
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nStartTime = 0;
|
||||||
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nTimeout = 999999999999ULL;
|
consensus.vDeployments[Consensus::DEPLOYMENT_BIP147].nTimeout = 999999999999ULL;
|
||||||
|
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].bit = 3;
|
||||||
|
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nStartTime = 0;
|
||||||
|
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0003].nTimeout = 999999999999ULL;
|
||||||
|
|
||||||
// The best chain should have at least this much work.
|
// The best chain should have at least this much work.
|
||||||
consensus.nMinimumChainWork = uint256S("0x00");
|
consensus.nMinimumChainWork = uint256S("0x00");
|
||||||
|
@ -18,6 +18,8 @@ inline unsigned int MaxBlockSigOps(bool fDIP0001Active /*= false */)
|
|||||||
{
|
{
|
||||||
return MaxBlockSize(fDIP0001Active) / 50;
|
return MaxBlockSize(fDIP0001Active) / 50;
|
||||||
}
|
}
|
||||||
|
/** The maximum allowed size of version 3 extra payload */
|
||||||
|
static const unsigned int MAX_TX_EXTRA_PAYLOAD = 10000;
|
||||||
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
|
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
|
||||||
static const int COINBASE_MATURITY = 100;
|
static const int COINBASE_MATURITY = 100;
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ enum DeploymentPos
|
|||||||
DEPLOYMENT_CSV, // Deployment of BIP68, BIP112, and BIP113.
|
DEPLOYMENT_CSV, // Deployment of BIP68, BIP112, and BIP113.
|
||||||
DEPLOYMENT_DIP0001, // Deployment of DIP0001 and lower transaction fees.
|
DEPLOYMENT_DIP0001, // Deployment of DIP0001 and lower transaction fees.
|
||||||
DEPLOYMENT_BIP147, // Deployment of BIP147 (NULLDUMMY)
|
DEPLOYMENT_BIP147, // Deployment of BIP147 (NULLDUMMY)
|
||||||
|
DEPLOYMENT_DIP0003, // Deployment of DIP0002 and DIP0003 (txv3 and deterministic MN lists)
|
||||||
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in versionbits.cpp
|
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in versionbits.cpp
|
||||||
MAX_VERSION_BITS_DEPLOYMENTS
|
MAX_VERSION_BITS_DEPLOYMENTS
|
||||||
};
|
};
|
||||||
|
@ -39,6 +39,7 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con
|
|||||||
|
|
||||||
// Update global DIP0001 activation status
|
// Update global DIP0001 activation status
|
||||||
fDIP0001ActiveAtTip = pindexNew->nHeight >= Params().GetConsensus().DIP0001Height;
|
fDIP0001ActiveAtTip = pindexNew->nHeight >= Params().GetConsensus().DIP0001Height;
|
||||||
|
fDIP0003ActiveAtTip = (VersionBitsState(pindexNew->pprev, Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0003, versionbitscache) == THRESHOLD_ACTIVE);
|
||||||
|
|
||||||
if (fInitialDownload)
|
if (fInitialDownload)
|
||||||
return;
|
return;
|
||||||
|
84
src/evo/specialtx.cpp
Normal file
84
src/evo/specialtx.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// 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 "primitives/transaction.h"
|
||||||
|
#include "primitives/block.h"
|
||||||
|
#include "consensus/validation.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "clientversion.h"
|
||||||
|
#include "validation.h"
|
||||||
|
#include "chainparams.h"
|
||||||
|
|
||||||
|
#include "specialtx.h"
|
||||||
|
|
||||||
|
bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindex, CValidationState& state)
|
||||||
|
{
|
||||||
|
AssertLockHeld(cs_main);
|
||||||
|
|
||||||
|
if (tx.nVersion < 3 || tx.nType == TRANSACTION_NORMAL)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (pindex && VersionBitsState(pindex->pprev, Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0003, versionbitscache) != THRESHOLD_ACTIVE) {
|
||||||
|
return state.DoS(10, false, REJECT_INVALID, "bad-tx-type");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (tx.nType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return state.DoS(10, false, REJECT_INVALID, "bad-tx-type");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProcessSpecialTx(const CTransaction& tx, const CBlockIndex* pindex, CValidationState& state)
|
||||||
|
{
|
||||||
|
if (tx.nVersion < 3 || tx.nType == TRANSACTION_NORMAL)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
switch (tx.nType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return state.DoS(100, false, REJECT_INVALID, "bad-tx-type");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UndoSpecialTx(const CTransaction& tx, const CBlockIndex* pindex)
|
||||||
|
{
|
||||||
|
if (tx.nVersion < 3 || tx.nType == TRANSACTION_NORMAL)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
switch (tx.nType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CValidationState& state)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < (int)block.vtx.size(); i++) {
|
||||||
|
const CTransaction& tx = *block.vtx[i];
|
||||||
|
if (!CheckSpecialTx(tx, pindex, state))
|
||||||
|
return false;
|
||||||
|
if (!ProcessSpecialTx(tx, pindex, state))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex)
|
||||||
|
{
|
||||||
|
for (int i = (int)block.vtx.size() - 1; i >= 0; --i) {
|
||||||
|
const CTransaction& tx = *block.vtx[i];
|
||||||
|
if (!UndoSpecialTx(tx, pindex))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 CalcTxInputsHash(const CTransaction& tx)
|
||||||
|
{
|
||||||
|
CHashWriter hw(CLIENT_VERSION, SER_GETHASH);
|
||||||
|
for (const auto& in : tx.vin) {
|
||||||
|
hw << in.prevout;
|
||||||
|
}
|
||||||
|
return hw.GetHash();
|
||||||
|
}
|
52
src/evo/specialtx.h
Normal file
52
src/evo/specialtx.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// 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_SPECIALTX_H
|
||||||
|
#define DASH_SPECIALTX_H
|
||||||
|
|
||||||
|
#include "streams.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "primitives/transaction.h"
|
||||||
|
|
||||||
|
class CBlock;
|
||||||
|
class CBlockIndex;
|
||||||
|
class CValidationState;
|
||||||
|
|
||||||
|
bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindex, CValidationState& state);
|
||||||
|
bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CValidationState& state);
|
||||||
|
bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline bool GetTxPayload(const std::vector<unsigned char>& payload, T& obj)
|
||||||
|
{
|
||||||
|
CDataStream ds(payload, SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
try {
|
||||||
|
ds >> obj;
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return ds.empty();
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
inline bool GetTxPayload(const CMutableTransaction& tx, T& obj)
|
||||||
|
{
|
||||||
|
return GetTxPayload(tx.vExtraPayload, obj);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
inline bool GetTxPayload(const CTransaction& tx, T& obj)
|
||||||
|
{
|
||||||
|
return GetTxPayload(tx.vExtraPayload, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void SetTxPayload(CMutableTransaction& tx, const T& payload)
|
||||||
|
{
|
||||||
|
CDataStream ds(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
ds << payload;
|
||||||
|
tx.vExtraPayload.assign(ds.begin(), ds.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 CalcTxInputsHash(const CTransaction& tx);
|
||||||
|
|
||||||
|
#endif//DASH_SPECIALTX_H
|
@ -1704,6 +1704,11 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Needs to be called after chain is initialized
|
||||||
|
if (chainActive.Tip() && chainActive.Tip()->pprev) {
|
||||||
|
fDIP0003ActiveAtTip = VersionBitsState(chainActive.Tip()->pprev, Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0003, versionbitscache) == THRESHOLD_ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
uiInterface.InitMessage(_("Verifying blocks..."));
|
uiInterface.InitMessage(_("Verifying blocks..."));
|
||||||
if (fHavePruned && GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
|
if (fHavePruned && GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
|
||||||
LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks",
|
LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks",
|
||||||
|
@ -60,8 +60,8 @@ std::string CTxOut::ToString() const
|
|||||||
return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, HexStr(scriptPubKey).substr(0, 30));
|
return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, HexStr(scriptPubKey).substr(0, 30));
|
||||||
}
|
}
|
||||||
|
|
||||||
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {}
|
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nType(TRANSACTION_NORMAL), nLockTime(0) {}
|
||||||
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {}
|
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), nType(tx.nType), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), vExtraPayload(tx.vExtraPayload) {}
|
||||||
|
|
||||||
uint256 CMutableTransaction::GetHash() const
|
uint256 CMutableTransaction::GetHash() const
|
||||||
{
|
{
|
||||||
@ -71,12 +71,14 @@ uint256 CMutableTransaction::GetHash() const
|
|||||||
std::string CMutableTransaction::ToString() const
|
std::string CMutableTransaction::ToString() const
|
||||||
{
|
{
|
||||||
std::string str;
|
std::string str;
|
||||||
str += strprintf("CMutableTransaction(hash=%s, ver=%d, vin.size=%u, vout.size=%u, nLockTime=%u)\n",
|
str += strprintf("CMutableTransaction(hash=%s, ver=%d, type=%d, vin.size=%u, vout.size=%u, nLockTime=%u, vExtraPayload.size=%d)\n",
|
||||||
GetHash().ToString().substr(0,10),
|
GetHash().ToString().substr(0,10),
|
||||||
nVersion,
|
nVersion,
|
||||||
|
nType,
|
||||||
vin.size(),
|
vin.size(),
|
||||||
vout.size(),
|
vout.size(),
|
||||||
nLockTime);
|
nLockTime,
|
||||||
|
vExtraPayload.size());
|
||||||
for (unsigned int i = 0; i < vin.size(); i++)
|
for (unsigned int i = 0; i < vin.size(); i++)
|
||||||
str += " " + vin[i].ToString() + "\n";
|
str += " " + vin[i].ToString() + "\n";
|
||||||
for (unsigned int i = 0; i < vout.size(); i++)
|
for (unsigned int i = 0; i < vout.size(); i++)
|
||||||
@ -90,9 +92,9 @@ uint256 CTransaction::ComputeHash() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* For backward compatibility, the hash is initialized to 0. TODO: remove the need for this default constructor entirely. */
|
/* For backward compatibility, the hash is initialized to 0. TODO: remove the need for this default constructor entirely. */
|
||||||
CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0), hash() {}
|
CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), nType(TRANSACTION_NORMAL), vin(), vout(), nLockTime(0), hash() {}
|
||||||
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
|
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), nType(tx.nType), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), vExtraPayload(tx.vExtraPayload), hash(ComputeHash()) {}
|
||||||
CTransaction::CTransaction(CMutableTransaction &&tx) : nVersion(tx.nVersion), vin(std::move(tx.vin)), vout(std::move(tx.vout)), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
|
CTransaction::CTransaction(CMutableTransaction &&tx) : nVersion(tx.nVersion), nType(tx.nType), vin(std::move(tx.vin)), vout(std::move(tx.vout)), nLockTime(tx.nLockTime), vExtraPayload(tx.vExtraPayload), hash(ComputeHash()) {}
|
||||||
|
|
||||||
CAmount CTransaction::GetValueOut() const
|
CAmount CTransaction::GetValueOut() const
|
||||||
{
|
{
|
||||||
@ -140,12 +142,14 @@ unsigned int CTransaction::GetTotalSize() const
|
|||||||
std::string CTransaction::ToString() const
|
std::string CTransaction::ToString() const
|
||||||
{
|
{
|
||||||
std::string str;
|
std::string str;
|
||||||
str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%u, vout.size=%u, nLockTime=%u)\n",
|
str += strprintf("CTransaction(hash=%s, ver=%d, type=%d, vin.size=%u, vout.size=%u, nLockTime=%u, vExtraPayload.size=%d)\n",
|
||||||
GetHash().ToString().substr(0,10),
|
GetHash().ToString().substr(0,10),
|
||||||
nVersion,
|
nVersion,
|
||||||
|
nType,
|
||||||
vin.size(),
|
vin.size(),
|
||||||
vout.size(),
|
vout.size(),
|
||||||
nLockTime);
|
nLockTime,
|
||||||
|
vExtraPayload.size());
|
||||||
for (unsigned int i = 0; i < vin.size(); i++)
|
for (unsigned int i = 0; i < vin.size(); i++)
|
||||||
str += " " + vin[i].ToString() + "\n";
|
str += " " + vin[i].ToString() + "\n";
|
||||||
for (unsigned int i = 0; i < vout.size(); i++)
|
for (unsigned int i = 0; i < vout.size(); i++)
|
||||||
|
@ -11,6 +11,11 @@
|
|||||||
#include "serialize.h"
|
#include "serialize.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
|
|
||||||
|
/** Transaction types */
|
||||||
|
enum {
|
||||||
|
TRANSACTION_NORMAL = 0,
|
||||||
|
};
|
||||||
|
|
||||||
/** An outpoint - a combination of a transaction hash and an index n into its vout */
|
/** An outpoint - a combination of a transaction hash and an index n into its vout */
|
||||||
class COutPoint
|
class COutPoint
|
||||||
{
|
{
|
||||||
@ -215,17 +220,19 @@ public:
|
|||||||
// adapting relay policy by bumping MAX_STANDARD_VERSION, and then later date
|
// adapting relay policy by bumping MAX_STANDARD_VERSION, and then later date
|
||||||
// bumping the default CURRENT_VERSION at which point both CURRENT_VERSION and
|
// bumping the default CURRENT_VERSION at which point both CURRENT_VERSION and
|
||||||
// MAX_STANDARD_VERSION will be equal.
|
// MAX_STANDARD_VERSION will be equal.
|
||||||
static const int32_t MAX_STANDARD_VERSION=2;
|
static const int32_t MAX_STANDARD_VERSION=3;
|
||||||
|
|
||||||
// The local variables are made const to prevent unintended modification
|
// The local variables are made const to prevent unintended modification
|
||||||
// without updating the cached hash value. However, CTransaction is not
|
// without updating the cached hash value. However, CTransaction is not
|
||||||
// actually immutable; deserialization and assignment are implemented,
|
// actually immutable; deserialization and assignment are implemented,
|
||||||
// and bypass the constness. This is safe, as they update the entire
|
// and bypass the constness. This is safe, as they update the entire
|
||||||
// structure, including the hash.
|
// structure, including the hash.
|
||||||
const int32_t nVersion;
|
const int16_t nVersion;
|
||||||
|
const int16_t nType;
|
||||||
const std::vector<CTxIn> vin;
|
const std::vector<CTxIn> vin;
|
||||||
const std::vector<CTxOut> vout;
|
const std::vector<CTxOut> vout;
|
||||||
const uint32_t nLockTime;
|
const uint32_t nLockTime;
|
||||||
|
const std::vector<uint8_t> vExtraPayload; // only available for special transaction types
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Memory only. */
|
/** Memory only. */
|
||||||
@ -243,10 +250,13 @@ public:
|
|||||||
|
|
||||||
template <typename Stream>
|
template <typename Stream>
|
||||||
inline void Serialize(Stream& s) const {
|
inline void Serialize(Stream& s) const {
|
||||||
s << this->nVersion;
|
int32_t n32bitVersion = this->nVersion | (this->nType << 16);
|
||||||
|
s << n32bitVersion;
|
||||||
s << vin;
|
s << vin;
|
||||||
s << vout;
|
s << vout;
|
||||||
s << nLockTime;
|
s << nLockTime;
|
||||||
|
if (this->nVersion >= 3 && this->nType != TRANSACTION_NORMAL)
|
||||||
|
s << vExtraPayload;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This deserializing constructor is provided instead of an Unserialize method.
|
/** This deserializing constructor is provided instead of an Unserialize method.
|
||||||
@ -301,10 +311,12 @@ public:
|
|||||||
/** A mutable version of CTransaction. */
|
/** A mutable version of CTransaction. */
|
||||||
struct CMutableTransaction
|
struct CMutableTransaction
|
||||||
{
|
{
|
||||||
int32_t nVersion;
|
int16_t nVersion;
|
||||||
|
int16_t nType;
|
||||||
std::vector<CTxIn> vin;
|
std::vector<CTxIn> vin;
|
||||||
std::vector<CTxOut> vout;
|
std::vector<CTxOut> vout;
|
||||||
uint32_t nLockTime;
|
uint32_t nLockTime;
|
||||||
|
std::vector<uint8_t> vExtraPayload; // only available for special transaction types
|
||||||
|
|
||||||
CMutableTransaction();
|
CMutableTransaction();
|
||||||
CMutableTransaction(const CTransaction& tx);
|
CMutableTransaction(const CTransaction& tx);
|
||||||
@ -313,10 +325,18 @@ struct CMutableTransaction
|
|||||||
|
|
||||||
template <typename Stream, typename Operation>
|
template <typename Stream, typename Operation>
|
||||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||||
READWRITE(this->nVersion);
|
int32_t n32bitVersion = this->nVersion | (this->nType << 16);
|
||||||
|
READWRITE(n32bitVersion);
|
||||||
|
if (ser_action.ForRead()) {
|
||||||
|
this->nVersion = (int16_t) (n32bitVersion & 0xffff);
|
||||||
|
this->nType = (int16_t) ((n32bitVersion >> 16) & 0xffff);
|
||||||
|
}
|
||||||
READWRITE(vin);
|
READWRITE(vin);
|
||||||
READWRITE(vout);
|
READWRITE(vout);
|
||||||
READWRITE(nLockTime);
|
READWRITE(nLockTime);
|
||||||
|
if (this->nVersion >= 3 && this->nType != TRANSACTION_NORMAL) {
|
||||||
|
READWRITE(vExtraPayload);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Stream>
|
template <typename Stream>
|
||||||
|
@ -1274,6 +1274,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
|
|||||||
softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
|
softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
|
||||||
BIP9SoftForkDescPushBack(bip9_softforks, "csv", consensusParams, Consensus::DEPLOYMENT_CSV);
|
BIP9SoftForkDescPushBack(bip9_softforks, "csv", consensusParams, Consensus::DEPLOYMENT_CSV);
|
||||||
BIP9SoftForkDescPushBack(bip9_softforks, "dip0001", consensusParams, Consensus::DEPLOYMENT_DIP0001);
|
BIP9SoftForkDescPushBack(bip9_softforks, "dip0001", consensusParams, Consensus::DEPLOYMENT_DIP0001);
|
||||||
|
BIP9SoftForkDescPushBack(bip9_softforks, "dip0003", consensusParams, Consensus::DEPLOYMENT_DIP0003);
|
||||||
BIP9SoftForkDescPushBack(bip9_softforks, "bip147", consensusParams, Consensus::DEPLOYMENT_BIP147);
|
BIP9SoftForkDescPushBack(bip9_softforks, "bip147", consensusParams, Consensus::DEPLOYMENT_BIP147);
|
||||||
obj.push_back(Pair("softforks", softforks));
|
obj.push_back(Pair("softforks", softforks));
|
||||||
obj.push_back(Pair("bip9_softforks", bip9_softforks));
|
obj.push_back(Pair("bip9_softforks", bip9_softforks));
|
||||||
|
@ -65,6 +65,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
|
|||||||
entry.push_back(Pair("txid", txid.GetHex()));
|
entry.push_back(Pair("txid", txid.GetHex()));
|
||||||
entry.push_back(Pair("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)));
|
entry.push_back(Pair("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)));
|
||||||
entry.push_back(Pair("version", tx.nVersion));
|
entry.push_back(Pair("version", tx.nVersion));
|
||||||
|
entry.push_back(Pair("type", tx.nType));
|
||||||
entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
|
entry.push_back(Pair("locktime", (int64_t)tx.nLockTime));
|
||||||
UniValue vin(UniValue::VARR);
|
UniValue vin(UniValue::VARR);
|
||||||
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
|
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
|
||||||
@ -121,6 +122,11 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
|
|||||||
}
|
}
|
||||||
entry.push_back(Pair("vout", vout));
|
entry.push_back(Pair("vout", vout));
|
||||||
|
|
||||||
|
if (!tx.vExtraPayload.empty()) {
|
||||||
|
entry.push_back(Pair("extraPayloadSize", (int)tx.vExtraPayload.size()));
|
||||||
|
entry.push_back(Pair("extraPayload", HexStr(tx.vExtraPayload)));
|
||||||
|
}
|
||||||
|
|
||||||
if (!hashBlock.IsNull()) {
|
if (!hashBlock.IsNull()) {
|
||||||
entry.push_back(Pair("blockhash", hashBlock.GetHex()));
|
entry.push_back(Pair("blockhash", hashBlock.GetHex()));
|
||||||
BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
|
BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
|
||||||
@ -196,6 +202,8 @@ UniValue getrawtransaction(const JSONRPCRequest& request)
|
|||||||
" }\n"
|
" }\n"
|
||||||
" ,...\n"
|
" ,...\n"
|
||||||
" ],\n"
|
" ],\n"
|
||||||
|
" \"extraPayloadSize\" : n (numeric) Size of DIP2 extra payload. Only present if it's a special TX\n"
|
||||||
|
" \"extraPayload\" : \"hex\" (string) Hex encoded DIP2 extra payload data. Only present if it's a special TX\n"
|
||||||
" \"blockhash\" : \"hash\", (string) the block hash\n"
|
" \"blockhash\" : \"hash\", (string) the block hash\n"
|
||||||
" \"confirmations\" : n, (numeric) The confirmations\n"
|
" \"confirmations\" : n, (numeric) The confirmations\n"
|
||||||
" \"time\" : ttt, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT)\n"
|
" \"time\" : ttt, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT)\n"
|
||||||
@ -500,6 +508,7 @@ UniValue decoderawtransaction(const JSONRPCRequest& request)
|
|||||||
" \"txid\" : \"id\", (string) The transaction id\n"
|
" \"txid\" : \"id\", (string) The transaction id\n"
|
||||||
" \"size\" : n, (numeric) The transaction size\n"
|
" \"size\" : n, (numeric) The transaction size\n"
|
||||||
" \"version\" : n, (numeric) The version\n"
|
" \"version\" : n, (numeric) The version\n"
|
||||||
|
" \"type\" : n, (numeric) The type\n"
|
||||||
" \"locktime\" : ttt, (numeric) The lock time\n"
|
" \"locktime\" : ttt, (numeric) The lock time\n"
|
||||||
" \"vin\" : [ (array of json objects)\n"
|
" \"vin\" : [ (array of json objects)\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
@ -530,6 +539,8 @@ UniValue decoderawtransaction(const JSONRPCRequest& request)
|
|||||||
" }\n"
|
" }\n"
|
||||||
" ,...\n"
|
" ,...\n"
|
||||||
" ],\n"
|
" ],\n"
|
||||||
|
" \"extraPayloadSize\" : n (numeric) Size of DIP2 extra payload. Only present if it's a special TX\n"
|
||||||
|
" \"extraPayload\" : \"hex\" (string) Hex encoded DIP2 extra payload data. Only present if it's a special TX\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
|
||||||
"\nExamples:\n"
|
"\nExamples:\n"
|
||||||
|
@ -1098,7 +1098,8 @@ public:
|
|||||||
template<typename S>
|
template<typename S>
|
||||||
void Serialize(S &s) const {
|
void Serialize(S &s) const {
|
||||||
// Serialize nVersion
|
// Serialize nVersion
|
||||||
::Serialize(s, txTo.nVersion);
|
int32_t n32bitVersion = txTo.nVersion | (txTo.nType << 16);
|
||||||
|
::Serialize(s, n32bitVersion);
|
||||||
// Serialize vin
|
// Serialize vin
|
||||||
unsigned int nInputs = fAnyoneCanPay ? 1 : txTo.vin.size();
|
unsigned int nInputs = fAnyoneCanPay ? 1 : txTo.vin.size();
|
||||||
::WriteCompactSize(s, nInputs);
|
::WriteCompactSize(s, nInputs);
|
||||||
@ -1111,6 +1112,8 @@ public:
|
|||||||
SerializeOutput(s, nOutput);
|
SerializeOutput(s, nOutput);
|
||||||
// Serialize nLockTime
|
// Serialize nLockTime
|
||||||
::Serialize(s, txTo.nLockTime);
|
::Serialize(s, txTo.nLockTime);
|
||||||
|
if (txTo.nVersion >= 3 && txTo.nType != TRANSACTION_NORMAL)
|
||||||
|
::Serialize(s, txTo.vExtraPayload);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,6 +42,8 @@
|
|||||||
#include "masternodeman.h"
|
#include "masternodeman.h"
|
||||||
#include "masternode-payments.h"
|
#include "masternode-payments.h"
|
||||||
|
|
||||||
|
#include "evo/specialtx.h"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
@ -89,6 +91,7 @@ int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
|
|||||||
bool fEnableReplacement = DEFAULT_ENABLE_REPLACEMENT;
|
bool fEnableReplacement = DEFAULT_ENABLE_REPLACEMENT;
|
||||||
|
|
||||||
std::atomic<bool> fDIP0001ActiveAtTip{false};
|
std::atomic<bool> fDIP0001ActiveAtTip{false};
|
||||||
|
std::atomic<bool> fDIP0003ActiveAtTip{false};
|
||||||
|
|
||||||
uint256 hashAssumeValid;
|
uint256 hashAssumeValid;
|
||||||
|
|
||||||
@ -517,6 +520,8 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fChe
|
|||||||
// Size limits
|
// Size limits
|
||||||
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_LEGACY_BLOCK_SIZE)
|
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_LEGACY_BLOCK_SIZE)
|
||||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize");
|
return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize");
|
||||||
|
if (tx.vExtraPayload.size() > MAX_TX_EXTRA_PAYLOAD)
|
||||||
|
return state.DoS(100, false, REJECT_INVALID, "bad-txns-payload-oversize");
|
||||||
|
|
||||||
// Check for negative or overflow output values
|
// Check for negative or overflow output values
|
||||||
CAmount nValueOut = 0;
|
CAmount nValueOut = 0;
|
||||||
@ -560,6 +565,20 @@ bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state,
|
|||||||
{
|
{
|
||||||
int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1;
|
int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1;
|
||||||
bool fDIP0001Active_context = nHeight >= consensusParams.DIP0001Height;
|
bool fDIP0001Active_context = nHeight >= consensusParams.DIP0001Height;
|
||||||
|
bool fDIP0003Active_context = VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_DIP0003, versionbitscache) == THRESHOLD_ACTIVE;
|
||||||
|
|
||||||
|
if (fDIP0003Active_context) {
|
||||||
|
// check version 3 transaction types
|
||||||
|
if (tx.nVersion >= 3) {
|
||||||
|
if (tx.nType != TRANSACTION_NORMAL) {
|
||||||
|
return state.DoS(100, false, REJECT_INVALID, "bad-txns-type");
|
||||||
|
}
|
||||||
|
if (tx.IsCoinBase() && tx.nType != TRANSACTION_NORMAL)
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Size limits
|
// Size limits
|
||||||
if (fDIP0001Active_context && ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_STANDARD_TX_SIZE)
|
if (fDIP0001Active_context && ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_STANDARD_TX_SIZE)
|
||||||
@ -617,6 +636,9 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
|
|||||||
if (!ContextualCheckTransaction(tx, state, Params().GetConsensus(), chainActive.Tip()))
|
if (!ContextualCheckTransaction(tx, state, Params().GetConsensus(), chainActive.Tip()))
|
||||||
return error("%s: ContextualCheckTransaction: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
|
return error("%s: ContextualCheckTransaction: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
|
||||||
|
|
||||||
|
if (!CheckSpecialTx(tx, chainActive.Tip(), state))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Coinbase is only valid in a block, not as a loose transaction
|
// Coinbase is only valid in a block, not as a loose transaction
|
||||||
if (tx.IsCoinBase())
|
if (tx.IsCoinBase())
|
||||||
return state.DoS(100, false, REJECT_INVALID, "coinbase");
|
return state.DoS(100, false, REJECT_INVALID, "coinbase");
|
||||||
@ -1774,6 +1796,10 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s
|
|||||||
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > addressUnspentIndex;
|
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > addressUnspentIndex;
|
||||||
std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> > spentIndex;
|
std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> > spentIndex;
|
||||||
|
|
||||||
|
if (!UndoSpecialTxsInBlock(block, pindex)) {
|
||||||
|
return DISCONNECT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
// undo transactions in reverse order
|
// undo transactions in reverse order
|
||||||
for (int i = block.vtx.size() - 1; i >= 0; i--) {
|
for (int i = block.vtx.size() - 1; i >= 0; i--) {
|
||||||
const CTransaction &tx = *(block.vtx[i]);
|
const CTransaction &tx = *(block.vtx[i]);
|
||||||
@ -1885,6 +1911,9 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pindex->pprev && pindex->pprev->pprev && VersionBitsState(pindex->pprev->pprev, Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0003, versionbitscache) != THRESHOLD_ACTIVE) {
|
||||||
|
fDIP0003ActiveAtTip = false;
|
||||||
|
}
|
||||||
|
|
||||||
// move best block pointer to prevout block
|
// move best block pointer to prevout block
|
||||||
view.SetBestBlock(pindex->pprev->GetBlockHash());
|
view.SetBestBlock(pindex->pprev->GetBlockHash());
|
||||||
@ -2153,6 +2182,12 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
|
|||||||
flags |= SCRIPT_VERIFY_NULLDUMMY;
|
flags |= SCRIPT_VERIFY_NULLDUMMY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!fJustCheck && VersionBitsState(pindex->pprev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_DIP0003, versionbitscache) == THRESHOLD_ACTIVE) {
|
||||||
|
if (!fDIP0003ActiveAtTip)
|
||||||
|
LogPrintf("ConnectBlock -- DIP0003 got activated at height %d\n", pindex->nHeight);
|
||||||
|
fDIP0003ActiveAtTip = true;
|
||||||
|
}
|
||||||
|
|
||||||
int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1;
|
int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1;
|
||||||
LogPrint("bench", " - Fork checks: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeForks * 0.000001);
|
LogPrint("bench", " - Fork checks: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeForks * 0.000001);
|
||||||
|
|
||||||
@ -2310,6 +2345,9 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
|
|||||||
int64_t nTime3 = GetTimeMicros(); nTimeConnect += nTime3 - nTime2;
|
int64_t nTime3 = GetTimeMicros(); nTimeConnect += nTime3 - nTime2;
|
||||||
LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime3 - nTime2), 0.001 * (nTime3 - nTime2) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime3 - nTime2) / (nInputs-1), nTimeConnect * 0.000001);
|
LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime3 - nTime2), 0.001 * (nTime3 - nTime2) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime3 - nTime2) / (nInputs-1), nTimeConnect * 0.000001);
|
||||||
|
|
||||||
|
if (!ProcessSpecialTxsInBlock(block, pindex, state))
|
||||||
|
return false;
|
||||||
|
|
||||||
// DASH : MODIFIED TO CHECK MASTERNODE PAYMENTS AND SUPERBLOCKS
|
// DASH : MODIFIED TO CHECK MASTERNODE PAYMENTS AND SUPERBLOCKS
|
||||||
|
|
||||||
// It's possible that we simply don't have enough data and this could fail
|
// It's possible that we simply don't have enough data and this could fail
|
||||||
|
@ -189,6 +189,8 @@ extern bool fLargeWorkInvalidChainFound;
|
|||||||
extern std::map<uint256, int64_t> mapRejectedBlocks;
|
extern std::map<uint256, int64_t> mapRejectedBlocks;
|
||||||
|
|
||||||
extern std::atomic<bool> fDIP0001ActiveAtTip;
|
extern std::atomic<bool> fDIP0001ActiveAtTip;
|
||||||
|
extern std::atomic<bool> fDIP0003ActiveAtTip;
|
||||||
|
|
||||||
|
|
||||||
/** Block hash whose ancestors we will assume to have valid scripts without checking them. */
|
/** Block hash whose ancestors we will assume to have valid scripts without checking them. */
|
||||||
extern uint256 hashAssumeValid;
|
extern uint256 hashAssumeValid;
|
||||||
|
@ -26,6 +26,11 @@ const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION
|
|||||||
/*.name =*/ "bip147",
|
/*.name =*/ "bip147",
|
||||||
/*.gbt_force =*/ true,
|
/*.gbt_force =*/ true,
|
||||||
/*.check_mn_protocol =*/ false,
|
/*.check_mn_protocol =*/ false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/*.name =*/ "dip0003",
|
||||||
|
/*.gbt_force =*/ true,
|
||||||
|
/*.check_mn_protocol =*/ false,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2962,9 +2962,13 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool ov
|
|||||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
||||||
coinControl.Select(txin.prevout);
|
coinControl.Select(txin.prevout);
|
||||||
|
|
||||||
|
int nExtraPayloadSize = 0;
|
||||||
|
if (tx.nVersion >= 3 && tx.nType != TRANSACTION_NORMAL)
|
||||||
|
nExtraPayloadSize = (int)tx.vExtraPayload.size();
|
||||||
|
|
||||||
CReserveKey reservekey(this);
|
CReserveKey reservekey(this);
|
||||||
CWalletTx wtx;
|
CWalletTx wtx;
|
||||||
if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosInOut, strFailReason, &coinControl, false))
|
if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosInOut, strFailReason, &coinControl, false, ALL_COINS, false, nExtraPayloadSize))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (nChangePosInOut != -1)
|
if (nChangePosInOut != -1)
|
||||||
@ -3403,7 +3407,7 @@ bool CWallet::ConvertList(std::vector<CTxIn> vecTxIn, std::vector<CAmount>& vecA
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet,
|
bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet,
|
||||||
int& nChangePosInOut, std::string& strFailReason, const CCoinControl* coinControl, bool sign, AvailableCoinsType nCoinType, bool fUseInstantSend)
|
int& nChangePosInOut, std::string& strFailReason, const CCoinControl* coinControl, bool sign, AvailableCoinsType nCoinType, bool fUseInstantSend, int nExtraPayloadSize)
|
||||||
{
|
{
|
||||||
CAmount nFeePay = fUseInstantSend ? CTxLockRequest().GetMinFee() : 0;
|
CAmount nFeePay = fUseInstantSend ? CTxLockRequest().GetMinFee() : 0;
|
||||||
|
|
||||||
@ -3705,6 +3709,11 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
|
|||||||
|
|
||||||
unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
|
unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
|
||||||
|
if (nExtraPayloadSize != 0) {
|
||||||
|
// account for extra payload in fee calculation
|
||||||
|
nBytes += GetSizeOfCompactSize(nExtraPayloadSize) + nExtraPayloadSize;
|
||||||
|
}
|
||||||
|
|
||||||
if (nBytes > MAX_STANDARD_TX_SIZE) {
|
if (nBytes > MAX_STANDARD_TX_SIZE) {
|
||||||
// Do not create oversized transactions (bad-txns-oversize).
|
// Do not create oversized transactions (bad-txns-oversize).
|
||||||
strFailReason = _("Transaction too large");
|
strFailReason = _("Transaction too large");
|
||||||
|
@ -936,7 +936,7 @@ public:
|
|||||||
* @note passing nChangePosInOut as -1 will result in setting a random position
|
* @note passing nChangePosInOut as -1 will result in setting a random position
|
||||||
*/
|
*/
|
||||||
bool CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,
|
bool CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,
|
||||||
std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend=false);
|
std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend=false, int nExtraPayloadSize = 0);
|
||||||
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state, const std::string& strCommand="tx");
|
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state, const std::string& strCommand="tx");
|
||||||
|
|
||||||
bool CreateCollateralTransaction(CMutableTransaction& txCollateral, std::string& strReason);
|
bool CreateCollateralTransaction(CMutableTransaction& txCollateral, std::string& strReason);
|
||||||
|
Loading…
Reference in New Issue
Block a user