mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
Use BLS keys for the DIP3 operator key (#2352)
* Use BLS keys for operator keys * Add "bls generate" RPC to generate BLS keys * Use unique_ptr to store blsKeyOperator and blsPubKeyOperator Needed because the Chia BLS library crashes when keys are created before the library is initialized, even if keys are not used. This is the case here as we have static instances here. * Remove unnecessary CheckSignature calls This seems to be some garbage I left in by mistake. * Fixed review comments * Fix rpc help for operator keys All keys that are used as examples are random. None of the secret keys belongs to any of the public keys. * Use .GetHash() instead of ::SerializeHash() for BLS pubkeys in txmempool.cpp * Rename mapProTxBlsPubKeys to mapProTxBlsPubKeyHashes
This commit is contained in:
parent
3313bbd515
commit
c9d2745188
@ -279,7 +279,9 @@ class DIP3Test(BitcoinTestFramework):
|
||||
mn.is_protx = False
|
||||
mn.p2p_port = p2p_port(mn.idx)
|
||||
|
||||
mn.mnkey = node.masternode('genkey')
|
||||
blsKey = node.bls('generate')
|
||||
mn.legacyMnkey = node.masternode('genkey')
|
||||
mn.blsMnkey = blsKey['secret']
|
||||
mn.collateral_address = node.getnewaddress()
|
||||
mn.collateral_txid = node.sendtoaddress(mn.collateral_address, 1000)
|
||||
rawtx = node.getrawtransaction(mn.collateral_txid, 1)
|
||||
@ -302,10 +304,12 @@ class DIP3Test(BitcoinTestFramework):
|
||||
mn.is_protx = True
|
||||
mn.p2p_port = p2p_port(mn.idx)
|
||||
|
||||
blsKey = node.bls('generate')
|
||||
mn.ownerAddr = node.getnewaddress()
|
||||
mn.operatorAddr = mn.ownerAddr
|
||||
mn.operatorAddr = blsKey['public']
|
||||
mn.votingAddr = mn.ownerAddr
|
||||
mn.mnkey = node.dumpprivkey(mn.operatorAddr)
|
||||
mn.legacyMnkey = node.masternode('genkey')
|
||||
mn.blsMnkey = blsKey['secret']
|
||||
mn.collateral_address = node.getnewaddress()
|
||||
|
||||
mn.collateral_txid = node.protx('register', mn.collateral_address, '1000', '127.0.0.1:%d' % mn.p2p_port, '0', mn.ownerAddr, mn.operatorAddr, mn.votingAddr, 0, mn.collateral_address)
|
||||
@ -323,7 +327,7 @@ class DIP3Test(BitcoinTestFramework):
|
||||
def start_mn(self, mn):
|
||||
while len(self.nodes) <= mn.idx:
|
||||
self.nodes.append(None)
|
||||
extra_args = ['-masternode=1', '-masternodeprivkey=%s' % mn.mnkey]
|
||||
extra_args = ['-masternode=1', '-masternodeprivkey=%s' % mn.legacyMnkey, '-masternodeblsprivkey=%s' % mn.blsMnkey]
|
||||
n = start_node(mn.idx, self.options.tmpdir, self.extra_args + extra_args, redirect_stderr=True)
|
||||
self.nodes[mn.idx] = n
|
||||
for i in range(0, self.num_nodes):
|
||||
@ -341,7 +345,7 @@ class DIP3Test(BitcoinTestFramework):
|
||||
return mn
|
||||
|
||||
def test_protx_update_service(self, mn):
|
||||
self.nodes[0].protx('update_service', mn.collateral_txid, '127.0.0.2:%d' % mn.p2p_port, '0')
|
||||
self.nodes[0].protx('update_service', mn.collateral_txid, '127.0.0.2:%d' % mn.p2p_port, '0', mn.blsMnkey)
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
for node in self.nodes:
|
||||
@ -351,7 +355,7 @@ class DIP3Test(BitcoinTestFramework):
|
||||
assert_equal(mn_list['%s-%d' % (mn.collateral_txid, mn.collateral_vout)]['address'], '127.0.0.2:%d' % mn.p2p_port)
|
||||
|
||||
# undo
|
||||
self.nodes[0].protx('update_service', mn.collateral_txid, '127.0.0.1:%d' % mn.p2p_port, '0')
|
||||
self.nodes[0].protx('update_service', mn.collateral_txid, '127.0.0.1:%d' % mn.p2p_port, '0', mn.blsMnkey)
|
||||
self.nodes[0].generate(1)
|
||||
|
||||
def force_finish_mnsync(self, node):
|
||||
@ -374,7 +378,7 @@ class DIP3Test(BitcoinTestFramework):
|
||||
time.sleep(0.1)
|
||||
|
||||
def write_mnconf_line(self, mn, f):
|
||||
conf_line = "%s %s:%d %s %s %d\n" % (mn.alias, '127.0.0.1', mn.p2p_port, mn.mnkey, mn.collateral_txid, mn.collateral_vout)
|
||||
conf_line = "%s %s:%d %s %s %d\n" % (mn.alias, '127.0.0.1', mn.p2p_port, mn.legacyMnkey, mn.collateral_txid, mn.collateral_vout)
|
||||
f.write(conf_line)
|
||||
|
||||
def write_mnconf(self, mns):
|
||||
@ -594,12 +598,14 @@ class DIP3Test(BitcoinTestFramework):
|
||||
# Try to create ProTx (should still fail)
|
||||
address = node.getnewaddress()
|
||||
key = node.getnewaddress()
|
||||
assert_raises_jsonrpc(None, "bad-tx-type", node.protx, 'register', address, '1000', '127.0.0.1:10000', '0', key, key, key, 0, address)
|
||||
blsKey = node.bls('generate')
|
||||
assert_raises_jsonrpc(None, "bad-tx-type", node.protx, 'register', address, '1000', '127.0.0.1:10000', '0', key, blsKey['public'], key, 0, address)
|
||||
|
||||
def test_success_create_protx(self, node):
|
||||
address = node.getnewaddress()
|
||||
key = node.getnewaddress()
|
||||
txid = node.protx('register', address, '1000', '127.0.0.1:10000', '0', key, key, key, 0, address)
|
||||
blsKey = node.bls('generate')
|
||||
txid = node.protx('register', address, '1000', '127.0.0.1:10000', '0', key, blsKey['public'], key, 0, address)
|
||||
rawtx = node.getrawtransaction(txid, 1)
|
||||
self.mine_double_spend(node, rawtx['vin'], address, use_mnmerkleroot_from_tip=True)
|
||||
self.sync_all()
|
||||
|
@ -59,7 +59,7 @@ void CActiveDeterministicMasternodeManager::Init()
|
||||
|
||||
CDeterministicMNList mnList = deterministicMNManager->GetListAtChainTip();
|
||||
|
||||
CDeterministicMNCPtr dmn = mnList.GetMNByOperatorKey(activeMasternodeInfo.keyIDOperator);
|
||||
CDeterministicMNCPtr dmn = mnList.GetMNByOperatorKey(*activeMasternodeInfo.blsPubKeyOperator);
|
||||
if (!dmn) {
|
||||
// MN not appeared on the chain yet
|
||||
return;
|
||||
@ -234,7 +234,7 @@ bool CActiveLegacyMasternodeManager::SendMasternodePing(CConnman& connman)
|
||||
mnp.nSentinelVersion = nSentinelVersion;
|
||||
mnp.fSentinelIsCurrent =
|
||||
(abs(GetAdjustedTime() - nSentinelPingTime) < MASTERNODE_SENTINEL_PING_MAX_SECONDS);
|
||||
if(!mnp.Sign(activeMasternodeInfo.keyOperator, activeMasternodeInfo.keyIDOperator)) {
|
||||
if(!mnp.Sign(activeMasternodeInfo.legacyKeyOperator, activeMasternodeInfo.legacyKeyIDOperator)) {
|
||||
LogPrintf("CActiveLegacyMasternodeManager::SendMasternodePing -- ERROR: Couldn't sign Masternode Ping\n");
|
||||
return false;
|
||||
}
|
||||
@ -351,11 +351,11 @@ void CActiveLegacyMasternodeManager::ManageStateRemote()
|
||||
return;
|
||||
|
||||
LogPrint("masternode", "CActiveLegacyMasternodeManager::ManageStateRemote -- Start status = %s, type = %s, pinger enabled = %d, keyIDOperator = %s\n",
|
||||
GetStatus(), GetTypeString(), fPingerEnabled, activeMasternodeInfo.keyIDOperator.ToString());
|
||||
GetStatus(), GetTypeString(), fPingerEnabled, activeMasternodeInfo.legacyKeyIDOperator.ToString());
|
||||
|
||||
mnodeman.CheckMasternode(activeMasternodeInfo.keyIDOperator, true);
|
||||
mnodeman.CheckMasternode(activeMasternodeInfo.legacyKeyIDOperator, true);
|
||||
masternode_info_t infoMn;
|
||||
if(mnodeman.GetMasternodeInfo(activeMasternodeInfo.keyIDOperator, infoMn)) {
|
||||
if(mnodeman.GetMasternodeInfo(activeMasternodeInfo.legacyKeyIDOperator, infoMn)) {
|
||||
if(infoMn.nProtocolVersion != PROTOCOL_VERSION) {
|
||||
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
|
||||
strNotCapableReason = "Invalid protocol version";
|
||||
@ -376,12 +376,6 @@ void CActiveLegacyMasternodeManager::ManageStateRemote()
|
||||
}
|
||||
auto dmn = deterministicMNManager->GetListAtChainTip().GetMN(infoMn.outpoint.hash);
|
||||
if (dmn) {
|
||||
if (dmn->pdmnState->keyIDOperator != infoMn.keyIDOperator) {
|
||||
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
|
||||
strNotCapableReason = strprintf("Masternode collateral is a ProTx and masternode key does not match key from -masternodeprivkey");
|
||||
LogPrintf("CActiveLegacyMasternodeManager::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
|
||||
return;
|
||||
}
|
||||
if (dmn->pdmnState->addr != infoMn.addr) {
|
||||
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
|
||||
strNotCapableReason = strprintf("Masternode collateral is a ProTx and ProTx address does not match local address");
|
||||
|
@ -30,8 +30,11 @@ extern CActiveDeterministicMasternodeManager* activeMasternodeManager;
|
||||
|
||||
struct CActiveMasternodeInfo {
|
||||
// Keys for the active Masternode
|
||||
CKeyID keyIDOperator;
|
||||
CKey keyOperator;
|
||||
CKeyID legacyKeyIDOperator;
|
||||
CKey legacyKeyOperator;
|
||||
|
||||
std::unique_ptr<CBLSPublicKey> blsPubKeyOperator;
|
||||
std::unique_ptr<CBLSSecretKey> blsKeyOperator;
|
||||
|
||||
// Initialized while registering Masternode
|
||||
COutPoint outpoint;
|
||||
|
@ -33,9 +33,9 @@ std::string CDeterministicMNState::ToString() const
|
||||
}
|
||||
|
||||
return strprintf("CDeterministicMNState(nRegisteredHeight=%d, nLastPaidHeight=%d, nPoSePenalty=%d, nPoSeRevivedHeight=%d, nPoSeBanHeight=%d, nRevocationReason=%d, "
|
||||
"keyIDOwner=%s, keyIDOperator=%s, keyIDVoting=%s, addr=%s, nProtocolVersion=%d, payoutAddress=%s, operatorRewardAddress=%s)",
|
||||
"keyIDOwner=%s, pubKeyOperator=%s, keyIDVoting=%s, addr=%s, nProtocolVersion=%d, payoutAddress=%s, operatorRewardAddress=%s)",
|
||||
nRegisteredHeight, nLastPaidHeight, nPoSePenalty, nPoSeRevivedHeight, nPoSeBanHeight, nRevocationReason,
|
||||
keyIDOwner.ToString(), keyIDOperator.ToString(), keyIDVoting.ToString(), addr.ToStringIPPort(false), nProtocolVersion, payoutAddress, operatorRewardAddress);
|
||||
keyIDOwner.ToString(), pubKeyOperator.ToString(), keyIDVoting.ToString(), addr.ToStringIPPort(false), nProtocolVersion, payoutAddress, operatorRewardAddress);
|
||||
}
|
||||
|
||||
void CDeterministicMNState::ToJson(UniValue& obj) const
|
||||
@ -49,7 +49,7 @@ void CDeterministicMNState::ToJson(UniValue& obj) const
|
||||
obj.push_back(Pair("PoSeBanHeight", nPoSeBanHeight));
|
||||
obj.push_back(Pair("revocationReason", nRevocationReason));
|
||||
obj.push_back(Pair("keyIDOwner", keyIDOwner.ToString()));
|
||||
obj.push_back(Pair("keyIDOperator", keyIDOperator.ToString()));
|
||||
obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString()));
|
||||
obj.push_back(Pair("keyIDVoting", keyIDVoting.ToString()));
|
||||
obj.push_back(Pair("addr", addr.ToStringIPPort(false)));
|
||||
obj.push_back(Pair("protocolVersion", nProtocolVersion));
|
||||
@ -132,10 +132,10 @@ CDeterministicMNCPtr CDeterministicMNList::GetValidMN(const uint256& proTxHash)
|
||||
return dmn;
|
||||
}
|
||||
|
||||
CDeterministicMNCPtr CDeterministicMNList::GetMNByOperatorKey(const CKeyID& keyID)
|
||||
CDeterministicMNCPtr CDeterministicMNList::GetMNByOperatorKey(const CBLSPublicKey& pubKey)
|
||||
{
|
||||
for (const auto& p : mnMap) {
|
||||
if (p.second->pdmnState->keyIDOperator == keyID) {
|
||||
if (p.second->pdmnState->pubKeyOperator == pubKey) {
|
||||
return p.second;
|
||||
}
|
||||
}
|
||||
@ -256,7 +256,7 @@ void CDeterministicMNList::AddMN(const CDeterministicMNCPtr &dmn)
|
||||
mnMap = mnMap.set(dmn->proTxHash, dmn);
|
||||
AddUniqueProperty(dmn, dmn->pdmnState->addr);
|
||||
AddUniqueProperty(dmn, dmn->pdmnState->keyIDOwner);
|
||||
AddUniqueProperty(dmn, dmn->pdmnState->keyIDOperator);
|
||||
AddUniqueProperty(dmn, dmn->pdmnState->pubKeyOperator);
|
||||
}
|
||||
|
||||
void CDeterministicMNList::UpdateMN(const uint256 &proTxHash, const CDeterministicMNStateCPtr &pdmnState)
|
||||
@ -270,7 +270,7 @@ void CDeterministicMNList::UpdateMN(const uint256 &proTxHash, const CDeterminist
|
||||
|
||||
UpdateUniqueProperty(dmn, oldState->addr, pdmnState->addr);
|
||||
UpdateUniqueProperty(dmn, oldState->keyIDOwner, pdmnState->keyIDOwner);
|
||||
UpdateUniqueProperty(dmn, oldState->keyIDOperator, pdmnState->keyIDOperator);
|
||||
UpdateUniqueProperty(dmn, oldState->pubKeyOperator, pdmnState->pubKeyOperator);
|
||||
}
|
||||
|
||||
void CDeterministicMNList::RemoveMN(const uint256& proTxHash)
|
||||
@ -279,7 +279,7 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash)
|
||||
assert(dmn != nullptr);
|
||||
DeleteUniqueProperty(dmn, dmn->pdmnState->addr);
|
||||
DeleteUniqueProperty(dmn, dmn->pdmnState->keyIDOwner);
|
||||
DeleteUniqueProperty(dmn, dmn->pdmnState->keyIDOperator);
|
||||
DeleteUniqueProperty(dmn, dmn->pdmnState->pubKeyOperator);
|
||||
mnMap = mnMap.erase(proTxHash);
|
||||
}
|
||||
|
||||
@ -387,7 +387,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
|
||||
|
||||
if (newList.HasUniqueProperty(proTx.addr))
|
||||
return _state.DoS(100, false, REJECT_CONFLICT, "bad-protx-dup-addr");
|
||||
if (newList.HasUniqueProperty(proTx.keyIDOwner) || newList.HasUniqueProperty(proTx.keyIDOperator))
|
||||
if (newList.HasUniqueProperty(proTx.keyIDOwner) || newList.HasUniqueProperty(proTx.pubKeyOperator))
|
||||
return _state.DoS(100, false, REJECT_CONFLICT, "bad-protx-dup-key");
|
||||
|
||||
auto dmn = std::make_shared<CDeterministicMN>(tx.GetHash(), proTx);
|
||||
@ -426,7 +426,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
|
||||
|
||||
if (newState->nPoSeBanHeight != -1) {
|
||||
// only revive when all keys are set
|
||||
if (!newState->keyIDOperator.IsNull() && !newState->keyIDVoting.IsNull() && !newState->keyIDOwner.IsNull()) {
|
||||
if (newState->pubKeyOperator.IsValid() && !newState->keyIDVoting.IsNull() && !newState->keyIDOwner.IsNull()) {
|
||||
newState->nPoSeBanHeight = -1;
|
||||
newState->nPoSeRevivedHeight = nHeight;
|
||||
|
||||
@ -450,12 +450,12 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
|
||||
return _state.DoS(100, false, REJECT_INVALID, "bad-protx-hash");
|
||||
}
|
||||
auto newState = std::make_shared<CDeterministicMNState>(*dmn->pdmnState);
|
||||
if (newState->keyIDOperator != proTx.keyIDOperator) {
|
||||
if (newState->pubKeyOperator != proTx.pubKeyOperator) {
|
||||
// reset all operator related fields and put MN into PoSe-banned state in case the operator key changes
|
||||
newState->ResetOperatorFields();
|
||||
newState->BanIfNotBanned(nHeight);
|
||||
}
|
||||
newState->keyIDOperator = proTx.keyIDOperator;
|
||||
newState->pubKeyOperator = proTx.pubKeyOperator;
|
||||
newState->keyIDVoting = proTx.keyIDVoting;
|
||||
newState->scriptPayout = proTx.scriptPayout;
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "providertx.h"
|
||||
#include "dbwrapper.h"
|
||||
#include "sync.h"
|
||||
#include "bls/bls.h"
|
||||
|
||||
#include "immer/map.hpp"
|
||||
#include "immer/map_transient.hpp"
|
||||
@ -30,7 +31,7 @@ public:
|
||||
uint16_t nRevocationReason{CProUpRevTx::REASON_NOT_SPECIFIED};
|
||||
|
||||
CKeyID keyIDOwner;
|
||||
CKeyID keyIDOperator;
|
||||
CBLSPublicKey pubKeyOperator;
|
||||
CKeyID keyIDVoting;
|
||||
CService addr;
|
||||
int32_t nProtocolVersion;
|
||||
@ -42,7 +43,7 @@ public:
|
||||
CDeterministicMNState(const CProRegTx& proTx)
|
||||
{
|
||||
keyIDOwner = proTx.keyIDOwner;
|
||||
keyIDOperator = proTx.keyIDOperator;
|
||||
pubKeyOperator = proTx.pubKeyOperator;
|
||||
keyIDVoting = proTx.keyIDVoting;
|
||||
addr = proTx.addr;
|
||||
nProtocolVersion = proTx.nProtocolVersion;
|
||||
@ -63,7 +64,7 @@ public:
|
||||
READWRITE(nPoSeBanHeight);
|
||||
READWRITE(nRevocationReason);
|
||||
READWRITE(keyIDOwner);
|
||||
READWRITE(keyIDOperator);
|
||||
READWRITE(pubKeyOperator);
|
||||
READWRITE(keyIDVoting);
|
||||
READWRITE(addr);
|
||||
READWRITE(nProtocolVersion);
|
||||
@ -73,7 +74,7 @@ public:
|
||||
|
||||
void ResetOperatorFields()
|
||||
{
|
||||
keyIDOperator.SetNull();
|
||||
pubKeyOperator = CBLSPublicKey();
|
||||
addr = CService();
|
||||
nProtocolVersion = 0;
|
||||
scriptOperatorPayout = CScript();
|
||||
@ -95,7 +96,7 @@ public:
|
||||
nPoSeBanHeight == rhs.nPoSeBanHeight &&
|
||||
nRevocationReason == rhs.nRevocationReason &&
|
||||
keyIDOwner == rhs.keyIDOwner &&
|
||||
keyIDOperator == rhs.keyIDOperator &&
|
||||
pubKeyOperator == rhs.pubKeyOperator &&
|
||||
keyIDVoting == rhs.keyIDVoting &&
|
||||
addr == rhs.addr &&
|
||||
nProtocolVersion == rhs.nProtocolVersion &&
|
||||
@ -257,7 +258,7 @@ public:
|
||||
}
|
||||
CDeterministicMNCPtr GetMN(const uint256& proTxHash) const;
|
||||
CDeterministicMNCPtr GetValidMN(const uint256& proTxHash) const;
|
||||
CDeterministicMNCPtr GetMNByOperatorKey(const CKeyID& keyID);
|
||||
CDeterministicMNCPtr GetMNByOperatorKey(const CBLSPublicKey& pubKey);
|
||||
CDeterministicMNCPtr GetMNPayee() const;
|
||||
|
||||
/**
|
||||
|
@ -42,15 +42,31 @@ static bool CheckService(const uint256& proTxHash, const ProTx& proTx, const CBl
|
||||
}
|
||||
|
||||
template <typename ProTx>
|
||||
static bool CheckInputsHashAndSig(const CTransaction &tx, const ProTx& proTx, const CKeyID &keyID, CValidationState& state)
|
||||
static bool CheckSig(const ProTx& proTx, const CKeyID& keyID, CValidationState& state)
|
||||
{
|
||||
std::string strError;
|
||||
if (!CHashSigner::VerifyHash(::SerializeHash(proTx), keyID, proTx.vchSig, strError))
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-protx-sig", false, strError);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ProTx>
|
||||
static bool CheckSig(const ProTx& proTx, const CBLSPublicKey& pubKey, CValidationState& state)
|
||||
{
|
||||
if (!proTx.sig.VerifyInsecure(pubKey, ::SerializeHash(proTx)))
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-protx-sig", false);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ProTx, typename PubKey>
|
||||
static bool CheckInputsHashAndSig(const CTransaction &tx, const ProTx& proTx, const PubKey& pubKey, CValidationState& state)
|
||||
{
|
||||
uint256 inputsHash = CalcTxInputsHash(tx);
|
||||
if (inputsHash != proTx.inputsHash)
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-protx-inputs-hash");
|
||||
|
||||
std::string strError;
|
||||
if (!CHashSigner::VerifyHash(::SerializeHash(proTx), keyID, proTx.vchSig, strError))
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-protx-sig", false, strError);
|
||||
if (!CheckSig(proTx, pubKey, state))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -70,7 +86,7 @@ bool CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValid
|
||||
return state.DoS(10, false, REJECT_INVALID, "bad-protx-collateral-index");
|
||||
if (tx.vout[ptx.nCollateralIndex].nValue != 1000 * COIN)
|
||||
return state.DoS(10, false, REJECT_INVALID, "bad-protx-collateral");
|
||||
if (ptx.keyIDOwner.IsNull() || ptx.keyIDOperator.IsNull() || ptx.keyIDVoting.IsNull())
|
||||
if (ptx.keyIDOwner.IsNull() || !ptx.pubKeyOperator.IsValid() || ptx.keyIDVoting.IsNull())
|
||||
return state.DoS(10, false, REJECT_INVALID, "bad-protx-key-null");
|
||||
// we may support P2SH later, but restrict it for now (while in transitioning phase from old MN list to deterministic list)
|
||||
if (!ptx.scriptPayout.IsPayToPublicKeyHash())
|
||||
@ -82,7 +98,7 @@ bool CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValid
|
||||
return state.DoS(10, false, REJECT_INVALID, "bad-protx-payee-dest");
|
||||
}
|
||||
// don't allow reuse of collateral key for other keys (don't allow people to put the collateral key onto an online server)
|
||||
if (payoutDest == CTxDestination(ptx.keyIDOwner) || payoutDest == CTxDestination(ptx.keyIDOperator) || payoutDest == CTxDestination(ptx.keyIDVoting)) {
|
||||
if (payoutDest == CTxDestination(ptx.keyIDOwner) || payoutDest == CTxDestination(ptx.keyIDVoting)) {
|
||||
return state.DoS(10, false, REJECT_INVALID, "bad-protx-payee-reuse");
|
||||
}
|
||||
|
||||
@ -101,12 +117,12 @@ bool CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValid
|
||||
|
||||
if (pindexPrev) {
|
||||
auto mnList = deterministicMNManager->GetListForBlock(pindexPrev->GetBlockHash());
|
||||
if (mnList.HasUniqueProperty(ptx.keyIDOwner) || mnList.HasUniqueProperty(ptx.keyIDOperator)) {
|
||||
if (mnList.HasUniqueProperty(ptx.keyIDOwner) || mnList.HasUniqueProperty(ptx.pubKeyOperator)) {
|
||||
return state.DoS(10, false, REJECT_DUPLICATE, "bad-protx-dup-key");
|
||||
}
|
||||
|
||||
if (!deterministicMNManager->IsDeterministicMNsSporkActive(pindexPrev->nHeight)) {
|
||||
if (ptx.keyIDOwner != ptx.keyIDOperator || ptx.keyIDOwner != ptx.keyIDVoting) {
|
||||
if (ptx.keyIDOwner != ptx.keyIDVoting) {
|
||||
return state.DoS(10, false, REJECT_INVALID, "bad-protx-key-not-same");
|
||||
}
|
||||
}
|
||||
@ -147,7 +163,7 @@ bool CheckProUpServTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVa
|
||||
}
|
||||
|
||||
// we can only check the signature if pindexPrev != NULL and the MN is known
|
||||
if (!CheckInputsHashAndSig(tx, ptx, mn->pdmnState->keyIDOperator, state))
|
||||
if (!CheckInputsHashAndSig(tx, ptx, mn->pdmnState->pubKeyOperator, state))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -165,7 +181,7 @@ bool CheckProUpRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVal
|
||||
if (ptx.nVersion > CProRegTx::CURRENT_VERSION)
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-protx-version");
|
||||
|
||||
if (ptx.keyIDOperator.IsNull() || ptx.keyIDVoting.IsNull())
|
||||
if (!ptx.pubKeyOperator.IsValid() || ptx.keyIDVoting.IsNull())
|
||||
return state.DoS(10, false, REJECT_INVALID, "bad-protx-key-null");
|
||||
// we may support P2SH later, but restrict it for now (while in transitioning phase from old MN list to deterministic list)
|
||||
if (!ptx.scriptPayout.IsPayToPublicKeyHash())
|
||||
@ -184,7 +200,7 @@ bool CheckProUpRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVal
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-protx-hash");
|
||||
|
||||
// don't allow reuse of collateral key for other keys (don't allow people to put the collateral key onto an online server)
|
||||
if (payoutDest == CTxDestination(dmn->pdmnState->keyIDOwner) || payoutDest == CTxDestination(ptx.keyIDOperator) || payoutDest == CTxDestination(ptx.keyIDVoting)) {
|
||||
if (payoutDest == CTxDestination(dmn->pdmnState->keyIDOwner) || payoutDest == CTxDestination(ptx.keyIDVoting)) {
|
||||
return state.DoS(10, false, REJECT_INVALID, "bad-protx-payee-reuse");
|
||||
}
|
||||
|
||||
@ -197,15 +213,15 @@ bool CheckProUpRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVal
|
||||
if (coin.out.scriptPubKey != ptx.scriptPayout)
|
||||
return state.DoS(10, false, REJECT_INVALID, "bad-protx-payee-collateral");
|
||||
|
||||
if (mnList.HasUniqueProperty(ptx.keyIDOperator)) {
|
||||
auto otherDmn = mnList.GetUniquePropertyMN(ptx.keyIDOperator);
|
||||
if (mnList.HasUniqueProperty(ptx.pubKeyOperator)) {
|
||||
auto otherDmn = mnList.GetUniquePropertyMN(ptx.pubKeyOperator);
|
||||
if (ptx.proTxHash != otherDmn->proTxHash) {
|
||||
return state.DoS(10, false, REJECT_DUPLICATE, "bad-protx-dup-key");
|
||||
}
|
||||
}
|
||||
|
||||
if (!deterministicMNManager->IsDeterministicMNsSporkActive(pindexPrev->nHeight)) {
|
||||
if (dmn->pdmnState->keyIDOwner != ptx.keyIDOperator || dmn->pdmnState->keyIDOwner != ptx.keyIDVoting) {
|
||||
if (dmn->pdmnState->keyIDOwner != ptx.keyIDVoting) {
|
||||
return state.DoS(10, false, REJECT_INVALID, "bad-protx-key-not-same");
|
||||
}
|
||||
}
|
||||
@ -239,7 +255,7 @@ bool CheckProUpRevTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVal
|
||||
if (!dmn)
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-protx-hash");
|
||||
|
||||
if (!CheckInputsHashAndSig(tx, ptx, dmn->pdmnState->keyIDOperator, state))
|
||||
if (!CheckInputsHashAndSig(tx, ptx, dmn->pdmnState->pubKeyOperator, state))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -254,8 +270,8 @@ std::string CProRegTx::ToString() const
|
||||
payee = CBitcoinAddress(dest).ToString();
|
||||
}
|
||||
|
||||
return strprintf("CProRegTx(nVersion=%d, nProtocolVersion=%d, nCollateralIndex=%d, addr=%s, nOperatorReward=%f, keyIDOwner=%s, keyIDOperator=%s, keyIDVoting=%s, scriptPayout=%s)",
|
||||
nVersion, nProtocolVersion, nCollateralIndex, addr.ToString(), (double)nOperatorReward / 100, keyIDOwner.ToString(), keyIDOperator.ToString(), keyIDVoting.ToString(), payee);
|
||||
return strprintf("CProRegTx(nVersion=%d, nProtocolVersion=%d, nCollateralIndex=%d, addr=%s, nOperatorReward=%f, keyIDOwner=%s, pubKeyOperator=%s, keyIDVoting=%s, scriptPayout=%s)",
|
||||
nVersion, nProtocolVersion, nCollateralIndex, addr.ToString(), (double)nOperatorReward / 100, keyIDOwner.ToString(), pubKeyOperator.ToString(), keyIDVoting.ToString(), payee);
|
||||
}
|
||||
|
||||
void CProRegTx::ToJson(UniValue& obj) const
|
||||
@ -267,7 +283,7 @@ void CProRegTx::ToJson(UniValue& obj) const
|
||||
obj.push_back(Pair("collateralIndex", (int)nCollateralIndex));
|
||||
obj.push_back(Pair("service", addr.ToString(false)));
|
||||
obj.push_back(Pair("keyIDOwner", keyIDOwner.ToString()));
|
||||
obj.push_back(Pair("keyIDOperator", keyIDOperator.ToString()));
|
||||
obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString()));
|
||||
obj.push_back(Pair("keyIDVoting", keyIDVoting.ToString()));
|
||||
|
||||
CTxDestination dest;
|
||||
@ -316,8 +332,8 @@ std::string CProUpRegTx::ToString() const
|
||||
payee = CBitcoinAddress(dest).ToString();
|
||||
}
|
||||
|
||||
return strprintf("CProUpRegTx(nVersion=%d, proTxHash=%s, keyIDOperator=%s, keyIDVoting=%s, payoutAddress=%s)",
|
||||
nVersion, proTxHash.ToString(), keyIDOperator.ToString(), keyIDVoting.ToString(), payee);
|
||||
return strprintf("CProUpRegTx(nVersion=%d, proTxHash=%s, pubKeyOperator=%s, keyIDVoting=%s, payoutAddress=%s)",
|
||||
nVersion, proTxHash.ToString(), pubKeyOperator.ToString(), keyIDVoting.ToString(), payee);
|
||||
}
|
||||
|
||||
void CProUpRegTx::ToJson(UniValue& obj) const
|
||||
@ -326,7 +342,7 @@ void CProUpRegTx::ToJson(UniValue& obj) const
|
||||
obj.setObject();
|
||||
obj.push_back(Pair("version", nVersion));
|
||||
obj.push_back(Pair("proTxHash", proTxHash.ToString()));
|
||||
obj.push_back(Pair("keyIDOperator", keyIDOperator.ToString()));
|
||||
obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString()));
|
||||
obj.push_back(Pair("keyIDVoting", keyIDVoting.ToString()));
|
||||
CTxDestination dest;
|
||||
if (ExtractDestination(scriptPayout, dest)) {
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "primitives/transaction.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "bls/bls.h"
|
||||
|
||||
#include "netaddress.h"
|
||||
#include "pubkey.h"
|
||||
@ -25,7 +26,7 @@ public:
|
||||
uint32_t nCollateralIndex{(uint32_t) - 1};
|
||||
CService addr;
|
||||
CKeyID keyIDOwner;
|
||||
CKeyID keyIDOperator;
|
||||
CBLSPublicKey pubKeyOperator;
|
||||
CKeyID keyIDVoting;
|
||||
uint16_t nOperatorReward{0};
|
||||
CScript scriptPayout;
|
||||
@ -43,7 +44,7 @@ public:
|
||||
READWRITE(nCollateralIndex);
|
||||
READWRITE(addr);
|
||||
READWRITE(keyIDOwner);
|
||||
READWRITE(keyIDOperator);
|
||||
READWRITE(pubKeyOperator);
|
||||
READWRITE(keyIDVoting);
|
||||
READWRITE(*(CScriptBase*)(&scriptPayout));
|
||||
READWRITE(nOperatorReward);
|
||||
@ -69,7 +70,7 @@ public:
|
||||
CService addr;
|
||||
CScript scriptOperatorPayout;
|
||||
uint256 inputsHash; // replay protection
|
||||
std::vector<unsigned char> vchSig;
|
||||
CBLSSignature sig;
|
||||
|
||||
public:
|
||||
ADD_SERIALIZE_METHODS;
|
||||
@ -84,7 +85,7 @@ public:
|
||||
READWRITE(*(CScriptBase*)(&scriptOperatorPayout));
|
||||
READWRITE(inputsHash);
|
||||
if (!(s.GetType() & SER_GETHASH)) {
|
||||
READWRITE(vchSig);
|
||||
READWRITE(sig);
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,7 +102,7 @@ public:
|
||||
public:
|
||||
uint16_t nVersion{CURRENT_VERSION}; // message version
|
||||
uint256 proTxHash;
|
||||
CKeyID keyIDOperator;
|
||||
CBLSPublicKey pubKeyOperator;
|
||||
CKeyID keyIDVoting;
|
||||
CScript scriptPayout;
|
||||
uint256 inputsHash; // replay protection
|
||||
@ -115,7 +116,7 @@ public:
|
||||
{
|
||||
READWRITE(nVersion);
|
||||
READWRITE(proTxHash);
|
||||
READWRITE(keyIDOperator);
|
||||
READWRITE(pubKeyOperator);
|
||||
READWRITE(keyIDVoting);
|
||||
READWRITE(*(CScriptBase*)(&scriptPayout));
|
||||
READWRITE(inputsHash);
|
||||
@ -148,7 +149,7 @@ public:
|
||||
uint256 proTxHash;
|
||||
uint16_t nReason{REASON_NOT_SPECIFIED};
|
||||
uint256 inputsHash; // replay protection
|
||||
std::vector<unsigned char> vchSig;
|
||||
CBLSSignature sig;
|
||||
|
||||
public:
|
||||
ADD_SERIALIZE_METHODS;
|
||||
@ -161,7 +162,7 @@ public:
|
||||
READWRITE(nReason);
|
||||
READWRITE(inputsHash);
|
||||
if (!(s.GetType() & SER_GETHASH)) {
|
||||
READWRITE(vchSig);
|
||||
READWRITE(sig);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
CSimplifiedMNListEntry::CSimplifiedMNListEntry(const CDeterministicMN& dmn) :
|
||||
proRegTxHash(dmn.proTxHash),
|
||||
service(dmn.pdmnState->addr),
|
||||
keyIDOperator(dmn.pdmnState->keyIDOperator),
|
||||
pubKeyOperator(dmn.pdmnState->pubKeyOperator),
|
||||
keyIDVoting(dmn.pdmnState->keyIDVoting),
|
||||
isValid(dmn.pdmnState->nPoSeBanHeight == -1)
|
||||
{
|
||||
@ -30,8 +30,8 @@ uint256 CSimplifiedMNListEntry::CalcHash() const
|
||||
|
||||
std::string CSimplifiedMNListEntry::ToString() const
|
||||
{
|
||||
return strprintf("CSimplifiedMNListEntry(proRegTxHash=%s, service=%s, keyIDOperator=%s, keyIDVoting=%s, isValie=%d)",
|
||||
proRegTxHash.ToString(), service.ToString(false), keyIDOperator.ToString(), keyIDVoting.ToString(), isValid);
|
||||
return strprintf("CSimplifiedMNListEntry(proRegTxHash=%s, service=%s, pubKeyOperator=%s, keyIDVoting=%s, isValie=%d)",
|
||||
proRegTxHash.ToString(), service.ToString(false), pubKeyOperator.ToString(), keyIDVoting.ToString(), isValid);
|
||||
}
|
||||
|
||||
void CSimplifiedMNListEntry::ToJson(UniValue& obj) const
|
||||
@ -40,8 +40,8 @@ void CSimplifiedMNListEntry::ToJson(UniValue& obj) const
|
||||
obj.setObject();
|
||||
obj.push_back(Pair("proRegTxHash", proRegTxHash.ToString()));
|
||||
obj.push_back(Pair("service", service.ToString(false)));
|
||||
obj.push_back(Pair("keyIDOperator", keyIDOperator.ToString()));
|
||||
obj.push_back(Pair("keyIDVoting", keyIDOperator.ToString()));
|
||||
obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString()));
|
||||
obj.push_back(Pair("keyIDVoting", keyIDVoting.ToString()));
|
||||
obj.push_back(Pair("isValid", isValid));
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "pubkey.h"
|
||||
#include "netaddress.h"
|
||||
#include "merkleblock.h"
|
||||
#include "bls/bls.h"
|
||||
|
||||
class UniValue;
|
||||
class CDeterministicMNList;
|
||||
@ -19,7 +20,7 @@ class CSimplifiedMNListEntry
|
||||
public:
|
||||
uint256 proRegTxHash;
|
||||
CService service;
|
||||
CKeyID keyIDOperator;
|
||||
CBLSPublicKey pubKeyOperator;
|
||||
CKeyID keyIDVoting;
|
||||
bool isValid;
|
||||
|
||||
@ -35,7 +36,7 @@ public:
|
||||
{
|
||||
READWRITE(proRegTxHash);
|
||||
READWRITE(service);
|
||||
READWRITE(keyIDOperator);
|
||||
READWRITE(pubKeyOperator);
|
||||
READWRITE(keyIDVoting);
|
||||
READWRITE(isValid);
|
||||
}
|
||||
|
@ -330,6 +330,24 @@ bool CGovernanceObject::CheckSignature(const CKeyID& keyID) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGovernanceObject::Sign(const CBLSSecretKey& key)
|
||||
{
|
||||
CBLSSignature sig = key.Sign(GetSignatureHash());
|
||||
sig.GetBuf(vchSig);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGovernanceObject::CheckSignature(const CBLSPublicKey& pubKey) const
|
||||
{
|
||||
CBLSSignature sig;
|
||||
sig.SetBuf(vchSig);
|
||||
if (!sig.VerifyInsecure(pubKey, GetSignatureHash())) {
|
||||
LogPrintf("CGovernanceObject::CheckSignature -- VerifyInsecure() failed\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Return the actual object from the vchData JSON structure.
|
||||
|
||||
@ -508,9 +526,16 @@ bool CGovernanceObject::IsValidLocally(std::string& strError, bool& fMissingMast
|
||||
}
|
||||
|
||||
// Check that we have a valid MN signature
|
||||
if (!CheckSignature(infoMn.keyIDOperator)) {
|
||||
strError = "Invalid masternode signature for: " + strOutpoint + ", pubkey id = " + infoMn.keyIDOperator.ToString();
|
||||
return false;
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
if (!CheckSignature(infoMn.blsPubKeyOperator)) {
|
||||
strError = "Invalid masternode signature for: " + strOutpoint + ", pubkey id = " + infoMn.blsPubKeyOperator.ToString();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!CheckSignature(infoMn.legacyKeyIDOperator)) {
|
||||
strError = "Invalid masternode signature for: " + strOutpoint + ", pubkey id = " + infoMn.legacyKeyIDOperator.ToString();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "sync.h"
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include "bls/bls.h"
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
@ -260,6 +261,8 @@ public:
|
||||
void SetMasternodeOutpoint(const COutPoint& outpoint);
|
||||
bool Sign(const CKey& key, const CKeyID& keyID);
|
||||
bool CheckSignature(const CKeyID& keyID) const;
|
||||
bool Sign(const CBLSSecretKey& key);
|
||||
bool CheckSignature(const CBLSPublicKey& pubKey) const;
|
||||
|
||||
std::string GetSignatureMessage() const;
|
||||
uint256 GetSignatureHash() const;
|
||||
|
@ -214,6 +214,26 @@ bool CGovernanceVote::CheckSignature(const CKeyID& keyID) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGovernanceVote::Sign(const CBLSSecretKey& key)
|
||||
{
|
||||
uint256 hash = GetSignatureHash();
|
||||
CBLSSignature sig = key.Sign(hash);
|
||||
sig.GetBuf(vchSig);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGovernanceVote::CheckSignature(const CBLSPublicKey& pubKey) const
|
||||
{
|
||||
uint256 hash = GetSignatureHash();
|
||||
CBLSSignature sig;
|
||||
sig.SetBuf(vchSig);
|
||||
if (!sig.VerifyInsecure(pubKey, hash)) {
|
||||
LogPrintf("CGovernanceVote::CheckSignature -- VerifyInsecure() failed\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGovernanceVote::IsValid(bool useVotingKey) const
|
||||
{
|
||||
if (nTime > GetAdjustedTime() + (60 * 60)) {
|
||||
@ -239,7 +259,15 @@ bool CGovernanceVote::IsValid(bool useVotingKey) const
|
||||
return false;
|
||||
}
|
||||
|
||||
return CheckSignature(useVotingKey ? infoMn.keyIDVoting : infoMn.keyIDOperator);
|
||||
if (useVotingKey) {
|
||||
return CheckSignature(infoMn.keyIDVoting);
|
||||
} else {
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
return CheckSignature(infoMn.blsPubKeyOperator);
|
||||
} else {
|
||||
return CheckSignature(infoMn.legacyKeyIDOperator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const CGovernanceVote& vote1, const CGovernanceVote& vote2)
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "key.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "bls/bls.h"
|
||||
|
||||
class CGovernanceVote;
|
||||
class CConnman;
|
||||
@ -96,6 +97,8 @@ public:
|
||||
|
||||
bool Sign(const CKey& key, const CKeyID& keyID);
|
||||
bool CheckSignature(const CKeyID& keyID) const;
|
||||
bool Sign(const CBLSSecretKey& key);
|
||||
bool CheckSignature(const CBLSPublicKey& pubKey) const;
|
||||
bool IsValid(bool useVotingKey) const;
|
||||
void Relay(CConnman& connman) const;
|
||||
|
||||
|
29
src/init.cpp
29
src/init.cpp
@ -1899,21 +1899,44 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
std::string strMasterNodePrivKey = GetArg("-masternodeprivkey", "");
|
||||
if(!strMasterNodePrivKey.empty()) {
|
||||
CPubKey pubKeyMasternode;
|
||||
if(!CMessageSigner::GetKeysFromSecret(strMasterNodePrivKey, activeMasternodeInfo.keyOperator, pubKeyMasternode))
|
||||
if(!CMessageSigner::GetKeysFromSecret(strMasterNodePrivKey, activeMasternodeInfo.legacyKeyOperator, pubKeyMasternode))
|
||||
return InitError(_("Invalid masternodeprivkey. Please see documenation."));
|
||||
|
||||
activeMasternodeInfo.keyIDOperator = pubKeyMasternode.GetID();
|
||||
activeMasternodeInfo.legacyKeyIDOperator = pubKeyMasternode.GetID();
|
||||
|
||||
LogPrintf(" keyIDOperator: %s\n", CBitcoinAddress(activeMasternodeInfo.keyIDOperator).ToString());
|
||||
LogPrintf(" keyIDOperator: %s\n", CBitcoinAddress(activeMasternodeInfo.legacyKeyIDOperator).ToString());
|
||||
} else {
|
||||
return InitError(_("You must specify a masternodeprivkey in the configuration. Please see documentation for help."));
|
||||
}
|
||||
|
||||
std::string strMasterNodeBLSPrivKey = GetArg("-masternodeblsprivkey", "");
|
||||
if(!strMasterNodeBLSPrivKey.empty()) {
|
||||
auto binKey = ParseHex(strMasterNodeBLSPrivKey);
|
||||
CBLSSecretKey keyOperator;
|
||||
keyOperator.SetBuf(binKey);
|
||||
if (keyOperator.IsValid()) {
|
||||
activeMasternodeInfo.blsKeyOperator = std::make_unique<CBLSSecretKey>(keyOperator);
|
||||
activeMasternodeInfo.blsPubKeyOperator = std::make_unique<CBLSPublicKey>(activeMasternodeInfo.blsKeyOperator->GetPublicKey());
|
||||
LogPrintf(" blsPubKeyOperator: %s\n", keyOperator.GetPublicKey().ToString());
|
||||
} else {
|
||||
return InitError(_("Invalid masternodeblsprivkey. Please see documenation."));
|
||||
}
|
||||
} else {
|
||||
InitWarning(_("You should specify a masternodeblsprivkey in the configuration. Please see documentation for help."));
|
||||
}
|
||||
|
||||
// init and register activeMasternodeManager
|
||||
activeMasternodeManager = new CActiveDeterministicMasternodeManager();
|
||||
RegisterValidationInterface(activeMasternodeManager);
|
||||
}
|
||||
|
||||
if (activeMasternodeInfo.blsKeyOperator == nullptr) {
|
||||
activeMasternodeInfo.blsKeyOperator = std::make_unique<CBLSSecretKey>();
|
||||
}
|
||||
if (activeMasternodeInfo.blsPubKeyOperator == nullptr) {
|
||||
activeMasternodeInfo.blsPubKeyOperator = std::make_unique<CBLSPublicKey>();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
LogPrintf("Using masternode config file %s\n", GetMasternodeConfigFile().string());
|
||||
|
||||
|
@ -1071,13 +1071,22 @@ bool CTxLockVote::CheckSignature() const
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if (!CHashSigner::VerifyHash(hash, infoMn.keyIDOperator, vchMasternodeSignature, strError)) {
|
||||
CBLSSignature sig;
|
||||
sig.SetBuf(vchMasternodeSignature);
|
||||
if (!sig.IsValid() || !sig.VerifyInsecure(infoMn.blsPubKeyOperator, hash)) {
|
||||
LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n");
|
||||
return false;
|
||||
}
|
||||
} else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if (!CHashSigner::VerifyHash(hash, infoMn.legacyKeyIDOperator, vchMasternodeSignature, strError)) {
|
||||
// could be a signature in old format
|
||||
std::string strMessage = txHash.ToString() + outpoint.ToStringShort();
|
||||
if (!CMessageSigner::VerifyMessage(infoMn.keyIDOperator, vchMasternodeSignature, strMessage, strError)) {
|
||||
if (!CMessageSigner::VerifyMessage(infoMn.legacyKeyIDOperator, vchMasternodeSignature, strMessage, strError)) {
|
||||
// nope, not in old format either
|
||||
LogPrintf("CTxLockVote::CheckSignature -- VerifyMessage() failed, error: %s\n", strError);
|
||||
return false;
|
||||
@ -1085,7 +1094,7 @@ bool CTxLockVote::CheckSignature() const
|
||||
}
|
||||
} else {
|
||||
std::string strMessage = txHash.ToString() + outpoint.ToStringShort();
|
||||
if (!CMessageSigner::VerifyMessage(infoMn.keyIDOperator, vchMasternodeSignature, strMessage, strError)) {
|
||||
if (!CMessageSigner::VerifyMessage(infoMn.legacyKeyIDOperator, vchMasternodeSignature, strMessage, strError)) {
|
||||
LogPrintf("CTxLockVote::CheckSignature -- VerifyMessage() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
@ -1098,27 +1107,32 @@ bool CTxLockVote::Sign()
|
||||
{
|
||||
std::string strError;
|
||||
|
||||
if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if (!CHashSigner::SignHash(hash, activeMasternodeInfo.keyOperator, vchMasternodeSignature)) {
|
||||
CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
|
||||
sig.GetBuf(vchMasternodeSignature);
|
||||
} else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if (!CHashSigner::SignHash(hash, activeMasternodeInfo.legacyKeyOperator, vchMasternodeSignature)) {
|
||||
LogPrintf("CTxLockVote::Sign -- SignHash() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.keyIDOperator, vchMasternodeSignature, strError)) {
|
||||
if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.legacyKeyIDOperator, vchMasternodeSignature, strError)) {
|
||||
LogPrintf("CTxLockVote::Sign -- VerifyHash() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
std::string strMessage = txHash.ToString() + outpoint.ToStringShort();
|
||||
|
||||
if (!CMessageSigner::SignMessage(strMessage, vchMasternodeSignature, activeMasternodeInfo.keyOperator)) {
|
||||
if (!CMessageSigner::SignMessage(strMessage, vchMasternodeSignature, activeMasternodeInfo.legacyKeyOperator)) {
|
||||
LogPrintf("CTxLockVote::Sign -- SignMessage() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CMessageSigner::VerifyMessage(activeMasternodeInfo.keyIDOperator, vchMasternodeSignature, strMessage, strError)) {
|
||||
if (!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, vchMasternodeSignature, strMessage, strError)) {
|
||||
LogPrintf("CTxLockVote::Sign -- VerifyMessage() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
|
@ -491,7 +491,7 @@ void CMasternodePayments::ProcessMessage(CNode* pfrom, const std::string& strCom
|
||||
}
|
||||
|
||||
int nDos = 0;
|
||||
if(!vote.CheckSignature(mnInfo.keyIDOperator, nCachedBlockHeight, nDos)) {
|
||||
if(!vote.CheckSignature(mnInfo.legacyKeyIDOperator, nCachedBlockHeight, nDos)) {
|
||||
if(nDos) {
|
||||
LOCK(cs_main);
|
||||
LogPrintf("MASTERNODEPAYMENTVOTE -- ERROR: invalid signature\n");
|
||||
@ -551,12 +551,12 @@ bool CMasternodePaymentVote::Sign()
|
||||
if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if(!CHashSigner::SignHash(hash, activeMasternodeInfo.keyOperator, vchSig)) {
|
||||
if(!CHashSigner::SignHash(hash, activeMasternodeInfo.legacyKeyOperator, vchSig)) {
|
||||
LogPrintf("CMasternodePaymentVote::%s -- SignHash() failed\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.keyIDOperator, vchSig, strError)) {
|
||||
if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.legacyKeyIDOperator, vchSig, strError)) {
|
||||
LogPrintf("CMasternodePaymentVote::%s -- VerifyHash() failed, error: %s\n", __func__, strError);
|
||||
return false;
|
||||
}
|
||||
@ -565,12 +565,12 @@ bool CMasternodePaymentVote::Sign()
|
||||
std::to_string(nBlockHeight) +
|
||||
ScriptToAsmStr(payee);
|
||||
|
||||
if(!CMessageSigner::SignMessage(strMessage, vchSig, activeMasternodeInfo.keyOperator)) {
|
||||
if(!CMessageSigner::SignMessage(strMessage, vchSig, activeMasternodeInfo.legacyKeyOperator)) {
|
||||
LogPrintf("CMasternodePaymentVote::%s -- SignMessage() failed\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!CMessageSigner::VerifyMessage(activeMasternodeInfo.keyIDOperator, vchSig, strMessage, strError)) {
|
||||
if(!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, vchSig, strMessage, strError)) {
|
||||
LogPrintf("CMasternodePaymentVote::%s -- VerifyMessage() failed, error: %s\n", __func__, strError);
|
||||
return false;
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ CMasternode::CMasternode(const CMasternodeBroadcast& mnb) :
|
||||
|
||||
CMasternode::CMasternode(const uint256 &proTxHash, const CDeterministicMNCPtr& dmn) :
|
||||
masternode_info_t{ MASTERNODE_ENABLED, dmn->pdmnState->nProtocolVersion, GetAdjustedTime(),
|
||||
COutPoint(proTxHash, dmn->nCollateralIndex), dmn->pdmnState->addr, CKeyID(), dmn->pdmnState->keyIDOwner, dmn->pdmnState->keyIDOperator, dmn->pdmnState->keyIDVoting},
|
||||
COutPoint(proTxHash, dmn->nCollateralIndex), dmn->pdmnState->addr, CKeyID(), dmn->pdmnState->keyIDOwner, dmn->pdmnState->pubKeyOperator, dmn->pdmnState->keyIDVoting},
|
||||
fAllowMixingTx(true)
|
||||
{
|
||||
CTxDestination dest;
|
||||
@ -74,7 +74,7 @@ bool CMasternode::UpdateFromNewBroadcast(CMasternodeBroadcast& mnb, CConnman& co
|
||||
|
||||
pubKeyMasternode = mnb.pubKeyMasternode;
|
||||
keyIDOwner = mnb.pubKeyMasternode.GetID();
|
||||
keyIDOperator = mnb.pubKeyMasternode.GetID();
|
||||
legacyKeyIDOperator = mnb.pubKeyMasternode.GetID();
|
||||
keyIDVoting = mnb.pubKeyMasternode.GetID();
|
||||
sigTime = mnb.sigTime;
|
||||
vchSig = mnb.vchSig;
|
||||
@ -89,7 +89,7 @@ bool CMasternode::UpdateFromNewBroadcast(CMasternodeBroadcast& mnb, CConnman& co
|
||||
mnodeman.mapSeenMasternodePing.insert(std::make_pair(lastPing.GetHash(), lastPing));
|
||||
}
|
||||
// if it matches our Masternode privkey...
|
||||
if(fMasternodeMode && keyIDOperator == activeMasternodeInfo.keyIDOperator) {
|
||||
if(fMasternodeMode && legacyKeyIDOperator == activeMasternodeInfo.legacyKeyIDOperator) {
|
||||
nPoSeBanScore = -MASTERNODE_POSE_BAN_MAX_SCORE;
|
||||
if(nProtocolVersion == PROTOCOL_VERSION) {
|
||||
// ... and PROTOCOL_VERSION, then we've been remotely activated ...
|
||||
@ -203,7 +203,7 @@ void CMasternode::Check(bool fForce)
|
||||
}
|
||||
|
||||
int nActiveStatePrev = nActiveState;
|
||||
bool fOurMasternode = fMasternodeMode && activeMasternodeInfo.keyIDOperator == keyIDOperator;
|
||||
bool fOurMasternode = fMasternodeMode && activeMasternodeInfo.legacyKeyIDOperator == legacyKeyIDOperator;
|
||||
|
||||
// masternode doesn't meet payment protocol requirements ...
|
||||
bool fRequireUpdate = nProtocolVersion < mnpayments.GetMinMasternodePaymentsProto() ||
|
||||
@ -512,7 +512,7 @@ bool CMasternodeBroadcast::SimpleCheck(int& nDos)
|
||||
}
|
||||
|
||||
CScript pubkeyScript2;
|
||||
pubkeyScript2 = GetScriptForDestination(keyIDOperator);
|
||||
pubkeyScript2 = GetScriptForDestination(legacyKeyIDOperator);
|
||||
|
||||
if(pubkeyScript2.size() != 25) {
|
||||
LogPrintf("CMasternodeBroadcast::SimpleCheck -- keyIDOperator has the wrong size\n");
|
||||
@ -569,7 +569,7 @@ bool CMasternodeBroadcast::Update(CMasternode* pmn, int& nDos, CConnman& connman
|
||||
}
|
||||
|
||||
// if ther was no masternode broadcast recently or if it matches our Masternode privkey...
|
||||
if(!pmn->IsBroadcastedWithin(MASTERNODE_MIN_MNB_SECONDS) || (fMasternodeMode && keyIDOperator == activeMasternodeInfo.keyIDOperator)) {
|
||||
if(!pmn->IsBroadcastedWithin(MASTERNODE_MIN_MNB_SECONDS) || (fMasternodeMode && legacyKeyIDOperator == activeMasternodeInfo.legacyKeyIDOperator)) {
|
||||
// take the newest entry
|
||||
LogPrintf("CMasternodeBroadcast::Update -- Got UPDATED Masternode entry: addr=%s\n", addr.ToString());
|
||||
if(pmn->UpdateFromNewBroadcast(*this, connman)) {
|
||||
@ -586,7 +586,7 @@ bool CMasternodeBroadcast::CheckOutpoint(int& nDos)
|
||||
{
|
||||
// we are a masternode with the same outpoint (i.e. already activated) and this mnb is ours (matches our Masternode privkey)
|
||||
// so nothing to do here for us
|
||||
if(fMasternodeMode && outpoint == activeMasternodeInfo.outpoint && keyIDOperator == activeMasternodeInfo.keyIDOperator) {
|
||||
if(fMasternodeMode && outpoint == activeMasternodeInfo.outpoint && legacyKeyIDOperator == activeMasternodeInfo.legacyKeyIDOperator) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -692,7 +692,7 @@ bool CMasternodeBroadcast::Sign(const CKey& keyCollateralAddress)
|
||||
}
|
||||
} else {
|
||||
std::string strMessage = addr.ToString(false) + std::to_string(sigTime) +
|
||||
keyIDCollateralAddress.ToString() + keyIDOperator.ToString() +
|
||||
keyIDCollateralAddress.ToString() + legacyKeyIDOperator.ToString() +
|
||||
std::to_string(nProtocolVersion);
|
||||
|
||||
if (!CMessageSigner::SignMessage(strMessage, vchSig, keyCollateralAddress)) {
|
||||
@ -720,7 +720,7 @@ bool CMasternodeBroadcast::CheckSignature(int& nDos) const
|
||||
if (!CHashSigner::VerifyHash(hash, keyIDCollateralAddress, vchSig, strError)) {
|
||||
// maybe it's in old format
|
||||
std::string strMessage = addr.ToString(false) + std::to_string(sigTime) +
|
||||
keyIDCollateralAddress.ToString() + keyIDOperator.ToString() +
|
||||
keyIDCollateralAddress.ToString() + legacyKeyIDOperator.ToString() +
|
||||
std::to_string(nProtocolVersion);
|
||||
|
||||
if (!CMessageSigner::VerifyMessage(keyIDCollateralAddress, vchSig, strMessage, strError)){
|
||||
@ -732,7 +732,7 @@ bool CMasternodeBroadcast::CheckSignature(int& nDos) const
|
||||
}
|
||||
} else {
|
||||
std::string strMessage = addr.ToString(false) + std::to_string(sigTime) +
|
||||
keyIDCollateralAddress.ToString() + keyIDOperator.ToString() +
|
||||
keyIDCollateralAddress.ToString() + legacyKeyIDOperator.ToString() +
|
||||
std::to_string(nProtocolVersion);
|
||||
|
||||
if(!CMessageSigner::VerifyMessage(keyIDCollateralAddress, vchSig, strMessage, strError)){
|
||||
@ -935,7 +935,7 @@ bool CMasternodePing::CheckAndUpdate(CMasternode* pmn, bool fFromNewBroadcast, i
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CheckSignature(pmn->keyIDOperator, nDos)) return false;
|
||||
if (!CheckSignature(pmn->legacyKeyIDOperator, nDos)) return false;
|
||||
|
||||
// so, ping seems to be ok
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "key.h"
|
||||
#include "validation.h"
|
||||
#include "spork.h"
|
||||
#include "bls/bls.h"
|
||||
|
||||
#include "evo/deterministicmns.h"
|
||||
|
||||
@ -110,15 +111,15 @@ struct masternode_info_t
|
||||
CPubKey const& pkCollAddr, CPubKey const& pkMN) :
|
||||
nActiveState{activeState}, nProtocolVersion{protoVer}, sigTime{sTime},
|
||||
outpoint{outpnt}, addr{addr},
|
||||
pubKeyCollateralAddress{pkCollAddr}, pubKeyMasternode{pkMN}, keyIDCollateralAddress{pkCollAddr.GetID()}, keyIDOwner{pkMN.GetID()}, keyIDOperator{pkMN.GetID()}, keyIDVoting{pkMN.GetID()} {}
|
||||
pubKeyCollateralAddress{pkCollAddr}, pubKeyMasternode{pkMN}, keyIDCollateralAddress{pkCollAddr.GetID()}, keyIDOwner{pkMN.GetID()}, legacyKeyIDOperator{pkMN.GetID()}, keyIDVoting{pkMN.GetID()} {}
|
||||
|
||||
// only called when the network is in deterministic MN list mode
|
||||
masternode_info_t(int activeState, int protoVer, int64_t sTime,
|
||||
COutPoint const& outpnt, CService const& addr,
|
||||
CKeyID const& pkCollAddr, CKeyID const& pkOwner, CKeyID const& pkOperator, CKeyID const& pkVoting) :
|
||||
CKeyID const& pkCollAddr, CKeyID const& pkOwner, CBLSPublicKey const& pkOperator, CKeyID const& pkVoting) :
|
||||
nActiveState{activeState}, nProtocolVersion{protoVer}, sigTime{sTime},
|
||||
outpoint{outpnt}, addr{addr},
|
||||
pubKeyCollateralAddress{}, pubKeyMasternode{}, keyIDCollateralAddress{pkCollAddr}, keyIDOwner{pkOwner}, keyIDOperator{pkOperator}, keyIDVoting{pkVoting} {}
|
||||
pubKeyCollateralAddress{}, pubKeyMasternode{}, keyIDCollateralAddress{pkCollAddr}, keyIDOwner{pkOwner}, blsPubKeyOperator{pkOperator}, keyIDVoting{pkVoting} {}
|
||||
|
||||
int nActiveState = 0;
|
||||
int nProtocolVersion = 0;
|
||||
@ -130,7 +131,8 @@ struct masternode_info_t
|
||||
CPubKey pubKeyMasternode{}; // this will be invalid/unset when the network switches to deterministic MNs (luckely it's only important for the broadcast hash)
|
||||
CKeyID keyIDCollateralAddress{};
|
||||
CKeyID keyIDOwner{};
|
||||
CKeyID keyIDOperator{};
|
||||
CKeyID legacyKeyIDOperator{};
|
||||
CBLSPublicKey blsPubKeyOperator;
|
||||
CKeyID keyIDVoting{};
|
||||
|
||||
int64_t nLastDsq = 0; //the dsq count from the last dsq broadcast of this node
|
||||
@ -201,7 +203,8 @@ public:
|
||||
READWRITE(pubKeyMasternode);
|
||||
READWRITE(keyIDCollateralAddress);
|
||||
READWRITE(keyIDOwner);
|
||||
READWRITE(keyIDOperator);
|
||||
READWRITE(legacyKeyIDOperator);
|
||||
READWRITE(blsPubKeyOperator);
|
||||
READWRITE(keyIDVoting);
|
||||
READWRITE(lastPing);
|
||||
READWRITE(vchSig);
|
||||
@ -358,7 +361,7 @@ public:
|
||||
if (ser_action.ForRead()) {
|
||||
keyIDCollateralAddress = pubKeyCollateralAddress.GetID();
|
||||
keyIDOwner = pubKeyMasternode.GetID();
|
||||
keyIDOperator = pubKeyMasternode.GetID();
|
||||
legacyKeyIDOperator = pubKeyMasternode.GetID();
|
||||
keyIDVoting = pubKeyMasternode.GetID();
|
||||
}
|
||||
}
|
||||
|
@ -388,7 +388,7 @@ void CMasternodeMan::AddDeterministicMasternodes()
|
||||
|
||||
// make sure we use the splitted keys from now on
|
||||
mn->keyIDOwner = dmn->pdmnState->keyIDOwner;
|
||||
mn->keyIDOperator = dmn->pdmnState->keyIDOperator;
|
||||
mn->blsPubKeyOperator = dmn->pdmnState->pubKeyOperator;
|
||||
mn->keyIDVoting = dmn->pdmnState->keyIDVoting;
|
||||
mn->addr = dmn->pdmnState->addr;
|
||||
mn->nProtocolVersion = dmn->pdmnState->nProtocolVersion;
|
||||
@ -598,15 +598,10 @@ bool CMasternodeMan::GetMasternodeInfo(const COutPoint& outpoint, masternode_inf
|
||||
bool CMasternodeMan::GetMasternodeInfo(const CKeyID& keyIDOperator, masternode_info_t& mnInfoRet) {
|
||||
LOCK(cs);
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
auto dmn = mnList.GetMNByOperatorKey(keyIDOperator);
|
||||
if (dmn) {
|
||||
return GetMasternodeInfo(COutPoint(dmn->proTxHash, dmn->nCollateralIndex), mnInfoRet);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
for (const auto& mnpair : mapMasternodes) {
|
||||
if (mnpair.second.keyIDOperator == keyIDOperator) {
|
||||
if (mnpair.second.legacyKeyIDOperator == keyIDOperator) {
|
||||
mnInfoRet = mnpair.second.GetInfo();
|
||||
return true;
|
||||
}
|
||||
@ -615,11 +610,6 @@ bool CMasternodeMan::GetMasternodeInfo(const CKeyID& keyIDOperator, masternode_i
|
||||
}
|
||||
}
|
||||
|
||||
bool CMasternodeMan::GetMasternodeInfo(const CPubKey& pubKeyOperator, masternode_info_t& mnInfoRet)
|
||||
{
|
||||
return GetMasternodeInfo(pubKeyOperator.GetID(), mnInfoRet);
|
||||
}
|
||||
|
||||
bool CMasternodeMan::GetMasternodeInfo(const CScript& payee, masternode_info_t& mnInfoRet)
|
||||
{
|
||||
CTxDestination dest;
|
||||
@ -1399,24 +1389,24 @@ void CMasternodeMan::SendVerifyReply(CNode* pnode, CMasternodeVerification& mnv,
|
||||
if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
uint256 hash = mnv.GetSignatureHash1(blockHash);
|
||||
|
||||
if(!CHashSigner::SignHash(hash, activeMasternodeInfo.keyOperator, mnv.vchSig1)) {
|
||||
if(!CHashSigner::SignHash(hash, activeMasternodeInfo.legacyKeyOperator, mnv.vchSig1)) {
|
||||
LogPrintf("CMasternodeMan::SendVerifyReply -- SignHash() failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.keyIDOperator, mnv.vchSig1, strError)) {
|
||||
if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.legacyKeyIDOperator, mnv.vchSig1, strError)) {
|
||||
LogPrintf("CMasternodeMan::SendVerifyReply -- VerifyHash() failed, error: %s\n", strError);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
std::string strMessage = strprintf("%s%d%s", activeMasternodeInfo.service.ToString(false), mnv.nonce, blockHash.ToString());
|
||||
|
||||
if(!CMessageSigner::SignMessage(strMessage, mnv.vchSig1, activeMasternodeInfo.keyOperator)) {
|
||||
if(!CMessageSigner::SignMessage(strMessage, mnv.vchSig1, activeMasternodeInfo.legacyKeyOperator)) {
|
||||
LogPrintf("MasternodeMan::SendVerifyReply -- SignMessage() failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!CMessageSigner::VerifyMessage(activeMasternodeInfo.keyIDOperator, mnv.vchSig1, strMessage, strError)) {
|
||||
if(!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, mnv.vchSig1, strMessage, strError)) {
|
||||
LogPrintf("MasternodeMan::SendVerifyReply -- VerifyMessage() failed, error: %s\n", strError);
|
||||
return;
|
||||
}
|
||||
@ -1486,10 +1476,10 @@ void CMasternodeMan::ProcessVerifyReply(CNode* pnode, CMasternodeVerification& m
|
||||
if(CAddress(mnpair.second.addr, NODE_NETWORK) == pnode->addr) {
|
||||
bool fFound = false;
|
||||
if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
fFound = CHashSigner::VerifyHash(hash1, mnpair.second.keyIDOperator, mnv.vchSig1, strError);
|
||||
fFound = CHashSigner::VerifyHash(hash1, mnpair.second.legacyKeyIDOperator, mnv.vchSig1, strError);
|
||||
// we don't care about mnv with signature in old format
|
||||
} else {
|
||||
fFound = CMessageSigner::VerifyMessage(mnpair.second.keyIDOperator, mnv.vchSig1, strMessage1, strError);
|
||||
fFound = CMessageSigner::VerifyMessage(mnpair.second.legacyKeyIDOperator, mnv.vchSig1, strMessage1, strError);
|
||||
}
|
||||
if (fFound) {
|
||||
// found it!
|
||||
@ -1511,12 +1501,12 @@ void CMasternodeMan::ProcessVerifyReply(CNode* pnode, CMasternodeVerification& m
|
||||
if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
uint256 hash2 = mnv.GetSignatureHash2(blockHash);
|
||||
|
||||
if(!CHashSigner::SignHash(hash2, activeMasternodeInfo.keyOperator, mnv.vchSig2)) {
|
||||
if(!CHashSigner::SignHash(hash2, activeMasternodeInfo.legacyKeyOperator, mnv.vchSig2)) {
|
||||
LogPrintf("MasternodeMan::ProcessVerifyReply -- SignHash() failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!CHashSigner::VerifyHash(hash2, activeMasternodeInfo.keyIDOperator, mnv.vchSig2, strError)) {
|
||||
if(!CHashSigner::VerifyHash(hash2, activeMasternodeInfo.legacyKeyIDOperator, mnv.vchSig2, strError)) {
|
||||
LogPrintf("MasternodeMan::ProcessVerifyReply -- VerifyHash() failed, error: %s\n", strError);
|
||||
return;
|
||||
}
|
||||
@ -1524,12 +1514,12 @@ void CMasternodeMan::ProcessVerifyReply(CNode* pnode, CMasternodeVerification& m
|
||||
std::string strMessage2 = strprintf("%s%d%s%s%s", mnv.addr.ToString(false), mnv.nonce, blockHash.ToString(),
|
||||
mnv.masternodeOutpoint1.ToStringShort(), mnv.masternodeOutpoint2.ToStringShort());
|
||||
|
||||
if(!CMessageSigner::SignMessage(strMessage2, mnv.vchSig2, activeMasternodeInfo.keyOperator)) {
|
||||
if(!CMessageSigner::SignMessage(strMessage2, mnv.vchSig2, activeMasternodeInfo.legacyKeyOperator)) {
|
||||
LogPrintf("MasternodeMan::ProcessVerifyReply -- SignMessage() failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!CMessageSigner::VerifyMessage(activeMasternodeInfo.keyIDOperator, mnv.vchSig2, strMessage2, strError)) {
|
||||
if(!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, mnv.vchSig2, strMessage2, strError)) {
|
||||
LogPrintf("MasternodeMan::ProcessVerifyReply -- VerifyMessage() failed, error: %s\n", strError);
|
||||
return;
|
||||
}
|
||||
@ -1642,12 +1632,12 @@ void CMasternodeMan::ProcessVerifyBroadcast(CNode* pnode, const CMasternodeVerif
|
||||
uint256 hash1 = mnv.GetSignatureHash1(blockHash);
|
||||
uint256 hash2 = mnv.GetSignatureHash2(blockHash);
|
||||
|
||||
if(!CHashSigner::VerifyHash(hash1, pmn1->keyIDOperator, mnv.vchSig1, strError)) {
|
||||
if(!CHashSigner::VerifyHash(hash1, pmn1->legacyKeyIDOperator, mnv.vchSig1, strError)) {
|
||||
LogPrintf("MasternodeMan::ProcessVerifyBroadcast -- VerifyHash() failed, error: %s\n", strError);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!CHashSigner::VerifyHash(hash2, pmn2->keyIDOperator, mnv.vchSig2, strError)) {
|
||||
if(!CHashSigner::VerifyHash(hash2, pmn2->legacyKeyIDOperator, mnv.vchSig2, strError)) {
|
||||
LogPrintf("MasternodeMan::ProcessVerifyBroadcast -- VerifyHash() failed, error: %s\n", strError);
|
||||
return;
|
||||
}
|
||||
@ -1656,12 +1646,12 @@ void CMasternodeMan::ProcessVerifyBroadcast(CNode* pnode, const CMasternodeVerif
|
||||
std::string strMessage2 = strprintf("%s%d%s%s%s", mnv.addr.ToString(false), mnv.nonce, blockHash.ToString(),
|
||||
mnv.masternodeOutpoint1.ToStringShort(), mnv.masternodeOutpoint2.ToStringShort());
|
||||
|
||||
if(!CMessageSigner::VerifyMessage(pmn1->keyIDOperator, mnv.vchSig1, strMessage1, strError)) {
|
||||
if(!CMessageSigner::VerifyMessage(pmn1->legacyKeyIDOperator, mnv.vchSig1, strMessage1, strError)) {
|
||||
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- VerifyMessage() for masternode1 failed, error: %s\n", strError);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!CMessageSigner::VerifyMessage(pmn2->keyIDOperator, mnv.vchSig2, strMessage2, strError)) {
|
||||
if(!CMessageSigner::VerifyMessage(pmn2->legacyKeyIDOperator, mnv.vchSig2, strMessage2, strError)) {
|
||||
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- VerifyMessage() for masternode2 failed, error: %s\n", strError);
|
||||
return;
|
||||
}
|
||||
@ -1781,7 +1771,7 @@ bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CNode* pfrom, CMasternodeBr
|
||||
Add(mnb);
|
||||
masternodeSync.BumpAssetLastTime("CMasternodeMan::CheckMnbAndUpdateMasternodeList - new");
|
||||
// if it matches our Masternode privkey...
|
||||
if(fMasternodeMode && mnb.keyIDOperator == activeMasternodeInfo.keyIDOperator) {
|
||||
if(fMasternodeMode && mnb.legacyKeyIDOperator == activeMasternodeInfo.legacyKeyIDOperator) {
|
||||
mnb.nPoSeBanScore = -MASTERNODE_POSE_BAN_MAX_SCORE;
|
||||
if(mnb.nProtocolVersion == PROTOCOL_VERSION) {
|
||||
// ... and PROTOCOL_VERSION, then we've been remotely activated ...
|
||||
@ -1865,7 +1855,7 @@ void CMasternodeMan::CheckMasternode(const CKeyID& keyIDOperator, bool fForce)
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
for (auto& mnpair : mapMasternodes) {
|
||||
if (mnpair.second.keyIDOperator == keyIDOperator) {
|
||||
if (mnpair.second.legacyKeyIDOperator == keyIDOperator) {
|
||||
mnpair.second.Check(fForce);
|
||||
return;
|
||||
}
|
||||
|
@ -173,7 +173,6 @@ public:
|
||||
bool GetMasternodeInfo(const uint256& proTxHash, masternode_info_t& mnInfoRet);
|
||||
bool GetMasternodeInfo(const COutPoint& outpoint, masternode_info_t& mnInfoRet);
|
||||
bool GetMasternodeInfo(const CKeyID& keyIDOperator, masternode_info_t& mnInfoRet);
|
||||
bool GetMasternodeInfo(const CPubKey& pubKeyOperator, masternode_info_t& mnInfoRet);
|
||||
bool GetMasternodeInfo(const CScript& payee, masternode_info_t& mnInfoRet);
|
||||
|
||||
/// Find an entry in the masternode list that is next to be paid
|
||||
|
@ -1997,7 +1997,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||
// we have no idea about (e.g we were offline)? How to handle them?
|
||||
}
|
||||
|
||||
if(!dstx.CheckSignature(mn.keyIDOperator)) {
|
||||
if (!dstx.CheckSignature(mn.legacyKeyIDOperator, mn.blsPubKeyOperator)) {
|
||||
LogPrint("privatesend", "DSTX -- CheckSignature() failed for %s\n", hashTx.ToString());
|
||||
return false;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string&
|
||||
masternode_info_t infoMn;
|
||||
if(!mnodeman.GetMasternodeInfo(dsq.masternodeOutpoint, infoMn)) return;
|
||||
|
||||
if(!dsq.CheckSignature(infoMn.keyIDOperator)) {
|
||||
if(!dsq.CheckSignature(infoMn.legacyKeyIDOperator, infoMn.blsPubKeyOperator)) {
|
||||
// we probably have outdated info
|
||||
mnodeman.AskForMN(pfrom, dsq.masternodeOutpoint, connman);
|
||||
return;
|
||||
|
@ -102,7 +102,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm
|
||||
masternode_info_t mnInfo;
|
||||
if(!mnodeman.GetMasternodeInfo(dsq.masternodeOutpoint, mnInfo)) return;
|
||||
|
||||
if(!dsq.CheckSignature(mnInfo.keyIDOperator)) {
|
||||
if(!dsq.CheckSignature(mnInfo.legacyKeyIDOperator, mnInfo.blsPubKeyOperator)) {
|
||||
// we probably have outdated info
|
||||
mnodeman.AskForMN(pfrom, dsq.masternodeOutpoint, connman);
|
||||
return;
|
||||
|
@ -51,15 +51,19 @@ bool CDarksendQueue::Sign()
|
||||
|
||||
std::string strError = "";
|
||||
|
||||
if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
|
||||
sig.GetBuf(vchSig);
|
||||
} else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if (!CHashSigner::SignHash(hash, activeMasternodeInfo.keyOperator, vchSig)) {
|
||||
if (!CHashSigner::SignHash(hash, activeMasternodeInfo.legacyKeyOperator, vchSig)) {
|
||||
LogPrintf("CDarksendQueue::Sign -- SignHash() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.keyIDOperator, vchSig, strError)) {
|
||||
if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.legacyKeyIDOperator, vchSig, strError)) {
|
||||
LogPrintf("CDarksendQueue::Sign -- VerifyHash() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
@ -69,12 +73,12 @@ bool CDarksendQueue::Sign()
|
||||
std::to_string(nTime) +
|
||||
std::to_string(fReady);
|
||||
|
||||
if(!CMessageSigner::SignMessage(strMessage, vchSig, activeMasternodeInfo.keyOperator)) {
|
||||
if(!CMessageSigner::SignMessage(strMessage, vchSig, activeMasternodeInfo.legacyKeyOperator)) {
|
||||
LogPrintf("CDarksendQueue::Sign -- SignMessage() failed, %s\n", ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!CMessageSigner::VerifyMessage(activeMasternodeInfo.keyIDOperator, vchSig, strMessage, strError)) {
|
||||
if(!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, vchSig, strMessage, strError)) {
|
||||
LogPrintf("CDarksendQueue::Sign -- VerifyMessage() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
@ -83,11 +87,19 @@ bool CDarksendQueue::Sign()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDarksendQueue::CheckSignature(const CKeyID& keyIDOperator) const
|
||||
bool CDarksendQueue::CheckSignature(const CKeyID& keyIDOperator, const CBLSPublicKey& blsPubKey) const
|
||||
{
|
||||
std::string strError = "";
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
CBLSSignature sig;
|
||||
sig.SetBuf(vchSig);
|
||||
if (!sig.IsValid() || !sig.VerifyInsecure(blsPubKey, hash)) {
|
||||
LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n");
|
||||
return false;
|
||||
}
|
||||
} else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if (!CHashSigner::VerifyHash(hash, keyIDOperator, vchSig, strError)) {
|
||||
@ -131,27 +143,32 @@ bool CDarksendBroadcastTx::Sign()
|
||||
|
||||
std::string strError = "";
|
||||
|
||||
if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if (!CHashSigner::SignHash(hash, activeMasternodeInfo.keyOperator, vchSig)) {
|
||||
CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash);
|
||||
sig.GetBuf(vchSig);
|
||||
} else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if (!CHashSigner::SignHash(hash, activeMasternodeInfo.legacyKeyOperator, vchSig)) {
|
||||
LogPrintf("CDarksendBroadcastTx::Sign -- SignHash() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.keyIDOperator, vchSig, strError)) {
|
||||
if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.legacyKeyIDOperator, vchSig, strError)) {
|
||||
LogPrintf("CDarksendBroadcastTx::Sign -- VerifyHash() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
std::string strMessage = tx->GetHash().ToString() + std::to_string(sigTime);
|
||||
|
||||
if(!CMessageSigner::SignMessage(strMessage, vchSig, activeMasternodeInfo.keyOperator)) {
|
||||
if(!CMessageSigner::SignMessage(strMessage, vchSig, activeMasternodeInfo.legacyKeyOperator)) {
|
||||
LogPrintf("CDarksendBroadcastTx::Sign -- SignMessage() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!CMessageSigner::VerifyMessage(activeMasternodeInfo.keyIDOperator, vchSig, strMessage, strError)) {
|
||||
if(!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, vchSig, strMessage, strError)) {
|
||||
LogPrintf("CDarksendBroadcastTx::Sign -- VerifyMessage() failed, error: %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
@ -160,11 +177,20 @@ bool CDarksendBroadcastTx::Sign()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDarksendBroadcastTx::CheckSignature(const CKeyID& keyIDOperator) const
|
||||
bool CDarksendBroadcastTx::CheckSignature(const CKeyID& keyIDOperator, const CBLSPublicKey& blsPubKey) const
|
||||
{
|
||||
std::string strError = "";
|
||||
|
||||
if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
CBLSSignature sig;
|
||||
sig.SetBuf(vchSig);
|
||||
if (!sig.IsValid() || !sig.VerifyInsecure(blsPubKey, hash)) {
|
||||
LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n");
|
||||
return false;
|
||||
}
|
||||
} else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) {
|
||||
uint256 hash = GetSignatureHash();
|
||||
|
||||
if (!CHashSigner::VerifyHash(hash, keyIDOperator, vchSig, strError)) {
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "sync.h"
|
||||
#include "tinyformat.h"
|
||||
#include "timedata.h"
|
||||
#include "bls/bls.h"
|
||||
|
||||
class CPrivateSend;
|
||||
class CConnman;
|
||||
@ -229,7 +230,7 @@ public:
|
||||
*/
|
||||
bool Sign();
|
||||
/// Check if we have a valid Masternode address
|
||||
bool CheckSignature(const CKeyID& keyIDOperator) const;
|
||||
bool CheckSignature(const CKeyID& keyIDOperator, const CBLSPublicKey& blsPubKey) const;
|
||||
|
||||
bool Relay(CConnman &connman);
|
||||
|
||||
@ -307,7 +308,7 @@ public:
|
||||
uint256 GetSignatureHash() const;
|
||||
|
||||
bool Sign();
|
||||
bool CheckSignature(const CKeyID& keyIDOperator) const;
|
||||
bool CheckSignature(const CKeyID& keyIDOperator, const CBLSPublicKey& blsPubKey) const;
|
||||
|
||||
void SetConfirmedHeight(int nConfirmedHeightIn) { nConfirmedHeight = nConfirmedHeightIn; }
|
||||
bool IsExpired(int nHeight);
|
||||
|
@ -244,7 +244,7 @@ UniValue gobject_submit(const JSONRPCRequest& request)
|
||||
|
||||
bool fMnFound = mnodeman.Has(activeMasternodeInfo.outpoint);
|
||||
|
||||
DBG( std::cout << "gobject: submit activeMasternodeInfo.keyIDOperator = " << activeMasternodeInfo.keyIDOperator.ToString()
|
||||
DBG( std::cout << "gobject: submit activeMasternodeInfo.keyIDOperator = " << activeMasternodeInfo.legacyKeyIDOperator.ToString()
|
||||
<< ", outpoint = " << activeMasternodeInfo.outpoint.ToStringShort()
|
||||
<< ", params.size() = " << request.params.size()
|
||||
<< ", fMnFound = " << fMnFound << std::endl; );
|
||||
@ -294,7 +294,11 @@ UniValue gobject_submit(const JSONRPCRequest& request)
|
||||
if (govobj.GetObjectType() == GOVERNANCE_OBJECT_TRIGGER) {
|
||||
if (fMnFound) {
|
||||
govobj.SetMasternodeOutpoint(activeMasternodeInfo.outpoint);
|
||||
govobj.Sign(activeMasternodeInfo.keyOperator, activeMasternodeInfo.keyIDOperator);
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
govobj.Sign(*activeMasternodeInfo.blsKeyOperator);
|
||||
} else {
|
||||
govobj.Sign(activeMasternodeInfo.legacyKeyOperator, activeMasternodeInfo.legacyKeyIDOperator);
|
||||
}
|
||||
} else {
|
||||
LogPrintf("gobject(submit) -- Object submission rejected because node is not a masternode\n");
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Only valid masternodes can submit this type of object");
|
||||
@ -353,6 +357,10 @@ UniValue gobject_vote_conf(const JSONRPCRequest& request)
|
||||
if (request.fHelp || request.params.size() != 4)
|
||||
gobject_vote_conf_help();
|
||||
|
||||
if(deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Can't use vote-conf when deterministic masternodes are active");
|
||||
}
|
||||
|
||||
uint256 hash;
|
||||
|
||||
hash = ParseHashV(request.params[1], "Object hash");
|
||||
@ -402,20 +410,8 @@ UniValue gobject_vote_conf(const JSONRPCRequest& request)
|
||||
return returnObj;
|
||||
}
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
if (govObjType == GOVERNANCE_OBJECT_PROPOSAL && mn.keyIDVoting != activeMasternodeInfo.keyIDOperator) {
|
||||
nFailed++;
|
||||
statusObj.push_back(Pair("result", "failed"));
|
||||
statusObj.push_back(Pair("errorMessage", "Can't vote on proposal when operator key does not match voting key"));
|
||||
resultsObj.push_back(Pair("dash.conf", statusObj));
|
||||
returnObj.push_back(Pair("overall", strprintf("Voted successfully %d time(s) and failed %d time(s).", nSuccessful, nFailed)));
|
||||
returnObj.push_back(Pair("detail", resultsObj));
|
||||
return returnObj;
|
||||
}
|
||||
}
|
||||
|
||||
CGovernanceVote vote(mn.outpoint, hash, eVoteSignal, eVoteOutcome);
|
||||
if (!vote.Sign(activeMasternodeInfo.keyOperator, activeMasternodeInfo.keyIDOperator)) {
|
||||
if (!vote.Sign(activeMasternodeInfo.legacyKeyOperator, activeMasternodeInfo.legacyKeyIDOperator)) {
|
||||
nFailed++;
|
||||
statusObj.push_back(Pair("result", "failed"));
|
||||
statusObj.push_back(Pair("errorMessage", "Failure to sign."));
|
||||
|
@ -1063,7 +1063,7 @@ UniValue masternodelist(const JSONRPCRequest& request)
|
||||
obj.push_back(Pair(strOutpoint, HexStr(mn.keyIDOwner)));
|
||||
} else if (strMode == "keyIDOperator") {
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, HexStr(mn.keyIDOperator)));
|
||||
obj.push_back(Pair(strOutpoint, HexStr(mn.legacyKeyIDOperator)));
|
||||
} else if (strMode == "keyIDVoting") {
|
||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||
obj.push_back(Pair(strOutpoint, HexStr(mn.keyIDVoting)));
|
||||
@ -1248,7 +1248,7 @@ UniValue masternodebroadcast(const JSONRPCRequest& request)
|
||||
resultObj.push_back(Pair("outpoint", mnb.outpoint.ToStringShort()));
|
||||
resultObj.push_back(Pair("addr", mnb.addr.ToString()));
|
||||
resultObj.push_back(Pair("keyIDCollateralAddress", CBitcoinAddress(mnb.keyIDCollateralAddress).ToString()));
|
||||
resultObj.push_back(Pair("keyIDMasternode", CBitcoinAddress(mnb.keyIDOperator).ToString()));
|
||||
resultObj.push_back(Pair("keyIDMasternode", CBitcoinAddress(mnb.legacyKeyIDOperator).ToString()));
|
||||
resultObj.push_back(Pair("vchSig", EncodeBase64(&mnb.vchSig[0], mnb.vchSig.size())));
|
||||
resultObj.push_back(Pair("sigTime", mnb.sigTime));
|
||||
resultObj.push_back(Pair("protocolVersion", mnb.nProtocolVersion));
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "evo/deterministicmns.h"
|
||||
#include "evo/simplifiedmns.h"
|
||||
|
||||
#include "bls/bls.h"
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
extern UniValue signrawtransaction(const JSONRPCRequest& request);
|
||||
extern UniValue sendrawtransaction(const JSONRPCRequest& request);
|
||||
@ -57,15 +59,33 @@ static CKeyID ParsePubKeyIDFromAddress(const std::string& strAddress, const std:
|
||||
return keyID;
|
||||
}
|
||||
|
||||
static CBLSPublicKey ParseBLSPubKey(const std::string& hexKey, const std::string& paramName)
|
||||
{
|
||||
auto binKey = ParseHex(hexKey);
|
||||
CBLSPublicKey pubKey;
|
||||
pubKey.SetBuf(binKey);
|
||||
if (!pubKey.IsValid()) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be a valid BLS address, not %s", paramName, hexKey));
|
||||
}
|
||||
return pubKey;
|
||||
}
|
||||
|
||||
static CBLSSecretKey ParseBLSSecretKey(const std::string& hexKey, const std::string& paramName)
|
||||
{
|
||||
auto binKey = ParseHex(hexKey);
|
||||
CBLSSecretKey secKey;
|
||||
secKey.SetBuf(binKey);
|
||||
if (!secKey.IsValid()) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be a valid BLS secret key", paramName));
|
||||
}
|
||||
return secKey;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
|
||||
template<typename SpecialTxPayload>
|
||||
static void FundSpecialTx(CMutableTransaction& tx, SpecialTxPayload payload)
|
||||
{
|
||||
// resize so that fee calculation is correct
|
||||
payload.vchSig.resize(65);
|
||||
|
||||
CDataStream ds(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ds << payload;
|
||||
tx.vExtraPayload.assign(ds.begin(), ds.end());
|
||||
@ -107,6 +127,15 @@ static void SignSpecialTxPayload(const CMutableTransaction& tx, SpecialTxPayload
|
||||
}
|
||||
}
|
||||
|
||||
template<typename SpecialTxPayload>
|
||||
static void SignSpecialTxPayload(const CMutableTransaction& tx, SpecialTxPayload& payload, const CBLSSecretKey& key)
|
||||
{
|
||||
payload.inputsHash = CalcTxInputsHash(tx);
|
||||
|
||||
uint256 hash = ::SerializeHash(payload);
|
||||
payload.sig = key.Sign(hash);
|
||||
}
|
||||
|
||||
static std::string SignAndSendSpecialTx(const CMutableTransaction& tx)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
@ -160,7 +189,7 @@ void protx_register_help()
|
||||
"9. \"payoutAddress\" (string, required) The dash address to use for masternode reward payments\n"
|
||||
" Must match \"collateralAddress\"."
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("protx", "register \"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" 1000 \"1.2.3.4:1234\" 0 \"93Fd7XY2zF4q9YKTZUSFxLgp4Xs7MuaMnvY9kpvH7V8oXWqsCC1\" XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG")
|
||||
+ HelpExampleCli("protx", "register \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\" 1000 \"1.2.3.4:1234\" 0 \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\"")
|
||||
);
|
||||
}
|
||||
|
||||
@ -200,11 +229,8 @@ UniValue protx_register(const JSONRPCRequest& request)
|
||||
ptx.nProtocolVersion = PROTOCOL_VERSION;
|
||||
|
||||
CKey keyOwner = ParsePrivKey(request.params[5].get_str(), true);
|
||||
CKeyID keyIDOperator = keyOwner.GetPubKey().GetID();
|
||||
CBLSPublicKey pubKeyOperator = ParseBLSPubKey(request.params[6].get_str(), "operator BLS address");
|
||||
CKeyID keyIDVoting = keyOwner.GetPubKey().GetID();
|
||||
if (request.params[6].get_str() != "0" && request.params[6].get_str() != "") {
|
||||
keyIDOperator = ParsePubKeyIDFromAddress(request.params[6].get_str(), "operator address");
|
||||
}
|
||||
if (request.params[7].get_str() != "0" && request.params[7].get_str() != "") {
|
||||
keyIDVoting = ParsePubKeyIDFromAddress(request.params[7].get_str(), "voting address");
|
||||
}
|
||||
@ -219,10 +245,11 @@ UniValue protx_register(const JSONRPCRequest& request)
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("invalid payout address: %s", request.params[9].get_str()));
|
||||
|
||||
ptx.keyIDOwner = keyOwner.GetPubKey().GetID();
|
||||
ptx.keyIDOperator = keyIDOperator;
|
||||
ptx.pubKeyOperator = pubKeyOperator;
|
||||
ptx.keyIDVoting = keyIDVoting;
|
||||
ptx.scriptPayout = GetScriptForDestination(payoutAddress.Get());
|
||||
|
||||
SignSpecialTxPayload(tx, ptx, keyOwner); // make sure sig is set, otherwise fee calculation won't be correct
|
||||
FundSpecialTx(tx, ptx);
|
||||
|
||||
uint32_t collateralIndex = (uint32_t) - 1;
|
||||
@ -235,7 +262,7 @@ UniValue protx_register(const JSONRPCRequest& request)
|
||||
assert(collateralIndex != (uint32_t) - 1);
|
||||
ptx.nCollateralIndex = collateralIndex;
|
||||
|
||||
SignSpecialTxPayload(tx, ptx, keyOwner);
|
||||
SignSpecialTxPayload(tx, ptx, keyOwner); // redo signing
|
||||
SetTxPayload(tx, ptx);
|
||||
|
||||
return SignAndSendSpecialTx(tx);
|
||||
@ -244,7 +271,7 @@ UniValue protx_register(const JSONRPCRequest& request)
|
||||
void protx_update_service_help()
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"protx update_service \"proTxHash\" \"ipAndPort\" protocolVersion (\"operatorPayoutAddress\")\n"
|
||||
"protx update_service \"proTxHash\" \"ipAndPort\" protocolVersion \"operatorKey\" (\"operatorPayoutAddress\")\n"
|
||||
"\nCreates and sends a ProUpServTx to the network. This will update the address and protocol version\n"
|
||||
"of a masternode. The operator key of the masternode must be known to your wallet.\n"
|
||||
"If this is done for a masternode that got PoSe-banned, the ProUpServTx will also revive this masternode.\n"
|
||||
@ -254,10 +281,12 @@ void protx_update_service_help()
|
||||
" Must be unique on the network.\n"
|
||||
"3. \"protocolVersion\" (numeric, required) The protocol version of your masternode.\n"
|
||||
" Can be 0 to default to the clients protocol version\n"
|
||||
"4. \"operatorPayoutAddress\" (string, optional) The address used for operator reward payments.\n"
|
||||
"4. \"operatorKey\" (string, required) The operator private key belonging to the\n"
|
||||
" registered operator public key.\n"
|
||||
"5. \"operatorPayoutAddress\" (string, optional) The address used for operator reward payments.\n"
|
||||
" Only allowed when the ProRegTx had a non-zero operatorReward value.\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("protx", "update_service \"0123456701234567012345670123456701234567012345670123456701234567\" \"1.2.3.4:1234\" 0")
|
||||
+ HelpExampleCli("protx", "update_service \"0123456701234567012345670123456701234567012345670123456701234567\" \"1.2.3.4:1234\" 0 5a2e15982e62f1e0b7cf9783c64cf7e3af3f90a52d6c40f6f95d624c0b1621cd")
|
||||
);
|
||||
}
|
||||
|
||||
@ -279,8 +308,10 @@ UniValue protx_update_service(const JSONRPCRequest& request)
|
||||
ptx.nProtocolVersion = PROTOCOL_VERSION;
|
||||
}
|
||||
|
||||
if (request.params.size() > 4) {
|
||||
CBitcoinAddress payoutAddress(request.params[4].get_str());
|
||||
CBLSSecretKey keyOperator = ParseBLSSecretKey(request.params[4].get_str(), "operatorKey");
|
||||
|
||||
if (request.params.size() > 5) {
|
||||
CBitcoinAddress payoutAddress(request.params[5].get_str());
|
||||
if (!payoutAddress.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("invalid operator payout address: %s", request.params[4].get_str()));
|
||||
ptx.scriptOperatorPayout = GetScriptForDestination(payoutAddress.Get());
|
||||
@ -291,9 +322,8 @@ UniValue protx_update_service(const JSONRPCRequest& request)
|
||||
throw std::runtime_error(strprintf("masternode with proTxHash %s not found", ptx.proTxHash.ToString()));
|
||||
}
|
||||
|
||||
CKey keyOperator;
|
||||
if (!pwalletMain->GetKey(dmn->pdmnState->keyIDOperator, keyOperator)) {
|
||||
throw std::runtime_error(strprintf("operator key %s not found in your wallet", dmn->pdmnState->keyIDOperator.ToString()));
|
||||
if (keyOperator.GetPublicKey() != dmn->pdmnState->pubKeyOperator) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("the operator key does not belong to the registered public key"));
|
||||
}
|
||||
|
||||
CMutableTransaction tx;
|
||||
@ -316,7 +346,7 @@ void protx_update_registrar_help()
|
||||
"The owner key of the masternode must be known to your wallet.\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"proTxHash\" (string, required) The hash of the initial ProRegTx.\n"
|
||||
"2. \"operatorKeyAddr\" (string, required) The operator key address. The private key does not have to be known by your wallet.\n"
|
||||
"2. \"operatorPubKey\" (string, required) The operator public key. The private key does not have to be known by you.\n"
|
||||
" It has to match the private key which is later used when operating the masternode.\n"
|
||||
" If set to \"0\" or an empty string, the last on-chain operator key of the masternode will be used.\n"
|
||||
"3. \"votingKeyAddr\" (string, required) The voting key address. The private key does not have to be known by your wallet.\n"
|
||||
@ -326,7 +356,7 @@ void protx_update_registrar_help()
|
||||
" Must match \"collateralAddress\" of initial ProRegTx.\n"
|
||||
" If set to \"0\" or an empty string, the last on-chain payout address of the masternode will be used.\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("protx", "update_registrar \"0123456701234567012345670123456701234567012345670123456701234567\" \"<operatorKeyAddr>\" \"0\" \"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\"")
|
||||
+ HelpExampleCli("protx", "update_registrar \"0123456701234567012345670123456701234567012345670123456701234567\" \"982eb34b7c7f614f29e5c665bc3605f1beeef85e3395ca12d3be49d2868ecfea5566f11cedfad30c51b2403f2ad95b67\" \"0\" \"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\"")
|
||||
);
|
||||
}
|
||||
|
||||
@ -343,12 +373,12 @@ UniValue protx_update_registrar(const JSONRPCRequest& request)
|
||||
if (!dmn) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("masternode %s not found", ptx.proTxHash.ToString()));
|
||||
}
|
||||
ptx.keyIDOperator = dmn->pdmnState->keyIDOperator;
|
||||
ptx.pubKeyOperator = dmn->pdmnState->pubKeyOperator;
|
||||
ptx.keyIDVoting = dmn->pdmnState->keyIDVoting;
|
||||
ptx.scriptPayout = dmn->pdmnState->scriptPayout;
|
||||
|
||||
if (request.params[2].get_str() != "0" && request.params[2].get_str() != "") {
|
||||
ptx.keyIDOperator = ParsePubKeyIDFromAddress(request.params[2].get_str(), "operator address");
|
||||
ptx.pubKeyOperator = ParseBLSPubKey(request.params[2].get_str(), "operator BLS address");
|
||||
}
|
||||
if (request.params[3].get_str() != "0" && request.params[3].get_str() != "") {
|
||||
ptx.keyIDVoting = ParsePubKeyIDFromAddress(request.params[3].get_str(), "operator address");
|
||||
@ -386,9 +416,11 @@ void protx_revoke_help()
|
||||
"The operator key of the masternode must be known to your wallet.\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"proTxHash\" (string, required) The hash of the initial ProRegTx.\n"
|
||||
"2. reason (numeric, optional) The reason for revocation.\n"
|
||||
"2. \"operatorKey\" (string, required) The operator private key belonging to the\n"
|
||||
" registered operator public key.\n"
|
||||
"3. reason (numeric, optional) The reason for revocation.\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("protx", "revoke \"0123456701234567012345670123456701234567012345670123456701234567\" \"<operatorKeyAddr>\"")
|
||||
+ HelpExampleCli("protx", "revoke \"0123456701234567012345670123456701234567012345670123456701234567\" \"072f36a77261cdd5d64c32d97bac417540eddca1d5612f416feb07ff75a8e240\"")
|
||||
);
|
||||
}
|
||||
|
||||
@ -401,8 +433,10 @@ UniValue protx_revoke(const JSONRPCRequest& request)
|
||||
ptx.nVersion = CProRegTx::CURRENT_VERSION;
|
||||
ptx.proTxHash = ParseHashV(request.params[1], "proTxHash");
|
||||
|
||||
if (request.params.size() > 2) {
|
||||
int32_t nReason = ParseInt32V(request.params[2], "reason");
|
||||
CBLSSecretKey keyOperator = ParseBLSSecretKey(request.params[2].get_str(), "operatorKey");
|
||||
|
||||
if (request.params.size() > 3) {
|
||||
int32_t nReason = ParseInt32V(request.params[3], "reason");
|
||||
if (nReason < 0 || nReason >= CProUpRevTx::REASON_LAST)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("invalid reason %d, must be between 0 and %d", nReason, CProUpRevTx::REASON_LAST));
|
||||
ptx.nReason = (uint16_t)nReason;
|
||||
@ -413,9 +447,8 @@ UniValue protx_revoke(const JSONRPCRequest& request)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("masternode %s not found", ptx.proTxHash.ToString()));
|
||||
}
|
||||
|
||||
CKey keyOperator;
|
||||
if (!pwalletMain->GetKey(dmn->pdmnState->keyIDOperator, keyOperator)) {
|
||||
throw std::runtime_error(strprintf("operator key %s not found in your wallet", dmn->pdmnState->keyIDOwner.ToString()));
|
||||
if (keyOperator.GetPublicKey() != dmn->pdmnState->pubKeyOperator) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("the operator key does not belong to the registered public key"));
|
||||
}
|
||||
|
||||
CMutableTransaction tx;
|
||||
@ -471,7 +504,7 @@ UniValue BuildDMNListEntry(const CDeterministicMNCPtr& dmn, bool detailed)
|
||||
o.push_back(Pair("confirmations", confirmations));
|
||||
|
||||
bool hasOwnerKey = pwalletMain->HaveKey(dmn->pdmnState->keyIDOwner);
|
||||
bool hasOperatorKey = pwalletMain->HaveKey(dmn->pdmnState->keyIDOperator);
|
||||
bool hasOperatorKey = false; //pwalletMain->HaveKey(dmn->pdmnState->keyIDOperator);
|
||||
bool hasVotingKey = pwalletMain->HaveKey(dmn->pdmnState->keyIDVoting);
|
||||
|
||||
bool ownsCollateral = false;
|
||||
@ -522,7 +555,6 @@ UniValue protx_list(const JSONRPCRequest& request)
|
||||
deterministicMNManager->GetListAtChainTip().ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) {
|
||||
if (setOutpts.count(dmn->proTxHash) ||
|
||||
pwalletMain->HaveKey(dmn->pdmnState->keyIDOwner) ||
|
||||
pwalletMain->HaveKey(dmn->pdmnState->keyIDOperator) ||
|
||||
pwalletMain->HaveKey(dmn->pdmnState->keyIDVoting) ||
|
||||
CheckWalletOwnsScript(dmn->pdmnState->scriptPayout) ||
|
||||
CheckWalletOwnsScript(dmn->pdmnState->scriptOperatorPayout)) {
|
||||
@ -646,9 +678,38 @@ UniValue protx(const JSONRPCRequest& request)
|
||||
}
|
||||
#endif//ENABLE_WALLET
|
||||
|
||||
UniValue bls_generate(const JSONRPCRequest& request)
|
||||
{
|
||||
CBLSSecretKey sk;
|
||||
sk.MakeNewKey();
|
||||
|
||||
UniValue ret(UniValue::VOBJ);
|
||||
ret.push_back(Pair("secret", sk.ToString()));
|
||||
ret.push_back(Pair("public", sk.GetPublicKey().ToString()));
|
||||
return ret;
|
||||
}
|
||||
|
||||
UniValue _bls(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.params.empty()) {
|
||||
throw std::runtime_error(
|
||||
"bls \"command\" ...\n"
|
||||
);
|
||||
}
|
||||
|
||||
std::string command = request.params[0].get_str();
|
||||
|
||||
if (command == "generate") {
|
||||
return bls_generate(request);
|
||||
} else {
|
||||
throw std::runtime_error("invalid command: " + command);
|
||||
}
|
||||
}
|
||||
|
||||
static const CRPCCommand commands[] =
|
||||
{ // category name actor (function) okSafeMode
|
||||
// --------------------- ------------------------ ----------------------- ----------
|
||||
{ "evo", "bls", &_bls, false, {} },
|
||||
#ifdef ENABLE_WALLET
|
||||
// these require the wallet to be enabled to fund the transactions
|
||||
{ "evo", "protx", &protx, false, {} },
|
||||
|
@ -94,9 +94,10 @@ static void SignTransaction(CMutableTransaction& tx, const CKey& coinbaseKey)
|
||||
}
|
||||
}
|
||||
|
||||
static CMutableTransaction CreateProRegTx(SimpleUTXOMap& utxos, int port, const CScript& scriptPayout, const CKey& coinbaseKey, CKey& mnKeyRet)
|
||||
static CMutableTransaction CreateProRegTx(SimpleUTXOMap& utxos, int port, const CScript& scriptPayout, const CKey& coinbaseKey, CKey& ownerKeyRet, CBLSSecretKey& operatorKeyRet)
|
||||
{
|
||||
mnKeyRet.MakeNewKey(true);
|
||||
ownerKeyRet.MakeNewKey(true);
|
||||
operatorKeyRet.MakeNewKey();
|
||||
|
||||
CAmount change;
|
||||
auto inputs = SelectUTXOs(utxos, 1000 * COIN, change);
|
||||
@ -105,9 +106,9 @@ static CMutableTransaction CreateProRegTx(SimpleUTXOMap& utxos, int port, const
|
||||
proTx.nProtocolVersion = PROTOCOL_VERSION;
|
||||
proTx.nCollateralIndex = 0;
|
||||
proTx.addr = LookupNumeric("1.1.1.1", port);
|
||||
proTx.keyIDOwner = mnKeyRet.GetPubKey().GetID();
|
||||
proTx.keyIDOperator = mnKeyRet.GetPubKey().GetID();
|
||||
proTx.keyIDVoting = mnKeyRet.GetPubKey().GetID();
|
||||
proTx.keyIDOwner = ownerKeyRet.GetPubKey().GetID();
|
||||
proTx.pubKeyOperator = operatorKeyRet.GetPublicKey();
|
||||
proTx.keyIDVoting = ownerKeyRet.GetPubKey().GetID();
|
||||
proTx.scriptPayout = scriptPayout;
|
||||
|
||||
CMutableTransaction tx;
|
||||
@ -115,14 +116,14 @@ static CMutableTransaction CreateProRegTx(SimpleUTXOMap& utxos, int port, const
|
||||
tx.nType = TRANSACTION_PROVIDER_REGISTER;
|
||||
FundTransaction(tx, utxos, scriptPayout, 1000 * COIN, coinbaseKey);
|
||||
proTx.inputsHash = CalcTxInputsHash(tx);
|
||||
CHashSigner::SignHash(::SerializeHash(proTx), mnKeyRet, proTx.vchSig);
|
||||
CHashSigner::SignHash(::SerializeHash(proTx), ownerKeyRet, proTx.vchSig);
|
||||
SetTxPayload(tx, proTx);
|
||||
SignTransaction(tx, coinbaseKey);
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
static CMutableTransaction CreateProUpServTx(SimpleUTXOMap& utxos, const uint256& proTxHash, const CKey& mnKey, int port, const CScript& scriptOperatorPayout, const CKey& coinbaseKey)
|
||||
static CMutableTransaction CreateProUpServTx(SimpleUTXOMap& utxos, const uint256& proTxHash, const CBLSSecretKey& operatorKey, int port, const CScript& scriptOperatorPayout, const CKey& coinbaseKey)
|
||||
{
|
||||
CAmount change;
|
||||
auto inputs = SelectUTXOs(utxos, 1 * COIN, change);
|
||||
@ -138,21 +139,21 @@ static CMutableTransaction CreateProUpServTx(SimpleUTXOMap& utxos, const uint256
|
||||
tx.nType = TRANSACTION_PROVIDER_UPDATE_SERVICE;
|
||||
FundTransaction(tx, utxos, GetScriptForDestination(coinbaseKey.GetPubKey().GetID()), 1 * COIN, coinbaseKey);
|
||||
proTx.inputsHash = CalcTxInputsHash(tx);
|
||||
CHashSigner::SignHash(::SerializeHash(proTx), mnKey, proTx.vchSig);
|
||||
proTx.sig = operatorKey.Sign(::SerializeHash(proTx));
|
||||
SetTxPayload(tx, proTx);
|
||||
SignTransaction(tx, coinbaseKey);
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
static CMutableTransaction CreateProUpRegTx(SimpleUTXOMap& utxos, const uint256& proTxHash, const CKey& mnKey, const CKeyID& keyIDOperator, const CKeyID& keyIDVoting, const CScript& scriptPayout, const CKey& coinbaseKey)
|
||||
static CMutableTransaction CreateProUpRegTx(SimpleUTXOMap& utxos, const uint256& proTxHash, const CKey& mnKey, const CBLSPublicKey& pubKeyOperator, const CKeyID& keyIDVoting, const CScript& scriptPayout, const CKey& coinbaseKey)
|
||||
{
|
||||
CAmount change;
|
||||
auto inputs = SelectUTXOs(utxos, 1 * COIN, change);
|
||||
|
||||
CProUpRegTx proTx;
|
||||
proTx.proTxHash = proTxHash;
|
||||
proTx.keyIDOperator = keyIDOperator;
|
||||
proTx.pubKeyOperator = pubKeyOperator;
|
||||
proTx.keyIDVoting = keyIDVoting;
|
||||
proTx.scriptPayout = scriptPayout;
|
||||
|
||||
@ -168,7 +169,7 @@ static CMutableTransaction CreateProUpRegTx(SimpleUTXOMap& utxos, const uint256&
|
||||
return tx;
|
||||
}
|
||||
|
||||
static CMutableTransaction CreateProUpRevTx(SimpleUTXOMap& utxos, const uint256& proTxHash, const CKey& mnKey, const CKey& coinbaseKey)
|
||||
static CMutableTransaction CreateProUpRevTx(SimpleUTXOMap& utxos, const uint256& proTxHash, const CBLSSecretKey& operatorKey, const CKey& coinbaseKey)
|
||||
{
|
||||
CAmount change;
|
||||
auto inputs = SelectUTXOs(utxos, 1 * COIN, change);
|
||||
@ -181,7 +182,7 @@ static CMutableTransaction CreateProUpRevTx(SimpleUTXOMap& utxos, const uint256&
|
||||
tx.nType = TRANSACTION_PROVIDER_UPDATE_REVOKE;
|
||||
FundTransaction(tx, utxos, GetScriptForDestination(coinbaseKey.GetPubKey().GetID()), 1 * COIN, coinbaseKey);
|
||||
proTx.inputsHash = CalcTxInputsHash(tx);
|
||||
CHashSigner::SignHash(::SerializeHash(proTx), mnKey, proTx.vchSig);
|
||||
proTx.sig = operatorKey.Sign(::SerializeHash(proTx));
|
||||
SetTxPayload(tx, proTx);
|
||||
SignTransaction(tx, coinbaseKey);
|
||||
|
||||
@ -218,8 +219,9 @@ BOOST_AUTO_TEST_SUITE(evo_dip3_activation_tests)
|
||||
BOOST_FIXTURE_TEST_CASE(dip3_activation, TestChainDIP3BeforeActivationSetup)
|
||||
{
|
||||
auto utxos = BuildSimpleUtxoMap(coinbaseTxns);
|
||||
CKey mnKey;
|
||||
auto tx = CreateProRegTx(utxos, 1, GetScriptForDestination(payoutAddress.Get()), coinbaseKey, mnKey);
|
||||
CKey ownerKey;
|
||||
CBLSSecretKey operatorKey;
|
||||
auto tx = CreateProRegTx(utxos, 1, GetScriptForDestination(payoutAddress.Get()), coinbaseKey, ownerKey, operatorKey);
|
||||
std::vector<CMutableTransaction> txns = {tx};
|
||||
|
||||
int nHeight = chainActive.Height();
|
||||
@ -260,14 +262,17 @@ BOOST_FIXTURE_TEST_CASE(dip3_protx, TestChainDIP3Setup)
|
||||
int port = 1;
|
||||
|
||||
std::vector<uint256> dmnHashes;
|
||||
std::map<uint256, CKey> mnKeys;
|
||||
std::map<uint256, CKey> ownerKeys;
|
||||
std::map<uint256, CBLSSecretKey> operatorKeys;
|
||||
|
||||
// register one MN per block
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
CKey mnKey;
|
||||
auto tx = CreateProRegTx(utxos, port++, GenerateRandomAddress(), coinbaseKey, mnKey);
|
||||
CKey ownerKey;
|
||||
CBLSSecretKey operatorKey;
|
||||
auto tx = CreateProRegTx(utxos, port++, GenerateRandomAddress(), coinbaseKey, ownerKey, operatorKey);
|
||||
dmnHashes.emplace_back(tx.GetHash());
|
||||
mnKeys.emplace(tx.GetHash(), mnKey);
|
||||
ownerKeys.emplace(tx.GetHash(), ownerKey);
|
||||
operatorKeys.emplace(tx.GetHash(), operatorKey);
|
||||
CreateAndProcessBlock({tx}, coinbaseKey);
|
||||
deterministicMNManager->UpdatedBlockTip(chainActive.Tip());
|
||||
|
||||
@ -302,10 +307,12 @@ BOOST_FIXTURE_TEST_CASE(dip3_protx, TestChainDIP3Setup)
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
std::vector<CMutableTransaction> txns;
|
||||
for (size_t j = 0; j < 3; j++) {
|
||||
CKey mnKey;
|
||||
auto tx = CreateProRegTx(utxos, port++, GenerateRandomAddress(), coinbaseKey, mnKey);
|
||||
CKey ownerKey;
|
||||
CBLSSecretKey operatorKey;
|
||||
auto tx = CreateProRegTx(utxos, port++, GenerateRandomAddress(), coinbaseKey, ownerKey, operatorKey);
|
||||
dmnHashes.emplace_back(tx.GetHash());
|
||||
mnKeys.emplace(tx.GetHash(), mnKey);
|
||||
ownerKeys.emplace(tx.GetHash(), ownerKey);
|
||||
operatorKeys.emplace(tx.GetHash(), operatorKey);
|
||||
txns.emplace_back(tx);
|
||||
}
|
||||
CreateAndProcessBlock(txns, coinbaseKey);
|
||||
@ -320,7 +327,7 @@ BOOST_FIXTURE_TEST_CASE(dip3_protx, TestChainDIP3Setup)
|
||||
}
|
||||
|
||||
// test ProUpServTx
|
||||
auto tx = CreateProUpServTx(utxos, dmnHashes[0], mnKeys[dmnHashes[0]], 1000, CScript(), coinbaseKey);
|
||||
auto tx = CreateProUpServTx(utxos, dmnHashes[0], operatorKeys[dmnHashes[0]], 1000, CScript(), coinbaseKey);
|
||||
CreateAndProcessBlock({tx}, coinbaseKey);
|
||||
deterministicMNManager->UpdatedBlockTip(chainActive.Tip());
|
||||
BOOST_ASSERT(chainActive.Height() == nHeight + 1);
|
||||
@ -330,7 +337,7 @@ BOOST_FIXTURE_TEST_CASE(dip3_protx, TestChainDIP3Setup)
|
||||
BOOST_ASSERT(dmn != nullptr && dmn->pdmnState->addr.GetPort() == 1000);
|
||||
|
||||
// test ProUpRevTx
|
||||
tx = CreateProUpRevTx(utxos, dmnHashes[0], mnKeys[dmnHashes[0]], coinbaseKey);
|
||||
tx = CreateProUpRevTx(utxos, dmnHashes[0], operatorKeys[dmnHashes[0]], coinbaseKey);
|
||||
CreateAndProcessBlock({tx}, coinbaseKey);
|
||||
deterministicMNManager->UpdatedBlockTip(chainActive.Tip());
|
||||
BOOST_ASSERT(chainActive.Height() == nHeight + 1);
|
||||
@ -356,10 +363,10 @@ BOOST_FIXTURE_TEST_CASE(dip3_protx, TestChainDIP3Setup)
|
||||
}
|
||||
|
||||
// test reviving the MN
|
||||
CKey newOperatorKey;
|
||||
newOperatorKey.MakeNewKey(false);
|
||||
CBLSSecretKey newOperatorKey;
|
||||
newOperatorKey.MakeNewKey();
|
||||
dmn = deterministicMNManager->GetListAtChainTip().GetMN(dmnHashes[0]);
|
||||
tx = CreateProUpRegTx(utxos, dmnHashes[0], mnKeys[dmnHashes[0]], newOperatorKey.GetPubKey().GetID(), newOperatorKey.GetPubKey().GetID(), dmn->pdmnState->scriptPayout, coinbaseKey);
|
||||
tx = CreateProUpRegTx(utxos, dmnHashes[0], ownerKeys[dmnHashes[0]], newOperatorKey.GetPublicKey(), ownerKeys[dmnHashes[0]].GetPubKey().GetID(), dmn->pdmnState->scriptPayout, coinbaseKey);
|
||||
CreateAndProcessBlock({tx}, coinbaseKey);
|
||||
deterministicMNManager->UpdatedBlockTip(chainActive.Tip());
|
||||
BOOST_ASSERT(chainActive.Height() == nHeight + 1);
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "test/test_dash.h"
|
||||
|
||||
#include "bls/bls.h"
|
||||
#include "evo/simplifiedmns.h"
|
||||
#include "netbase.h"
|
||||
|
||||
@ -21,7 +22,13 @@ BOOST_AUTO_TEST_CASE(simplifiedmns_merkleroots)
|
||||
std::string ip = strprintf("%d.%d.%d.%d", 0, 0, 0, i);
|
||||
Lookup(ip.c_str(), smle.service, i, false);
|
||||
|
||||
smle.keyIDOperator.SetHex(strprintf("%040x", i));
|
||||
uint8_t skBuf[CBLSSecretKey::SerSize];
|
||||
memset(skBuf, 0, sizeof(skBuf));
|
||||
skBuf[0] = (uint8_t)i;
|
||||
CBLSSecretKey sk;
|
||||
sk.SetBuf(skBuf, sizeof(skBuf));
|
||||
|
||||
smle.pubKeyOperator = sk.GetPublicKey();
|
||||
smle.keyIDVoting.SetHex(strprintf("%040x", i));
|
||||
smle.isValid = true;
|
||||
|
||||
@ -29,21 +36,21 @@ BOOST_AUTO_TEST_CASE(simplifiedmns_merkleroots)
|
||||
}
|
||||
|
||||
std::vector<std::string> expectedHashes = {
|
||||
"aa8bfb825f433bcd6f1039f27c77ed269386e05577b0fe9afc4e16b1af0076b2",
|
||||
"686a19dba9b515f77f11027cd1e92e6a8c650448bf4616101fd5ddbe6e2629e7",
|
||||
"c2efc1b08daa791c71e1d5887be3eaa136381f783fcc5b7efdc5909db38701bb",
|
||||
"ce394197d6e1684467fbf2e1619f71ae9d1a6cf6548b2235e4289f95d4bccbbd",
|
||||
"aeeaf7b498aa7d5fa92ee0028499b4f165c31662f5e9b0a80e6e13b38fd61f8d",
|
||||
"0c1c8dc9dc82eb5432a557580e5d3d930943ce0d0db5daebc51267afb46b6d48",
|
||||
"1c4add10ea844a46734473e48c2f781059b35382219d0cf67d6432b540e0bbbe",
|
||||
"1ae1ad5ff4dd4c09469d21d569a025d467dca1e407581a2815175528e139b7da",
|
||||
"d59b231cdc80ce7eda3a3f37608abda818659c189d31a7ef42024d496e290cbc",
|
||||
"2d5e6c87e3d4e5b3fdd600f561e8dec1ea720560569398006050480232f1257c",
|
||||
"3d6af35f08efeea22f3c8fcb78038e56dac221f3173ca4e2230ea8ae3cbd3c60",
|
||||
"ecf547077c37b79da954c4ef46a3c4fb136746366bfb81192ed01de96fd66348",
|
||||
"626af5fb8192ead7bbd79ad7bfe2c3ea82714fdfd9ac49b88d7a411aa6956853",
|
||||
"6c84a4485fb2ba35b4dcd4d89cbdd3d813446514bb7a2046b6b1b9813beaac0f",
|
||||
"453ca2a83140da73a37794fe6fddd701ea5066f21c2f1df8a33b6ff6134043c3",
|
||||
"1465924a81df1d0fb46d2571e65296c0fddab30d1b4d104f182f80a6e45362fa",
|
||||
"cb466084403067b699a50bd46e53145ebfd57af9a076a13432f524e41ec2d899",
|
||||
"0f6a720d0119f5b83469d884ec2a7d739c1d653142e5d36b569cddaf735a6149",
|
||||
"8794379559c77d67902a5e894739bd574f25ff6cd48612f7156c5fafaefefd4e",
|
||||
"4738d4f17c76b4e61f028d9426f40242eb56977fe805704d980ff57ad3f60b90",
|
||||
"6342b7ce87a299a0fb070ec040a45613f082b0c99395698a6f712e85be87ad06",
|
||||
"0be7143f4fb357333350a7e28606713933e9819c83c71009b9ea97476d86b78e",
|
||||
"d13dfedc920490a8c6d9b555d740f2944ac83eeb8c3923a51261371a8118ffe0",
|
||||
"c0c4638fcefe09380adff61d59c064be03a18690245b89be20223df737590d46",
|
||||
"4cce41032bb341adb9b9f3f6ba1de3c812f0d1630e3a561c7aae00f39e49c6d4",
|
||||
"3e8c9ad9e2cf0520a96b6bc58aafb7009365a1d8f357047a40430b782142ed69",
|
||||
"bde7a1b61a263a7e0dfe474c850c4f9d642d9a03da501a366800e03093e48cd9",
|
||||
"e221a3e14868251083eea718e698cc81739b016665a9024d798a14c0e9417c35",
|
||||
"b1be038e40bc8ee6a19dbbe70c92d7bc0880ccc54c4bd54eab6b7a30d0650ab1",
|
||||
"0607e1d850e27c336e8d65722fc82eae7ab5331fd88a4fbfcff6c3a1bb6364da",
|
||||
};
|
||||
std::vector<std::string> calculatedHashes;
|
||||
|
||||
@ -56,8 +63,9 @@ BOOST_AUTO_TEST_CASE(simplifiedmns_merkleroots)
|
||||
|
||||
CSimplifiedMNList sml(entries);
|
||||
|
||||
std::string expectedMerkleRoot = "926efc8dc7b5b060254b102670b918133fea67c5e1bc2703d596e49672878c22";
|
||||
std::string expectedMerkleRoot = "a7fae13820022ddba6cf54ba9b234dfed54ccfa86c2635c5627287f1ffa5497f";
|
||||
std::string calculatedMerkleRoot = sml.CalcMerkleRoot(nullptr).ToString();
|
||||
//printf("merkleRoot=\"%s\",\n", calculatedMerkleRoot.c_str());
|
||||
|
||||
BOOST_CHECK(expectedMerkleRoot == calculatedMerkleRoot);
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ extern void noui_connect();
|
||||
BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
|
||||
{
|
||||
ECC_Start();
|
||||
BLSInit();
|
||||
SetupEnvironment();
|
||||
SetupNetworking();
|
||||
InitSignatureCache();
|
||||
|
@ -448,7 +448,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
|
||||
}
|
||||
mapProTxAddresses.emplace(proTx.addr, tx.GetHash());
|
||||
mapProTxPubKeyIDs.emplace(proTx.keyIDOwner, tx.GetHash());
|
||||
mapProTxPubKeyIDs.emplace(proTx.keyIDOperator, tx.GetHash());
|
||||
mapProTxBlsPubKeyHashes.emplace(proTx.pubKeyOperator.GetHash(), tx.GetHash());
|
||||
} else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) {
|
||||
CProUpServTx proTx;
|
||||
if (!GetTxPayload(tx, proTx)) {
|
||||
@ -460,7 +460,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
|
||||
if (!GetTxPayload(tx, proTx)) {
|
||||
assert(false);
|
||||
}
|
||||
mapProTxPubKeyIDs.emplace(proTx.keyIDOperator, tx.GetHash());
|
||||
mapProTxBlsPubKeyHashes.emplace(proTx.pubKeyOperator.GetHash(), tx.GetHash());
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -645,7 +645,7 @@ void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason)
|
||||
}
|
||||
mapProTxAddresses.erase(proTx.addr);
|
||||
mapProTxPubKeyIDs.erase(proTx.keyIDOwner);
|
||||
mapProTxPubKeyIDs.erase(proTx.keyIDOperator);
|
||||
mapProTxBlsPubKeyHashes.erase(proTx.pubKeyOperator.GetHash());
|
||||
} else if (it->GetTx().nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) {
|
||||
CProUpServTx proTx;
|
||||
if (!GetTxPayload(it->GetTx(), proTx)) {
|
||||
@ -657,7 +657,7 @@ void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason)
|
||||
if (!GetTxPayload(it->GetTx(), proTx)) {
|
||||
assert(false);
|
||||
}
|
||||
mapProTxPubKeyIDs.erase(proTx.keyIDOperator);
|
||||
mapProTxBlsPubKeyHashes.erase(proTx.pubKeyOperator.GetHash());
|
||||
}
|
||||
|
||||
totalTxSize -= it->GetTxSize();
|
||||
@ -796,6 +796,16 @@ void CTxMemPool::removeProTxPubKeyConflicts(const CTransaction &tx, const CKeyID
|
||||
}
|
||||
}
|
||||
|
||||
void CTxMemPool::removeProTxPubKeyConflicts(const CTransaction &tx, const CBLSPublicKey &pubKey)
|
||||
{
|
||||
if (mapProTxBlsPubKeyHashes.count(pubKey.GetHash())) {
|
||||
uint256 conflictHash = mapProTxBlsPubKeyHashes[pubKey.GetHash()];
|
||||
if (conflictHash != tx.GetHash() && mapTx.count(conflictHash)) {
|
||||
removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTxMemPool::removeProTxConflicts(const CTransaction &tx)
|
||||
{
|
||||
if (tx.nType == TRANSACTION_PROVIDER_REGISTER) {
|
||||
@ -811,7 +821,7 @@ void CTxMemPool::removeProTxConflicts(const CTransaction &tx)
|
||||
}
|
||||
}
|
||||
removeProTxPubKeyConflicts(tx, proTx.keyIDOwner);
|
||||
removeProTxPubKeyConflicts(tx, proTx.keyIDOperator);
|
||||
removeProTxPubKeyConflicts(tx, proTx.pubKeyOperator);
|
||||
} else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) {
|
||||
CProUpServTx proTx;
|
||||
if (!GetTxPayload(tx, proTx)) {
|
||||
@ -830,7 +840,7 @@ void CTxMemPool::removeProTxConflicts(const CTransaction &tx)
|
||||
assert(false);
|
||||
}
|
||||
|
||||
removeProTxPubKeyConflicts(tx, proTx.keyIDOperator);
|
||||
removeProTxPubKeyConflicts(tx, proTx.pubKeyOperator);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1117,7 +1127,7 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const {
|
||||
CProRegTx proTx;
|
||||
if (!GetTxPayload(tx, proTx))
|
||||
assert(false);
|
||||
return mapProTxAddresses.count(proTx.addr) || mapProTxPubKeyIDs.count(proTx.keyIDOwner) || mapProTxPubKeyIDs.count(proTx.keyIDOperator);
|
||||
return mapProTxAddresses.count(proTx.addr) || mapProTxPubKeyIDs.count(proTx.keyIDOwner) || mapProTxBlsPubKeyHashes.count(proTx.pubKeyOperator.GetHash());
|
||||
} else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) {
|
||||
CProUpServTx proTx;
|
||||
if (!GetTxPayload(tx, proTx))
|
||||
@ -1128,8 +1138,8 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const {
|
||||
CProUpRegTx proTx;
|
||||
if (!GetTxPayload(tx, proTx))
|
||||
assert(false);
|
||||
auto it = mapProTxPubKeyIDs.find(proTx.keyIDOperator);
|
||||
return it != mapProTxPubKeyIDs.end() && it->second != proTx.proTxHash;
|
||||
auto it = mapProTxBlsPubKeyHashes.find(proTx.pubKeyOperator.GetHash());
|
||||
return it != mapProTxBlsPubKeyHashes.end() && it->second != proTx.proTxHash;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "sync.h"
|
||||
#include "random.h"
|
||||
#include "netaddress.h"
|
||||
#include "bls/bls.h"
|
||||
|
||||
#undef foreach
|
||||
#include "boost/multi_index_container.hpp"
|
||||
@ -535,6 +536,7 @@ private:
|
||||
|
||||
std::map<CService, uint256> mapProTxAddresses;
|
||||
std::map<CKeyID, uint256> mapProTxPubKeyIDs;
|
||||
std::map<uint256, uint256> mapProTxBlsPubKeyHashes;
|
||||
|
||||
void UpdateParent(txiter entry, txiter parent, bool add);
|
||||
void UpdateChild(txiter entry, txiter child, bool add);
|
||||
@ -579,6 +581,7 @@ public:
|
||||
void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags);
|
||||
void removeConflicts(const CTransaction &tx);
|
||||
void removeProTxPubKeyConflicts(const CTransaction &tx, const CKeyID &keyId);
|
||||
void removeProTxPubKeyConflicts(const CTransaction &tx, const CBLSPublicKey &pubKey);
|
||||
void removeProTxConflicts(const CTransaction &tx);
|
||||
void removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user