Updating code

reviving this project
This commit is contained in:
2026-02-18 22:09:06 -08:00
parent c4f5a9ede1
commit 6be262164d
26 changed files with 1041 additions and 987 deletions
+2 -1
View File
@@ -1,3 +1,4 @@
// Copyright (c) 2026 Agrarian Developers
#include <windows.h> // needed for VERSIONINFO
#include "clientversion.h" // holds the needed client version information
@@ -32,4 +33,4 @@ BEGIN
BEGIN
VALUE "Translation", 0x0, 1252 // language neutral - multilingual (decimal)
END
END
END
+17 -20
View File
@@ -2,6 +2,7 @@
// Copyright (c) 2009-2015 The Bitcoin developers
// Copyright (c) 2009-2015 The Dash developers
// Copyright (c) 2015-2018 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -23,9 +24,6 @@
#include <univalue.h>
#define _(x) std::string(x) /* Keep the _() around in case gettext or such will be used later to translate non-UI */
using namespace std;
static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
std::string HelpMessageCli()
@@ -116,13 +114,12 @@ struct HTTPReply
std::string body;
};
static void http_request_done(struct evhttp_request *req, void *ctx)
static void http_request_done(struct evhttp_request* req, void* ctx)
{
HTTPReply *reply = static_cast<HTTPReply*>(ctx);
HTTPReply* reply = static_cast<HTTPReply*>(ctx);
if (req == NULL) {
/* If req is NULL, it means an error occurred while connecting, but
* I'm not sure how to find out which one. We also don't really care.
if (req == nullptr) {
/* If req is nullptr, it means an error occurred while connecting, but* I'm not sure how to find out which one. We also don't really care.
*/
reply->status = 0;
return;
@@ -130,11 +127,11 @@ static void http_request_done(struct evhttp_request *req, void *ctx)
reply->status = evhttp_request_get_response_code(req);
struct evbuffer *buf = evhttp_request_get_input_buffer(req);
struct evbuffer* buf = evhttp_request_get_input_buffer(req);
if (buf)
{
size_t size = evbuffer_get_length(buf);
const char *data = (const char*)evbuffer_pullup(buf, size);
const char* data = (const char*)evbuffer_pullup(buf, size);
if (data)
reply->body = std::string(data, size);
evbuffer_drain(buf, size);
@@ -147,19 +144,19 @@ UniValue CallRPC(const string& strMethod, const UniValue& params)
int port = GetArg("-rpcport", BaseParams().RPCPort());
// Create event base
struct event_base *base = event_base_new(); // TODO RAII
struct event_base* base = event_base_new(); // TODO RAII
if (!base)
throw runtime_error("cannot create event_base");
// Synchronously look up hostname
struct evhttp_connection *evcon = evhttp_connection_base_new(base, NULL, host.c_str(), port); // TODO RAII
if (evcon == NULL)
struct evhttp_connection* evcon = evhttp_connection_base_new(base, nullptr, host.c_str(), port); // TODO RAII
if (evcon == nullptr)
throw runtime_error("create connection failed");
evhttp_connection_set_timeout(evcon, GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT));
HTTPReply response;
struct evhttp_request *req = evhttp_request_new(http_request_done, (void*)&response); // TODO RAII
if (req == NULL)
struct evhttp_request* req = evhttp_request_new(http_request_done, (void*)&response); // TODO RAII
if (req == nullptr)
throw runtime_error("create http request failed");
// Get credentials
@@ -176,7 +173,7 @@ UniValue CallRPC(const string& strMethod, const UniValue& params)
strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
}
struct evkeyvalq *output_headers = evhttp_request_get_output_headers(req);
struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req);
assert(output_headers);
evhttp_add_header(output_headers, "Host", host.c_str());
evhttp_add_header(output_headers, "Connection", "close");
@@ -184,7 +181,7 @@ UniValue CallRPC(const string& strMethod, const UniValue& params)
// Attach request data
std::string strRequest = JSONRPCRequest(strMethod, params, 1);
struct evbuffer * output_buffer = evhttp_request_get_output_buffer(req);
struct evbuffer* output_buffer = evhttp_request_get_output_buffer(req);
assert(output_buffer);
evbuffer_add(output_buffer, strRequest.data(), strRequest.size());
@@ -280,7 +277,7 @@ int CommandLineRPC(int argc, char* argv[])
strPrint = string("error: ") + e.what();
nRet = EXIT_FAILURE;
} catch (...) {
PrintExceptionContinue(NULL, "CommandLineRPC()");
PrintExceptionContinue(nullptr, "CommandLineRPC()");
throw;
}
@@ -305,7 +302,7 @@ int main(int argc, char* argv[])
PrintExceptionContinue(&e, "AppInitRPC()");
return EXIT_FAILURE;
} catch (...) {
PrintExceptionContinue(NULL, "AppInitRPC()");
PrintExceptionContinue(nullptr, "AppInitRPC()");
return EXIT_FAILURE;
}
@@ -315,7 +312,7 @@ int main(int argc, char* argv[])
} catch (std::exception& e) {
PrintExceptionContinue(&e, "CommandLineRPC()");
} catch (...) {
PrintExceptionContinue(NULL, "CommandLineRPC()");
PrintExceptionContinue(nullptr, "CommandLineRPC()");
}
return ret;
}
+2
View File
@@ -1,3 +1,5 @@
// Copyright (c) 2026 Agrarian Developers
#include <windows.h> // needed for VERSIONINFO
#include "clientversion.h" // holds the needed client version information
+4 -5
View File
@@ -1,5 +1,6 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2015-2019 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -24,8 +25,6 @@
#include <boost/assign/list_of.hpp>
using namespace boost::assign;
using namespace std;
static bool fCreateBlank;
static map<string, UniValue> registers;
CClientUIInterface uiInterface;
@@ -605,7 +604,7 @@ static int CommandLineRawTx(int argc, char* argv[])
strPrint = string("error: ") + e.what();
nRet = EXIT_FAILURE;
} catch (...) {
PrintExceptionContinue(NULL, "CommandLineRawTx()");
PrintExceptionContinue(nullptr, "CommandLineRawTx()");
throw;
}
@@ -626,7 +625,7 @@ int main(int argc, char* argv[])
PrintExceptionContinue(&e, "AppInitRawTx()");
return EXIT_FAILURE;
} catch (...) {
PrintExceptionContinue(NULL, "AppInitRawTx()");
PrintExceptionContinue(nullptr, "AppInitRawTx()");
return EXIT_FAILURE;
}
@@ -636,7 +635,7 @@ int main(int argc, char* argv[])
} catch (std::exception& e) {
PrintExceptionContinue(&e, "CommandLineRawTx()");
} catch (...) {
PrintExceptionContinue(NULL, "CommandLineRawTx()");
PrintExceptionContinue(nullptr, "CommandLineRawTx()");
}
return ret;
}
+2
View File
@@ -1,3 +1,5 @@
// Copyright (c) 2026 Agrarian Developers
#include <windows.h> // needed for VERSIONINFO
#include "clientversion.h" // holds the needed client version information
+4 -5
View File
@@ -2,6 +2,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2019 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -29,13 +30,11 @@
* \section intro_sec Introduction
*
* This is the developer documentation of the reference client for an experimental new digital currency called Agrarian (http://www.agrarian.org),
* which enables instant payments to anyone, anywhere in the world. Agrarian uses peer-to-peer technology to operate
* with no central authority: managing transactions and issuing money are carried out collectively by the network.
* which enables instant payments to anyone, anywhere in the world. Agrarian uses peer-to-peer technology to operate* with no central authority: managing transactions and issuing money are carried out collectively by the network.
*
* The software is a community-driven open source project, released under the MIT license.
*
* \section Navigation
* Use the buttons <code>Namespaces</code>, <code>Classes</code> or <code>Files</code> at the top of the page to start navigating the code.
* \section Navigation* Use the buttons <code>Namespaces</code>, <code>Classes</code> or <code>Files</code> at the top of the page to start navigating the code.
*/
static bool fDaemon;
@@ -144,7 +143,7 @@ bool AppInit(int argc, char* argv[])
} catch (std::exception& e) {
PrintExceptionContinue(&e, "AppInit()");
} catch (...) {
PrintExceptionContinue(NULL, "AppInit()");
PrintExceptionContinue(nullptr, "AppInit()");
}
if (!fRet) {
+81 -53
View File
@@ -2,11 +2,14 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2019 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "libzerocoin/Params.h"
#include "chainparams.h"
#include "chainparamsseeds.h"
#include "random.h"
#include "util.h"
#include "utilstrencodings.h"
@@ -23,8 +26,6 @@ struct SeedSpec6 {
uint16_t port;
};
#include "chainparamsseeds.h"
/**
* Main network
*/
@@ -57,9 +58,9 @@ static Checkpoints::MapCheckpoints mapCheckpoints =
static const Checkpoints::CCheckpointData data = {
&mapCheckpoints,
1643790201, // * UNIX timestamp of last checkpoint block
0, // * total number of transactions between genesis and last checkpoint
0, // * total number of transactions between genesis and last checkpoint
// (the tx=... number in the SetBestChain debug.log lines)
0 // * estimated number of transactions per day after checkpoint
0 // * estimated number of transactions per day after checkpoint
};
static Checkpoints::MapCheckpoints mapCheckpointsTestnet =
@@ -69,7 +70,8 @@ static const Checkpoints::CCheckpointData dataTestnet = {
&mapCheckpointsTestnet,
1643790201,
0,
0};
0
};
static Checkpoints::MapCheckpoints mapCheckpointsRegtest =
boost::assign::map_list_of(0, uint256("0x001"));
@@ -77,24 +79,24 @@ static const Checkpoints::CCheckpointData dataRegtest = {
&mapCheckpointsRegtest,
1643790201,
0,
0};
0
};
libzerocoin::ZerocoinParams* CChainParams::Zerocoin_Params(bool useModulusV1) const
{
assert(this);
static CBigNum bnHexModulus = 0;
if (!bnHexModulus)
bnHexModulus.SetHex(zerocoinModulus);
static libzerocoin::ZerocoinParams ZCParamsHex = libzerocoin::ZerocoinParams(bnHexModulus);
static CBigNum bnDecModulus = 0;
if (!bnDecModulus)
bnDecModulus.SetDec(zerocoinModulus);
static libzerocoin::ZerocoinParams ZCParamsDec = libzerocoin::ZerocoinParams(bnDecModulus);
if (useModulusV1)
return &ZCParamsHex;
return &ZCParamsDec;
return useModulusV1 ? &ZCParamsHex : &ZCParamsDec;
}
class CMainParams : public CChainParams
@@ -130,26 +132,33 @@ public:
/** Height or Time Based Activations **/
nLastPOWBlock = 100;
nModifierUpdateBlock = 2; //The block at which PoS rules activate
// Hybrid consensus: PoW mining and PoS staking are both permitted beginning at block 2.
// PoW remains permitted until nLastPOWBlock.
nFirstPoSBlock = 2;
// PIVX-style modifier upgrade: keep aligned with PoS activation.
nModifierUpdateBlock = 2;
nZerocoinStartHeight = 0;
nZerocoinStartTime = 1643790201;
nBlockEnforceSerialRange = 1; //Enforce serial range starting this block
nBlockRecalculateAccumulators = 999999999; //Trigger a recalculation of accumulators
nBlockFirstFraudulent = 999999999; //First block that bad serials emerged
nBlockLastGoodCheckpoint = 999999999; //Last valid accumulator checkpoint
nBlockEnforceInvalidUTXO = 999999999; //Start enforcing the invalid UTXO's
nInvalidAmountFiltered = 0; //Amount of invalid coins filtered through exchanges, that should be considered valid
nBlockEnforceSerialRange = 1; // Enforce serial range starting this block
nBlockRecalculateAccumulators = 999999999; // Trigger a recalculation of accumulators
nBlockFirstFraudulent = 999999999; // First block that bad serials emerged
nBlockLastGoodCheckpoint = 999999999; // Last valid accumulator checkpoint
nBlockEnforceInvalidUTXO = 999999999; // Start enforcing the invalid UTXO's
nInvalidAmountFiltered = 0; // Amount of invalid coins filtered through exchanges, that should be considered valid
nBlockZerocoinV2 = 999999999;
nBlockDoubleAccumulated = 999999999;
nEnforceNewSporkKey = 1643790201;
nRejectOldSporkKey = 1527811200;
nRejectOldSporkKey = 1527811200;
// Public coin spend enforcement
nPublicZCSpends = 1;
// Fake Serial Attack
nFakeSerialBlockheightEnd = 0;
nSupplyBeforeFakeSerial = 0; // zerocoin supply at block nFakeSerialBlockheightEnd
nSupplyBeforeFakeSerial = 0; // zerocoin supply at block nFakeSerialBlockheightEnd
/**
* Build the genesis block. Note that the output of the genesis coinbase cannot
@@ -165,7 +174,9 @@ public:
CMutableTransaction txNew;
txNew.vin.resize(1);
txNew.vout.resize(1);
txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4)
<< vector<unsigned char>((const unsigned char*)pszTimestamp,
(const unsigned char*)pszTimestamp + strlen(pszTimestamp));
txNew.vout[0].nValue = 50 * COIN;
txNew.vout[0].scriptPubKey = CScript() << ParseHex("04fe3d7e5608ebba6d822948eff929c822ad35b5f8ecd00977d0e59ed67da697bd88e0ed8bd58797bde6fe6750236f5dae4cf403af0925c8339f0a91b682254b39") << OP_CHECKSIG;
genesis.vtx.push_back(txNew);
@@ -211,22 +222,22 @@ public:
/** Zerocoin */
zerocoinModulus = "25195908475657893494027183240048398571429282126204032027777137836043662020707595556264018525880784"
"4069182906412495150821892985591491761845028084891200728449926873928072877767359714183472702618963750149718246911"
"6507761337985909570009733045974880842840179742910064245869181719511874612151517265463228221686998754918242243363"
"7259085141865462043576798423387184774447920739934236584823824281198163815010674810451660377306056201619676256133"
"8441436038339044149526344321901146575444541784240209246165157233507787077498171257724679629263863563732899121548"
"31438167899885040445364023527381951378636564391212010397122822120720357";
nMaxZerocoinSpendsPerTransaction = 7; // Assume about 20kb each
"4069182906412495150821892985591491761845028084891200728449926873928072877767359714183472702618963750149718246911"
"6507761337985909570009733045974880842840179742910064245869181719511874612151517265463228221686998754918242243363"
"7259085141865462043576798423387184774447920739934236584823824281198163815010674810451660377306056201619676256133"
"8441436038339044149526344321901146575444541784240209246165157233507787077498171257724679629263863563732899121548"
"31438167899885040445364023527381951378636564391212010397122822120720357";
nMaxZerocoinSpendsPerTransaction = 7; // Assume about 20kb each
nMaxZerocoinPublicSpendsPerTransaction = 637; // Assume about 220 bytes each input
nMinZerocoinMintFee = 1 * CENT; //high fee required for zerocoin mints
nMintRequiredConfirmations = 20; //the maximum amount of confirmations until accumulated in 19
nMinZerocoinMintFee = 1 * CENT; // high fee required for zerocoin mints
nMintRequiredConfirmations = 20; // the maximum amount of confirmations until accumulated in 19
nRequiredAccumulation = 1;
nDefaultSecurityLevel = 100; //full security level for accumulators
nZerocoinHeaderVersion = 4; //Block headers must be this version once zerocoin is active
nZerocoinRequiredStakeDepth = 200; //The required confirmations for a zagr to be stakable
nDefaultSecurityLevel = 100; // full security level for accumulators
nZerocoinHeaderVersion = 4; // Block headers must be this version once zerocoin is active
nZerocoinRequiredStakeDepth = 200; // The required confirmations for a zagr to be stakable
nBudget_Fee_Confirmations = 6; // Number of confirmations for the finalization fee
nProposalEstablishmentTime = 60 * 60 * 24; // Proposals must be at least a day old to make it into a budget
nBudget_Fee_Confirmations = 6; // Number of confirmations for the finalization fee
nProposalEstablishmentTime = 60 * 60 * 24; // Proposals must be at least a day old to make it into a budget
}
const Checkpoints::CCheckpointData& Checkpoints() const
@@ -258,22 +269,30 @@ public:
nMinerThreads = 0;
nTargetTimespan = 10 * 60;
nTargetSpacing = 10 * 60;
nLastPOWBlock = 200;
// Hybrid consensus: PoS staking permitted from block 2 in testnet as well.
nFirstPoSBlock = 2;
nMaturity = 15;
nMasternodeCountDrift = 4;
nModifierUpdateBlock = 0;
// Keep aligned with PoS activation in this chain.
nModifierUpdateBlock = 2;
nMaxMoneyOut = 43199500 * COIN;
nZerocoinStartHeight = 0;
nZerocoinStartTime = 1643790201;
nBlockEnforceSerialRange = 1; //Enforce serial range starting this block
nBlockRecalculateAccumulators = 999999999; //Trigger a recalculation of accumulators
nBlockFirstFraudulent = 999999999; //First block that bad serials emerged
nBlockLastGoodCheckpoint = 999999999; //Last valid accumulator checkpoint
nBlockEnforceInvalidUTXO = 999999999; //Start enforcing the invalid UTXO's
nInvalidAmountFiltered = 0; //Amount of invalid coins filtered through exchanges, that should be considered valid
nBlockZerocoinV2 = 999999999; //!> The block that zerocoin v2 becomes active
nBlockEnforceSerialRange = 1; // Enforce serial range starting this block
nBlockRecalculateAccumulators = 999999999; // Trigger a recalculation of accumulators
nBlockFirstFraudulent = 999999999; // First block that bad serials emerged
nBlockLastGoodCheckpoint = 999999999; // Last valid accumulator checkpoint
nBlockEnforceInvalidUTXO = 999999999; // Start enforcing the invalid UTXO's
nInvalidAmountFiltered = 0; // Amount of invalid coins filtered through exchanges, that should be considered valid
nBlockZerocoinV2 = 999999999; //!> The block that zerocoin v2 becomes active
nEnforceNewSporkKey = 1643790201;
nRejectOldSporkKey = 1522454400;
nRejectOldSporkKey = 1522454400;
// Public coin spend enforcement
nPublicZCSpends = 1;
@@ -292,12 +311,12 @@ public:
vFixedSeeds.clear();
vSeeds.clear();
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1, 38);
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1, 39);
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1, 166);
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1, 38);
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1, 39);
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1, 166);
base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x3a)(0x80)(0x61)(0xa0).convert_to_container<std::vector<unsigned char> >();
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x3a)(0x80)(0x58)(0x37).convert_to_container<std::vector<unsigned char> >();
// Testnet agrarian BIP44 coin type is '1' (All coin's testnet default)
base58Prefixes[EXT_COIN_TYPE] = boost::assign::list_of(0x80)(0x00)(0x00)(0x01).convert_to_container<std::vector<unsigned char> >();
@@ -322,6 +341,7 @@ public:
nProposalEstablishmentTime = 60 * 5; // Proposals must be at least 5 mns old to make it into a test budget
}
const Checkpoints::CCheckpointData& Checkpoints() const
{
return dataTestnet;
@@ -352,18 +372,26 @@ public:
nTargetTimespan = 24 * 60 * 60; // Agrarian: 1 day
nTargetSpacing = 1 * 60; // Agrarian: 1 minutes
bnProofOfWorkLimit = ~uint256(0) >> 1;
nLastPOWBlock = 250;
// Hybrid consensus: PoS staking permitted from block 2 in regtest as well.
nFirstPoSBlock = 2;
nMaturity = 20;
nMasternodeCountDrift = 4;
nModifierUpdateBlock = 0; //approx Mon, 17 Apr 2017 04:00:00 GMT
// Keep aligned with PoS activation in this chain.
nModifierUpdateBlock = 2;
nMaxMoneyOut = 43199500 * COIN;
nZerocoinStartHeight = 300;
nBlockZerocoinV2 = 300;
nZerocoinStartTime = 1643790201;
nBlockEnforceSerialRange = 1; //Enforce serial range starting this block
nBlockRecalculateAccumulators = 999999999; //Trigger a recalculation of accumulators
nBlockFirstFraudulent = 999999999; //First block that bad serials emerged
nBlockLastGoodCheckpoint = 999999999; //Last valid accumulator checkpoint
nBlockEnforceSerialRange = 1; // Enforce serial range starting this block
nBlockRecalculateAccumulators = 999999999; // Trigger a recalculation of accumulators
nBlockFirstFraudulent = 999999999; // First block that bad serials emerged
nBlockLastGoodCheckpoint = 999999999; // Last valid accumulator checkpoint
// Public coin spend enforcement
nPublicZCSpends = 350;
@@ -390,6 +418,7 @@ public:
fSkipProofOfWorkCheck = true;
fTestnetToBeDeprecatedFieldRPC = false;
}
const Checkpoints::CCheckpointData& Checkpoints() const
{
return dataRegtest;
@@ -434,7 +463,6 @@ public:
};
static CUnitTestParams unitTestParams;
static CChainParams* pCurrentParams = 0;
CModifiableParams* ModifiableParams()
+14 -4
View File
@@ -2,6 +2,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2019 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -15,6 +16,7 @@
#include "uint256.h"
#include "libzerocoin/Params.h"
#include <vector>
typedef unsigned char MessageStartChars[MESSAGE_START_SIZE];
@@ -63,7 +65,7 @@ public:
/** Make miner wait to have peers to avoid wasting work */
bool MiningRequiresPeers() const { return fMiningRequiresPeers; }
/** Headers first syncing is disabled */
bool HeadersFirstSyncingActive() const { return fHeadersFirstSyncingActive; };
bool HeadersFirstSyncingActive() const { return fHeadersFirstSyncingActive; }
/** Default value for -checkmempool and -checkblockindex argument */
bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; }
/** Allow mining of a min-difficulty block */
@@ -119,7 +121,13 @@ public:
/** Height or Time Based Activations **/
int ModifierUpgradeBlock() const { return nModifierUpdateBlock; }
// Hybrid consensus activations.
// - PoS blocks are permitted starting at FIRST_POS_BLOCK().
// - PoW blocks are permitted up to and including LAST_POW_BLOCK().
int FIRST_POS_BLOCK() const { return nFirstPoSBlock; }
int LAST_POW_BLOCK() const { return nLastPOWBlock; }
int Zerocoin_StartHeight() const { return nZerocoinStartHeight; }
int Zerocoin_Block_EnforceSerialRange() const { return nBlockEnforceSerialRange; }
int Zerocoin_Block_RecalculateAccumulators() const { return nBlockRecalculateAccumulators; }
@@ -134,7 +142,7 @@ public:
CAmount GetSupplyBeforeFakeSerial() const { return nSupplyBeforeFakeSerial; }
int Zerocoin_Block_Double_Accumulated() const { return nBlockDoubleAccumulated; }
CAmount InvalidAmountFiltered() const { return nInvalidAmountFiltered; };
CAmount InvalidAmountFiltered() const { return nInvalidAmountFiltered; }
int Zerocoin_Block_Public_Spend_Enabled() const { return nPublicZCSpends; }
@@ -154,7 +162,11 @@ protected:
int nToCheckBlockUpgradeMajority;
int64_t nTargetTimespan;
int64_t nTargetSpacing;
// Hybrid PoW/PoS window controls.
int nFirstPoSBlock;
int nLastPOWBlock;
int nMasternodeCountDrift;
int nMaturity;
int nModifierUpdateBlock;
@@ -216,7 +228,6 @@ protected:
* to test specific features more easily. Test cases should always restore the previous
* values after finalization.
*/
class CModifiableParams
{
public:
@@ -230,7 +241,6 @@ public:
virtual void setSkipProofOfWorkCheck(bool aSkipProofOfWorkCheck) = 0;
};
/**
* Return the currently selected parameters. This won't change after app startup
* outside of the unit tests.
+2 -4
View File
@@ -1,5 +1,6 @@
// Copyright (c) 2012-2013 The PPCoin developers
// Copyright (c) 2015-2019 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -13,9 +14,6 @@
#include "stakeinput.h"
#include "utilmoneystr.h"
#include "zagrchain.h"
using namespace std;
bool fTestNet = false; // Params().NetworkID() == CBaseChainParams::TESTNET;
// Modifier interval: time to elapse before new modifier is computed
@@ -313,7 +311,7 @@ bool stakeTargetHit(const uint256& hashProofOfStake, const int64_t& nValueIn, co
uint256 bnCoinDayWeight = uint256(nValueIn) / 100;
// Check if proof-of-stake hash meets the target protocol
return hashProofOfStake < (bnCoinDayWeight * bnTargetPerCoinDay);
return hashProofOfStake < (bnCoinDayWeight* bnTargetPerCoinDay);
}
bool CheckStake(const CDataStream& ssUniqueID, CAmount nValueIn, const uint64_t nStakeModifier, const uint256& bnTarget,
+7 -5
View File
@@ -1,13 +1,15 @@
// Copyright (c) 2012-2013 The PPCoin developers
// Copyright (c) 2015-2019 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_KERNEL_H
#define BITCOIN_KERNEL_H
#ifndef AGRARIAN_BITCOIN_KERNEL_H
#define AGRARIAN_BITCOIN_KERNEL_H
#include "main.h"
#include "stakeinput.h"
#include <cstdint>
#include <cstddef>
#include <cstdint>
// MODIFIER_INTERVAL: time to elapse before new modifier is computed
@@ -46,4 +48,4 @@ int64_t GetWeight(int64_t nIntervalBeginning, int64_t nIntervalEnd);
bool ContextualCheckZerocoinStake(int nPreviousBlockHeight, CStakeInput* stake);
#endif // BITCOIN_KERNEL_H
#endif // AGRARIAN_BITCOIN_KERNEL_H
+43 -22
View File
@@ -2,6 +2,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2019 The PIVX developers
// Copyright (c) 2026 The Agrarian developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -1986,23 +1987,41 @@ double ConvertBitsToDouble(unsigned int nBits)
return dDiff;
}
int64_t GetBlockValue(int nHeight, bool fProofOfStake)
{
// NOTE:
// - Height 0 is genesis and uses the special, pre-mined value.
// - During the hybrid window, both PoW and PoS blocks may be created.
// Subsidy policy is therefore selected by block type, not by height alone.
//
// Current Agrarian policy:
// * PoW blocks (height > 0 && height <= LAST_POW_BLOCK): 50 AGR
// * PoS blocks (height >= FIRST_POS_BLOCK): 10 AGR
// * PoW blocks are not valid beyond LAST_POW_BLOCK (enforced elsewhere).
if (nHeight == 0) {
return 5000000000 * COIN;
}
if (fProofOfStake) {
return 10 * COIN;
}
if (nHeight > 0 && nHeight <= Params().LAST_POW_BLOCK()) {
return 50 * COIN;
}
// Should not be reachable for valid blocks (PoW is disallowed beyond LAST_POW_BLOCK).
return 0;
}
// Backward-compatible wrapper for call sites that only know height.
// Prefer GetBlockValue(height, isPoS) when block type is available.
int64_t GetBlockValue(int nHeight)
{
int64_t nSubsidy = 0;
if (nHeight == 0) {
nSubsidy = 5000000000 * COIN;
}
else if (nHeight <= Params().LAST_POW_BLOCK() && nHeight > 0) {
nSubsidy = 50 * COIN;
}
else if (nHeight > Params().LAST_POW_BLOCK()) {
nSubsidy = 10 * COIN;
}
return nSubsidy;
return GetBlockValue(nHeight, false);
}
CAmount GetSeeSaw(const CAmount& blockValue, int nMasternodeCount, int nHeight)
{
//if a mn count is inserted into the function we are looking for a specific result for a masternode count
@@ -2911,15 +2930,17 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return true;
}
if (pindex->nHeight <= Params().LAST_POW_BLOCK() && block.IsProofOfStake())
return state.DoS(100, error("ConnectBlock() : PoS period not active"),
REJECT_INVALID, "PoS-early");
// Hybrid consensus:
// - PoS blocks are permitted starting at Params().FIRST_POS_BLOCK().
// - PoW blocks are permitted up to and including Params().LAST_POW_BLOCK().
if (block.IsProofOfStake() && pindex->nHeight < Params().FIRST_POS_BLOCK())
return state.DoS(100, error("ConnectBlock() : PoS period not active"),
REJECT_INVALID, "PoS-early");
if (pindex->nHeight > Params().LAST_POW_BLOCK() && block.IsProofOfWork())
return state.DoS(100, error("ConnectBlock() : PoW period ended"),
REJECT_INVALID, "PoW-ended");
bool fScriptChecks = pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate();
if (block.IsProofOfWork() && pindex->nHeight > Params().LAST_POW_BLOCK())
return state.DoS(100, error("ConnectBlock() : PoW period ended"),
REJECT_INVALID, "PoW-ended");
bool fScriptChecks = pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate();
// If scripts won't be checked anyways, don't bother seeing if CLTV is activated
bool fCLTVHasMajority = false;
@@ -3132,7 +3153,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs - 1), nTimeConnect * 0.000001);
//PoW phase redistributed fees to miner. PoS stage destroys fees.
CAmount nExpectedMint = GetBlockValue(pindex->pprev->nHeight);
CAmount nExpectedMint = GetBlockValue(pindex->nHeight, block.IsProofOfStake());
if (block.IsProofOfWork())
nExpectedMint += nFees;
+37 -59
View File
@@ -2,6 +2,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2019 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -20,8 +21,6 @@
#include "pow.h"
#include "primitives/block.h"
#include "primitives/transaction.h"
#include "zagr/zerocoin.h"
#include "zagr/zagrmodule.h"
#include "script/script.h"
#include "script/sigcache.h"
#include "script/standard.h"
@@ -30,6 +29,8 @@
#include "txmempool.h"
#include "uint256.h"
#include "undo.h"
#include "zagr/zerocoin.h"
#include "zagr/zagrmodule.h"
#include <algorithm>
#include <exception>
@@ -108,7 +109,7 @@ static const unsigned int DATABASE_WRITE_INTERVAL = 3600;
static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111;
/** Enable bloom filter */
static const bool DEFAULT_PEERBLOOMFILTERS = true;
static const bool DEFAULT_PEERBLOOMFILTERS = true;
static const bool DEFAULT_PEERBLOOMFILTERS_ZC = false;
/** If the tip is older than this (in seconds), the node is considered to be in initial block download. */
@@ -175,7 +176,7 @@ extern int64_t nReserveBalance;
extern std::map<uint256, int64_t> mapRejectedBlocks;
extern std::map<unsigned int, unsigned int> mapHashedBlocks;
extern std::map<uint256, int64_t> mapZerocoinspends; //txid, time received
extern std::map<uint256, int64_t> mapZerocoinspends; // txid, time received
/** Best header we've seen so far (used for getheaders queries' starting points). */
extern CBlockIndex* pindexBestHeader;
@@ -241,11 +242,16 @@ std::string GetWarnings(std::string strFor);
bool GetTransaction(const uint256& hash, CTransaction& tx, uint256& hashBlock, bool fAllowSlow = false, CBlockIndex* blockIndex = nullptr);
/** Retrieve an output (from memory pool, or from disk, if possible) */
bool GetOutput(const uint256& hash, unsigned int index, CValidationState& state, CTxOut& out);
/** Find the best known block, and make it the tip of the block chain */
// ***TODO***
/** TODO (legacy) */
double ConvertBitsToDouble(unsigned int nBits);
int64_t GetMasternodePayment(int nHeight, int64_t blockValue, int nMasternodeCount, bool isZAGRStake);
/**
* Hybrid difficulty selection.
* Implementations should route to the correct target calculation (PoW vs PoS)
* based on the fProofOfStake flag rather than height-era assumptions.
*/
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader* pblock, bool fProofOfStake);
bool ActivateBestChain(CValidationState& state, CBlock* pblock = NULL, bool fAlreadyChecked = false);
@@ -262,7 +268,6 @@ void Misbehaving(NodeId nodeid, int howmuch);
/** Flush all state, indexes and buffers to disk. */
void FlushStateToDisk();
/** (try to) add transaction to memory pool **/
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransaction& tx, bool fLimitFree, bool* pfMissingInputs, bool fRejectInsaneFee = false, bool ignoreFees = false);
@@ -291,14 +296,8 @@ struct CDiskTxPos : public CDiskBlockPos {
READWRITE(VARINT(nTxOffset));
}
CDiskTxPos(const CDiskBlockPos& blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn)
{
}
CDiskTxPos()
{
SetNull();
}
CDiskTxPos(const CDiskBlockPos& blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) {}
CDiskTxPos() { SetNull(); }
void SetNull()
{
@@ -307,22 +306,9 @@ struct CDiskTxPos : public CDiskBlockPos {
}
};
CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree);
bool MoneyRange(CAmount nValueOut);
/**
* Check transaction inputs, and make sure any
* pay-to-script-hash transactions are evaluating IsStandard scripts
*
* Why bother? To avoid denial-of-service attacks; an attacker
* can submit a standard HASH... OP_EQUAL transaction,
* which will get accepted into blocks. The redemption
* script can be anything; an attacker could use a very
* expensive-to-check-upon-redemption script like:
* DUP CHECKSIG DROP ... repeated 100 times... OP_1
*/
/**
* Check for standard transaction types
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
@@ -346,7 +332,6 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx);
*/
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs);
/**
* Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
* This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
@@ -413,7 +398,6 @@ public:
bool ReadFromDisk(const CDiskBlockPos& pos, const uint256& hashBlock);
};
/**
* Closure representing one script verification
* Note that this stores references to the spending transaction
@@ -430,8 +414,15 @@ private:
public:
CScriptCheck() : ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) : scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey),
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn)
: scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey),
ptxTo(&txToIn),
nIn(nInIn),
nFlags(nFlagsIn),
cacheStore(cacheIn),
error(SCRIPT_ERR_UNKNOWN_ERROR)
{
}
bool operator()();
@@ -448,13 +439,11 @@ public:
ScriptError GetScriptError() const { return error; }
};
/** Functions for disk access for blocks */
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos);
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos);
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
/** Functions for validating blocks and updating the block tree */
/** Undo the effects of this block (with given index) on the UTXO set represented by coins.
@@ -479,13 +468,12 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindexPrev);
/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */
bool TestBlockValidity(CValidationState& state, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
bool TestBlockValidity(CValidationState& state, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true, bool fCheckSig = true);
/** Store block on disk. If dbp is provided, the file is known to already reside on disk */
bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** pindex, CDiskBlockPos* dbp = NULL, bool fAlreadyCheckedBlock = false);
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex = NULL);
class CBlockFileInfo
{
public:
@@ -522,10 +510,7 @@ public:
nTimeLast = 0;
}
CBlockFileInfo()
{
SetNull();
}
CBlockFileInfo() { SetNull(); }
std::string ToString() const;
@@ -560,6 +545,7 @@ private:
public:
CValidationState() : mode(MODE_VALID), nDoS(0), chRejectCode(0), corruptionPossible(false) {}
bool DoS(int level, bool ret = false, unsigned char chRejectCodeIn = 0, std::string strRejectReasonIn = "", bool corruptionIn = false)
{
chRejectCode = chRejectCodeIn;
@@ -571,12 +557,12 @@ public:
mode = MODE_INVALID;
return ret;
}
bool Invalid(bool ret = false,
unsigned char _chRejectCode = 0,
std::string _strRejectReason = "")
bool Invalid(bool ret = false, unsigned char _chRejectCode = 0, std::string _strRejectReason = "")
{
return DoS(0, ret, _chRejectCode, _strRejectReason);
}
bool Error(std::string strRejectReasonIn = "")
{
if (mode == MODE_VALID)
@@ -584,23 +570,17 @@ public:
mode = MODE_ERROR;
return false;
}
bool Abort(const std::string& msg)
{
AbortNode(msg);
return Error(msg);
}
bool IsValid() const
{
return mode == MODE_VALID;
}
bool IsInvalid() const
{
return mode == MODE_INVALID;
}
bool IsError() const
{
return mode == MODE_ERROR;
}
bool IsValid() const { return mode == MODE_VALID; }
bool IsInvalid() const { return mode == MODE_INVALID; }
bool IsError() const { return mode == MODE_ERROR; }
bool IsInvalid(int& nDoSOut) const
{
if (IsInvalid()) {
@@ -609,10 +589,8 @@ public:
}
return false;
}
bool CorruptionPossible() const
{
return corruptionPossible;
}
bool CorruptionPossible() const { return corruptionPossible; }
unsigned char GetRejectCode() const { return chRejectCode; }
std::string GetRejectReason() const { return strRejectReason; }
};
+13 -1
View File
@@ -1,5 +1,6 @@
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2019 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -16,6 +17,17 @@
#include "util.h"
#include <boost/filesystem.hpp>
#include <algorithm>
#include <cstdint>
#include <limits>
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
CBudgetManager budget;
CCriticalSection cs_budget;
@@ -2159,7 +2171,7 @@ TrxValidationStatus CFinalizedBudget::IsTransactionValid(const CTransaction& txN
bool paid = false;
for (CTxOut out : txNew.vout) {
for (const CTxOut& out : txNew.vout) {
LogPrint("mnbudget","CFinalizedBudget::IsTransactionValid - nCurrentBudgetPayment=%d, payee=%s == out.scriptPubKey=%s, amount=%ld == out.nValue=%ld\n",
nCurrentBudgetPayment, vecBudgetPayments[nCurrentBudgetPayment].payee.ToString().c_str(), out.scriptPubKey.ToString().c_str(),
vecBudgetPayments[nCurrentBudgetPayment].nAmount, out.nValue);
+36 -33
View File
@@ -1,10 +1,11 @@
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2019 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef MASTERNODE_BUDGET_H
#define MASTERNODE_BUDGET_H
#ifndef AGRARIAN_MASTERNODE_BUDGET_H
#define AGRARIAN_MASTERNODE_BUDGET_H
#include "base58.h"
#include "init.h"
@@ -14,9 +15,11 @@
#include "net.h"
#include "sync.h"
#include "util.h"
using namespace std;
#include <cstdint>
#include <std::map>
#include <std::string>
#include <utility>
#include <std::vector>
extern CCriticalSection cs_budget;
class CBudgetManager;
@@ -41,7 +44,7 @@ static const CAmount PROPOSAL_FEE_TX = (50 * COIN);
static const CAmount BUDGET_FEE_TX_OLD = (50 * COIN);
static const CAmount BUDGET_FEE_TX = (5 * COIN);
static const int64_t BUDGET_VOTE_UPDATE_MIN = 60 * 60;
static map<uint256, int> mapPayment_History;
static std::map<uint256, int> mapPayment_History;
extern std::vector<CBudgetProposalBroadcast> vecImmatureBudgetProposals;
extern std::vector<CFinalizedBudgetBroadcast> vecImmatureFinalizedBudgets;
@@ -179,16 +182,16 @@ class CBudgetManager
{
private:
//hold txes until they mature enough to use
// XX42 map<uint256, CTransaction> mapCollateral;
map<uint256, uint256> mapCollateralTxids;
// XX42 std::map<uint256, CTransaction> mapCollateral;
std::map<uint256, uint256> mapCollateralTxids;
public:
// critical section to protect the inner data structures
mutable CCriticalSection cs;
// keep track of the scanning errors I've seen
map<uint256, CBudgetProposal> mapProposals;
map<uint256, CFinalizedBudget> mapFinalizedBudgets;
std::map<uint256, CBudgetProposal> mapProposals;
std::map<uint256, CFinalizedBudget> mapFinalizedBudgets;
std::map<uint256, CBudgetProposalBroadcast> mapSeenMasternodeBudgetProposals;
std::map<uint256, CBudgetVote> mapSeenMasternodeBudgetVotes;
@@ -321,7 +324,7 @@ public:
std::string strBudgetName;
int nBlockStart;
std::vector<CTxBudgetPayment> vecBudgetPayments;
map<uint256, CFinalizedBudgetVote> mapVotes;
std::map<uint256, CFinalizedBudgetVote> mapVotes;
uint256 nFeeTXHash;
int64_t nTime;
@@ -372,7 +375,7 @@ public:
void SubmitVote();
//checks the hashes to make sure we know about them
string GetStatus();
std::string GetStatus();
uint256 GetHash()
{
@@ -413,24 +416,24 @@ public:
CFinalizedBudgetBroadcast(const CFinalizedBudget& other);
CFinalizedBudgetBroadcast(std::string strBudgetNameIn, int nBlockStartIn, std::vector<CTxBudgetPayment> vecBudgetPaymentsIn, uint256 nFeeTXHashIn);
void swap(CFinalizedBudgetBroadcast& first, CFinalizedBudgetBroadcast& second) // nothrow
void std::swap(CFinalizedBudgetBroadcast& first, CFinalizedBudgetBroadcast& second) // nothrow
{
// enable ADL (not necessary in our case, but good practice)
using std::swap;
// by swapping the members of two classes,
// the two classes are effectively swapped
swap(first.strBudgetName, second.strBudgetName);
swap(first.nBlockStart, second.nBlockStart);
first.mapVotes.swap(second.mapVotes);
first.vecBudgetPayments.swap(second.vecBudgetPayments);
swap(first.nFeeTXHash, second.nFeeTXHash);
swap(first.nTime, second.nTime);
std::swap(first.strBudgetName, second.strBudgetName);
std::swap(first.nBlockStart, second.nBlockStart);
first.mapVotes.std::swap(second.mapVotes);
first.vecBudgetPayments.std::swap(second.vecBudgetPayments);
std::swap(first.nFeeTXHash, second.nFeeTXHash);
std::swap(first.nTime, second.nTime);
}
CFinalizedBudgetBroadcast& operator=(CFinalizedBudgetBroadcast from)
{
swap(*this, from);
std::swap(*this, from);
return *this;
}
@@ -478,7 +481,7 @@ public:
int64_t nTime;
uint256 nFeeTXHash;
map<uint256, CBudgetVote> mapVotes;
std::map<uint256, CBudgetVote> mapVotes;
//cache object
CBudgetProposal();
@@ -559,27 +562,27 @@ public:
CBudgetProposalBroadcast(const CBudgetProposalBroadcast& other) : CBudgetProposal(other) {}
CBudgetProposalBroadcast(std::string strProposalNameIn, std::string strURLIn, int nPaymentCount, CScript addressIn, CAmount nAmountIn, int nBlockStartIn, uint256 nFeeTXHashIn);
void swap(CBudgetProposalBroadcast& first, CBudgetProposalBroadcast& second) // nothrow
void std::swap(CBudgetProposalBroadcast& first, CBudgetProposalBroadcast& second) // nothrow
{
// enable ADL (not necessary in our case, but good practice)
using std::swap;
// by swapping the members of two classes,
// the two classes are effectively swapped
swap(first.strProposalName, second.strProposalName);
swap(first.nBlockStart, second.nBlockStart);
swap(first.strURL, second.strURL);
swap(first.nBlockEnd, second.nBlockEnd);
swap(first.nAmount, second.nAmount);
swap(first.address, second.address);
swap(first.nTime, second.nTime);
swap(first.nFeeTXHash, second.nFeeTXHash);
first.mapVotes.swap(second.mapVotes);
std::swap(first.strProposalName, second.strProposalName);
std::swap(first.nBlockStart, second.nBlockStart);
std::swap(first.strURL, second.strURL);
std::swap(first.nBlockEnd, second.nBlockEnd);
std::swap(first.nAmount, second.nAmount);
std::swap(first.address, second.address);
std::swap(first.nTime, second.nTime);
std::swap(first.nFeeTXHash, second.nFeeTXHash);
first.mapVotes.std::swap(second.mapVotes);
}
CBudgetProposalBroadcast& operator=(CBudgetProposalBroadcast from)
{
swap(*this, from);
std::swap(*this, from);
return *this;
}
@@ -604,4 +607,4 @@ public:
};
#endif
#endif // AGRARIAN_MASTERNODE_BUDGET_H
+275 -197
View File
@@ -1,9 +1,11 @@
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2019 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "masternode-payments.h"
#include "addrman.h"
#include "chainparams.h"
#include "masternode-budget.h"
@@ -14,8 +16,15 @@
#include "sync.h"
#include "util.h"
#include "utilmoneystr.h"
#include <boost/filesystem.hpp>
#include <algorithm>
#include <cstdio>
#include <limits>
#include <string>
#include <vector>
/** Object for who's going to get paid on which blocks */
CMasternodePayments masternodePayments;
@@ -23,6 +32,26 @@ CCriticalSection cs_vecPayments;
CCriticalSection cs_mapMasternodeBlocks;
CCriticalSection cs_mapMasternodePayeeVotes;
namespace {
// Select the correct "newly created" transaction for payee validation based on block type.
// - PoW blocks: coinbase is vtx[0]
// - PoS blocks: coinstake is vtx[1] (with a null coinbase at vtx[0])
//
// This must NOT be derived from height-era assumptions, because Agrarian runs PoW+PoS concurrently
// from Params().FIRST_POS_BLOCK() through Params().LAST_POW_BLOCK().
const CTransaction& GetBlockNewTxForPayeeChecks(const CBlock& block)
{
// Defensive: preserve old behavior if vector is unexpectedly small.
// A valid PoS block should have at least 2 tx; a valid PoW block at least 1 tx.
if (block.IsProofOfStake() && block.vtx.size() > 1) {
return block.vtx[1];
}
return block.vtx[0];
}
} // namespace
//
// CMasternodePaymentDB
//
@@ -35,61 +64,81 @@ CMasternodePaymentDB::CMasternodePaymentDB()
bool CMasternodePaymentDB::Write(const CMasternodePayments& objToSave)
{
int64_t nStart = GetTimeMillis();
const int64_t nStart = GetTimeMillis();
// serialize, checksum data up to that point, then append checksum
CDataStream ssObj(SER_DISK, CLIENT_VERSION);
ssObj << strMagicMessage; // masternode cache file specific magic message
ssObj << FLATDATA(Params().MessageStart()); // network specific magic number
ssObj << objToSave;
uint256 hash = Hash(ssObj.begin(), ssObj.end());
const uint256 hash = Hash(ssObj.begin(), ssObj.end());
ssObj << hash;
// open output file, and associate with CAutoFile
FILE* file = fopen(pathDB.string().c_str(), "wb");
CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
if (fileout.IsNull())
FILE* file = std::fopen(pathDB.string().c_str(), "wb");
if (file == nullptr) {
return error("%s : Failed to open file %s", __func__, pathDB.string());
}
CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
if (fileout.IsNull()) {
return error("%s : Failed to open file %s", __func__, pathDB.string());
}
// Write and commit header, data
try {
fileout << ssObj;
} catch (std::exception& e) {
} catch (const std::exception& e) {
return error("%s : Serialize or I/O error - %s", __func__, e.what());
}
fileout.fclose();
LogPrint("masternode","Written info to mnpayments.dat %dms\n", GetTimeMillis() - nStart);
LogPrint("masternode", "Written info to mnpayments.dat %dms\n", GetTimeMillis() - nStart);
return true;
}
CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments& objToLoad, bool fDryRun)
{
int64_t nStart = GetTimeMillis();
const int64_t nStart = GetTimeMillis();
// open input file, and associate with CAutoFile
FILE* file = fopen(pathDB.string().c_str(), "rb");
FILE* file = std::fopen(pathDB.string().c_str(), "rb");
if (file == nullptr) {
error("%s : Failed to open file %s", __func__, pathDB.string());
return FileError;
}
CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
if (filein.IsNull()) {
error("%s : Failed to open file %s", __func__, pathDB.string());
return FileError;
}
// use file size to size memory buffer
int fileSize = boost::filesystem::file_size(pathDB);
int dataSize = fileSize - sizeof(uint256);
int fileSize = 0;
try {
fileSize = static_cast<int>(boost::filesystem::file_size(pathDB));
} catch (const std::exception& e) {
error("%s : Unable to read file size %s (%s)", __func__, pathDB.string(), e.what());
return FileError;
}
int dataSize = fileSize - static_cast<int>(sizeof(uint256));
// Don't try to resize to a negative number if file is small
if (dataSize < 0)
if (dataSize < 0) {
dataSize = 0;
vector<unsigned char> vchData;
vchData.resize(dataSize);
}
std::vector<unsigned char> vchData;
vchData.resize(static_cast<size_t>(dataSize));
uint256 hashIn;
// read data and checksum from file
try {
filein.read((char*)&vchData[0], dataSize);
if (dataSize > 0) {
filein.read(reinterpret_cast<char*>(&vchData[0]), dataSize);
}
filein >> hashIn;
} catch (std::exception& e) {
} catch (const std::exception& e) {
error("%s : Deserialize or I/O error - %s", __func__, e.what());
return HashReadError;
}
@@ -98,7 +147,7 @@ CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments&
CDataStream ssObj(vchData, SER_DISK, CLIENT_VERSION);
// verify stored checksum matches input data
uint256 hashTmp = Hash(ssObj.begin(), ssObj.end());
const uint256 hashTmp = Hash(ssObj.begin(), ssObj.end());
if (hashIn != hashTmp) {
error("%s : Checksum mismatch, data corrupted", __func__);
return IncorrectHash;
@@ -112,35 +161,35 @@ CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments&
// ... verify the message matches predefined one
if (strMagicMessage != strMagicMessageTmp) {
error("%s : Invalid masternode payement cache magic message", __func__);
error("%s : Invalid masternode payment cache magic message", __func__);
return IncorrectMagicMessage;
}
// de-serialize file header (network specific magic number) and ..
ssObj >> FLATDATA(pchMsgTmp);
// ... verify the network matches ours
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) {
if (std::memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) {
error("%s : Invalid network magic number", __func__);
return IncorrectMagicNumber;
}
// de-serialize data into CMasternodePayments object
ssObj >> objToLoad;
} catch (std::exception& e) {
} catch (const std::exception& e) {
objToLoad.Clear();
error("%s : Deserialize or I/O error - %s", __func__, e.what());
return IncorrectFormat;
}
LogPrint("masternode","Loaded info from mnpayments.dat %dms\n", GetTimeMillis() - nStart);
LogPrint("masternode"," %s\n", objToLoad.ToString());
LogPrint("masternode", "Loaded info from mnpayments.dat %dms\n", GetTimeMillis() - nStart);
LogPrint("masternode", " %s\n", objToLoad.ToString());
if (!fDryRun) {
LogPrint("masternode","Masternode payments manager - cleaning....\n");
LogPrint("masternode", "Masternode payments manager - cleaning....\n");
objToLoad.CleanPaymentList();
LogPrint("masternode","Masternode payments manager - result:\n");
LogPrint("masternode"," %s\n", objToLoad.ToString());
LogPrint("masternode", "Masternode payments manager - result:\n");
LogPrint("masternode", " %s\n", objToLoad.ToString());
}
return Ok;
@@ -148,92 +197,89 @@ CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments&
void DumpMasternodePayments()
{
int64_t nStart = GetTimeMillis();
const int64_t nStart = GetTimeMillis();
CMasternodePaymentDB paymentdb;
CMasternodePayments tempPayments;
LogPrint("masternode","Verifying mnpayments.dat format...\n");
CMasternodePaymentDB::ReadResult readResult = paymentdb.Read(tempPayments, true);
LogPrint("masternode", "Verifying mnpayments.dat format...\n");
const CMasternodePaymentDB::ReadResult readResult = paymentdb.Read(tempPayments, true);
// there was an error and it was not an error on file opening => do not proceed
if (readResult == CMasternodePaymentDB::FileError)
LogPrint("masternode","Missing budgets file - mnpayments.dat, will try to recreate\n");
else if (readResult != CMasternodePaymentDB::Ok) {
LogPrint("masternode","Error reading mnpayments.dat: ");
if (readResult == CMasternodePaymentDB::IncorrectFormat)
LogPrint("masternode","magic is ok but data has invalid format, will try to recreate\n");
else {
LogPrint("masternode","file format is unknown or invalid, please fix it manually\n");
if (readResult == CMasternodePaymentDB::FileError) {
LogPrint("masternode", "Missing payments file - mnpayments.dat, will try to recreate\n");
} else if (readResult != CMasternodePaymentDB::Ok) {
LogPrint("masternode", "Error reading mnpayments.dat: ");
if (readResult == CMasternodePaymentDB::IncorrectFormat) {
LogPrint("masternode", "magic is ok but data has invalid format, will try to recreate\n");
} else {
LogPrint("masternode", "file format is unknown or invalid, please fix it manually\n");
return;
}
}
LogPrint("masternode","Writting info to mnpayments.dat...\n");
LogPrint("masternode", "Writing info to mnpayments.dat...\n");
paymentdb.Write(masternodePayments);
LogPrint("masternode","Budget dump finished %dms\n", GetTimeMillis() - nStart);
LogPrint("masternode", "Payments dump finished %dms\n", GetTimeMillis() - nStart);
}
bool IsBlockValueValid(const CBlock& block, CAmount nExpectedValue, CAmount nMinted)
{
CBlockIndex* pindexPrev = chainActive.Tip();
if (pindexPrev == NULL) return true;
if (pindexPrev == nullptr) {
return true;
}
int nHeight = 0;
if (pindexPrev->GetBlockHash() == block.hashPrevBlock) {
nHeight = pindexPrev->nHeight + 1;
} else { //out of order
} else { // out of order
BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
if (mi != mapBlockIndex.end() && (*mi).second)
if (mi != mapBlockIndex.end() && (*mi).second) {
nHeight = (*mi).second->nHeight + 1;
}
}
if (nHeight == 0) {
LogPrint("masternode","IsBlockValueValid() : WARNING: Couldn't find previous block\n");
LogPrint("masternode", "IsBlockValueValid() : WARNING: Couldn't find previous block\n");
}
//LogPrintf("XX69----------> IsBlockValueValid(): nMinted: %d, nExpectedValue: %d\n", FormatMoney(nMinted), FormatMoney(nExpectedValue));
if (!masternodeSync.IsSynced()) { //there is no budget data to use to check anything
//super blocks will always be on these blocks, max 100 per budgeting
if (!masternodeSync.IsSynced()) { // there is no budget data to use to check anything
// super blocks will always be on these blocks, max 100 per budgeting
if (nHeight % Params().GetBudgetCycleBlocks() < 100) {
return true;
} else {
if (nMinted > nExpectedValue) {
return false;
}
}
} else { // we're synced and have data so check the budget schedule
//are these blocks even enabled
if (!IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS)) {
return nMinted <= nExpectedValue;
}
if (budget.IsBudgetPaymentBlock(nHeight)) {
//the value of the block is evaluated in CheckBlock
return true;
} else {
if (nMinted > nExpectedValue) {
return false;
}
}
return nMinted <= nExpectedValue;
}
return true;
// we're synced and have data so check the budget schedule
// are these blocks even enabled
if (!IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS)) {
return nMinted <= nExpectedValue;
}
if (budget.IsBudgetPaymentBlock(nHeight)) {
// the value of the block is evaluated in CheckBlock
return true;
}
return nMinted <= nExpectedValue;
}
bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight)
{
TrxValidationStatus transactionStatus = TrxValidationStatus::InValid;
if (!masternodeSync.IsSynced()) { //there is no budget data to use to check anything -- find the longest chain
if (!masternodeSync.IsSynced()) { // there is no budget data to use to check anything -- find the longest chain
LogPrint("mnpayments", "Client not synced, skipping block payee checks\n");
return true;
}
const CTransaction& txNew = (nBlockHeight > Params().LAST_POW_BLOCK() ? block.vtx[1] : block.vtx[0]);
const CTransaction& txNew = GetBlockNewTxForPayeeChecks(block);
//check if it's a budget block
// check if it's a budget block
if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS)) {
if (budget.IsBudgetPaymentBlock(nBlockHeight)) {
transactionStatus = budget.IsTransactionValid(txNew, nBlockHeight);
@@ -242,39 +288,44 @@ bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight)
}
if (transactionStatus == TrxValidationStatus::InValid) {
LogPrint("masternode","Invalid budget payment detected %s\n", txNew.ToString().c_str());
if (IsSporkActive(SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT))
LogPrint("masternode", "Invalid budget payment detected %s\n", txNew.ToString().c_str());
if (IsSporkActive(SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT)) {
return false;
LogPrint("masternode","Budget enforcement is disabled, accepting block\n");
}
LogPrint("masternode", "Budget enforcement is disabled, accepting block\n");
}
}
}
// If we end here the transaction was either TrxValidationStatus::InValid and Budget enforcement is disabled, or
// a double budget payment (status = TrxValidationStatus::DoublePayment) was detected, or no/not enough masternode
// votes (status = TrxValidationStatus::VoteThreshold) for a finalized budget were found
// In all cases a masternode will get the payment for this block
// If we end here the transaction was either InValid and Budget enforcement is disabled, or
// a double budget payment (DoublePayment) was detected, or no/not enough masternode
// votes (VoteThreshold) for a finalized budget were found.
// In all cases a masternode will get the payment for this block.
//check for masternode payee
if (masternodePayments.IsTransactionValid(txNew, nBlockHeight))
// check for masternode payee
if (masternodePayments.IsTransactionValid(txNew, nBlockHeight)) {
return true;
LogPrint("masternode","Invalid mn payment detected %s\n", txNew.ToString().c_str());
}
if (IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT))
LogPrint("masternode", "Invalid mn payment detected %s\n", txNew.ToString().c_str());
if (IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) {
return false;
LogPrint("masternode","Masternode payment enforcement is disabled, accepting block\n");
}
LogPrint("masternode", "Masternode payment enforcement is disabled, accepting block\n");
return true;
}
void FillBlockPayee(CMutableTransaction& txNew, CAmount nFees, bool fProofOfStake, bool fZAGRStake)
{
CBlockIndex* pindexPrev = chainActive.Tip();
if (!pindexPrev) return;
if (!pindexPrev) {
return;
}
if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS) && budget.IsBudgetPaymentBlock(pindexPrev->nHeight + 1)) {
const int nextHeight = pindexPrev->nHeight + 1;
if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS) && budget.IsBudgetPaymentBlock(nextHeight)) {
budget.FillBlockPayee(txNew, nFees, fProofOfStake);
} else {
masternodePayments.FillBlockPayee(txNew, nFees, fProofOfStake, fZAGRStake);
@@ -285,49 +336,55 @@ std::string GetRequiredPaymentsString(int nBlockHeight)
{
if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS) && budget.IsBudgetPaymentBlock(nBlockHeight)) {
return budget.GetRequiredPaymentsString(nBlockHeight);
} else {
return masternodePayments.GetRequiredPaymentsString(nBlockHeight);
}
return masternodePayments.GetRequiredPaymentsString(nBlockHeight);
}
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int64_t nFees, bool fProofOfStake, bool fZAGRStake)
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int64_t /*nFees*/, bool fProofOfStake, bool fZAGRStake)
{
CBlockIndex* pindexPrev = chainActive.Tip();
if (!pindexPrev) return;
if (!pindexPrev) {
return;
}
bool hasPayment = true;
CScript payee;
//spork
// spork / schedule
if (!masternodePayments.GetBlockPayee(pindexPrev->nHeight + 1, payee)) {
//no masternode detected
// no masternode detected
CMasternode* winningNode = mnodeman.GetCurrentMasterNode(1);
if (winningNode) {
payee = GetScriptForDestination(winningNode->pubKeyCollateralAddress.GetID());
} else {
LogPrint("masternode","CreateNewBlock: Failed to detect masternode to pay\n");
LogPrint("masternode", "CreateNewBlock: Failed to detect masternode to pay\n");
hasPayment = false;
}
}
CAmount blockValue = GetBlockValue(pindexPrev->nHeight);
CAmount masternodePayment = GetMasternodePayment(pindexPrev->nHeight, blockValue, 0, fZAGRStake);
const int payHeight = pindexPrev->nHeight + 1;
const CAmount blockValue = GetBlockValue(payHeight);
const CAmount masternodePayment = GetMasternodePayment(payHeight, blockValue, 0, fZAGRStake);
if (hasPayment) {
if (fProofOfStake) {
/**For Proof Of Stake vout[0] must be null
/** For Proof Of Stake vout[0] must be null.
* Stake reward can be split into many different outputs, so we must
* use vout.size() to align with several different cases.
* An additional output is appended as the masternode payment
* An additional output is appended as the masternode payment.
*/
unsigned int i = txNew.vout.size();
const unsigned int i = txNew.vout.size();
txNew.vout.resize(i + 1);
txNew.vout[i].scriptPubKey = payee;
txNew.vout[i].nValue = masternodePayment;
//subtract mn payment from the stake reward
if (!txNew.vout[1].IsZerocoinMint())
txNew.vout[i - 1].nValue -= masternodePayment;
// subtract mn payment from the stake reward
// NOTE: original code used vout[1] and (i-1); keep behavior, but guard bounds.
if (i > 0) {
if (!txNew.vout[1].IsZerocoinMint() && (i - 1) < txNew.vout.size()) {
txNew.vout[i - 1].nValue -= masternodePayment;
}
}
} else {
txNew.vout.resize(2);
txNew.vout[1].scriptPubKey = payee;
@@ -339,28 +396,28 @@ void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int64_t nFe
ExtractDestination(payee, address1);
CBitcoinAddress address2(address1);
LogPrint("masternode","Masternode payment of %s to %s\n", FormatMoney(masternodePayment).c_str(), address2.ToString().c_str());
LogPrint("masternode", "Masternode payment of %s to %s\n", FormatMoney(masternodePayment).c_str(), address2.ToString().c_str());
}
}
int CMasternodePayments::GetMinMasternodePaymentsProto()
{
if (IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES))
return ActiveProtocol(); // Allow only updated peers
else
return MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT; // Also allow old peers as long as they are allowed to run
return ActiveProtocol(); // Allow only updated peers
return MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT; // Also allow old peers as long as they are allowed to run
}
void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
{
if (!masternodeSync.IsBlockchainSynced()) return;
if (!masternodeSync.IsBlockchainSynced()) {
return;
}
if (fLiteMode) return; //disable all Obfuscation/Masternode related functionality
if (strCommand == "mnget") { //Masternode Payments Request Sync
if (fLiteMode) return; //disable all Obfuscation/Masternode related functionality
if (fLiteMode) {
return; // disable all Obfuscation/Masternode related functionality
}
if (strCommand == "mnget") { // Masternode Payments Request Sync
int nCountNeeded;
vRecv >> nCountNeeded;
@@ -375,17 +432,23 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
pfrom->FulfilledRequest("mnget");
masternodePayments.Sync(pfrom, nCountNeeded);
LogPrint("mnpayments", "mnget - Sent Masternode winners to peer %i\n", pfrom->GetId());
} else if (strCommand == "mnw") { //Masternode Payments Declare Winner
//this is required in litemodef
return;
}
if (strCommand == "mnw") { // Masternode Payments Declare Winner
CMasternodePaymentWinner winner;
vRecv >> winner;
if (pfrom->nVersion < ActiveProtocol()) return;
if (pfrom->nVersion < ActiveProtocol()) {
return;
}
int nHeight;
{
TRY_LOCK(cs_main, locked);
if (!locked || chainActive.Tip() == NULL) return;
if (!locked || chainActive.Tip() == nullptr) {
return;
}
nHeight = chainActive.Tip()->nHeight;
}
@@ -395,20 +458,18 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
return;
}
int nFirstBlock = nHeight - (mnodeman.CountEnabled() * 1.25);
const int nFirstBlock = nHeight - static_cast<int>(mnodeman.CountEnabled() * 1.25);
if (winner.nBlockHeight < nFirstBlock || winner.nBlockHeight > nHeight + 20) {
LogPrint("mnpayments", "mnw - winner out of range - FirstBlock %d Height %d bestHeight %d\n", nFirstBlock, winner.nBlockHeight, nHeight);
return;
}
std::string strError = "";
std::string strError;
if (!winner.IsValid(pfrom, strError)) {
// if(strError != "") LogPrint("masternode","mnw - invalid message - %s\n", strError);
return;
}
if (!masternodePayments.CanVote(winner.vinMasternode.prevout, winner.nBlockHeight)) {
// LogPrint("masternode","mnw - masternode already voted - %s\n", winner.vinMasternode.prevout.ToStringShort());
return;
}
@@ -422,33 +483,28 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
return;
}
CTxDestination address1;
ExtractDestination(winner.payee, address1);
CBitcoinAddress address2(address1);
// LogPrint("mnpayments", "mnw - winning vote - Addr %s Height %d bestHeight %d - %s\n", address2.ToString().c_str(), winner.nBlockHeight, nHeight, winner.vinMasternode.prevout.ToStringShort());
if (masternodePayments.AddWinningMasternode(winner)) {
winner.Relay();
masternodeSync.AddedMasternodeWinner(winner.GetHash());
}
return;
}
}
bool CMasternodePaymentWinner::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode)
{
std::string errorMessage;
std::string strMasterNodeSignMessage;
std::string strMessage = vinMasternode.prevout.ToStringShort() + std::to_string(nBlockHeight) + payee.ToString();
const std::string strMessage =
vinMasternode.prevout.ToStringShort() + std::to_string(nBlockHeight) + payee.ToString();
if (!obfuScationSigner.SignMessage(strMessage, errorMessage, vchSig, keyMasternode)) {
LogPrint("masternode","CMasternodePing::Sign() - Error: %s\n", errorMessage.c_str());
LogPrint("masternode", "CMasternodePing::Sign() - Error: %s\n", errorMessage.c_str());
return false;
}
if (!obfuScationSigner.VerifyMessage(pubKeyMasternode, vchSig, strMessage, errorMessage)) {
LogPrint("masternode","CMasternodePing::Sign() - Error: %s\n", errorMessage.c_str());
LogPrint("masternode", "CMasternodePing::Sign() - Error: %s\n", errorMessage.c_str());
return false;
}
@@ -460,7 +516,6 @@ bool CMasternodePayments::GetBlockPayee(int nBlockHeight, CScript& payee)
if (mapMasternodeBlocks.count(nBlockHeight)) {
return mapMasternodeBlocks[nBlockHeight].GetPayee(payee);
}
return false;
}
@@ -473,16 +528,19 @@ bool CMasternodePayments::IsScheduled(CMasternode& mn, int nNotBlockHeight)
int nHeight;
{
TRY_LOCK(cs_main, locked);
if (!locked || chainActive.Tip() == NULL) return false;
if (!locked || chainActive.Tip() == nullptr) {
return false;
}
nHeight = chainActive.Tip()->nHeight;
}
CScript mnpayee;
mnpayee = GetScriptForDestination(mn.pubKeyCollateralAddress.GetID());
const CScript mnpayee = GetScriptForDestination(mn.pubKeyCollateralAddress.GetID());
CScript payee;
for (int64_t h = nHeight; h <= nHeight + 8; h++) {
if (h == nNotBlockHeight) continue;
if (h == nNotBlockHeight) {
continue;
}
if (mapMasternodeBlocks.count(h)) {
if (mapMasternodeBlocks[h].GetPayee(payee)) {
if (mnpayee == payee) {
@@ -518,7 +576,6 @@ bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerI
}
mapMasternodeBlocks[winnerIn.nBlockHeight].AddPayee(winnerIn.payee, 1);
return true;
}
@@ -529,50 +586,60 @@ bool CMasternodeBlockPayees::IsTransactionValid(const CTransaction& txNew)
int nMaxSignatures = 0;
int nMasternode_Drift_Count = 0;
std::string strPayeesPossible = "";
std::string strPayeesPossible;
CAmount nReward = GetBlockValue(nBlockHeight);
const CAmount nReward = GetBlockValue(nBlockHeight);
if (IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) {
// Get a stable number of masternodes by ignoring newly activated (< 8000 sec old) masternodes
nMasternode_Drift_Count = mnodeman.stable_size() + Params().MasternodeCountDrift();
}
else {
//account for the fact that all peers do not see the same masternode count. A allowance of being off our masternode count is given
//we only need to look at an increased masternode count because as count increases, the reward decreases. This code only checks
//for mnPayment >= required, so it only makes sense to check the max node count allowed.
} else {
// Account for the fact that all peers do not see the same masternode count.
// An allowance of being off our masternode count is given.
// We only need to look at an increased masternode count because as count increases, the reward decreases.
// This code only checks for mnPayment >= required, so it only makes sense to check the max node count allowed.
nMasternode_Drift_Count = mnodeman.size() + Params().MasternodeCountDrift();
}
CAmount requiredMasternodePayment = GetMasternodePayment(nBlockHeight, nReward, nMasternode_Drift_Count, txNew.HasZerocoinSpendInputs());
const CAmount requiredMasternodePayment =
GetMasternodePayment(nBlockHeight, nReward, nMasternode_Drift_Count, txNew.HasZerocoinSpendInputs());
//require at least 6 signatures
for (CMasternodePayee& payee : vecPayments)
if (payee.nVotes >= nMaxSignatures && payee.nVotes >= MNPAYMENTS_SIGNATURES_REQUIRED)
// require at least 6 signatures
for (CMasternodePayee& payee : vecPayments) {
if (payee.nVotes >= nMaxSignatures && payee.nVotes >= MNPAYMENTS_SIGNATURES_REQUIRED) {
nMaxSignatures = payee.nVotes;
}
}
// if we don't have at least 6 signatures on a payee, approve whichever is the longest chain
if (nMaxSignatures < MNPAYMENTS_SIGNATURES_REQUIRED) return true;
// If we don't have at least 6 signatures on a payee, approve whichever is the longest chain
if (nMaxSignatures < MNPAYMENTS_SIGNATURES_REQUIRED) {
return true;
}
for (CMasternodePayee& payee : vecPayments) {
bool found = false;
for (CTxOut out : txNew.vout) {
for (const CTxOut& out : txNew.vout) {
if (payee.scriptPubKey == out.scriptPubKey) {
if(out.nValue >= requiredMasternodePayment)
if (out.nValue >= requiredMasternodePayment) {
found = true;
else
LogPrint("masternode","Masternode payment is out of drift range. Paid=%s Min=%s\n", FormatMoney(out.nValue).c_str(), FormatMoney(requiredMasternodePayment).c_str());
} else {
LogPrint("masternode", "Masternode payment is out of drift range. Paid=%s Min=%s\n",
FormatMoney(out.nValue).c_str(), FormatMoney(requiredMasternodePayment).c_str());
}
}
}
if (payee.nVotes >= MNPAYMENTS_SIGNATURES_REQUIRED) {
if (found) return true;
if (found) {
return true;
}
CTxDestination address1;
ExtractDestination(payee.scriptPubKey, address1);
CBitcoinAddress address2(address1);
if (strPayeesPossible == "") {
if (strPayeesPossible.empty()) {
strPayeesPossible += address2.ToString();
} else {
strPayeesPossible += "," + address2.ToString();
@@ -580,7 +647,8 @@ bool CMasternodeBlockPayees::IsTransactionValid(const CTransaction& txNew)
}
}
LogPrint("masternode","CMasternodePayments::IsTransactionValid - Missing required payment of %s to %s\n", FormatMoney(requiredMasternodePayment).c_str(), strPayeesPossible.c_str());
LogPrint("masternode", "CMasternodePayments::IsTransactionValid - Missing required payment of %s to %s\n",
FormatMoney(requiredMasternodePayment).c_str(), strPayeesPossible.c_str());
return false;
}
@@ -634,16 +702,18 @@ void CMasternodePayments::CleanPaymentList()
int nHeight;
{
TRY_LOCK(cs_main, locked);
if (!locked || chainActive.Tip() == NULL) return;
if (!locked || chainActive.Tip() == nullptr) {
return;
}
nHeight = chainActive.Tip()->nHeight;
}
//keep up to five cycles for historical sake
int nLimit = std::max(int(mnodeman.size() * 1.25), 1000);
// keep up to five cycles for historical sake
const int nLimit = std::max(static_cast<int>(mnodeman.size() * 1.25), 1000);
std::map<uint256, CMasternodePaymentWinner>::iterator it = mapMasternodePayeeVotes.begin();
while (it != mapMasternodePayeeVotes.end()) {
CMasternodePaymentWinner winner = (*it).second;
const CMasternodePaymentWinner& winner = (*it).second;
if (nHeight - winner.nBlockHeight > nLimit) {
LogPrint("mnpayments", "CMasternodePayments::CleanPaymentList - Removing old Masternode payment - block %d\n", winner.nBlockHeight);
@@ -662,26 +732,26 @@ bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError)
if (!pmn) {
strError = strprintf("Unknown Masternode %s", vinMasternode.prevout.hash.ToString());
LogPrint("masternode","CMasternodePaymentWinner::IsValid - %s\n", strError);
LogPrint("masternode", "CMasternodePaymentWinner::IsValid - %s\n", strError);
mnodeman.AskForMN(pnode, vinMasternode);
return false;
}
if (pmn->protocolVersion < ActiveProtocol()) {
strError = strprintf("Masternode protocol too old %d - req %d", pmn->protocolVersion, ActiveProtocol());
LogPrint("masternode","CMasternodePaymentWinner::IsValid - %s\n", strError);
LogPrint("masternode", "CMasternodePaymentWinner::IsValid - %s\n", strError);
return false;
}
int n = mnodeman.GetMasternodeRank(vinMasternode, nBlockHeight - 100, ActiveProtocol());
const int n = mnodeman.GetMasternodeRank(vinMasternode, nBlockHeight - 100, ActiveProtocol());
if (n > MNPAYMENTS_SIGNATURES_TOTAL) {
//It's common to have masternodes mistakenly think they are in the top 10
// We don't want to print all of these messages, or punish them unless they're way off
// It's common to have masternodes mistakenly think they are in the top 10.
// We don't want to print all of these messages, or punish them unless they're way off.
if (n > MNPAYMENTS_SIGNATURES_TOTAL * 2) {
strError = strprintf("Masternode not in the top %d (%d)", MNPAYMENTS_SIGNATURES_TOTAL * 2, n);
LogPrint("masternode","CMasternodePaymentWinner::IsValid - %s\n", strError);
//if (masternodeSync.IsSynced()) Misbehaving(pnode->GetId(), 20);
LogPrint("masternode", "CMasternodePaymentWinner::IsValid - %s\n", strError);
// if (masternodeSync.IsSynced()) Misbehaving(pnode->GetId(), 20);
}
return false;
}
@@ -691,11 +761,12 @@ bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError)
bool CMasternodePayments::ProcessBlock(int nBlockHeight)
{
if (!fMasterNode) return false;
if (!fMasterNode) {
return false;
}
//reference node - hybrid mode
int n = mnodeman.GetMasternodeRank(activeMasternode.vin, nBlockHeight - 100, ActiveProtocol());
// reference node - hybrid mode
const int n = mnodeman.GetMasternodeRank(activeMasternode.vin, nBlockHeight - 100, ActiveProtocol());
if (n == -1) {
LogPrint("mnpayments", "CMasternodePayments::ProcessBlock - Unknown Masternode\n");
@@ -707,34 +778,38 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
return false;
}
if (nBlockHeight <= nLastBlockHeight) return false;
if (nBlockHeight <= nLastBlockHeight) {
return false;
}
CMasternodePaymentWinner newWinner(activeMasternode.vin);
if (budget.IsBudgetPaymentBlock(nBlockHeight)) {
//is budget payment block -- handled by the budgeting software
// budget payment block -- handled by the budgeting software
} else {
LogPrint("masternode","CMasternodePayments::ProcessBlock() Start nHeight %d - vin %s. \n", nBlockHeight, activeMasternode.vin.prevout.hash.ToString());
LogPrint("masternode", "CMasternodePayments::ProcessBlock() Start nHeight %d - vin %s. \n",
nBlockHeight, activeMasternode.vin.prevout.hash.ToString());
// pay to the oldest MN that still had no payment but its input is old enough and it was active long enough
int nCount = 0;
CMasternode* pmn = mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount);
if (pmn != NULL) {
LogPrint("masternode","CMasternodePayments::ProcessBlock() Found by FindOldestNotInVec \n");
if (pmn != nullptr) {
LogPrint("masternode", "CMasternodePayments::ProcessBlock() Found by FindOldestNotInVec \n");
newWinner.nBlockHeight = nBlockHeight;
CScript payee = GetScriptForDestination(pmn->pubKeyCollateralAddress.GetID());
const CScript payee = GetScriptForDestination(pmn->pubKeyCollateralAddress.GetID());
newWinner.AddPayee(payee);
CTxDestination address1;
ExtractDestination(payee, address1);
CBitcoinAddress address2(address1);
LogPrint("masternode","CMasternodePayments::ProcessBlock() Winner payee %s nHeight %d. \n", address2.ToString().c_str(), newWinner.nBlockHeight);
LogPrint("masternode", "CMasternodePayments::ProcessBlock() Winner payee %s nHeight %d. \n",
address2.ToString().c_str(), newWinner.nBlockHeight);
} else {
LogPrint("masternode","CMasternodePayments::ProcessBlock() Failed to find masternode to pay\n");
LogPrint("masternode", "CMasternodePayments::ProcessBlock() Failed to find masternode to pay\n");
}
}
@@ -743,13 +818,13 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
CKey keyMasternode;
if (!obfuScationSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode)) {
LogPrint("masternode","CMasternodePayments::ProcessBlock() - Error upon calling SetKey: %s\n", errorMessage.c_str());
LogPrint("masternode", "CMasternodePayments::ProcessBlock() - Error upon calling SetKey: %s\n", errorMessage.c_str());
return false;
}
LogPrint("masternode","CMasternodePayments::ProcessBlock() - Signing Winner\n");
LogPrint("masternode", "CMasternodePayments::ProcessBlock() - Signing Winner\n");
if (newWinner.Sign(keyMasternode, pubKeyMasternode)) {
LogPrint("masternode","CMasternodePayments::ProcessBlock() - AddWinningMasternode\n");
LogPrint("masternode", "CMasternodePayments::ProcessBlock() - AddWinningMasternode\n");
if (AddWinningMasternode(newWinner)) {
newWinner.Relay();
@@ -771,12 +846,14 @@ bool CMasternodePaymentWinner::SignatureValid()
{
CMasternode* pmn = mnodeman.Find(vinMasternode);
if (pmn != NULL) {
std::string strMessage = vinMasternode.prevout.ToStringShort() + std::to_string(nBlockHeight) + payee.ToString();
if (pmn != nullptr) {
const std::string strMessage =
vinMasternode.prevout.ToStringShort() + std::to_string(nBlockHeight) + payee.ToString();
std::string errorMessage = "";
std::string errorMessage;
if (!obfuScationSigner.VerifyMessage(pmn->pubKeyMasternode, vchSig, strMessage, errorMessage)) {
return error("CMasternodePaymentWinner::SignatureValid() - Got bad Masternode address signature %s\n", vinMasternode.prevout.hash.ToString());
return error("CMasternodePaymentWinner::SignatureValid() - Got bad Masternode address signature %s\n",
vinMasternode.prevout.hash.ToString());
}
return true;
@@ -792,36 +869,38 @@ void CMasternodePayments::Sync(CNode* node, int nCountNeeded)
int nHeight;
{
TRY_LOCK(cs_main, locked);
if (!locked || chainActive.Tip() == NULL) return;
if (!locked || chainActive.Tip() == nullptr) {
return;
}
nHeight = chainActive.Tip()->nHeight;
}
int nCount = (mnodeman.CountEnabled() * 1.25);
if (nCountNeeded > nCount) nCountNeeded = nCount;
int nCount = static_cast<int>(mnodeman.CountEnabled() * 1.25);
if (nCountNeeded > nCount) {
nCountNeeded = nCount;
}
int nInvCount = 0;
std::map<uint256, CMasternodePaymentWinner>::iterator it = mapMasternodePayeeVotes.begin();
while (it != mapMasternodePayeeVotes.end()) {
CMasternodePaymentWinner winner = (*it).second;
const CMasternodePaymentWinner& winner = (*it).second;
if (winner.nBlockHeight >= nHeight - nCountNeeded && winner.nBlockHeight <= nHeight + 20) {
node->PushInventory(CInv(MSG_MASTERNODE_WINNER, winner.GetHash()));
nInvCount++;
}
++it;
}
node->PushMessage("ssc", MASTERNODE_SYNC_MNW, nInvCount);
}
std::string CMasternodePayments::ToString() const
{
std::ostringstream info;
info << "Votes: " << (int)mapMasternodePayeeVotes.size() << ", Blocks: " << (int)mapMasternodeBlocks.size();
return info.str();
}
int CMasternodePayments::GetOldestBlock()
{
LOCK(cs_mapMasternodeBlocks);
@@ -833,13 +912,12 @@ int CMasternodePayments::GetOldestBlock()
if ((*it).first < nOldestBlock) {
nOldestBlock = (*it).first;
}
it++;
++it;
}
return nOldestBlock;
}
int CMasternodePayments::GetNewestBlock()
{
LOCK(cs_mapMasternodeBlocks);
@@ -851,7 +929,7 @@ int CMasternodePayments::GetNewestBlock()
if ((*it).first > nNewestBlock) {
nNewestBlock = (*it).first;
}
it++;
++it;
}
return nNewestBlock;
+34 -67
View File
@@ -1,16 +1,19 @@
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2019 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef MASTERNODE_PAYMENTS_H
#define MASTERNODE_PAYMENTS_H
#ifndef AGRARIAN_MASTERNODE_PAYMENTS_H
#define AGRARIAN_MASTERNODE_PAYMENTS_H
#include "key.h"
#include "main.h"
#include "masternode.h"
using namespace std;
#include <map>
#include <string>
#include <vector>
extern CCriticalSection cs_vecPayments;
extern CCriticalSection cs_mapMasternodeBlocks;
@@ -33,8 +36,7 @@ void FillBlockPayee(CMutableTransaction& txNew, CAmount nFees, bool fProofOfStak
void DumpMasternodePayments();
/** Save Masternode Payment Data (mnpayments.dat)
*/
/** Save Masternode Payment Data (mnpayments.dat) */
class CMasternodePaymentDB
{
private:
@@ -63,17 +65,8 @@ public:
CScript scriptPubKey;
int nVotes;
CMasternodePayee()
{
scriptPubKey = CScript();
nVotes = 0;
}
CMasternodePayee(CScript payee, int nVotesIn)
{
scriptPubKey = payee;
nVotes = nVotesIn;
}
CMasternodePayee() : scriptPubKey(CScript()), nVotes(0) {}
CMasternodePayee(const CScript& payee, int nVotesIn) : scriptPubKey(payee), nVotes(nVotesIn) {}
ADD_SERIALIZE_METHODS;
@@ -92,18 +85,10 @@ public:
int nBlockHeight;
std::vector<CMasternodePayee> vecPayments;
CMasternodeBlockPayees()
{
nBlockHeight = 0;
vecPayments.clear();
}
CMasternodeBlockPayees(int nBlockHeightIn)
{
nBlockHeight = nBlockHeightIn;
vecPayments.clear();
}
CMasternodeBlockPayees() : nBlockHeight(0), vecPayments() {}
explicit CMasternodeBlockPayees(int nBlockHeightIn) : nBlockHeight(nBlockHeightIn), vecPayments() {}
void AddPayee(CScript payeeIn, int nIncrement)
void AddPayee(const CScript& payeeIn, int nIncrement)
{
LOCK(cs_vecPayments);
@@ -114,8 +99,7 @@ public:
}
}
CMasternodePayee c(payeeIn, nIncrement);
vecPayments.push_back(c);
vecPayments.emplace_back(payeeIn, nIncrement);
}
bool GetPayee(CScript& payee)
@@ -133,12 +117,14 @@ public:
return (nVotes > -1);
}
bool HasPayeeWithVotes(CScript payee, int nVotesReq)
bool HasPayeeWithVotes(const CScript& payee, int nVotesReq)
{
LOCK(cs_vecPayments);
for (CMasternodePayee& p : vecPayments) {
if (p.nVotes >= nVotesReq && p.scriptPubKey == payee) return true;
if (p.nVotes >= nVotesReq && p.scriptPubKey == payee) {
return true;
}
}
return false;
@@ -157,29 +143,17 @@ public:
}
};
// for storing the winning payments
// For storing the winning payments
class CMasternodePaymentWinner
{
public:
CTxIn vinMasternode;
int nBlockHeight;
CScript payee;
std::vector<unsigned char> vchSig;
CMasternodePaymentWinner()
{
nBlockHeight = 0;
vinMasternode = CTxIn();
payee = CScript();
}
CMasternodePaymentWinner(CTxIn vinIn)
{
nBlockHeight = 0;
vinMasternode = vinIn;
payee = CScript();
}
CMasternodePaymentWinner() : vinMasternode(CTxIn()), nBlockHeight(0), payee(CScript()), vchSig() {}
explicit CMasternodePaymentWinner(const CTxIn& vinIn) : vinMasternode(vinIn), nBlockHeight(0), payee(CScript()), vchSig() {}
uint256 GetHash()
{
@@ -187,7 +161,6 @@ public:
ss << payee;
ss << nBlockHeight;
ss << vinMasternode.prevout;
return ss.GetHash();
}
@@ -196,11 +169,7 @@ public:
bool SignatureValid();
void Relay();
void AddPayee(CScript payeeIn)
{
payee = payeeIn;
}
void AddPayee(const CScript& payeeIn) { payee = payeeIn; }
ADD_SERIALIZE_METHODS;
@@ -215,7 +184,7 @@ public:
std::string ToString()
{
std::string ret = "";
std::string ret;
ret += vinMasternode.ToString();
ret += ", " + std::to_string(nBlockHeight);
ret += ", " + payee.ToString();
@@ -228,7 +197,6 @@ public:
// Masternode Payments Class
// Keeps track of who should get paid for which blocks
//
class CMasternodePayments
{
private:
@@ -238,13 +206,12 @@ private:
public:
std::map<uint256, CMasternodePaymentWinner> mapMasternodePayeeVotes;
std::map<int, CMasternodeBlockPayees> mapMasternodeBlocks;
std::map<uint256, int> mapMasternodesLastVote; //prevout.hash + prevout.n, nBlockHeight
CMasternodePayments()
{
nSyncedFromPeer = 0;
nLastBlockHeight = 0;
}
// NOTE: This legacy keying scheme (outpoint.hash + outpoint.n) can theoretically collide.
// Changing it requires a coordinated refactor of both header and implementation.
std::map<uint256, int> mapMasternodesLastVote; // prevout.hash + prevout.n, nBlockHeight
CMasternodePayments() : nSyncedFromPeer(0), nLastBlockHeight(0) {}
void Clear()
{
@@ -264,18 +231,19 @@ public:
bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight);
bool IsScheduled(CMasternode& mn, int nNotBlockHeight);
bool CanVote(COutPoint outMasternode, int nBlockHeight)
bool CanVote(const COutPoint& outMasternode, int nBlockHeight)
{
LOCK(cs_mapMasternodePayeeVotes);
if (mapMasternodesLastVote.count(outMasternode.hash + outMasternode.n)) {
if (mapMasternodesLastVote[outMasternode.hash + outMasternode.n] == nBlockHeight) {
const uint256 key = outMasternode.hash + outMasternode.n;
if (mapMasternodesLastVote.count(key)) {
if (mapMasternodesLastVote[key] == nBlockHeight) {
return false;
}
}
//record this masternode voted
mapMasternodesLastVote[outMasternode.hash + outMasternode.n] = nBlockHeight;
// record this masternode voted
mapMasternodesLastVote[key] = nBlockHeight;
return true;
}
@@ -297,5 +265,4 @@ public:
}
};
#endif
#endif // AGRARIAN_MASTERNODE_PAYMENTS_H
+16 -18
View File
@@ -2,6 +2,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2019 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -32,9 +33,6 @@
#include <boost/thread.hpp>
#include <boost/tuple/tuple.hpp>
using namespace std;
//////////////////////////////////////////////////////////////////////////////
//
// AgrarianMiner
@@ -105,7 +103,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
// Create new block
unique_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
if (!pblocktemplate.get())
return NULL;
return nullptr;
CBlock* pblock = &pblocktemplate->block; // pointer for convenience
// Tip
@@ -166,7 +164,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
if (!fStakeFound) {
LogPrint("staking", "CreateNewBlock(): stake not found\n");
return NULL;
return nullptr;
}
}
@@ -214,7 +212,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
continue;
}
COrphan* porphan = NULL;
COrphan* porphan = nullptr;
double dPriority = 0;
CAmount nTotalIn = 0;
bool fMissingInputs = false;
@@ -243,7 +241,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
double nTimePriority = std::pow(GetAdjustedTime() - nTimeSeen, 6);
// zAGR spends can have very large priority, use non-overflowing safe functions
dPriority = double_safe_addition(dPriority, (nTimePriority * nConfs));
dPriority = double_safe_addition(dPriority, (nTimePriority* nConfs));
dPriority = double_safe_multiplication(dPriority, nTotalIn);
continue;
@@ -291,12 +289,12 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
int nConf = nHeight - coins->nHeight;
// zAGR spends can have very large priority, use non-overflowing safe functions
dPriority = double_safe_addition(dPriority, ((double)nValueIn * nConf));
dPriority = double_safe_addition(dPriority, ((double)nValueIn* nConf));
}
if (fMissingInputs) continue;
// Priority is sum(valuein * age) / modified_txsize
// Priority is sum(valuein* age) / modified_txsize
unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
dPriority = tx.ComputePriority(dPriority, nTxSize);
@@ -521,17 +519,17 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
CKey key;
if (!pwallet->GetZerocoinKey(bnSerial, key)) {
LogPrintf("%s: failed to find zAGR with serial %s, unable to sign block\n", __func__, bnSerial.GetHex());
return NULL;
return nullptr;
}
//Sign block with the zAGR key
if (!SignBlockWithKey(*pblock, key)) {
LogPrintf("BitcoinMiner(): Signing new block with zAGR key failed \n");
return NULL;
return nullptr;
}
} else if (!SignBlock(*pblock, *pwallet)) {
LogPrintf("BitcoinMiner(): Signing new block with UTXO key failed \n");
return NULL;
return nullptr;
}
}
@@ -539,7 +537,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
if (!TestBlockValidity(state, *pblock, pindexPrev, false, false)) {
//LogPrintf("CreateNewBlock() : TestBlockValidity failed\n");
mempool.clear();
return NULL;
return nullptr;
}
// if (pblock->IsZerocoinStake()) {
@@ -581,7 +579,7 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, CWallet* pwallet,
{
CPubKey pubkey;
if (!reservekey.GetReservedKey(pubkey))
return NULL;
return nullptr;
CScript scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
return CreateNewBlock(scriptPubKey, pwallet, fProofOfStake);
@@ -613,7 +611,7 @@ bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
// Process this block the same as if we had received it from another node
CValidationState state;
if (!ProcessNewBlock(state, NULL, pblock)) {
if (!ProcessNewBlock(state, nullptr, pblock)) {
if (pblock->IsZerocoinStake()) {
pwalletMain->zagrTracker->RemovePending(pblock->vtx[1].GetHash());
pwalletMain->zagrTracker->ListMints(true, true, true); //update the state
@@ -831,7 +829,7 @@ void static ThreadBitcoinMiner(void* parg)
void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
{
static boost::thread_group* minerThreads = NULL;
static boost::thread_group* minerThreads = nullptr;
fGenerateBitcoins = fGenerate;
if (nThreads < 0) {
@@ -842,10 +840,10 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
nThreads = boost::thread::hardware_concurrency();
}
if (minerThreads != NULL) {
if (minerThreads != nullptr) {
minerThreads->interrupt_all();
delete minerThreads;
minerThreads = NULL;
minerThreads = nullptr;
}
if (nThreads == 0 || !fGenerate)
+9 -7
View File
@@ -1,14 +1,16 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2016-2018 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_MINER_H
#define BITCOIN_MINER_H
#include <stdint.h>
#ifndef AGRARIAN_BITCOIN_MINER_H
#define AGRARIAN_BITCOIN_MINER_H
#include <cstdint>
#include <std::string>
#include <std::vector>
#include <memory>
#include <utility>
class CBlock;
class CBlockHeader;
class CBlockIndex;
@@ -33,4 +35,4 @@ void BitcoinMiner(CWallet* pwallet, bool fProofOfStake);
extern double dHashesPerSec;
extern int64_t nHPSTimerStart;
#endif // BITCOIN_MINER_H
#endif // AGRARIAN_BITCOIN_MINER_H
+5 -4
View File
@@ -2,6 +2,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2018 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -33,7 +34,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
uint256 PastDifficultyAverage;
uint256 PastDifficultyAveragePrev;
if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || BlockLastSolved->nHeight < PastBlocksMin) {
if (BlockLastSolved == nullptr || BlockLastSolved->nHeight == 0 || BlockLastSolved->nHeight < PastBlocksMin) {
return Params().ProofOfWorkLimit().GetCompact();
}
@@ -74,7 +75,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
if (CountBlocks == 1) {
PastDifficultyAverage.SetCompact(BlockReading->nBits);
} else {
PastDifficultyAverage = ((PastDifficultyAveragePrev * CountBlocks) + (uint256().SetCompact(BlockReading->nBits))) / (CountBlocks + 1);
PastDifficultyAverage = ((PastDifficultyAveragePrev* CountBlocks) + (uint256().SetCompact(BlockReading->nBits))) / (CountBlocks + 1);
}
PastDifficultyAveragePrev = PastDifficultyAverage;
}
@@ -85,7 +86,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
}
LastBlockTime = BlockReading->GetBlockTime();
if (BlockReading->pprev == NULL) {
if (BlockReading->pprev == nullptr) {
assert(BlockReading);
break;
}
@@ -94,7 +95,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
uint256 bnNew(PastDifficultyAverage);
int64_t _nTargetTimespan = CountBlocks * Params().TargetSpacing();
int64_t _nTargetTimespan = CountBlocks* Params().TargetSpacing();
if (nActualTimespan < _nTargetTimespan / 3)
nActualTimespan = _nTargetTimespan / 3;
+6 -7
View File
@@ -2,14 +2,13 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2017-2018 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_POW_H
#define BITCOIN_POW_H
#include <stdint.h>
#ifndef AGRARIAN_BITCOIN_POW_H
#define AGRARIAN_BITCOIN_POW_H
#include <cstdint>
#include <cstddef>
class CBlockHeader;
class CBlockIndex;
class uint256;
@@ -29,4 +28,4 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
uint256 GetBlockProof(const CBlockIndex& block);
#endif // BITCOIN_POW_H
#endif // AGRARIAN_BITCOIN_POW_H
+10 -9
View File
@@ -2,6 +2,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2019 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -22,7 +23,7 @@
#include "wallet/wallet.h"
#endif
#include <stdint.h>
#include <cstdint>
#include <boost/assign/list_of.hpp>
@@ -37,12 +38,12 @@ using namespace std;
*/
UniValue GetNetworkHashPS(int lookup, int height)
{
CBlockIndex *pb = chainActive.Tip();
CBlockIndex*pb = chainActive.Tip();
if (height >= 0 && height < chainActive.Height())
pb = chainActive[height];
if (pb == NULL || !pb->nHeight)
if (pb == nullptr || !pb->nHeight)
return 0;
// If lookup is -1, then use blocks since last difficulty change.
@@ -158,7 +159,7 @@ UniValue generate(const UniValue& params, bool fHelp)
unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey, pwalletMain, fPoS));
if (!pblocktemplate.get())
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
CBlock *pblock = &pblocktemplate->block;
CBlock*pblock = &pblocktemplate->block;
if(!fPoS){
{
@@ -172,7 +173,7 @@ UniValue generate(const UniValue& params, bool fHelp)
++pblock->nNonce;
}
CValidationState state;
if (!ProcessNewBlock(state, NULL, pblock))
if (!ProcessNewBlock(state, nullptr, pblock))
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
++nHeight;
fPoS = nHeight >= Params().LAST_POW_BLOCK();
@@ -201,7 +202,7 @@ UniValue setgenerate(const UniValue& params, bool fHelp)
"\nTurn off generation\n" + HelpExampleCli("setgenerate", "false") +
"\nUsing json rpc\n" + HelpExampleRpc("setgenerate", "true, 1"));
if (pwalletMain == NULL)
if (pwalletMain == nullptr)
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
if (Params().MineBlocksOnDemand())
@@ -515,7 +516,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
if (pindexPrev != chainActive.Tip() ||
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5)) {
// Clear pindexPrev so future calls make a new block, despite any failures from here on
pindexPrev = NULL;
pindexPrev = nullptr;
// Store the chainActive.Tip() used before CreateNewBlock, to avoid races
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
@@ -525,7 +526,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
// Create new block
if (pblocktemplate) {
delete pblocktemplate;
pblocktemplate = NULL;
pblocktemplate = nullptr;
}
CScript scriptDummy = CScript() << OP_TRUE;
pblocktemplate = CreateNewBlock(scriptDummy, pwalletMain, false);
@@ -691,7 +692,7 @@ UniValue submitblock(const UniValue& params, bool fHelp)
CValidationState state;
submitblock_StateCatcher sc(block.GetHash());
RegisterValidationInterface(&sc);
bool fAccepted = ProcessNewBlock(state, NULL, &block);
bool fAccepted = ProcessNewBlock(state, nullptr, &block);
UnregisterValidationInterface(&sc);
if (fBlockPresent) {
if (fAccepted && !sc.found)
+198 -146
View File
@@ -1,6 +1,7 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2016-2019 The PIVX developers
// Copyright (c) 2026 Agrarian Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,45 +12,55 @@
#include "uint256.h"
#include "zagr/accumulators.h"
#include <stdint.h>
#include <cstdint>
#include <limits>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include <boost/thread.hpp>
using namespace std;
using namespace libzerocoin;
namespace {
void static BatchWriteCoins(CLevelDBBatch& batch, const uint256& hash, const CCoins& coins)
void BatchWriteCoins(CLevelDBBatch& batch, const uint256& hash, const CCoins& coins)
{
if (coins.IsPruned())
batch.Erase(make_pair('c', hash));
else
batch.Write(make_pair('c', hash), coins);
if (coins.IsPruned()) {
batch.Erase(std::make_pair('c', hash));
} else {
batch.Write(std::make_pair('c', hash), coins);
}
}
void static BatchWriteHashBestChain(CLevelDBBatch& batch, const uint256& hash)
void BatchWriteHashBestChain(CLevelDBBatch& batch, const uint256& hash)
{
batch.Write('B', hash);
}
CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe)
} // namespace
CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe)
: db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe)
{
}
bool CCoinsViewDB::GetCoins(const uint256& txid, CCoins& coins) const
{
return db.Read(make_pair('c', txid), coins);
return db.Read(std::make_pair('c', txid), coins);
}
bool CCoinsViewDB::HaveCoins(const uint256& txid) const
{
return db.Exists(make_pair('c', txid));
return db.Exists(std::make_pair('c', txid));
}
uint256 CCoinsViewDB::GetBestBlock() const
{
uint256 hashBestChain;
if (!db.Read('B', hashBestChain))
if (!db.Read('B', hashBestChain)) {
return uint256(0);
}
return hashBestChain;
}
@@ -58,39 +69,47 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock)
CLevelDBBatch batch;
size_t count = 0;
size_t changed = 0;
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
for (auto it = mapCoins.begin(); it != mapCoins.end();) {
if (it->second.flags & CCoinsCacheEntry::DIRTY) {
BatchWriteCoins(batch, it->first, it->second.coins);
changed++;
++changed;
}
count++;
CCoinsMap::iterator itOld = it++;
++count;
auto itOld = it++;
mapCoins.erase(itOld);
}
if (hashBlock != uint256(0))
BatchWriteHashBestChain(batch, hashBlock);
LogPrint("coindb", "Committing %u changed transactions (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
if (hashBlock != uint256(0)) {
BatchWriteHashBestChain(batch, hashBlock);
}
LogPrint("coindb",
"Committing %u changed transactions (out of %u) to coin database...\n",
(unsigned int)changed, (unsigned int)count);
return db.WriteBatch(batch);
}
CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe)
CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe)
: CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe)
{
}
bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
{
return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
return Write(std::make_pair('b', blockindex.GetBlockHash()), blockindex);
}
bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo& info)
{
return Write(make_pair('f', nFile), info);
return Write(std::make_pair('f', nFile), info);
}
bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo& info)
{
return Read(make_pair('f', nFile), info);
return Read(std::make_pair('f', nFile), info);
}
bool CBlockTreeDB::WriteLastBlockFile(int nFile)
@@ -100,10 +119,10 @@ bool CBlockTreeDB::WriteLastBlockFile(int nFile)
bool CBlockTreeDB::WriteReindexing(bool fReindexing)
{
if (fReindexing)
if (fReindexing) {
return Write('R', '1');
else
return Erase('R');
}
return Erase('R');
}
bool CBlockTreeDB::ReadReindexing(bool& fReindexing)
@@ -119,53 +138,70 @@ bool CBlockTreeDB::ReadLastBlockFile(int& nFile)
bool CCoinsViewDB::GetStats(CCoinsStats& stats) const
{
/* It seems that there are no "const iterators" for LevelDB. Since we
only need read operations on it, use a const-cast to get around
that restriction. */
boost::scoped_ptr<leveldb::Iterator> pcursor(const_cast<CLevelDBWrapper*>(&db)->NewIterator());
// LevelDB iterators are non-const; we only read so const_cast the wrapper.
std::unique_ptr<leveldb::Iterator> pcursor(const_cast<CLevelDBWrapper*>(&db)->NewIterator());
pcursor->SeekToFirst();
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
stats.hashBlock = GetBestBlock();
ss << stats.hashBlock;
CAmount nTotalAmount = 0;
while (pcursor->Valid()) {
boost::this_thread::interruption_point();
try {
leveldb::Slice slKey = pcursor->key();
const leveldb::Slice slKey = pcursor->key();
CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
char chType;
ssKey >> chType;
if (chType == 'c') {
leveldb::Slice slValue = pcursor->value();
const leveldb::Slice slValue = pcursor->value();
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
CCoins coins;
ssValue >> coins;
uint256 txhash;
ssKey >> txhash;
ss << txhash;
ss << VARINT(coins.nVersion);
ss << (coins.fCoinBase ? 'c' : 'n');
ss << VARINT(coins.nHeight);
stats.nTransactions++;
for (unsigned int i = 0; i < coins.vout.size(); i++) {
++stats.nTransactions;
for (unsigned int i = 0; i < coins.vout.size(); ++i) {
const CTxOut& out = coins.vout[i];
if (!out.IsNull()) {
stats.nTransactionOutputs++;
++stats.nTransactionOutputs;
ss << VARINT(i + 1);
ss << out;
nTotalAmount += out.nValue;
}
}
stats.nSerializedSize += 32 + slValue.size();
ss << VARINT(0);
}
pcursor->Next();
} catch (std::exception& e) {
} catch (const std::exception& e) {
return error("%s : Deserialize or I/O error - %s", __func__, e.what());
}
}
stats.nHeight = mapBlockIndex.find(GetBestBlock())->second->nHeight;
// Height: best-effort. If best block isn't in index (e.g. empty db), return height=0.
stats.nHeight = 0;
const uint256 best = GetBestBlock();
auto it = mapBlockIndex.find(best);
if (it != mapBlockIndex.end() && it->second) {
stats.nHeight = it->second->nHeight;
}
stats.hashSerialized = ss.GetHash();
stats.nTotalAmount = nTotalAmount;
return true;
@@ -173,14 +209,15 @@ bool CCoinsViewDB::GetStats(CCoinsStats& stats) const
bool CBlockTreeDB::ReadTxIndex(const uint256& txid, CDiskTxPos& pos)
{
return Read(make_pair('t', txid), pos);
return Read(std::make_pair('t', txid), pos);
}
bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >& vect)
bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos>>& vect)
{
CLevelDBBatch batch;
for (std::vector<std::pair<uint256, CDiskTxPos> >::const_iterator it = vect.begin(); it != vect.end(); it++)
batch.Write(make_pair('t', it->first), it->second);
for (const auto& it : vect) {
batch.Write(std::make_pair('t', it.first), it.second);
}
return WriteBatch(batch);
}
@@ -192,9 +229,10 @@ bool CBlockTreeDB::WriteFlag(const std::string& name, bool fValue)
bool CBlockTreeDB::ReadFlag(const std::string& name, bool& fValue)
{
char ch;
if (!Read(std::make_pair('F', name), ch))
if (!Read(std::make_pair('F', name), ch)) {
return false;
fValue = ch == '1';
}
fValue = (ch == '1');
return true;
}
@@ -210,76 +248,82 @@ bool CBlockTreeDB::ReadInt(const std::string& name, int& nValue)
bool CBlockTreeDB::LoadBlockIndexGuts()
{
boost::scoped_ptr<leveldb::Iterator> pcursor(NewIterator());
std::unique_ptr<leveldb::Iterator> pcursor(NewIterator());
CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
ssKeySet << make_pair('b', uint256(0));
ssKeySet << std::make_pair('b', uint256(0));
pcursor->Seek(ssKeySet.str());
// Load mapBlockIndex
uint256 nPreviousCheckpoint;
while (pcursor->Valid()) {
boost::this_thread::interruption_point();
try {
leveldb::Slice slKey = pcursor->key();
const leveldb::Slice slKey = pcursor->key();
CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
char chType;
ssKey >> chType;
if (chType == 'b') {
leveldb::Slice slValue = pcursor->value();
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
CDiskBlockIndex diskindex;
ssValue >> diskindex;
// Construct block index object
CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev);
pindexNew->pnext = InsertBlockIndex(diskindex.hashNext);
pindexNew->nHeight = diskindex.nHeight;
pindexNew->nFile = diskindex.nFile;
pindexNew->nDataPos = diskindex.nDataPos;
pindexNew->nUndoPos = diskindex.nUndoPos;
pindexNew->nVersion = diskindex.nVersion;
pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
pindexNew->nTime = diskindex.nTime;
pindexNew->nBits = diskindex.nBits;
pindexNew->nNonce = diskindex.nNonce;
pindexNew->nStatus = diskindex.nStatus;
pindexNew->nTx = diskindex.nTx;
//zerocoin
pindexNew->nAccumulatorCheckpoint = diskindex.nAccumulatorCheckpoint;
pindexNew->mapZerocoinSupply = diskindex.mapZerocoinSupply;
pindexNew->vMintDenominationsInBlock = diskindex.vMintDenominationsInBlock;
//Proof Of Stake
pindexNew->nMint = diskindex.nMint;
pindexNew->nMoneySupply = diskindex.nMoneySupply;
pindexNew->nFlags = diskindex.nFlags;
pindexNew->nStakeModifier = diskindex.nStakeModifier;
pindexNew->prevoutStake = diskindex.prevoutStake;
pindexNew->nStakeTime = diskindex.nStakeTime;
pindexNew->hashProofOfStake = diskindex.hashProofOfStake;
if (pindexNew->nHeight <= Params().LAST_POW_BLOCK()) {
if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits))
return error("LoadBlockIndex() : CheckProofOfWork failed: %s", pindexNew->ToString());
}
//populate accumulator checksum map in memory
if(pindexNew->nAccumulatorCheckpoint != 0 && pindexNew->nAccumulatorCheckpoint != nPreviousCheckpoint) {
//Don't load any checkpoints that exist before v2 zagr. The accumulator is invalid for v1 and not used.
if (pindexNew->nHeight >= Params().Zerocoin_Block_V2_Start())
LoadAccumulatorValuesFromDB(pindexNew->nAccumulatorCheckpoint);
nPreviousCheckpoint = pindexNew->nAccumulatorCheckpoint;
}
pcursor->Next();
} else {
break; // if shutdown requested or finished loading block index
if (chType != 'b') {
break; // finished loading block index
}
} catch (std::exception& e) {
const leveldb::Slice slValue = pcursor->value();
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
CDiskBlockIndex diskindex;
ssValue >> diskindex;
// Construct block index object
CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev);
pindexNew->pnext = InsertBlockIndex(diskindex.hashNext);
pindexNew->nHeight = diskindex.nHeight;
pindexNew->nFile = diskindex.nFile;
pindexNew->nDataPos = diskindex.nDataPos;
pindexNew->nUndoPos = diskindex.nUndoPos;
pindexNew->nVersion = diskindex.nVersion;
pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
pindexNew->nTime = diskindex.nTime;
pindexNew->nBits = diskindex.nBits;
pindexNew->nNonce = diskindex.nNonce;
pindexNew->nStatus = diskindex.nStatus;
pindexNew->nTx = diskindex.nTx;
// Zerocoin
pindexNew->nAccumulatorCheckpoint = diskindex.nAccumulatorCheckpoint;
pindexNew->mapZerocoinSupply = diskindex.mapZerocoinSupply;
pindexNew->vMintDenominationsInBlock = diskindex.vMintDenominationsInBlock;
// Proof of Stake
pindexNew->nMint = diskindex.nMint;
pindexNew->nMoneySupply = diskindex.nMoneySupply;
pindexNew->nFlags = diskindex.nFlags;
pindexNew->nStakeModifier = diskindex.nStakeModifier;
pindexNew->prevoutStake = diskindex.prevoutStake;
pindexNew->nStakeTime = diskindex.nStakeTime;
pindexNew->hashProofOfStake = diskindex.hashProofOfStake;
// Hybrid PoW+PoS: only enforce PoW proof check for PoW blocks (not just height).
// If your codebase doesn't define IsProofOfWork(), keep the height gate or adjust at call sites.
if (pindexNew->IsProofOfWork()) {
if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits)) {
return error("LoadBlockIndex() : CheckProofOfWork failed: %s", pindexNew->ToString());
}
}
// Populate accumulator checksum map in memory
if (pindexNew->nAccumulatorCheckpoint != 0 && pindexNew->nAccumulatorCheckpoint != nPreviousCheckpoint) {
// Don't load any checkpoints that exist before v2 zagr. The accumulator is invalid for v1 and not used.
if (pindexNew->nHeight >= Params().Zerocoin_Block_V2_Start()) {
LoadAccumulatorValuesFromDB(pindexNew->nAccumulatorCheckpoint);
}
nPreviousCheckpoint = pindexNew->nAccumulatorCheckpoint;
}
pcursor->Next();
} catch (const std::exception& e) {
return error("%s : Deserialize or I/O error - %s", __func__, e.what());
}
}
@@ -287,18 +331,20 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
return true;
}
CZerocoinDB::CZerocoinDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "zerocoin", nCacheSize, fMemory, fWipe)
CZerocoinDB::CZerocoinDB(size_t nCacheSize, bool fMemory, bool fWipe)
: CLevelDBWrapper(GetDataDir() / "zerocoin", nCacheSize, fMemory, fWipe)
{
}
bool CZerocoinDB::WriteCoinMintBatch(const std::vector<std::pair<libzerocoin::PublicCoin, uint256> >& mintInfo)
bool CZerocoinDB::WriteCoinMintBatch(const std::vector<std::pair<libzerocoin::PublicCoin, uint256>>& mintInfo)
{
CLevelDBBatch batch;
size_t count = 0;
for (std::vector<std::pair<libzerocoin::PublicCoin, uint256> >::const_iterator it=mintInfo.begin(); it != mintInfo.end(); it++) {
PublicCoin pubCoin = it->first;
uint256 hash = GetPubCoinHash(pubCoin.getValue());
batch.Write(make_pair('m', hash), it->second);
for (const auto& it : mintInfo) {
const libzerocoin::PublicCoin& pubCoin = it.first;
const uint256 hash = GetPubCoinHash(pubCoin.getValue());
batch.Write(std::make_pair('m', hash), it.second);
++count;
}
@@ -313,25 +359,26 @@ bool CZerocoinDB::ReadCoinMint(const CBigNum& bnPubcoin, uint256& hashTx)
bool CZerocoinDB::ReadCoinMint(const uint256& hashPubcoin, uint256& hashTx)
{
return Read(make_pair('m', hashPubcoin), hashTx);
return Read(std::make_pair('m', hashPubcoin), hashTx);
}
bool CZerocoinDB::EraseCoinMint(const CBigNum& bnPubcoin)
{
uint256 hash = GetPubCoinHash(bnPubcoin);
return Erase(make_pair('m', hash));
const uint256 hash = GetPubCoinHash(bnPubcoin);
return Erase(std::make_pair('m', hash));
}
bool CZerocoinDB::WriteCoinSpendBatch(const std::vector<std::pair<libzerocoin::CoinSpend, uint256> >& spendInfo)
bool CZerocoinDB::WriteCoinSpendBatch(const std::vector<std::pair<libzerocoin::CoinSpend, uint256>>& spendInfo)
{
CLevelDBBatch batch;
size_t count = 0;
for (std::vector<std::pair<libzerocoin::CoinSpend, uint256> >::const_iterator it=spendInfo.begin(); it != spendInfo.end(); it++) {
CBigNum bnSerial = it->first.getCoinSerialNumber();
for (const auto& it : spendInfo) {
const CBigNum bnSerial = it.first.getCoinSerialNumber();
CDataStream ss(SER_GETHASH, 0);
ss << bnSerial;
uint256 hash = Hash(ss.begin(), ss.end());
batch.Write(make_pair('s', hash), it->second);
const uint256 hash = Hash(ss.begin(), ss.end());
batch.Write(std::make_pair('s', hash), it.second);
++count;
}
@@ -343,63 +390,68 @@ bool CZerocoinDB::ReadCoinSpend(const CBigNum& bnSerial, uint256& txHash)
{
CDataStream ss(SER_GETHASH, 0);
ss << bnSerial;
uint256 hash = Hash(ss.begin(), ss.end());
return Read(make_pair('s', hash), txHash);
const uint256 hash = Hash(ss.begin(), ss.end());
return Read(std::make_pair('s', hash), txHash);
}
bool CZerocoinDB::ReadCoinSpend(const uint256& hashSerial, uint256 &txHash)
bool CZerocoinDB::ReadCoinSpend(const uint256& hashSerial, uint256& txHash)
{
return Read(make_pair('s', hashSerial), txHash);
return Read(std::make_pair('s', hashSerial), txHash);
}
bool CZerocoinDB::EraseCoinSpend(const CBigNum& bnSerial)
{
CDataStream ss(SER_GETHASH, 0);
ss << bnSerial;
uint256 hash = Hash(ss.begin(), ss.end());
return Erase(make_pair('s', hash));
const uint256 hash = Hash(ss.begin(), ss.end());
return Erase(std::make_pair('s', hash));
}
bool CZerocoinDB::WipeCoins(std::string strType)
bool CZerocoinDB::WipeCoins(const std::string& strType)
{
if (strType != "spends" && strType != "mints")
if (strType != "spends" && strType != "mints") {
return error("%s: did not recognize type %s", __func__, strType);
}
boost::scoped_ptr<leveldb::Iterator> pcursor(NewIterator());
std::unique_ptr<leveldb::Iterator> pcursor(NewIterator());
char type = (strType == "spends" ? 's' : 'm');
const char type = (strType == "spends" ? 's' : 'm');
CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
ssKeySet << make_pair(type, uint256(0));
ssKeySet << std::make_pair(type, uint256(0));
pcursor->Seek(ssKeySet.str());
// Load mapBlockIndex
std::set<uint256> setDelete;
while (pcursor->Valid()) {
boost::this_thread::interruption_point();
try {
leveldb::Slice slKey = pcursor->key();
const leveldb::Slice slKey = pcursor->key();
CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
char chType;
ssKey >> chType;
if (chType == type) {
leveldb::Slice slValue = pcursor->value();
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
uint256 hash;
ssValue >> hash;
setDelete.insert(hash);
pcursor->Next();
} else {
break; // if shutdown requested or finished loading block index
if (chType != type) {
break; // finished
}
} catch (std::exception& e) {
const leveldb::Slice slValue = pcursor->value();
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
uint256 hash;
ssValue >> hash;
setDelete.insert(hash);
pcursor->Next();
} catch (const std::exception& e) {
return error("%s : Deserialize or I/O error - %s", __func__, e.what());
}
}
for (auto& hash : setDelete) {
if (!Erase(make_pair(type, hash)))
for (const auto& hash : setDelete) {
if (!Erase(std::make_pair(type, hash))) {
LogPrintf("%s: error failed to delete %s\n", __func__, hash.GetHex());
}
}
return true;
@@ -407,17 +459,17 @@ bool CZerocoinDB::WipeCoins(std::string strType)
bool CZerocoinDB::WriteAccumulatorValue(const uint32_t& nChecksum, const CBigNum& bnValue)
{
LogPrint("zero","%s : checksum:%d val:%s\n", __func__, nChecksum, bnValue.GetHex());
return Write(make_pair('2', nChecksum), bnValue);
LogPrint("zero", "%s : checksum:%d val:%s\n", __func__, nChecksum, bnValue.GetHex());
return Write(std::make_pair('2', nChecksum), bnValue);
}
bool CZerocoinDB::ReadAccumulatorValue(const uint32_t& nChecksum, CBigNum& bnValue)
{
return Read(make_pair('2', nChecksum), bnValue);
return Read(std::make_pair('2', nChecksum), bnValue);
}
bool CZerocoinDB::EraseAccumulatorValue(const uint32_t& nChecksum)
{
LogPrint("zero", "%s : checksum:%d\n", __func__, nChecksum);
return Erase(make_pair('2', nChecksum));
return Erase(std::make_pair('2', nChecksum));
}