mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
add ehf special tx (#4577)
This commit is contained in:
parent
06ebacbb9a
commit
459bc3ee7e
@ -169,6 +169,7 @@ BITCOIN_CORE_H = \
|
||||
evo/deterministicmns.h \
|
||||
evo/evodb.h \
|
||||
evo/mnauth.h \
|
||||
evo/mnhftx.h \
|
||||
evo/providertx.h \
|
||||
evo/simplifiedmns.h \
|
||||
evo/specialtx.h \
|
||||
@ -356,6 +357,7 @@ libdash_server_a_SOURCES = \
|
||||
evo/deterministicmns.cpp \
|
||||
evo/evodb.cpp \
|
||||
evo/mnauth.cpp \
|
||||
evo/mnhftx.cpp \
|
||||
evo/providertx.cpp \
|
||||
evo/simplifiedmns.cpp \
|
||||
evo/specialtx.cpp \
|
||||
|
@ -181,6 +181,7 @@ BITCOIN_TESTS =\
|
||||
test/sighash_tests.cpp \
|
||||
test/sigopcount_tests.cpp \
|
||||
test/skiplist_tests.cpp \
|
||||
test/specialtx_tests.cpp \
|
||||
test/streams_tests.cpp \
|
||||
test/subsidy_tests.cpp \
|
||||
test/sync_tests.cpp \
|
||||
|
@ -212,6 +212,7 @@ bool CBloomFilter::CheckSpecialTransactionMatchesAndUpdate(const CTransaction &t
|
||||
}
|
||||
case(TRANSACTION_COINBASE):
|
||||
case(TRANSACTION_QUORUM_COMMITMENT):
|
||||
case(TRANSACTION_MNHF_SIGNAL):
|
||||
// No additional checks for this transaction types
|
||||
return false;
|
||||
}
|
||||
|
@ -281,6 +281,7 @@ public:
|
||||
consensus.llmqTypeChainLocks = Consensus::LLMQType::LLMQ_400_60;
|
||||
consensus.llmqTypeInstantSend = Consensus::LLMQType::LLMQ_50_60;
|
||||
consensus.llmqTypePlatform = Consensus::LLMQType::LLMQ_100_67;
|
||||
consensus.llmqTypeMnhf = Consensus::LLMQType::LLMQ_400_85;
|
||||
|
||||
fDefaultConsistencyChecks = false;
|
||||
fRequireStandard = true;
|
||||
@ -492,6 +493,7 @@ public:
|
||||
consensus.llmqTypeChainLocks = Consensus::LLMQType::LLMQ_50_60;
|
||||
consensus.llmqTypeInstantSend = Consensus::LLMQType::LLMQ_50_60;
|
||||
consensus.llmqTypePlatform = Consensus::LLMQType::LLMQ_100_67;
|
||||
consensus.llmqTypeMnhf = Consensus::LLMQType::LLMQ_50_60;
|
||||
|
||||
fDefaultConsistencyChecks = false;
|
||||
fRequireStandard = false;
|
||||
@ -685,6 +687,7 @@ public:
|
||||
consensus.llmqTypeChainLocks = Consensus::LLMQType::LLMQ_50_60;
|
||||
consensus.llmqTypeInstantSend = Consensus::LLMQType::LLMQ_50_60;
|
||||
consensus.llmqTypePlatform = Consensus::LLMQType::LLMQ_100_67;
|
||||
consensus.llmqTypeMnhf = Consensus::LLMQType::LLMQ_50_60;
|
||||
|
||||
UpdateDevnetLLMQChainLocksFromArgs(args);
|
||||
UpdateDevnetLLMQInstantSendFromArgs(args);
|
||||
@ -922,6 +925,7 @@ public:
|
||||
consensus.llmqTypeChainLocks = Consensus::LLMQType::LLMQ_TEST;
|
||||
consensus.llmqTypeInstantSend = Consensus::LLMQType::LLMQ_TEST;
|
||||
consensus.llmqTypePlatform = Consensus::LLMQType::LLMQ_TEST;
|
||||
consensus.llmqTypeMnhf = Consensus::LLMQType::LLMQ_TEST;
|
||||
|
||||
UpdateLLMQTestParametersFromArgs(args);
|
||||
}
|
||||
|
@ -116,6 +116,7 @@ struct Params {
|
||||
LLMQType llmqTypeChainLocks;
|
||||
LLMQType llmqTypeInstantSend{LLMQType::LLMQ_NONE};
|
||||
LLMQType llmqTypePlatform{LLMQType::LLMQ_NONE};
|
||||
LLMQType llmqTypeMnhf{LLMQType::LLMQ_NONE};
|
||||
};
|
||||
} // namespace Consensus
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <spentindex.h>
|
||||
|
||||
#include <evo/cbtx.h>
|
||||
#include <evo/mnhftx.h>
|
||||
#include <evo/providertx.h>
|
||||
#include <evo/specialtx.h>
|
||||
#include <llmq/commitment.h>
|
||||
@ -305,6 +306,13 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
|
||||
qcTx.ToJson(obj);
|
||||
entry.pushKV("qcTx", obj);
|
||||
}
|
||||
} else if (tx.nType == TRANSACTION_MNHF_SIGNAL) {
|
||||
MNHFTxPayload mnhfTx;
|
||||
if (GetTxPayload(tx, mnhfTx)) {
|
||||
UniValue obj;
|
||||
mnhfTx.ToJson(obj);
|
||||
entry.pushKV("mnhfTx", obj);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hashBlock.IsNull())
|
||||
|
70
src/evo/mnhftx.cpp
Normal file
70
src/evo/mnhftx.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2021-2022 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 <consensus/validation.h>
|
||||
#include <evo/mnhftx.h>
|
||||
#include <evo/specialtx.h>
|
||||
#include <llmq/commitment.h>
|
||||
#include <llmq/signing.h>
|
||||
|
||||
#include <chain.h>
|
||||
#include <chainparams.h>
|
||||
#include <validation.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
extern const std::string CBLSIG_REQUESTID_PREFIX = "clsig";
|
||||
|
||||
bool MNHFTx::Verify(const CBlockIndex* pQuorumIndex) const
|
||||
{
|
||||
if (nVersion == 0 || nVersion > CURRENT_VERSION) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Consensus::LLMQType llmqType = Params().GetConsensus().llmqTypeMnhf;
|
||||
int signOffset{llmq::GetLLMQParams(llmqType).dkgInterval};
|
||||
|
||||
const uint256 requestId = ::SerializeHash(std::make_pair(CBLSIG_REQUESTID_PREFIX, pQuorumIndex->nHeight));
|
||||
return llmq::CSigningManager::VerifyRecoveredSig(llmqType, pQuorumIndex->nHeight, requestId, pQuorumIndex->GetBlockHash(), sig, 0) ||
|
||||
llmq::CSigningManager::VerifyRecoveredSig(llmqType, pQuorumIndex->nHeight, requestId, pQuorumIndex->GetBlockHash(), sig, signOffset);
|
||||
}
|
||||
|
||||
bool CheckMNHFTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
MNHFTxPayload mnhfTx;
|
||||
if (!GetTxPayload(tx, mnhfTx)) {
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-mnhf-payload");
|
||||
}
|
||||
|
||||
if (mnhfTx.nVersion == 0 || mnhfTx.nVersion > MNHFTxPayload::CURRENT_VERSION) {
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-mnhf-version");
|
||||
}
|
||||
|
||||
const CBlockIndex* pindexQuorum = LookupBlockIndex(mnhfTx.signal.quorumHash);
|
||||
if (!pindexQuorum) {
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-mnhf-quorum-hash");
|
||||
}
|
||||
|
||||
if (pindexQuorum != pindexPrev->GetAncestor(pindexQuorum->nHeight)) {
|
||||
// not part of active chain
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-mnhf-quorum-hash");
|
||||
}
|
||||
|
||||
if (!Params().GetConsensus().llmqs.count(Params().GetConsensus().llmqTypeMnhf)) {
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-mnhf-type");
|
||||
}
|
||||
|
||||
if (!mnhfTx.signal.Verify(pindexQuorum)) {
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-mnhf-invalid");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MNHFTx::ToString() const
|
||||
{
|
||||
return strprintf("MNHFTx(nVersion=%d, quorumHash=%s, sig=%s)",
|
||||
nVersion, quorumHash.ToString(), sig.ToString());
|
||||
}
|
||||
|
74
src/evo/mnhftx.h
Normal file
74
src/evo/mnhftx.h
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright (c) 2021-2022 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 BITCOIN_EVO_MNHFTX_H
|
||||
#define BITCOIN_EVO_MNHFTX_H
|
||||
|
||||
#include <bls/bls.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <sync.h>
|
||||
#include <threadsafety.h>
|
||||
#include <univalue.h>
|
||||
|
||||
class CBlockIndex;
|
||||
class CValidationState;
|
||||
extern CCriticalSection cs_main;
|
||||
|
||||
// mnhf signal special transaction
|
||||
class MNHFTx
|
||||
{
|
||||
public:
|
||||
static constexpr uint16_t CURRENT_VERSION = 1;
|
||||
|
||||
uint16_t nVersion{CURRENT_VERSION};
|
||||
uint256 quorumHash;
|
||||
CBLSSignature sig;
|
||||
|
||||
MNHFTx() = default;
|
||||
bool Verify(const CBlockIndex* pQuorumIndex) const;
|
||||
|
||||
SERIALIZE_METHODS(MNHFTx, obj)
|
||||
{
|
||||
READWRITE(obj.nVersion, obj.quorumHash, obj.sig);
|
||||
}
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
void ToJson(UniValue& obj) const
|
||||
{
|
||||
obj.clear();
|
||||
obj.setObject();
|
||||
obj.pushKV("version", (int)nVersion);
|
||||
obj.pushKV("quorumHash", quorumHash.ToString());
|
||||
obj.pushKV("sig", sig.ToString());
|
||||
}
|
||||
};
|
||||
|
||||
class MNHFTxPayload
|
||||
{
|
||||
public:
|
||||
static constexpr uint16_t CURRENT_VERSION = 1;
|
||||
|
||||
uint16_t nVersion{CURRENT_VERSION};
|
||||
MNHFTx signal;
|
||||
|
||||
SERIALIZE_METHODS(MNHFTxPayload, obj)
|
||||
{
|
||||
READWRITE(obj.nVersion, obj.signal);
|
||||
}
|
||||
|
||||
void ToJson(UniValue& obj) const
|
||||
{
|
||||
obj.setObject();
|
||||
obj.pushKV("version", (int)nVersion);
|
||||
|
||||
UniValue mnhfObj;
|
||||
signal.ToJson(mnhfObj);
|
||||
obj.pushKV("signal", mnhfObj);
|
||||
}
|
||||
};
|
||||
|
||||
bool CheckMNHFTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
#endif // BITCOIN_EVO_MNHFTX_H
|
@ -6,16 +6,19 @@
|
||||
|
||||
#include <chainparams.h>
|
||||
#include <consensus/validation.h>
|
||||
#include <hash.h>
|
||||
#include <primitives/block.h>
|
||||
#include <validation.h>
|
||||
#include <evo/cbtx.h>
|
||||
#include <evo/deterministicmns.h>
|
||||
#include <llmq/commitment.h>
|
||||
#include <evo/mnhftx.h>
|
||||
#include <hash.h>
|
||||
#include <llmq/blockprocessor.h>
|
||||
#include <llmq/commitment.h>
|
||||
#include <primitives/block.h>
|
||||
#include <validation.h>
|
||||
|
||||
bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
|
||||
if (tx.nVersion != 3 || tx.nType == TRANSACTION_NORMAL)
|
||||
return true;
|
||||
|
||||
@ -37,6 +40,8 @@ bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVali
|
||||
return CheckCbTx(tx, pindexPrev, state);
|
||||
case TRANSACTION_QUORUM_COMMITMENT:
|
||||
return llmq::CheckLLMQCommitment(tx, pindexPrev, state);
|
||||
case TRANSACTION_MNHF_SIGNAL:
|
||||
return VersionBitsTipState(Params().GetConsensus(), Consensus::DEPLOYMENT_GOV_FEE) == ThresholdState::ACTIVE && CheckMNHFTx(tx, pindexPrev, state);
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
LogPrintf("%s -- failed: %s\n", __func__, e.what());
|
||||
@ -62,6 +67,8 @@ bool ProcessSpecialTx(const CTransaction& tx, const CBlockIndex* pindex, CValida
|
||||
return true; // nothing to do
|
||||
case TRANSACTION_QUORUM_COMMITMENT:
|
||||
return true; // handled per block
|
||||
case TRANSACTION_MNHF_SIGNAL:
|
||||
return true; // handled per block
|
||||
}
|
||||
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-tx-type-proc");
|
||||
@ -83,6 +90,8 @@ bool UndoSpecialTx(const CTransaction& tx, const CBlockIndex* pindex)
|
||||
return true; // nothing to do
|
||||
case TRANSACTION_QUORUM_COMMITMENT:
|
||||
return true; // handled per block
|
||||
case TRANSACTION_MNHF_SIGNAL:
|
||||
return true; // handled per block
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -18,7 +18,7 @@ class CValidationState;
|
||||
|
||||
extern CCriticalSection cs_main;
|
||||
|
||||
bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view);
|
||||
bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CValidationState& state, const CCoinsViewCache& view, bool fJustCheck, bool fCheckCbTxMerleRoots) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
|
@ -21,6 +21,7 @@ enum {
|
||||
TRANSACTION_PROVIDER_UPDATE_REVOKE = 4,
|
||||
TRANSACTION_COINBASE = 5,
|
||||
TRANSACTION_QUORUM_COMMITMENT = 6,
|
||||
TRANSACTION_MNHF_SIGNAL = 7,
|
||||
};
|
||||
|
||||
/** An outpoint - a combination of a transaction hash and an index n into its vout */
|
||||
|
84
src/test/specialtx_tests.cpp
Normal file
84
src/test/specialtx_tests.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2021 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 <bls/bls.h>
|
||||
#include <consensus/validation.h>
|
||||
#include <evo/mnhftx.h>
|
||||
#include <evo/specialtx.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <uint256.h>
|
||||
#include <util/strencodings.h>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <test/setup_common.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
|
||||
bool VerifyMNHFTx(const CTransaction& tx, CValidationState& state)
|
||||
{
|
||||
MNHFTxPayload mnhfTx;
|
||||
if (!GetTxPayload(tx, mnhfTx)) {
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-mnhf-payload");
|
||||
}
|
||||
|
||||
if (mnhfTx.nVersion == 0 || mnhfTx.nVersion > MNHFTxPayload::CURRENT_VERSION) {
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-mnhf-version");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static CMutableTransaction CreateMNHFTx(const uint256& mnhfTxHash, const CBLSSignature& cblSig, const uint16_t& versionBit)
|
||||
{
|
||||
MNHFTxPayload extraPayload;
|
||||
extraPayload.nVersion = 1;
|
||||
extraPayload.signal.nVersion = versionBit;
|
||||
extraPayload.signal.quorumHash = mnhfTxHash;
|
||||
extraPayload.signal.sig = cblSig;
|
||||
|
||||
CMutableTransaction tx;
|
||||
tx.nVersion = 3;
|
||||
tx.nType = TRANSACTION_MNHF_SIGNAL;
|
||||
SetTxPayload(tx, extraPayload);
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(specialtx_tests, BasicTestingSetup)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(verify_mnhf_specialtx_tests)
|
||||
{
|
||||
int count = 10;
|
||||
uint16_t ver = 2;
|
||||
|
||||
std::vector<CBLSSignature> vec_sigs;
|
||||
std::vector<CBLSPublicKey> vec_pks;
|
||||
std::vector<CBLSSecretKey> vec_sks;
|
||||
|
||||
CBLSSecretKey sk;
|
||||
uint256 hash = GetRandHash();
|
||||
for (int i = 0; i < count; i++) {
|
||||
sk.MakeNewKey();
|
||||
vec_pks.push_back(sk.GetPublicKey());
|
||||
vec_sks.push_back(sk);
|
||||
}
|
||||
|
||||
CBLSSecretKey ag_sk = CBLSSecretKey::AggregateInsecure(vec_sks);
|
||||
CBLSPublicKey ag_pk = CBLSPublicKey::AggregateInsecure(vec_pks);
|
||||
|
||||
BOOST_CHECK(ag_sk.IsValid());
|
||||
BOOST_CHECK(ag_pk.IsValid());
|
||||
|
||||
uint256 verHash = uint256S(itostr(ver));
|
||||
auto sig = ag_sk.Sign(verHash);
|
||||
BOOST_CHECK(sig.VerifyInsecure(ag_pk, verHash));
|
||||
|
||||
const CMutableTransaction tx = CreateMNHFTx(hash, sig, ver);
|
||||
CValidationState state;
|
||||
BOOST_CHECK(VerifyMNHFTx(CTransaction(tx), state));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
@ -378,7 +378,8 @@ bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state,
|
||||
tx.nType != TRANSACTION_PROVIDER_UPDATE_REGISTRAR &&
|
||||
tx.nType != TRANSACTION_PROVIDER_UPDATE_REVOKE &&
|
||||
tx.nType != TRANSACTION_COINBASE &&
|
||||
tx.nType != TRANSACTION_QUORUM_COMMITMENT) {
|
||||
tx.nType != TRANSACTION_QUORUM_COMMITMENT &&
|
||||
tx.nType != TRANSACTION_MNHF_SIGNAL) {
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-type");
|
||||
}
|
||||
if (tx.IsCoinBase() && tx.nType != TRANSACTION_COINBASE)
|
||||
|
@ -105,6 +105,7 @@ EXPECTED_CIRCULAR_DEPENDENCIES=(
|
||||
"coinjoin/coinjoin -> llmq/chainlocks -> net -> coinjoin/coinjoin"
|
||||
"evo/deterministicmns -> llmq/utils -> net -> evo/deterministicmns"
|
||||
"evo/deterministicmns -> llmq/utils -> net -> masternode/sync -> evo/deterministicmns"
|
||||
"evo/mnhftx -> evo/specialtx -> evo/mnhftx"
|
||||
)
|
||||
|
||||
EXIT_CODE=0
|
||||
|
Loading…
Reference in New Issue
Block a user