2021-04-20 21:33:02 +02:00
|
|
|
// Copyright (c) 2014-2021 The Dash Core developers
|
2016-02-02 16:28:56 +01:00
|
|
|
// Distributed under the MIT software license, see the accompanying
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
2015-02-09 21:54:51 +01:00
|
|
|
|
2020-03-19 23:46:56 +01:00
|
|
|
#include <spork.h>
|
2018-03-02 14:15:04 +01:00
|
|
|
|
2020-03-19 23:46:56 +01:00
|
|
|
#include <chainparams.h>
|
Merge #11372: Address encoding cleanup
92f1f8b31 Split off key_io_tests from base58_tests (Pieter Wuille)
119b0f85e Split key_io (address/key encodings) off from base58 (Pieter Wuille)
ebfe217b1 Stop using CBase58Data for ext keys (Pieter Wuille)
32e69fa0d Replace CBitcoinSecret with {Encode,Decode}Secret (Pieter Wuille)
Pull request description:
This PR contains some of the changes left as TODO in #11167 (and built on top of that PR). They are not intended for backporting.
This removes the `CBase58`, `CBitcoinSecret`, `CBitcoinExtKey`, and `CBitcoinExtPubKey` classes, in favor of simple `Encode`/`Decode` functions. Furthermore, all Bitcoin-specific logic (addresses, WIF, BIP32) is moved to `key_io.{h,cpp}`, leaving `base58.{h,cpp}` as a pure utility that implements the base58 encoding/decoding logic.
Tree-SHA512: a5962c0ed27ad53cbe00f22af432cf11aa530e3efc9798e25c004bc9ed1b5673db5df3956e398ee2c085e3a136ac8da69fe7a7d97a05fb2eb3be0b60d0479655
Make linter happy
Dashify
2018-03-07 00:04:56 +01:00
|
|
|
#include <key_io.h>
|
2020-03-19 23:46:56 +01:00
|
|
|
#include <validation.h>
|
|
|
|
#include <messagesigner.h>
|
|
|
|
#include <net_processing.h>
|
|
|
|
#include <netmessagemaker.h>
|
2015-02-09 21:54:51 +01:00
|
|
|
|
2018-07-12 11:02:20 +02:00
|
|
|
#include <string>
|
2015-02-09 21:54:51 +01:00
|
|
|
|
2018-10-11 16:34:52 +02:00
|
|
|
const std::string CSporkManager::SERIALIZATION_VERSION_STRING = "CSporkManager-Version-2";
|
2018-09-26 16:15:02 +02:00
|
|
|
|
2019-05-29 20:18:31 +02:00
|
|
|
#define MAKE_SPORK_DEF(name, defaultValue) CSporkDef{name, defaultValue, #name}
|
|
|
|
std::vector<CSporkDef> sporkDefs = {
|
2019-07-09 16:50:08 +02:00
|
|
|
MAKE_SPORK_DEF(SPORK_2_INSTANTSEND_ENABLED, 4070908800ULL), // OFF
|
|
|
|
MAKE_SPORK_DEF(SPORK_3_INSTANTSEND_BLOCK_FILTERING, 4070908800ULL), // OFF
|
2019-05-29 20:18:31 +02:00
|
|
|
MAKE_SPORK_DEF(SPORK_9_SUPERBLOCKS_ENABLED, 4070908800ULL), // OFF
|
|
|
|
MAKE_SPORK_DEF(SPORK_17_QUORUM_DKG_ENABLED, 4070908800ULL), // OFF
|
|
|
|
MAKE_SPORK_DEF(SPORK_19_CHAINLOCKS_ENABLED, 4070908800ULL), // OFF
|
2020-03-16 11:06:38 +01:00
|
|
|
MAKE_SPORK_DEF(SPORK_21_QUORUM_ALL_CONNECTED, 4070908800ULL), // OFF
|
2021-01-11 04:23:01 +01:00
|
|
|
MAKE_SPORK_DEF(SPORK_23_QUORUM_POSE, 4070908800ULL), // OFF
|
2018-04-18 13:50:26 +02:00
|
|
|
};
|
2015-02-09 21:54:51 +01:00
|
|
|
|
2019-05-29 20:18:31 +02:00
|
|
|
CSporkManager sporkManager;
|
|
|
|
|
|
|
|
CSporkManager::CSporkManager()
|
|
|
|
{
|
2021-09-28 23:23:34 +02:00
|
|
|
LOCK(cs);
|
2019-05-29 20:18:31 +02:00
|
|
|
for (auto& sporkDef : sporkDefs) {
|
|
|
|
sporkDefsById.emplace(sporkDef.sporkId, &sporkDef);
|
|
|
|
sporkDefsByName.emplace(sporkDef.name, &sporkDef);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CSporkManager::SporkValueIsActive(SporkId nSporkID, int64_t &nActiveValueRet) const
|
2018-09-30 19:01:33 +02:00
|
|
|
{
|
2021-09-28 23:23:34 +02:00
|
|
|
AssertLockHeld(cs);
|
2018-09-30 19:01:33 +02:00
|
|
|
|
|
|
|
if (!mapSporksActive.count(nSporkID)) return false;
|
|
|
|
|
2021-01-21 03:04:14 +01:00
|
|
|
auto it = mapSporksCachedValues.find(nSporkID);
|
|
|
|
if (it != mapSporksCachedValues.end()) {
|
|
|
|
nActiveValueRet = it->second;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-09-30 19:01:33 +02:00
|
|
|
// calc how many values we have and how many signers vote for every value
|
Collection of minor performance optimizations (#2855)
* Merge #13176: Improve CRollingBloomFilter performance: replace modulus with FastMod
9aac9f90d5e56752cc6cbfac48063ad29a01143c replace modulus with FastMod (Martin Ankerl)
Pull request description:
Not sure if this is optimization is necessary, but anyway I have some spare time so here it is. This replaces the slow modulo operation with a much faster 64bit multiplication & shift. This works when the hash is uniformly distributed between 0 and 2^32-1. This speeds up the benchmark by a factor of about 1.3:
```
RollingBloom, 5, 1500000, 3.73733, 4.97569e-07, 4.99002e-07, 4.98372e-07 # before
RollingBloom, 5, 1500000, 2.86842, 3.81630e-07, 3.83730e-07, 3.82473e-07 # FastMod
```
Be aware that this changes the internal data of the filter, so this should probably
not be used for CBloomFilter because of interoperability problems.
Tree-SHA512: 04104f3fb09f56c9d14458a6aad919aeb0a5af944e8ee6a31f00e93c753e22004648c1cd65bf36752b6addec528d19fb665c27b955ce1666a85a928e17afa47a
* Use unordered_map in CSporkManager
In one of my profiling sessions with many InstantSend transactions
happening, calls into CSporkManager added up to about 1% of total CPU time.
This is easily avoidable by using unordered maps.
* Use std::unordered_map instead of std::map in limitedmap
* Use unordered_set for CNode::setAskFor
* Add serialization support for unordered maps and sets
* Use unordered_map for mapArgs and mapMultiArgs
* Let limitedmap prune in batches and use unordered_multimap
Due to the batched pruning, there is no need to maintain an ordered map
of values anymore. Only when nPruneAfterSize, there is a need to create
a temporary ordered vector of values to figure out what can be removed.
* Instead of using a multimap for mapAskFor, use a vector which we sort on demand
CNode::AskFor will now push entries into an initially unordered vector
instead of an ordered multimap. Only when we later want to use vecAskFor in
SendMessages, we sort the vector.
The vector will actually be mostly sorted in most cases as insertion order
usually mimics the desired ordering. Only the last few entries might need
some shuffling around. Doing the sort on-demand should be less wasteful
then trying to maintain correct order all the time.
* Fix compilation of tests
* Fix limitedmap tests
* Rename limitedmap to unordered_limitedmap to ensure backports conflict
This ensures that future backports that depends on limitedmap's ordering
conflict so that we are made aware of needed action.
* Fix compilation error on Travis
2019-04-11 14:42:14 +02:00
|
|
|
std::unordered_map<int64_t, int> mapValueCounts;
|
2018-09-30 19:01:33 +02:00
|
|
|
for (const auto& pair: mapSporksActive.at(nSporkID)) {
|
|
|
|
mapValueCounts[pair.second.nValue]++;
|
|
|
|
if (mapValueCounts.at(pair.second.nValue) >= nMinSporkKeys) {
|
|
|
|
// nMinSporkKeys is always more than the half of the max spork keys number,
|
|
|
|
// so there is only one such value and we can stop here
|
|
|
|
nActiveValueRet = pair.second.nValue;
|
2021-01-21 03:04:14 +01:00
|
|
|
mapSporksCachedValues[nSporkID] = nActiveValueRet;
|
2018-09-30 19:01:33 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-08-13 22:21:21 +02:00
|
|
|
void CSporkManager::Clear()
|
|
|
|
{
|
|
|
|
LOCK(cs);
|
|
|
|
mapSporksActive.clear();
|
|
|
|
mapSporksByHash.clear();
|
2018-09-26 16:15:58 +02:00
|
|
|
// sporkPubKeyID and sporkPrivKey should be set in init.cpp,
|
|
|
|
// we should not alter them here.
|
2018-08-13 22:21:21 +02:00
|
|
|
}
|
|
|
|
|
2018-09-26 16:15:02 +02:00
|
|
|
void CSporkManager::CheckAndRemove()
|
|
|
|
{
|
|
|
|
LOCK(cs);
|
2018-09-30 19:01:33 +02:00
|
|
|
bool fSporkAddressIsSet = !setSporkPubKeyIDs.empty();
|
2018-09-26 16:15:02 +02:00
|
|
|
assert(fSporkAddressIsSet);
|
|
|
|
|
|
|
|
auto itActive = mapSporksActive.begin();
|
|
|
|
while (itActive != mapSporksActive.end()) {
|
2018-09-30 19:01:33 +02:00
|
|
|
auto itSignerPair = itActive->second.begin();
|
|
|
|
while (itSignerPair != itActive->second.end()) {
|
2021-01-20 23:27:41 +01:00
|
|
|
bool fHasValidSig = setSporkPubKeyIDs.find(itSignerPair->first) != setSporkPubKeyIDs.end() &&
|
|
|
|
itSignerPair->second.CheckSignature(itSignerPair->first);
|
|
|
|
if (!fHasValidSig) {
|
2020-08-30 16:22:21 +02:00
|
|
|
mapSporksByHash.erase(itSignerPair->second.GetHash());
|
|
|
|
itActive->second.erase(itSignerPair++);
|
|
|
|
continue;
|
2018-09-30 19:01:33 +02:00
|
|
|
}
|
|
|
|
++itSignerPair;
|
|
|
|
}
|
|
|
|
if (itActive->second.empty()) {
|
|
|
|
mapSporksActive.erase(itActive++);
|
|
|
|
continue;
|
2018-09-26 16:15:02 +02:00
|
|
|
}
|
|
|
|
++itActive;
|
|
|
|
}
|
2018-09-30 19:01:33 +02:00
|
|
|
|
2018-09-26 16:15:02 +02:00
|
|
|
auto itByHash = mapSporksByHash.begin();
|
|
|
|
while (itByHash != mapSporksByHash.end()) {
|
2018-09-30 19:01:33 +02:00
|
|
|
bool found = false;
|
|
|
|
for (const auto& signer: setSporkPubKeyIDs) {
|
2020-08-30 16:22:21 +02:00
|
|
|
if (itByHash->second.CheckSignature(signer)) {
|
2018-09-30 19:01:33 +02:00
|
|
|
found = true;
|
|
|
|
break;
|
2018-09-26 16:15:02 +02:00
|
|
|
}
|
|
|
|
}
|
2018-09-30 19:01:33 +02:00
|
|
|
if (!found) {
|
|
|
|
mapSporksByHash.erase(itByHash++);
|
|
|
|
continue;
|
|
|
|
}
|
2018-09-26 16:15:02 +02:00
|
|
|
++itByHash;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-06 14:31:37 +01:00
|
|
|
void CSporkManager::ProcessSpork(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman)
|
2015-02-09 21:54:51 +01:00
|
|
|
{
|
|
|
|
|
2016-08-29 21:16:02 +02:00
|
|
|
if (strCommand == NetMsgType::SPORK) {
|
|
|
|
|
2015-02-09 21:54:51 +01:00
|
|
|
CSporkMessage spork;
|
|
|
|
vRecv >> spork;
|
|
|
|
|
|
|
|
uint256 hash = spork.GetHash();
|
2016-09-15 08:50:16 +02:00
|
|
|
|
|
|
|
std::string strLogMsg;
|
|
|
|
{
|
|
|
|
LOCK(cs_main);
|
2020-04-07 13:25:29 +02:00
|
|
|
EraseObjectRequest(pfrom->GetId(), CInv(MSG_SPORK, hash));
|
2016-09-15 08:50:16 +02:00
|
|
|
if(!chainActive.Tip()) return;
|
2017-05-07 09:59:42 +02:00
|
|
|
strLogMsg = strprintf("SPORK -- hash: %s id: %d value: %10d bestHeight: %d peer=%d", hash.ToString(), spork.nSporkID, spork.nValue, chainActive.Height(), pfrom->GetId());
|
2016-09-15 08:50:16 +02:00
|
|
|
}
|
2018-09-30 19:01:33 +02:00
|
|
|
|
2018-12-22 11:33:49 +01:00
|
|
|
if (spork.nTimeSigned > GetAdjustedTime() + 2 * 60 * 60) {
|
|
|
|
LOCK(cs_main);
|
2020-01-28 11:04:47 +01:00
|
|
|
LogPrint(BCLog::SPORK, "CSporkManager::ProcessSpork -- ERROR: too far into the future\n");
|
2018-12-22 11:33:49 +01:00
|
|
|
Misbehaving(pfrom->GetId(), 100);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-09-30 19:01:33 +02:00
|
|
|
CKeyID keyIDSigner;
|
2020-08-30 16:22:21 +02:00
|
|
|
|
2021-09-28 23:23:34 +02:00
|
|
|
if (!spork.GetSignerKeyID(keyIDSigner) || WITH_LOCK(cs, return !setSporkPubKeyIDs.count(keyIDSigner))) {
|
2020-08-30 16:22:21 +02:00
|
|
|
LOCK(cs_main);
|
|
|
|
LogPrint(BCLog::SPORK, "CSporkManager::ProcessSpork -- ERROR: invalid signature\n");
|
|
|
|
Misbehaving(pfrom->GetId(), 100);
|
|
|
|
return;
|
2018-09-30 19:01:33 +02:00
|
|
|
}
|
|
|
|
|
2018-08-11 00:34:28 +02:00
|
|
|
{
|
|
|
|
LOCK(cs); // make sure to not lock this together with cs_main
|
|
|
|
if (mapSporksActive.count(spork.nSporkID)) {
|
2018-09-30 19:01:33 +02:00
|
|
|
if (mapSporksActive[spork.nSporkID].count(keyIDSigner)) {
|
|
|
|
if (mapSporksActive[spork.nSporkID][keyIDSigner].nTimeSigned >= spork.nTimeSigned) {
|
2019-05-22 23:51:39 +02:00
|
|
|
LogPrint(BCLog::SPORK, "%s seen\n", strLogMsg);
|
2018-09-30 19:01:33 +02:00
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
LogPrintf("%s updated\n", strLogMsg);
|
|
|
|
}
|
2018-08-11 00:34:28 +02:00
|
|
|
} else {
|
2018-09-30 19:01:33 +02:00
|
|
|
LogPrintf("%s new signer\n", strLogMsg);
|
2018-08-11 00:34:28 +02:00
|
|
|
}
|
2015-02-09 21:54:51 +01:00
|
|
|
} else {
|
2018-08-11 00:34:28 +02:00
|
|
|
LogPrintf("%s new\n", strLogMsg);
|
2015-02-09 21:54:51 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-11 00:34:28 +02:00
|
|
|
{
|
|
|
|
LOCK(cs); // make sure to not lock this together with cs_main
|
2018-08-13 22:21:21 +02:00
|
|
|
mapSporksByHash[hash] = spork;
|
2018-09-30 19:01:33 +02:00
|
|
|
mapSporksActive[spork.nSporkID][keyIDSigner] = spork;
|
2021-01-21 03:04:14 +01:00
|
|
|
// Clear cached values on new spork being processed
|
|
|
|
mapSporksCachedActive.erase(spork.nSporkID);
|
|
|
|
mapSporksCachedValues.erase(spork.nSporkID);
|
2018-08-11 00:34:28 +02:00
|
|
|
}
|
2017-09-07 17:58:38 +02:00
|
|
|
spork.Relay(connman);
|
2015-02-09 21:54:51 +01:00
|
|
|
|
2016-08-29 21:16:02 +02:00
|
|
|
} else if (strCommand == NetMsgType::GETSPORKS) {
|
2018-08-11 00:34:28 +02:00
|
|
|
LOCK(cs); // make sure to not lock this together with cs_main
|
2018-07-12 11:07:51 +02:00
|
|
|
for (const auto& pair : mapSporksActive) {
|
2018-09-30 19:01:33 +02:00
|
|
|
for (const auto& signerSporkPair: pair.second) {
|
|
|
|
connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::SPORK, signerSporkPair.second));
|
|
|
|
}
|
2015-02-09 21:54:51 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-05-29 20:18:31 +02:00
|
|
|
bool CSporkManager::UpdateSpork(SporkId nSporkID, int64_t nValue, CConnman& connman)
|
2016-07-30 13:04:27 +02:00
|
|
|
{
|
2017-08-29 01:51:44 +02:00
|
|
|
CSporkMessage spork = CSporkMessage(nSporkID, nValue, GetAdjustedTime());
|
2016-07-30 13:04:27 +02:00
|
|
|
|
2021-09-28 23:23:34 +02:00
|
|
|
{
|
|
|
|
LOCK(cs);
|
2016-07-30 13:04:27 +02:00
|
|
|
|
2021-09-28 23:23:34 +02:00
|
|
|
if (!spork.Sign(sporkPrivKey)) {
|
|
|
|
LogPrintf("CSporkManager::%s -- ERROR: signing failed for spork %d\n", __func__, nSporkID);
|
|
|
|
return false;
|
|
|
|
}
|
2019-08-28 13:51:59 +02:00
|
|
|
|
2021-09-28 23:23:34 +02:00
|
|
|
CKeyID keyIDSigner;
|
|
|
|
if (!spork.GetSignerKeyID(keyIDSigner) || !setSporkPubKeyIDs.count(keyIDSigner)) {
|
|
|
|
LogPrintf("CSporkManager::UpdateSpork: failed to find keyid for private key\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
LogPrintf("CSporkManager::%s -- signed %d %s\n", __func__, nSporkID, spork.GetHash().ToString());
|
2019-08-28 13:51:59 +02:00
|
|
|
|
2020-11-28 20:06:51 +01:00
|
|
|
mapSporksByHash[spork.GetHash()] = spork;
|
|
|
|
mapSporksActive[nSporkID][keyIDSigner] = spork;
|
2021-01-21 03:04:14 +01:00
|
|
|
// Clear cached values on new spork being processed
|
|
|
|
mapSporksCachedActive.erase(spork.nSporkID);
|
|
|
|
mapSporksCachedValues.erase(spork.nSporkID);
|
2020-11-28 20:06:51 +01:00
|
|
|
}
|
2019-08-28 13:51:59 +02:00
|
|
|
|
|
|
|
spork.Relay(connman);
|
|
|
|
return true;
|
2016-07-30 13:04:27 +02:00
|
|
|
}
|
|
|
|
|
2021-01-22 06:57:42 +01:00
|
|
|
bool CSporkManager::IsSporkActive(SporkId nSporkID) const
|
2015-02-09 21:54:51 +01:00
|
|
|
{
|
2021-01-21 03:04:14 +01:00
|
|
|
LOCK(cs);
|
|
|
|
// If nSporkID is cached, and the cached value is true, then return early true
|
|
|
|
auto it = mapSporksCachedActive.find(nSporkID);
|
|
|
|
if (it != mapSporksCachedActive.end() && it->second) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-05-29 20:18:31 +02:00
|
|
|
int64_t nSporkValue = GetSporkValue(nSporkID);
|
2021-01-21 03:04:14 +01:00
|
|
|
// Get time is somewhat costly it looks like
|
|
|
|
bool ret = nSporkValue < GetAdjustedTime();
|
|
|
|
// Only cache true values
|
|
|
|
if (ret) {
|
|
|
|
mapSporksCachedActive[nSporkID] = ret;
|
|
|
|
}
|
|
|
|
return ret;
|
2015-02-09 21:54:51 +01:00
|
|
|
}
|
|
|
|
|
2021-01-22 06:57:42 +01:00
|
|
|
int64_t CSporkManager::GetSporkValue(SporkId nSporkID) const
|
2015-02-11 15:47:21 +01:00
|
|
|
{
|
2018-08-11 00:34:28 +02:00
|
|
|
LOCK(cs);
|
2018-09-30 19:01:33 +02:00
|
|
|
|
|
|
|
int64_t nSporkValue = -1;
|
|
|
|
if (SporkValueIsActive(nSporkID, nSporkValue)) {
|
|
|
|
return nSporkValue;
|
|
|
|
}
|
2016-08-29 21:16:02 +02:00
|
|
|
|
2019-05-29 20:18:31 +02:00
|
|
|
auto it = sporkDefsById.find(nSporkID);
|
|
|
|
if (it != sporkDefsById.end()) {
|
|
|
|
return it->second->defaultValue;
|
2015-02-11 15:47:21 +01:00
|
|
|
}
|
|
|
|
|
2019-05-22 23:51:39 +02:00
|
|
|
LogPrint(BCLog::SPORK, "CSporkManager::GetSporkValue -- Unknown Spork ID %d\n", nSporkID);
|
2018-04-18 13:50:26 +02:00
|
|
|
return -1;
|
2015-02-11 15:47:21 +01:00
|
|
|
}
|
|
|
|
|
2021-01-22 06:57:42 +01:00
|
|
|
SporkId CSporkManager::GetSporkIDByName(const std::string& strName) const
|
2015-02-12 05:05:09 +01:00
|
|
|
{
|
2021-09-28 23:23:34 +02:00
|
|
|
LOCK(cs);
|
2019-05-29 20:18:31 +02:00
|
|
|
auto it = sporkDefsByName.find(strName);
|
|
|
|
if (it == sporkDefsByName.end()) {
|
|
|
|
LogPrint(BCLog::SPORK, "CSporkManager::GetSporkIDByName -- Unknown Spork name '%s'\n", strName);
|
|
|
|
return SPORK_INVALID;
|
|
|
|
}
|
|
|
|
return it->second->sporkId;
|
2015-08-03 01:08:37 +02:00
|
|
|
}
|
2015-08-02 23:59:28 +02:00
|
|
|
|
2021-01-22 06:57:42 +01:00
|
|
|
std::string CSporkManager::GetSporkNameByID(SporkId nSporkID) const
|
2016-07-30 13:04:27 +02:00
|
|
|
{
|
2021-09-28 23:23:34 +02:00
|
|
|
LOCK(cs);
|
2019-05-29 20:18:31 +02:00
|
|
|
auto it = sporkDefsById.find(nSporkID);
|
|
|
|
if (it == sporkDefsById.end()) {
|
|
|
|
LogPrint(BCLog::SPORK, "CSporkManager::GetSporkNameByID -- Unknown Spork ID %d\n", nSporkID);
|
|
|
|
return "Unknown";
|
2016-08-29 21:16:02 +02:00
|
|
|
}
|
2019-05-29 20:18:31 +02:00
|
|
|
return it->second->name;
|
2015-02-12 05:05:09 +01:00
|
|
|
}
|
|
|
|
|
2021-01-22 06:57:42 +01:00
|
|
|
bool CSporkManager::GetSporkByHash(const uint256& hash, CSporkMessage &sporkRet) const
|
2018-08-13 22:21:21 +02:00
|
|
|
{
|
|
|
|
LOCK(cs);
|
|
|
|
|
|
|
|
const auto it = mapSporksByHash.find(hash);
|
|
|
|
|
|
|
|
if (it == mapSporksByHash.end())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
sporkRet = it->second;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-03-02 14:15:04 +01:00
|
|
|
bool CSporkManager::SetSporkAddress(const std::string& strAddress) {
|
2018-08-11 00:34:28 +02:00
|
|
|
LOCK(cs);
|
Merge #11117: Prepare for non-Base58 addresses (#3294)
* Merge #11117: Prepare for non-Base58 addresses
864cd2787 Move CBitcoinAddress to base58.cpp (Pieter Wuille)
5c8ff0d44 Introduce wrappers around CBitcoinAddress (Pieter Wuille)
Pull request description:
This patch removes the need for the intermediary Base58 type `CBitcoinAddress`, by providing {`Encode`,`Decode`,`IsValid`}`Destination` functions that directly operate on the conversion between `std::string`s and `CTxDestination`.
As a side, it also fixes a number of indentation issues, and removes probably several unnecessary implicit `CTxDestination`<->`CBitcoinAddress` conversions.
This change is far from complete. In follow-ups I'd like to:
* Split off the specific address and key encoding logic from base58.h, and move it to a address.h or so.
* Replace `CTxDestination` with a non-`boost::variant` version (which can be more efficient as `boost::variant` allocates everything on the heap, and remove the need for `boost::get<...>` and `IsValidDestination` calls everywhere).
* Do the same for `CBitcoinSecret`, `CBitcoinExtKey`, and `CBitcoinExtPubKey`.
However, I've tried to keep this patch to be minimally invasive, but still enough to support non-Base58 addresses. Perhaps a smaller patch is possible to hack Bech32 support into `CBitcoinAddress`, but I would consider that a move in the wrong direction.
Tree-SHA512: c2c77ffb57caeadf2429b1c2562ce60e8c7be8aa9f8e51b591f354b6b441162625b2efe14c023a1ae485cf2ed417263afa35c892891dfaa7844e7fbabccab85e
* CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* fix CBitcoinAddress GetKeyID check
Signed-off-by: Pasta <pasta@dashboost.org>
* fix providertx.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* hopefully fix governance-classes.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* partially fix governance-validators.cpp, unable to resolve "address.IsScript()"
Signed-off-by: Pasta <pasta@dashboost.org>
* partially fix governance-classes.cpp, unable to resolve "address.IsScript()"
Signed-off-by: Pasta <pasta@dashboost.org>
* fix governance-classes.h
Signed-off-by: Pasta <pasta@dashboost.org>
* DecodeTransaction -> DecodeDestination, fix governance-validators.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* More fixes for 3294
* Move GetIndexKey into rpc/misc.cpp near getAddressesFromParams
No need to have it in base58.cpp anymore as this is only used in getAddressesFromParams
Co-authored-by: Wladimir J. van der Laan <laanwj@gmail.com>
Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
Co-authored-by: Alexander Block <ablock84@gmail.com>
2020-01-22 11:35:04 +01:00
|
|
|
CTxDestination dest = DecodeDestination(strAddress);
|
|
|
|
const CKeyID *keyID = boost::get<CKeyID>(&dest);
|
|
|
|
if (!keyID) {
|
2018-03-02 14:15:04 +01:00
|
|
|
LogPrintf("CSporkManager::SetSporkAddress -- Failed to parse spork address\n");
|
|
|
|
return false;
|
|
|
|
}
|
Merge #11117: Prepare for non-Base58 addresses (#3294)
* Merge #11117: Prepare for non-Base58 addresses
864cd2787 Move CBitcoinAddress to base58.cpp (Pieter Wuille)
5c8ff0d44 Introduce wrappers around CBitcoinAddress (Pieter Wuille)
Pull request description:
This patch removes the need for the intermediary Base58 type `CBitcoinAddress`, by providing {`Encode`,`Decode`,`IsValid`}`Destination` functions that directly operate on the conversion between `std::string`s and `CTxDestination`.
As a side, it also fixes a number of indentation issues, and removes probably several unnecessary implicit `CTxDestination`<->`CBitcoinAddress` conversions.
This change is far from complete. In follow-ups I'd like to:
* Split off the specific address and key encoding logic from base58.h, and move it to a address.h or so.
* Replace `CTxDestination` with a non-`boost::variant` version (which can be more efficient as `boost::variant` allocates everything on the heap, and remove the need for `boost::get<...>` and `IsValidDestination` calls everywhere).
* Do the same for `CBitcoinSecret`, `CBitcoinExtKey`, and `CBitcoinExtPubKey`.
However, I've tried to keep this patch to be minimally invasive, but still enough to support non-Base58 addresses. Perhaps a smaller patch is possible to hack Bech32 support into `CBitcoinAddress`, but I would consider that a move in the wrong direction.
Tree-SHA512: c2c77ffb57caeadf2429b1c2562ce60e8c7be8aa9f8e51b591f354b6b441162625b2efe14c023a1ae485cf2ed417263afa35c892891dfaa7844e7fbabccab85e
* CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* fix CBitcoinAddress GetKeyID check
Signed-off-by: Pasta <pasta@dashboost.org>
* fix providertx.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* hopefully fix governance-classes.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* partially fix governance-validators.cpp, unable to resolve "address.IsScript()"
Signed-off-by: Pasta <pasta@dashboost.org>
* partially fix governance-classes.cpp, unable to resolve "address.IsScript()"
Signed-off-by: Pasta <pasta@dashboost.org>
* fix governance-classes.h
Signed-off-by: Pasta <pasta@dashboost.org>
* DecodeTransaction -> DecodeDestination, fix governance-validators.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* More fixes for 3294
* Move GetIndexKey into rpc/misc.cpp near getAddressesFromParams
No need to have it in base58.cpp anymore as this is only used in getAddressesFromParams
Co-authored-by: Wladimir J. van der Laan <laanwj@gmail.com>
Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
Co-authored-by: Alexander Block <ablock84@gmail.com>
2020-01-22 11:35:04 +01:00
|
|
|
setSporkPubKeyIDs.insert(*keyID);
|
2018-09-30 19:01:33 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CSporkManager::SetMinSporkKeys(int minSporkKeys)
|
|
|
|
{
|
2021-09-28 23:23:34 +02:00
|
|
|
LOCK(cs);
|
2018-09-30 19:01:33 +02:00
|
|
|
int maxKeysNumber = setSporkPubKeyIDs.size();
|
|
|
|
if ((minSporkKeys <= maxKeysNumber / 2) || (minSporkKeys > maxKeysNumber)) {
|
|
|
|
LogPrintf("CSporkManager::SetMinSporkKeys -- Invalid min spork signers number: %d\n", minSporkKeys);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
nMinSporkKeys = minSporkKeys;
|
2018-03-02 14:15:04 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-02-12 13:49:00 +01:00
|
|
|
bool CSporkManager::SetPrivKey(const std::string& strPrivKey)
|
2015-02-09 21:54:51 +01:00
|
|
|
{
|
2018-03-02 14:15:04 +01:00
|
|
|
CKey key;
|
|
|
|
CPubKey pubKey;
|
|
|
|
if(!CMessageSigner::GetKeysFromSecret(strPrivKey, key, pubKey)) {
|
|
|
|
LogPrintf("CSporkManager::SetPrivKey -- Failed to parse private key\n");
|
|
|
|
return false;
|
|
|
|
}
|
2015-02-09 21:54:51 +01:00
|
|
|
|
2021-09-28 23:23:34 +02:00
|
|
|
LOCK(cs);
|
2018-09-30 19:01:33 +02:00
|
|
|
if (setSporkPubKeyIDs.find(pubKey.GetID()) == setSporkPubKeyIDs.end()) {
|
|
|
|
LogPrintf("CSporkManager::SetPrivKey -- New private key does not belong to spork addresses\n");
|
2018-03-02 14:15:04 +01:00
|
|
|
return false;
|
|
|
|
}
|
2016-07-30 13:04:27 +02:00
|
|
|
|
2018-03-02 14:15:04 +01:00
|
|
|
CSporkMessage spork;
|
2020-08-30 16:22:21 +02:00
|
|
|
if (!spork.Sign(key)) {
|
2018-03-02 14:15:04 +01:00
|
|
|
LogPrintf("CSporkManager::SetPrivKey -- Test signing failed\n");
|
2015-02-09 21:54:51 +01:00
|
|
|
return false;
|
|
|
|
}
|
2019-08-28 13:51:59 +02:00
|
|
|
|
|
|
|
// Test signing successful, proceed
|
|
|
|
LogPrintf("CSporkManager::SetPrivKey -- Successfully initialized as spork signer\n");
|
|
|
|
sporkPrivKey = key;
|
|
|
|
return true;
|
2015-02-09 21:54:51 +01:00
|
|
|
}
|
|
|
|
|
2018-08-13 22:21:21 +02:00
|
|
|
std::string CSporkManager::ToString() const
|
|
|
|
{
|
|
|
|
LOCK(cs);
|
|
|
|
return strprintf("Sporks: %llu", mapSporksActive.size());
|
|
|
|
}
|
|
|
|
|
2018-02-16 15:54:53 +01:00
|
|
|
uint256 CSporkMessage::GetHash() const
|
|
|
|
{
|
|
|
|
return SerializeHash(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint256 CSporkMessage::GetSignatureHash() const
|
|
|
|
{
|
2018-09-30 19:01:33 +02:00
|
|
|
CHashWriter s(SER_GETHASH, 0);
|
|
|
|
s << nSporkID;
|
|
|
|
s << nValue;
|
|
|
|
s << nTimeSigned;
|
|
|
|
return s.GetHash();
|
2018-02-16 15:54:53 +01:00
|
|
|
}
|
|
|
|
|
2020-08-30 16:22:21 +02:00
|
|
|
bool CSporkMessage::Sign(const CKey& key)
|
2015-02-09 21:54:51 +01:00
|
|
|
{
|
2018-06-19 01:40:55 +02:00
|
|
|
if (!key.IsValid()) {
|
|
|
|
LogPrintf("CSporkMessage::Sign -- signing key is not valid\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-03-02 14:15:04 +01:00
|
|
|
CKeyID pubKeyId = key.GetPubKey().GetID();
|
2016-08-19 13:50:04 +02:00
|
|
|
std::string strError = "";
|
2015-02-09 21:54:51 +01:00
|
|
|
|
2020-08-30 16:22:21 +02:00
|
|
|
// Harden Spork6 so that it is active on testnet and no other networks
|
|
|
|
if (Params().NetworkIDString() == CBaseChainParams::TESTNET) {
|
2018-02-16 15:54:53 +01:00
|
|
|
uint256 hash = GetSignatureHash();
|
2015-02-09 21:54:51 +01:00
|
|
|
|
2018-02-16 15:54:53 +01:00
|
|
|
if(!CHashSigner::SignHash(hash, key, vchSig)) {
|
|
|
|
LogPrintf("CSporkMessage::Sign -- SignHash() failed\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-03-02 14:15:04 +01:00
|
|
|
if (!CHashSigner::VerifyHash(hash, pubKeyId, vchSig, strError)) {
|
2018-02-16 15:54:53 +01:00
|
|
|
LogPrintf("CSporkMessage::Sign -- VerifyHash() failed, error: %s\n", strError);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
2018-07-12 11:02:20 +02:00
|
|
|
std::string strMessage = std::to_string(nSporkID) + std::to_string(nValue) + std::to_string(nTimeSigned);
|
2018-02-16 15:54:53 +01:00
|
|
|
|
|
|
|
if(!CMessageSigner::SignMessage(strMessage, vchSig, key)) {
|
|
|
|
LogPrintf("CSporkMessage::Sign -- SignMessage() failed\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-03-02 14:15:04 +01:00
|
|
|
if(!CMessageSigner::VerifyMessage(pubKeyId, vchSig, strMessage, strError)) {
|
2018-02-16 15:54:53 +01:00
|
|
|
LogPrintf("CSporkMessage::Sign -- VerifyMessage() failed, error: %s\n", strError);
|
|
|
|
return false;
|
|
|
|
}
|
2015-02-09 21:54:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-08-30 16:22:21 +02:00
|
|
|
bool CSporkMessage::CheckSignature(const CKeyID& pubKeyId) const
|
2015-02-09 21:54:51 +01:00
|
|
|
{
|
2016-08-19 13:50:04 +02:00
|
|
|
std::string strError = "";
|
2015-02-09 21:54:51 +01:00
|
|
|
|
2020-08-30 16:22:21 +02:00
|
|
|
// Harden Spork6 so that it is active on testnet and no other networks
|
|
|
|
if (Params().NetworkIDString() == CBaseChainParams::TESTNET) {
|
2018-02-16 15:54:53 +01:00
|
|
|
uint256 hash = GetSignatureHash();
|
|
|
|
|
2018-03-02 14:15:04 +01:00
|
|
|
if (!CHashSigner::VerifyHash(hash, pubKeyId, vchSig, strError)) {
|
2020-01-28 11:04:47 +01:00
|
|
|
LogPrint(BCLog::SPORK, "CSporkMessage::CheckSignature -- VerifyHash() failed, error: %s\n", strError);
|
2018-02-16 15:54:53 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
2018-07-12 11:02:20 +02:00
|
|
|
std::string strMessage = std::to_string(nSporkID) + std::to_string(nValue) + std::to_string(nTimeSigned);
|
2018-02-16 15:54:53 +01:00
|
|
|
|
2018-03-02 14:15:04 +01:00
|
|
|
if (!CMessageSigner::VerifyMessage(pubKeyId, vchSig, strMessage, strError)){
|
2020-08-30 16:22:21 +02:00
|
|
|
LogPrint(BCLog::SPORK, "CSporkMessage::CheckSignature -- VerifyMessage() failed, error: %s\n", strError);
|
|
|
|
return false;
|
2018-02-16 15:54:53 +01:00
|
|
|
}
|
2015-02-09 21:54:51 +01:00
|
|
|
}
|
|
|
|
|
2016-07-30 13:04:27 +02:00
|
|
|
return true;
|
2015-02-09 21:54:51 +01:00
|
|
|
}
|
|
|
|
|
2021-01-22 06:57:42 +01:00
|
|
|
bool CSporkMessage::GetSignerKeyID(CKeyID &retKeyidSporkSigner) const
|
2018-09-30 19:01:33 +02:00
|
|
|
{
|
|
|
|
CPubKey pubkeyFromSig;
|
2020-08-30 16:22:21 +02:00
|
|
|
// Harden Spork6 so that it is active on testnet and no other networks
|
|
|
|
if (Params().NetworkIDString() == CBaseChainParams::TESTNET) {
|
2018-09-30 19:01:33 +02:00
|
|
|
if (!pubkeyFromSig.RecoverCompact(GetSignatureHash(), vchSig)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
std::string strMessage = std::to_string(nSporkID) + std::to_string(nValue) + std::to_string(nTimeSigned);
|
|
|
|
CHashWriter ss(SER_GETHASH, 0);
|
|
|
|
ss << strMessageMagic;
|
|
|
|
ss << strMessage;
|
|
|
|
if (!pubkeyFromSig.RecoverCompact(ss.GetHash(), vchSig)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
retKeyidSporkSigner = pubkeyFromSig.GetID();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-01-22 06:57:42 +01:00
|
|
|
void CSporkMessage::Relay(CConnman& connman) const
|
2015-02-09 21:54:51 +01:00
|
|
|
{
|
2016-07-30 13:04:27 +02:00
|
|
|
CInv inv(MSG_SPORK, GetHash());
|
2017-09-07 17:58:38 +02:00
|
|
|
connman.RelayInv(inv);
|
2015-04-03 00:51:08 +02:00
|
|
|
}
|