Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/bloom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ bool CBloomFilter::CheckScript(const CScript &script) const
return false;
}

bool CBloomFilter::CheckPayeeSharesScripts(const std::vector<PayoutShare>& payoutShares) const
{
return ranges::any_of(payoutShares, [&](const auto& payoutShare) { return CheckScript(payoutShare.scriptPayout); });
}
// If the transaction is a special transaction that has a registration
// transaction hash, test the registration transaction hash.
// If the transaction is a special transaction with any public keys or any
Expand All @@ -131,7 +135,7 @@ bool CBloomFilter::CheckSpecialTransactionMatchesAndUpdate(const CTransaction &t
if(contains(proTx.collateralOutpoint) ||
contains(proTx.keyIDOwner) ||
contains(proTx.keyIDVoting) ||
CheckScript(proTx.scriptPayout)) {
CheckPayeeSharesScripts(proTx.payoutShares)) {
if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_ALL)
insert(tx.GetHash());
return true;
Expand Down Expand Up @@ -159,7 +163,7 @@ bool CBloomFilter::CheckSpecialTransactionMatchesAndUpdate(const CTransaction &t
if(contains(proTx.proTxHash))
return true;
if(contains(proTx.keyIDVoting) ||
CheckScript(proTx.scriptPayout)) {
CheckPayeeSharesScripts(proTx.payoutShares)) {
if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_ALL)
insert(proTx.proTxHash);
return true;
Expand Down
2 changes: 2 additions & 0 deletions src/bloom.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class CScript;
class CTransaction;
class CTxOut;
class uint256;
class PayoutShare;

//! 20,000 items with fp rate < 0.1% or 10,000 items and <0.0001%
static constexpr unsigned int MAX_BLOOM_FILTER_SIZE = 36000; // bytes
Expand Down Expand Up @@ -56,6 +57,7 @@ class CBloomFilter

// Check matches for arbitrary script data elements
bool CheckScript(const CScript& script) const;
bool CheckPayeeSharesScripts(const std::vector<PayoutShare>& payoutShares) const;
// Check particular CTxOut helper
bool ProcessTxOut(const CTxOut& txout, const uint256& hash, unsigned int index);
// Check additional matches for special transactions
Expand Down
9 changes: 9 additions & 0 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,15 @@ class CRegTestParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nFalloffCoeff = 5; // this corresponds to 10 periods
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].useEHF = true;

consensus.vDeployments[Consensus::DEPLOYMENT_DIP0026].bit = 11;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0026].nStartTime = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0026].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0026].nWindowSize = 12;
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0026].nThresholdStart = 9; // 80% of 12
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0026].nThresholdMin = 7; // 60% of 12
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0026].nFalloffCoeff = 5; // this corresponds to 10 periods
consensus.vDeployments[Consensus::DEPLOYMENT_DIP0026].useEHF = true;

Comment thread
panleone marked this conversation as resolved.
// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x00");

Expand Down
3 changes: 2 additions & 1 deletion src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ enum DeploymentPos : uint16_t
DEPLOYMENT_TESTDUMMY,
DEPLOYMENT_V20, // Deployment of EHF, LLMQ Randomness Beacon
DEPLOYMENT_MN_RR, // Deployment of Masternode Reward Location Reallocation
DEPLOYMENT_DIP0026, // Deployment of Multi Payees in a single ProRegTx
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in deploymentinfo.cpp
MAX_VERSION_BITS_DEPLOYMENTS
};
constexpr bool ValidDeployment(DeploymentPos dep) { return DEPLOYMENT_TESTDUMMY <= dep && dep <= DEPLOYMENT_MN_RR; }
constexpr bool ValidDeployment(DeploymentPos dep) { return DEPLOYMENT_TESTDUMMY <= dep && dep <= DEPLOYMENT_DIP0026; }

/**
* Struct for each individual consensus rule change using BIP9.
Expand Down
4 changes: 4 additions & 0 deletions src/deploymentinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_B
/*.name =*/"mn_rr",
/*.gbt_force =*/true,
},
{
/*.name =*/"multi_mn_payee",
/*.gbt_force =*/true,
},
};

std::string DeploymentName(Consensus::BuriedDeployment dep)
Expand Down
11 changes: 7 additions & 4 deletions src/evo/deterministicmns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -877,7 +877,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, gsl::no
newState->pubKeyOperator = proTx.pubKeyOperator;
}
newState->keyIDVoting = proTx.keyIDVoting;
newState->scriptPayout = proTx.scriptPayout;
newState->payoutShares = proTx.payoutShares;

newList.UpdateMN(proTx.proTxHash, newState);

Expand Down Expand Up @@ -1513,7 +1513,8 @@ static std::optional<ProTx> GetValidatedPayload(const CTransaction& tx, gsl::not
return std::nullopt;
}
const bool is_basic_scheme_active{DeploymentActiveAfter(pindexPrev, Params().GetConsensus(), Consensus::DEPLOYMENT_V19)};
if (!ptx.IsTriviallyValid(is_basic_scheme_active, state)) {
const bool is_multi_payout_active{DeploymentActiveAfter(pindexPrev, Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0026)};
if (!ptx.IsTriviallyValid(is_basic_scheme_active, is_multi_payout_active, state)) {
// pass the state returned by the function above
return std::nullopt;
}
Expand Down Expand Up @@ -1706,8 +1707,10 @@ bool CheckProUpRegTx(const CTransaction& tx, gsl::not_null<const CBlockIndex*> p
const auto& ptx{*opt_ptx};

CTxDestination payoutDest;
if (!ExtractDestination(ptx.scriptPayout, payoutDest)) {
// should not happen as we checked script types before
const auto& scriptIterator = std::find_if(ptx.payoutShares.begin(), ptx.payoutShares.end(), [&](const auto& payoutShare){
return !ExtractDestination(payoutShare.scriptPayout, payoutDest);
});
if (scriptIterator != ptx.payoutShares.end()) {
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-payee-dest");
}

Expand Down
28 changes: 17 additions & 11 deletions src/evo/dmnstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,20 @@
std::string CDeterministicMNState::ToString() const
{
CTxDestination dest;
std::string payoutAddress = "unknown";
std::string payoutSharesStr;
std::string operatorPayoutAddress = "none";
if (ExtractDestination(scriptPayout, dest)) {
payoutAddress = EncodeDestination(dest);
for (const auto& payoutShare : payoutShares) {
if (!payoutSharesStr.empty()) payoutSharesStr += ", ";
payoutSharesStr += payoutShare.ToString();
}
if (ExtractDestination(scriptOperatorPayout, dest)) {
operatorPayoutAddress = EncodeDestination(dest);
}

return strprintf("CDeterministicMNState(nVersion=%d, nRegisteredHeight=%d, nLastPaidHeight=%d, nPoSePenalty=%d, nPoSeRevivedHeight=%d, nPoSeBanHeight=%d, nRevocationReason=%d, "
"ownerAddress=%s, pubKeyOperator=%s, votingAddress=%s, addr=%s, payoutAddress=%s, operatorPayoutAddress=%s)",
"ownerAddress=%s, pubKeyOperator=%s, votingAddress=%s, addr=%s, payoutShares=%s, operatorPayoutAddress=%s)",
nVersion, nRegisteredHeight, nLastPaidHeight, nPoSePenalty, nPoSeRevivedHeight, nPoSeBanHeight, nRevocationReason,
EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)), addr.ToStringIPPort(false), payoutAddress, operatorPayoutAddress);
EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)), addr.ToStringIPPort(false), payoutSharesStr, operatorPayoutAddress);
}

UniValue CDeterministicMNState::ToJson(MnType nType) const
Expand All @@ -52,10 +53,13 @@ UniValue CDeterministicMNState::ToJson(MnType nType) const
obj.pushKV("platformHTTPPort", platformHTTPPort);
}

UniValue payoutArray;
payoutArray.setArray();
CTxDestination dest;
if (ExtractDestination(scriptPayout, dest)) {
obj.pushKV("payoutAddress", EncodeDestination(dest));
for (const auto& payoutShare : payoutShares) {
payoutArray.push_back(payoutShare.ToJson());
}
obj.pushKV("payouts", payoutArray);
obj.pushKV("pubKeyOperator", pubKeyOperator.ToString());
if (ExtractDestination(scriptOperatorPayout, dest)) {
obj.pushKV("operatorPayoutAddress", EncodeDestination(dest));
Expand Down Expand Up @@ -100,11 +104,13 @@ UniValue CDeterministicMNStateDiff::ToJson(MnType nType) const
if (fields & Field_keyIDVoting) {
obj.pushKV("votingAddress", EncodeDestination(PKHash(state.keyIDVoting)));
}
if (fields & Field_scriptPayout) {
CTxDestination dest;
if (ExtractDestination(state.scriptPayout, dest)) {
obj.pushKV("payoutAddress", EncodeDestination(dest));
if (fields & Field_payoutShares) {
UniValue payoutArray;
payoutArray.setArray();
for (const auto& payoutShare : state.payoutShares) {
payoutArray.push_back(payoutShare.ToJson());
}
obj.pushKV("payouts", payoutArray);
}
if (fields & Field_scriptOperatorPayout) {
CTxDestination dest;
Expand Down
28 changes: 19 additions & 9 deletions src/evo/dmnstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ class CDeterministicMNState
CBLSLazyPublicKey pubKeyOperator;
CKeyID keyIDVoting;
CService addr;
CScript scriptPayout;
std::vector<PayoutShare> payoutShares;
CScript scriptOperatorPayout;

uint160 platformNodeID{};
Expand All @@ -170,7 +170,7 @@ class CDeterministicMNState
pubKeyOperator(proTx.pubKeyOperator),
keyIDVoting(proTx.keyIDVoting),
addr(proTx.addr),
scriptPayout(proTx.scriptPayout),
payoutShares(proTx.payoutShares),
platformNodeID(proTx.platformNodeID),
platformP2PPort(proTx.platformP2PPort),
platformHTTPPort(proTx.platformHTTPPort)
Expand All @@ -189,7 +189,7 @@ class CDeterministicMNState
pubKeyOperator(s.pubKeyOperator),
keyIDVoting(s.keyIDVoting),
addr(s.addr),
scriptPayout(s.scriptPayout),
payoutShares({PayoutShare(s.scriptPayout)}),
scriptOperatorPayout(s.scriptOperatorPayout) {}

explicit CDeterministicMNState(const CDeterministicMNState_mntype_format& s) :
Expand All @@ -206,7 +206,7 @@ class CDeterministicMNState
pubKeyOperator(s.pubKeyOperator),
keyIDVoting(s.keyIDVoting),
addr(s.addr),
scriptPayout(s.scriptPayout),
payoutShares({PayoutShare(s.scriptPayout)}),
scriptOperatorPayout(s.scriptOperatorPayout),
platformNodeID(s.platformNodeID),
platformP2PPort(s.platformP2PPort),
Expand Down Expand Up @@ -236,7 +236,7 @@ class CDeterministicMNState
READWRITE(
obj.keyIDVoting,
obj.addr,
obj.scriptPayout,
PayoutSharesSerializerWrapper(const_cast<std::vector<PayoutShare>&>(obj.payoutShares), (obj.nVersion < CProRegTx::MULTI_PAYOUT_VERSION)),
obj.scriptOperatorPayout,
obj.platformNodeID,
obj.platformP2PPort,
Expand Down Expand Up @@ -302,7 +302,7 @@ class CDeterministicMNStateDiff
Field_pubKeyOperator = 0x0200,
Field_keyIDVoting = 0x0400,
Field_addr = 0x0800,
Field_scriptPayout = 0x1000,
Field_payoutShares = 0x1000,
Field_scriptOperatorPayout = 0x2000,
Field_nConsecutivePayments = 0x4000,
Field_platformNodeID = 0x8000,
Expand All @@ -324,7 +324,7 @@ class CDeterministicMNStateDiff
DMN_STATE_DIFF_LINE(pubKeyOperator) \
DMN_STATE_DIFF_LINE(keyIDVoting) \
DMN_STATE_DIFF_LINE(addr) \
DMN_STATE_DIFF_LINE(scriptPayout) \
DMN_STATE_DIFF_LINE(payoutShares) \
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

really surprised it's that simple and does not require any special logic in SERIALIZE_METHODS.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, nice catch! It is not that simple indeed since CDeterministicMNStateDiff does not use the serialization of CDeterministicMNState, but I guess we can use the same trick we did with pubKeyOperator

Copy link
Copy Markdown
Author

@panleone panleone Jan 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, now every std::vector<PayoutShare> is serialized with the same helper class (whose compatibility with older versions is tested in trivially_valid and trivially_invalid unit tests).

CDeterministicMNStateDiff also uses this class + from now on each time it serializes a vector of PayoutShare it serializes also the version.

DMN_STATE_DIFF_LINE(scriptOperatorPayout) \
DMN_STATE_DIFF_LINE(nConsecutivePayments) \
DMN_STATE_DIFF_LINE(platformNodeID) \
Expand All @@ -344,20 +344,27 @@ class CDeterministicMNStateDiff
#define DMN_STATE_DIFF_LINE(f) if (a.f != b.f) { state.f = b.f; fields |= Field_##f; }
DMN_STATE_DIFF_ALL_FIELDS
#undef DMN_STATE_DIFF_LINE
if (fields & Field_pubKeyOperator) { state.nVersion = b.nVersion; fields |= Field_nVersion; }
if (fields & Field_pubKeyOperator || fields & Field_payoutShares) {
state.nVersion = b.nVersion;
fields |= Field_nVersion;
}
}

[[nodiscard]] UniValue ToJson(MnType nType) const;

SERIALIZE_METHODS(CDeterministicMNStateDiff, obj)
{
// NOTE: reading pubKeyOperator requires nVersion
// NOTE: reading pubKeyOperator and payoutShares requires nVersion
bool read_pubkey{false};
bool read_payoutShares{false};
READWRITE(VARINT(obj.fields));
#define DMN_STATE_DIFF_LINE(f) \
if (strcmp(#f, "pubKeyOperator") == 0 && (obj.fields & Field_pubKeyOperator)) {\
SER_READ(obj, read_pubkey = true); \
READWRITE(CBLSLazyPublicKeyVersionWrapper(const_cast<CBLSLazyPublicKey&>(obj.state.pubKeyOperator), obj.state.nVersion == CProRegTx::LEGACY_BLS_VERSION)); \
} else if (strcmp(#f, "payoutShares") == 0 && (obj.fields & Field_payoutShares)) {\
SER_READ(obj, read_payoutShares = true); \
READWRITE(PayoutSharesSerializerWrapper(const_cast<std::vector<PayoutShare>&>(obj.state.payoutShares), (obj.state.nVersion < CProRegTx::MULTI_PAYOUT_VERSION))); \
} else if (obj.fields & Field_##f) READWRITE(obj.state.f);

DMN_STATE_DIFF_ALL_FIELDS
Expand All @@ -366,6 +373,9 @@ class CDeterministicMNStateDiff
SER_READ(obj, obj.fields |= Field_nVersion);
SER_READ(obj, obj.state.pubKeyOperator.SetLegacy(obj.state.nVersion == CProRegTx::LEGACY_BLS_VERSION));
}
if (read_payoutShares) {
SER_READ(obj, obj.fields |= Field_nVersion);
}
}

void ApplyToState(CDeterministicMNState& target) const
Expand Down
Loading