Reorganized cheatcatcher for build issues
This commit is contained in:
@@ -310,6 +310,8 @@ libbitcoin_server_a_SOURCES = \
|
||||
cc/auction.cpp \
|
||||
cc/betprotocol.cpp \
|
||||
chain.cpp \
|
||||
cheatcatcher.h \
|
||||
cheatcatcher.cpp \
|
||||
checkpoints.cpp \
|
||||
crosschain.cpp \
|
||||
crypto/haraka.h \
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CC_STAKEGUARD_H
|
||||
#define CC_STAKEGUARD_H
|
||||
#ifndef STAKEGUARD_H
|
||||
#define STAKEGUARD_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@ extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
|
||||
extern uint32_t ASSETCHAIN_INIT, ASSETCHAINS_MAGIC;
|
||||
extern int32_t VERUS_BLOCK_POSUNITS, ASSETCHAINS_LWMAPOS, ASSETCHAINS_SAPLING, ASSETCHAINS_OVERWINTER;
|
||||
extern uint64_t ASSETCHAINS_SUPPLY, ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_VERUSHASH;
|
||||
extern std::string VERUS_CHEATCATCHER;
|
||||
|
||||
const arith_uint256 maxUint = UintToArith256(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
|
||||
|
||||
@@ -266,6 +267,21 @@ void *chainparams_commandline(void *ptr)
|
||||
mainParams.consensus.nLwmaPOSAjustedWeight = 46531;
|
||||
}
|
||||
|
||||
if (VERUS_CHEATCATCHER.size() == 77)
|
||||
{
|
||||
// if we are supposed to catch stake cheaters, there must be a valid sapling parameter, store the Sapling address here
|
||||
extern boost::optional<libzcash::SaplingPaymentAddress> cheatCatcher;
|
||||
libzcash::PaymentAddress addr = DecodePaymentAddress(mapArgs["-cheatcatcher"]);
|
||||
if (IsValidPaymentAddress(addr))
|
||||
{
|
||||
cheatCatcher = boost::get<libzcash::SaplingPaymentAddress>(addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "-cheatcatcher parameter is invalid Sapling payment address");
|
||||
}
|
||||
}
|
||||
|
||||
// only require coinbase protection on Verus from the Komodo family of coins
|
||||
if (strcmp(ASSETCHAINS_SYMBOL,"VRSC") == 0)
|
||||
{
|
||||
|
||||
133
src/cheatcatcher.cpp
Normal file
133
src/cheatcatcher.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/********************************************************************
|
||||
* (C) 2018 Michael Toutonghi
|
||||
*
|
||||
* Distributed under the MIT software license, see the accompanying
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
*
|
||||
* This crypto-condition eval solves the problem of nothing-at-stake
|
||||
* in a proof of stake consensus system.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cc/StakeGuard.h"
|
||||
#include "script/script.h"
|
||||
#include "main.h"
|
||||
#include "hash.h"
|
||||
#include "cheatcatcher.h"
|
||||
#include "streams.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
CCheatList cheatList;
|
||||
boost::optional<libzcash::SaplingPaymentAddress> cheatCatcher;
|
||||
|
||||
uint32_t CCheatList::Prune(uint32_t height)
|
||||
{
|
||||
uint32_t count;
|
||||
pair<multimap<const uint32_t, CTxHolder>::iterator, multimap<const uint32_t, CTxHolder>::iterator> range;
|
||||
vector<CTxHolder *> toPrune;
|
||||
|
||||
if (NetworkUpgradeActive(height, Params().GetConsensus(), Consensus::UPGRADE_SAPLING))
|
||||
{
|
||||
LOCK(cs_cheat);
|
||||
for (auto it = orderedCheatCandidates.begin(); it != orderedCheatCandidates.end() && it->second.height <= height; it--)
|
||||
{
|
||||
toPrune.push_back(&it->second);
|
||||
}
|
||||
count = toPrune.size();
|
||||
for (auto ptxHolder : toPrune)
|
||||
{
|
||||
Remove(*ptxHolder);
|
||||
}
|
||||
}
|
||||
return count; // return how many removed
|
||||
}
|
||||
|
||||
bool GetStakeParams(const CTransaction &stakeTx, CStakeParams &stakeParams);
|
||||
|
||||
bool CCheatList::IsCheatInList(const CTransaction &tx, CTransaction *cheatTx)
|
||||
{
|
||||
// for a tx to be cheat, it needs to spend the same UTXO and be for a different prior block
|
||||
// the list should be pruned before this call
|
||||
// we return the first valid cheat we find
|
||||
CVerusHashWriter hw = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
|
||||
|
||||
hw << tx.vin[0].prevout.hash;
|
||||
hw << tx.vin[0].prevout.n;
|
||||
uint256 utxo = hw.GetHash();
|
||||
|
||||
pair<multimap<const uint256, CTxHolder *>::iterator, multimap<const uint256, CTxHolder *>::iterator> range;
|
||||
CStakeParams p, s;
|
||||
|
||||
if (GetStakeParams(tx, p))
|
||||
{
|
||||
LOCK(cs_cheat);
|
||||
range = indexedCheatCandidates.equal_range(utxo);
|
||||
for (auto it = range.first; it != range.second; it++)
|
||||
{
|
||||
// we assume height is valid, as we should have pruned the list before checking. since the tx came out of a valid block,
|
||||
// what matters is if the prior hash matches
|
||||
CTransaction &cTx = it->second->tx;
|
||||
|
||||
// need both parameters to check
|
||||
if (GetStakeParams(cTx, s))
|
||||
{
|
||||
if (p.prevHash != s.prevHash)
|
||||
{
|
||||
cheatTx = &cTx;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCheatList::Add(CTxHolder &txh)
|
||||
{
|
||||
CVerusHashWriter hw = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
|
||||
if (NetworkUpgradeActive(txh.height, Params().GetConsensus(), Consensus::UPGRADE_SAPLING))
|
||||
{
|
||||
LOCK(cs_cheat);
|
||||
auto it = orderedCheatCandidates.insert(pair<const uint32_t, CTxHolder>(txh.height, txh));
|
||||
indexedCheatCandidates.insert(pair<const uint256, CTxHolder *>(txh.utxo, &it->second));
|
||||
}
|
||||
}
|
||||
|
||||
void CCheatList::Remove(const CTxHolder &txh)
|
||||
{
|
||||
// first narrow by source tx, then compare with tx hash
|
||||
uint32_t count;
|
||||
pair<multimap<const uint256, CTxHolder *>::iterator, multimap<const uint256, CTxHolder *>::iterator> range;
|
||||
vector<multimap<const uint256, CTxHolder *>::iterator> utxoPrune;
|
||||
vector<multimap<const int32_t, CTxHolder>::iterator> heightPrune;
|
||||
|
||||
{
|
||||
LOCK(cs_cheat);
|
||||
range = indexedCheatCandidates.equal_range(txh.utxo);
|
||||
for (auto it = range.first; it != range.second; it++)
|
||||
{
|
||||
uint256 hash = txh.tx.GetHash();
|
||||
if (hash == it->second->tx.GetHash())
|
||||
{
|
||||
utxoPrune.push_back(it);
|
||||
auto hrange = orderedCheatCandidates.equal_range(it->second->height);
|
||||
for (auto hit = hrange.first; hit != hrange.second; hit++)
|
||||
{
|
||||
if (hit->second.tx.GetHash() == hash)
|
||||
{
|
||||
heightPrune.push_back(hit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto it : utxoPrune)
|
||||
{
|
||||
indexedCheatCandidates.erase(it);
|
||||
}
|
||||
for (auto it : heightPrune)
|
||||
{
|
||||
orderedCheatCandidates.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
74
src/cheatcatcher.h
Normal file
74
src/cheatcatcher.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/********************************************************************
|
||||
* (C) 2018 Michael Toutonghi
|
||||
*
|
||||
* Distributed under the MIT software license, see the accompanying
|
||||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
*
|
||||
* This crypto-condition eval solves the problem of nothing-at-stake
|
||||
* in a proof of stake consensus system.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CHEATCATCHER_H
|
||||
#define CHEATCATCHER_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "streams.h"
|
||||
#include "script/script.h"
|
||||
#include "uint256.h"
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
class CTxHolder
|
||||
{
|
||||
public:
|
||||
uint256 utxo;
|
||||
uint32_t height;
|
||||
CTransaction tx;
|
||||
CTxHolder(const CTransaction &_tx, uint32_t _height) : height(_height), tx(_tx) {
|
||||
CVerusHashWriter hw = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
|
||||
|
||||
hw << tx.vin[0].prevout.hash;
|
||||
hw << tx.vin[0].prevout.n;
|
||||
utxo = hw.GetHash();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CCheatList
|
||||
{
|
||||
private:
|
||||
std::multimap<const int32_t, CTxHolder> orderedCheatCandidates;
|
||||
std::multimap<const uint256, CTxHolder *> indexedCheatCandidates;
|
||||
CCriticalSection cs_cheat;
|
||||
|
||||
public:
|
||||
CCheatList() {}
|
||||
|
||||
// prune all transactions in the list below height
|
||||
uint32_t Prune(uint32_t height);
|
||||
|
||||
// check to see if a transaction that could be a cheat for the passed transaction is in our list
|
||||
bool IsCheatInList(const CTransaction &tx, CTransaction *pcheatTx);
|
||||
|
||||
// check to see if there are cheat candidates of the same or greater block height in list
|
||||
bool IsHeightOrGreaterInList(uint32_t height)
|
||||
{
|
||||
auto range = orderedCheatCandidates.equal_range(height);
|
||||
return (range.first == orderedCheatCandidates.end());
|
||||
}
|
||||
|
||||
// add a potential cheat transaction to the list. we do this for all stake transactions from orphaned stakes
|
||||
bool Add(CTxHolder &txh);
|
||||
|
||||
// remove a transaction from the the list
|
||||
void Remove(const CTxHolder &txh);
|
||||
};
|
||||
|
||||
|
||||
extern CCheatList cheatList;
|
||||
extern boost::optional<libzcash::SaplingPaymentAddress> cheatCatcher;
|
||||
|
||||
#endif
|
||||
@@ -40,6 +40,7 @@ uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256
|
||||
static bool fCreateBlank;
|
||||
static std::map<std::string,UniValue> registers;
|
||||
static const int CONTINUE_EXECUTION=-1;
|
||||
boost::optional<libzcash::SaplingPaymentAddress> cheatCatcher;
|
||||
|
||||
//
|
||||
// This function returns either one of EXIT_ codes when it's expected to stop the process or
|
||||
|
||||
@@ -49,6 +49,7 @@ int32_t KOMODO_INSYNC,KOMODO_LASTMINED,prevKOMODO_LASTMINED,KOMODO_CCACTIVATE,JU
|
||||
std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY;
|
||||
uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE;
|
||||
bool VERUS_MINTBLOCKS;
|
||||
std::string VERUS_CHEATCATCHER;
|
||||
|
||||
char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096];
|
||||
uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
|
||||
|
||||
@@ -1661,21 +1661,7 @@ void komodo_args(char *argv0)
|
||||
else KOMODO_MININGTHREADS = 0;
|
||||
|
||||
VERUS_MINTBLOCKS = GetBoolArg("-mint", false);
|
||||
|
||||
// if we are supposed to catch stake cheaters, there must be a valid sapling parameter, store the Sapling address here
|
||||
extern boost::optional<libzcash::SaplingPaymentAddress> cheatCatcher;
|
||||
if (mapArgs["-cheatcatcher"].size() == 77)
|
||||
{
|
||||
libzcash::PaymentAddress addr = DecodePaymentAddress(mapArgs["-cheatcatcher"]);
|
||||
if (IsValidPaymentAddress(addr))
|
||||
{
|
||||
cheatCatcher = boost::get<libzcash::SaplingPaymentAddress>(addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "-cheatcatcher parameter is invalid Sapling payment address");
|
||||
}
|
||||
}
|
||||
VERUS_CHEATCATCHER = mapArgs["-cheatcatcher"].size();
|
||||
|
||||
if ( (KOMODO_EXCHANGEWALLET= GetBoolArg("-exchange", false)) != 0 )
|
||||
fprintf(stderr,"KOMODO_EXCHANGEWALLET mode active\n");
|
||||
|
||||
114
src/main.cpp
114
src/main.cpp
@@ -122,120 +122,6 @@ CScript COINBASE_FLAGS;
|
||||
|
||||
const string strMessageMagic = "Komodo Signed Message:\n";
|
||||
|
||||
CCheatList cheatList;
|
||||
boost::optional<libzcash::SaplingPaymentAddress> cheatCatcher;
|
||||
|
||||
uint32_t CCheatList::Prune(uint32_t height)
|
||||
{
|
||||
uint32_t count;
|
||||
pair<std::multimap<const uint32_t, CTxHolder>::iterator, std::multimap<const uint32_t, CTxHolder>::iterator> range;
|
||||
std::vector<CTxHolder *> toPrune;
|
||||
|
||||
if (NetworkUpgradeActive(height, Params().GetConsensus(), Consensus::UPGRADE_SAPLING))
|
||||
{
|
||||
LOCK(cs_cheat);
|
||||
for (auto it = orderedCheatCandidates.begin(); it != orderedCheatCandidates.end() && it->second.height <= height; it--)
|
||||
{
|
||||
toPrune.push_back(&it->second);
|
||||
}
|
||||
count = toPrune.size();
|
||||
for (auto ptxHolder : toPrune)
|
||||
{
|
||||
Remove(*ptxHolder);
|
||||
}
|
||||
}
|
||||
return count; // return how many removed
|
||||
}
|
||||
|
||||
bool GetStakeParams(const CTransaction &stakeTx, CStakeParams &stakeParams);
|
||||
|
||||
bool CCheatList::IsCheatInList(const CTransaction &tx, CTransaction *cheatTx)
|
||||
{
|
||||
// for a tx to be cheat, it needs to spend the same UTXO and be for a different prior block
|
||||
// the list should be pruned before this call
|
||||
// we return the first valid cheat we find
|
||||
CVerusHashWriter hw = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
|
||||
|
||||
hw << tx.vin[0].prevout.hash;
|
||||
hw << tx.vin[0].prevout.n;
|
||||
uint256 utxo = hw.GetHash();
|
||||
|
||||
pair<std::multimap<const uint256, CTxHolder *>::iterator, std::multimap<const uint256, CTxHolder *>::iterator> range;
|
||||
CStakeParams p, s;
|
||||
|
||||
if (GetStakeParams(tx, p))
|
||||
{
|
||||
LOCK(cs_cheat);
|
||||
range = indexedCheatCandidates.equal_range(utxo);
|
||||
for (auto it = range.first; it != range.second; it++)
|
||||
{
|
||||
// we assume height is valid, as we should have pruned the list before checking. since the tx came out of a valid block,
|
||||
// what matters is if the prior hash matches
|
||||
CTransaction &cTx = it->second->tx;
|
||||
|
||||
// need both parameters to check
|
||||
if (GetStakeParams(cTx, s))
|
||||
{
|
||||
if (p.prevHash != s.prevHash)
|
||||
{
|
||||
cheatTx = &cTx;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCheatList::Add(CTxHolder &txh)
|
||||
{
|
||||
CVerusHashWriter hw = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
|
||||
if (NetworkUpgradeActive(txh.height, Params().GetConsensus(), Consensus::UPGRADE_SAPLING))
|
||||
{
|
||||
LOCK(cs_cheat);
|
||||
auto it = orderedCheatCandidates.insert(pair<const uint32_t, CTxHolder>(txh.height, txh));
|
||||
indexedCheatCandidates.insert(pair<const uint256, CTxHolder *>(txh.utxo, &it->second));
|
||||
}
|
||||
}
|
||||
|
||||
void CCheatList::Remove(const CTxHolder &txh)
|
||||
{
|
||||
// first narrow by source tx, then compare with tx hash
|
||||
uint32_t count;
|
||||
pair<std::multimap<const uint256, CTxHolder *>::iterator, std::multimap<const uint256, CTxHolder *>::iterator> range;
|
||||
std::vector<std::multimap<const uint256, CTxHolder *>::iterator> utxoPrune;
|
||||
std::vector<std::multimap<const int32_t, CTxHolder>::iterator> heightPrune;
|
||||
|
||||
{
|
||||
LOCK(cs_cheat);
|
||||
range = indexedCheatCandidates.equal_range(txh.utxo);
|
||||
for (auto it = range.first; it != range.second; it++)
|
||||
{
|
||||
uint256 hash = txh.tx.GetHash();
|
||||
if (hash == it->second->tx.GetHash())
|
||||
{
|
||||
utxoPrune.push_back(it);
|
||||
auto hrange = orderedCheatCandidates.equal_range(it->second->height);
|
||||
for (auto hit = hrange.first; hit != hrange.second; hit++)
|
||||
{
|
||||
if (hit->second.tx.GetHash() == hash)
|
||||
{
|
||||
heightPrune.push_back(hit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto it : utxoPrune)
|
||||
{
|
||||
indexedCheatCandidates.erase(it);
|
||||
}
|
||||
for (auto it : heightPrune)
|
||||
{
|
||||
orderedCheatCandidates.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Internal stuff
|
||||
namespace {
|
||||
|
||||
|
||||
52
src/main.h
52
src/main.h
@@ -28,6 +28,7 @@
|
||||
#include "tinyformat.h"
|
||||
#include "txmempool.h"
|
||||
#include "uint256.h"
|
||||
#include "cheatcatcher.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
@@ -639,57 +640,6 @@ struct CDiskTxPos : public CDiskBlockPos
|
||||
}
|
||||
};
|
||||
|
||||
class CTxHolder
|
||||
{
|
||||
public:
|
||||
uint256 utxo;
|
||||
uint32_t height;
|
||||
CTransaction tx;
|
||||
CTxHolder(const CTransaction &_tx, uint32_t _height) : height(_height), tx(_tx) {
|
||||
CVerusHashWriter hw = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
|
||||
|
||||
hw << tx.vin[0].prevout.hash;
|
||||
hw << tx.vin[0].prevout.n;
|
||||
utxo = hw.GetHash();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CCheatList
|
||||
{
|
||||
private:
|
||||
std::multimap<const int32_t, CTxHolder> orderedCheatCandidates;
|
||||
std::multimap<const uint256, CTxHolder *> indexedCheatCandidates;
|
||||
CCriticalSection cs_cheat;
|
||||
|
||||
public:
|
||||
CCheatList() {}
|
||||
|
||||
// prune all transactions in the list below height
|
||||
uint32_t Prune(uint32_t height);
|
||||
|
||||
// check to see if a transaction that could be a cheat for the passed transaction is in our list
|
||||
bool IsCheatInList(const CTransaction &tx, CTransaction *pcheatTx);
|
||||
|
||||
// check to see if there are cheat candidates of the same or greater block height in list
|
||||
bool IsHeightOrGreaterInList(uint32_t height)
|
||||
{
|
||||
auto range = orderedCheatCandidates.equal_range(height);
|
||||
return (range.first == orderedCheatCandidates.end());
|
||||
}
|
||||
|
||||
// add a potential cheat transaction to the list. we do this for all stake transactions from orphaned stakes
|
||||
bool Add(CTxHolder &txh);
|
||||
|
||||
// remove a transaction from the the list
|
||||
void Remove(const CTxHolder &txh);
|
||||
};
|
||||
|
||||
|
||||
extern CCheatList cheatList;
|
||||
extern boost::optional<libzcash::SaplingPaymentAddress> cheatCatcher;
|
||||
|
||||
|
||||
CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree);
|
||||
|
||||
/**
|
||||
|
||||
@@ -241,7 +241,7 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount,
|
||||
CBlockIndex *ppast;
|
||||
if (cheatCatcher &&
|
||||
sapling && chainActive.Height() > 100 &&
|
||||
(ppast = chainActive[nHeight - 100]) &&
|
||||
(ppast = chainActive[nHeight - COINBASE_MATURITY]) &&
|
||||
ppast->IsVerusPOSBlock() &&
|
||||
cheatList.IsHeightOrGreaterInList(nHeight))
|
||||
{
|
||||
|
||||
@@ -23,6 +23,8 @@ int32_t ASSETCHAINS_LWMAPOS = 0;
|
||||
int32_t VERUS_BLOCK_POSUNITS = 1000;
|
||||
int32_t ASSETCHAINS_OVERWINTER = 227520 - 120;
|
||||
int32_t ASSETCHAINS_SAPLING = 227520;
|
||||
boost::optional<libzcash::SaplingPaymentAddress> cheatCatcher;
|
||||
std::string VERUS_CHEATCATCHER;
|
||||
|
||||
unsigned int MAX_BLOCK_SIGOPS = 20000;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user