Sync with latest Komodo changes

This commit is contained in:
Michael Toutonghi
2018-08-06 12:52:22 -07:00
150 changed files with 10076 additions and 2162 deletions

View File

@@ -10,6 +10,7 @@
#include "addrman.h"
#include "alert.h"
#include "arith_uint256.h"
#include "importcoin.h"
#include "chainparams.h"
#include "checkpoints.h"
#include "checkqueue.h"
@@ -19,8 +20,10 @@
#include "init.h"
#include "merkleblock.h"
#include "metrics.h"
#include "notarisationdb.h"
#include "net.h"
#include "pow.h"
#include "script/interpreter.h"
#include "txdb.h"
#include "txmempool.h"
#include "ui_interface.h"
@@ -55,7 +58,7 @@ using namespace std;
CCriticalSection cs_main;
extern uint8_t NOTARY_PUBKEY33[33];
extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN;
extern int32_t KOMODO_LOADINGBLOCKS,KOMODO_LONGESTCHAIN,KOMODO_INSYNC;
int32_t KOMODO_NEWBLOCKS;
int32_t komodo_block2pubkey33(uint8_t *pubkey33,CBlock *block);
void komodo_broadcast(CBlock *pblock,int32_t limit);
@@ -587,6 +590,24 @@ CBlockTreeDB *pblocktree = NULL;
#define KOMODO_ZCASH
#include "komodo.h"
UniValue komodo_snapshot(int top)
{
LOCK(cs_main);
int64_t total = -1;
UniValue result(UniValue::VOBJ);
if (fAddressIndex) {
if ( pblocktree != 0 ) {
result = pblocktree->Snapshot(top);
} else {
fprintf(stderr,"null pblocktree start with -addressindex=true\n");
}
} else {
fprintf(stderr,"getsnapshot requires -addressindex=true\n");
}
return(result);
}
//////////////////////////////////////////////////////////////////////////////
//
// mapOrphanTransactions
@@ -729,7 +750,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason, const int nHeight)
else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
reason = "bare-multisig";
return false;
} else if (txout.IsDust(::minRelayTxFee)) {
} else if (txout.scriptPubKey.IsPayToCryptoCondition() == 0 && txout.IsDust(::minRelayTxFee)) {
reason = "dust";
return false;
}
@@ -819,7 +840,10 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs,
{
if (tx.IsCoinBase())
return true; // Coinbases don't use vin normally
if (tx.IsCoinImport())
return tx.vin[0].scriptSig.IsCoinImport();
for (unsigned int i = 0; i < tx.vin.size(); i++)
{
const CTxOut& prev = mapInputs.GetOutputFor(tx.vin[i]);
@@ -890,7 +914,7 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx)
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs)
{
if (tx.IsCoinBase())
if (tx.IsCoinBase() || tx.IsCoinImport())
return 0;
unsigned int nSigOps = 0;
@@ -990,8 +1014,8 @@ bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state,
return state.DoS(dosLevel, error("ContextualCheckTransaction(): transaction is expired"), REJECT_INVALID, "tx-overwinter-expired");
}
}
if (!(tx.IsCoinBase() || tx.vjoinsplit.empty())) {
if (!(tx.IsMint() || tx.vjoinsplit.empty())) {
auto consensusBranchId = CurrentEpochBranchId(nHeight, Params().GetConsensus());
// Empty output script.
CScript scriptCode;
@@ -1053,7 +1077,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state,
if (!CheckTransactionWithoutProofVerification(tx, state)) {
return false;
} else {
// Ensure that zk-SNARKs verify
// Ensure that zk-SNARKs v|| y
BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
if (!joinsplit.Verify(*pzcashParams, verifier, tx.joinSplitPubKey)) {
return state.DoS(100, error("CheckTransaction(): joinsplit does not verify"),
@@ -1111,6 +1135,7 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
// Transactions can contain empty `vin` and `vout` so long as
// `vjoinsplit` is non-empty.
// Migrations may also have empty `vin`
if (tx.vin.empty() && tx.vjoinsplit.empty())
return state.DoS(10, error("CheckTransaction(): vin empty"),
REJECT_INVALID, "bad-txns-vin-empty");
@@ -1126,6 +1151,7 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
// Check for negative or overflow output values
CAmount nValueOut = 0;
int32_t iscoinbase = tx.IsCoinBase();
BOOST_FOREACH(const CTxOut& txout, tx.vout)
{
if (txout.nValue < 0)
@@ -1136,6 +1162,12 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
fprintf(stderr,"%.8f > max %.8f\n",(double)txout.nValue/COIN,(double)MAX_MONEY/COIN);
return state.DoS(100, error("CheckTransaction(): txout.nValue too high"),REJECT_INVALID, "bad-txns-vout-toolarge");
}
if ( ASSETCHAINS_PRIVATE != 0 )
{
fprintf(stderr,"private chain nValue %.8f iscoinbase.%d\n",(double)txout.nValue/COIN,iscoinbase);
if ( (txout.nValue > 0 && iscoinbase == 0) || tx.GetJoinSplitValueOut() > 0 )
return state.DoS(100, error("CheckTransaction(): this is a private chain, no public allowed"),REJECT_INVALID, "bad-txns-acprivacy-chain");
}
nValueOut += txout.nValue;
if (!MoneyRange(nValueOut))
return state.DoS(100, error("CheckTransaction(): txout total out of range"),
@@ -1145,6 +1177,11 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
// Ensure that joinsplit values are well-formed
BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit)
{
if ( ASSETCHAINS_PUBLIC != 0 )
{
return state.DoS(100, error("CheckTransaction(): this is a public chain, no privacy allowed"),
REJECT_INVALID, "bad-txns-acprivacy-chain");
}
if (joinsplit.vpub_old < 0) {
return state.DoS(100, error("CheckTransaction(): joinsplit.vpub_old negative"),
REJECT_INVALID, "bad-txns-vpub_old-negative");
@@ -1219,7 +1256,7 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
}
}
if (tx.IsCoinBase())
if (tx.IsMint())
{
// There should be no joinsplits in a coinbase transaction
if (tx.vjoinsplit.size() > 0)
@@ -1293,7 +1330,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
}
auto verifier = libzcash::ProofVerifier::Strict();
if ( komodo_validate_interest(tx,chainActive.Tip()->nHeight+1,chainActive.Tip()->GetMedianTimePast() + 777,0) < 0 )
if ( komodo_validate_interest(tx,chainActive.LastTip()->nHeight+1,chainActive.LastTip()->GetMedianTimePast() + 777,0) < 0 )
{
//fprintf(stderr,"AcceptToMemoryPool komodo_validate_interest failure\n");
return error("AcceptToMemoryPool: komodo_validate_interest failed");
@@ -1335,8 +1372,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
uint256 hash = tx.GetHash();
if (pool.exists(hash))
{
fprintf(stderr,"already in mempool\n");
return false;
//fprintf(stderr,"already in mempool\n");
return state.Invalid(false, REJECT_DUPLICATE, "already in mempool");
}
// Check for conflicts with in-memory transactions
@@ -1380,29 +1417,38 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// do we already have it?
if (view.HaveCoins(hash))
{
fprintf(stderr,"view.HaveCoins(hash) error\n");
return false;
//fprintf(stderr,"view.HaveCoins(hash) error\n");
return state.Invalid(false, REJECT_DUPLICATE, "already have coins");
}
// do all inputs exist?
// Note that this does not check for the presence of actual outputs (see the next check for that),
// and only helps with filling in pfMissingInputs (to determine missing vs spent).
BOOST_FOREACH(const CTxIn txin, tx.vin)
if (tx.IsCoinImport())
{
if (!view.HaveCoins(txin.prevout.hash))
// Inverse of normal case; if input exists, it's been spent
if (ExistsImportTombstone(tx, view))
return state.Invalid(false, REJECT_DUPLICATE, "import tombstone exists");
}
else
{
// do all inputs exist?
// Note that this does not check for the presence of actual outputs (see the next check for that),
// and only helps with filling in pfMissingInputs (to determine missing vs spent).
BOOST_FOREACH(const CTxIn txin, tx.vin)
{
if (pfMissingInputs)
*pfMissingInputs = true;
//fprintf(stderr,"missing inputs\n");
return false;
if (!view.HaveCoins(txin.prevout.hash))
{
if (pfMissingInputs)
*pfMissingInputs = true;
//fprintf(stderr,"missing inputs\n");
return false;
}
}
// are the actual inputs available?
if (!view.HaveInputs(tx))
{
//fprintf(stderr,"accept failure.1\n");
return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent");
}
}
// are the actual inputs available?
if (!view.HaveInputs(tx))
{
//fprintf(stderr,"accept failure.1\n");
return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent");
}
// are the joinsplit's requirements met?
if (!view.HaveJoinSplitRequirements(tx))
@@ -1414,7 +1460,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// Bring the best block into scope
view.GetBestBlock();
nValueIn = view.GetValueIn(chainActive.Tip()->nHeight,&interest,tx,chainActive.Tip()->nTime);
nValueIn = view.GetValueIn(chainActive.LastTip()->nHeight,&interest,tx,chainActive.LastTip()->nTime);
if ( 0 && interest != 0 )
fprintf(stderr,"add interest %.8f\n",(double)interest/COIN);
// we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool
@@ -1445,11 +1491,13 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// Keep track of transactions that spend a coinbase, which we re-scan
// during reorgs to ensure COINBASE_MATURITY is still met.
bool fSpendsCoinbase = false;
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
const CCoins *coins = view.AccessCoins(txin.prevout.hash);
if (coins->IsCoinBase()) {
fSpendsCoinbase = true;
break;
if (!tx.IsCoinImport()) {
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
const CCoins *coins = view.AccessCoins(txin.prevout.hash);
if (coins->IsCoinBase()) {
fSpendsCoinbase = true;
break;
}
}
}
@@ -1530,6 +1578,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// There is a similar check in CreateNewBlock() to prevent creating
// invalid blocks, however allowing such transactions into the mempool
// can be exploited as a DoS attack.
// XXX: is this neccesary for CryptoConditions?
if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
{
fprintf(stderr,"accept failure.10\n");
@@ -1606,6 +1655,47 @@ bool GetAddressUnspent(uint160 addressHash, int type,
return true;
}
bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock)
{
// need a GetTransaction without lock so the validation code for assets can run without deadlock
{
//fprintf(stderr,"check mempool\n");
if (mempool.lookup(hash, txOut))
{
//fprintf(stderr,"found in mempool\n");
return true;
}
}
//fprintf(stderr,"check disk\n");
if (fTxIndex) {
CDiskTxPos postx;
//fprintf(stderr,"ReadTxIndex\n");
if (pblocktree->ReadTxIndex(hash, postx)) {
//fprintf(stderr,"OpenBlockFile\n");
CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION);
if (file.IsNull())
return error("%s: OpenBlockFile failed", __func__);
CBlockHeader header;
//fprintf(stderr,"seek and read\n");
try {
file >> header;
fseek(file.Get(), postx.nTxOffset, SEEK_CUR);
file >> txOut;
} catch (const std::exception& e) {
return error("%s: Deserialize or I/O error - %s", __func__, e.what());
}
hashBlock = header.GetHash();
if (txOut.GetHash() != hash)
return error("%s: txid mismatch", __func__);
//fprintf(stderr,"found on disk\n");
return true;
}
}
//fprintf(stderr,"not found\n");
return false;
}
/** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */
bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow)
{
@@ -1762,6 +1852,7 @@ extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS];
extern uint32_t ASSETCHAINS_MAGIC;
extern uint64_t ASSETCHAINS_STAKED,ASSETCHAINS_LINEAR,ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY;
extern uint8_t ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE;
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
{
@@ -1858,7 +1949,7 @@ void CheckForkWarningConditions()
if (pindexBestForkTip && chainActive.Height() - pindexBestForkTip->nHeight >= 288)
pindexBestForkTip = NULL;
if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > chainActive.Tip()->nChainWork + (GetBlockProof(*chainActive.Tip()) * 6)))
if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > chainActive.LastTip()->nChainWork + (GetBlockProof(*chainActive.LastTip()) * 6)))
{
if (!fLargeWorkForkFound && pindexBestForkBase)
{
@@ -1893,7 +1984,7 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
AssertLockHeld(cs_main);
// If we are on a fork that is sufficiently large, set a warning flag
CBlockIndex* pfork = pindexNewForkTip;
CBlockIndex* plonger = chainActive.Tip();
CBlockIndex* plonger = chainActive.LastTip();
while (pfork && pfork != plonger)
{
while (plonger && plonger->nHeight > pfork->nHeight)
@@ -1950,7 +2041,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
pindexNew->GetBlockHash().ToString(), pindexNew->nHeight,
log(pindexNew->nChainWork.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S",
pindexNew->GetBlockTime()));
CBlockIndex *tip = chainActive.Tip();
CBlockIndex *tip = chainActive.LastTip();
assert (tip);
LogPrintf("%s: current best=%s height=%d log2_work=%.8g date=%s\n", __func__,
tip->GetBlockHash().ToString(), chainActive.Height(), log(tip->nChainWork.getdouble())/log(2.0),
@@ -1979,7 +2070,7 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txundo, int nHeight)
{
if (!tx.IsCoinBase()) // mark inputs spent
if (!tx.IsMint()) // mark inputs spent
{
txundo.vprevout.reserve(tx.vin.size());
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
@@ -2005,6 +2096,13 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txund
}
}
inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight); // add outputs
// Unorthodox state
if (tx.IsCoinImport()) {
// add a tombstone for the burnTx
AddImportTombstone(tx, inputs, nHeight);
}
}
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight)
@@ -2015,7 +2113,8 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight)
bool CScriptCheck::operator()() {
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, ServerTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), consensusBranchId, &error)) {
ServerTransactionSignatureChecker checker(ptxTo, nIn, amount, cacheStore, *txdata);
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, checker, consensusBranchId, &error)) {
return ::error("CScriptCheck(): %s:%d VerifySignature failed: %s", ptxTo->GetHash().ToString(), nIn, ScriptErrorString(error));
}
return true;
@@ -2079,14 +2178,14 @@ namespace Consensus {
// Check for negative or overflow input values
nValueIn += coins->vout[prevout.n].nValue;
#ifdef KOMODO_ENABLE_INTEREST
if ( ASSETCHAINS_SYMBOL[0] == 0 && nSpendHeight > 60000 )//chainActive.Tip() != 0 && chainActive.Tip()->nHeight >= 60000 )
if ( ASSETCHAINS_SYMBOL[0] == 0 && nSpendHeight > 60000 )//chainActive.LastTip() != 0 && chainActive.LastTip()->nHeight >= 60000 )
{
if ( coins->vout[prevout.n].nValue >= 10*COIN )
{
int64_t interest; int32_t txheight; uint32_t locktime;
if ( (interest= komodo_accrued_interest(&txheight,&locktime,prevout.hash,prevout.n,0,coins->vout[prevout.n].nValue,(int32_t)nSpendHeight-1)) != 0 )
{
//fprintf(stderr,"checkResult %.8f += val %.8f interest %.8f ht.%d lock.%u tip.%u\n",(double)nValueIn/COIN,(double)coins->vout[prevout.n].nValue/COIN,(double)interest/COIN,txheight,locktime,chainActive.Tip()->nTime);
//fprintf(stderr,"checkResult %.8f += val %.8f interest %.8f ht.%d lock.%u tip.%u\n",(double)nValueIn/COIN,(double)coins->vout[prevout.n].nValue/COIN,(double)interest/COIN,txheight,locktime,chainActive.LastTip()->nTime);
nValueIn += interest;
}
}
@@ -2134,7 +2233,7 @@ bool ContextualCheckInputs(
uint32_t consensusBranchId,
std::vector<CScriptCheck> *pvChecks)
{
if (!tx.IsCoinBase())
if (!tx.IsMint())
{
if (!Consensus::CheckTxInputs(tx, state, inputs, GetSpendHeight(inputs), consensusParams)) {
return false;
@@ -2186,7 +2285,13 @@ bool ContextualCheckInputs(
}
}
}
if (tx.IsCoinImport())
{
ServerTransactionSignatureChecker checker(&tx, 0, 0, false, txdata);
return VerifyCoinImport(tx.vin[0].scriptSig, checker, state);
}
return true;
}
@@ -2337,6 +2442,37 @@ static bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, const CO
return fClean;
}
void ConnectNotarisations(const CBlock &block, int height)
{
// Record Notarisations
NotarisationsInBlock notarisations = ScanBlockNotarisations(block, height);
if (notarisations.size() > 0) {
CLevelDBBatch batch;
batch.Write(block.GetHash(), notarisations);
WriteBackNotarisations(notarisations, batch);
pnotarisations->WriteBatch(batch, true);
LogPrintf("ConnectBlock: wrote %i block notarisations in block: %s\n",
notarisations.size(), block.GetHash().GetHex().data());
}
}
void DisconnectNotarisations(const CBlock &block)
{
// Delete from notarisations cache
NotarisationsInBlock nibs;
if (GetBlockNotarisations(block.GetHash(), nibs)) {
CLevelDBBatch batch;
batch.Erase(block.GetHash());
EraseBackNotarisations(nibs, batch);
pnotarisations->WriteBatch(batch, true);
LogPrintf("DisconnectTip: deleted %i block notarisations in block: %s\n",
nibs.size(), block.GetHash().GetHex().data());
}
}
bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean)
{
assert(pindex->GetBlockHash() == view.GetBestBlock());
@@ -2377,7 +2513,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
// undo unspent index
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), hash, k), CAddressUnspentValue()));
} else if (out.scriptPubKey.IsPayToPublicKeyHash()) {
}
else if (out.scriptPubKey.IsPayToPublicKeyHash()) {
vector<unsigned char> hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23);
// undo receiving activity
@@ -2386,7 +2523,28 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
// undo unspent index
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), hash, k), CAddressUnspentValue()));
} else {
}
else if (out.scriptPubKey.IsPayToPublicKey()) {
vector<unsigned char> hashBytes(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34);
// undo receiving activity
addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->nHeight, i, hash, k, false), out.nValue));
// undo unspent index
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), hash, k), CAddressUnspentValue()));
}
else if (out.scriptPubKey.IsPayToCryptoCondition()) {
vector<unsigned char> hashBytes(out.scriptPubKey.begin(), out.scriptPubKey.end());
// undo receiving activity
addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->nHeight, i, hash, k, false), out.nValue));
// undo unspent index
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), hash, k), CAddressUnspentValue()));
}
else {
continue;
}
@@ -2421,7 +2579,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
}
// restore inputs
if (i > 0) { // not coinbases
if (!tx.IsMint()) {
const CTxUndo &txundo = blockUndo.vtxundo[i-1];
if (txundo.vprevout.size() != tx.vin.size())
return error("DisconnectBlock(): transaction and undo data inconsistent");
@@ -2450,7 +2608,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight)));
} else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
}
else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
vector<unsigned char> hashBytes(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23);
// undo spending activity
@@ -2459,14 +2618,39 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
// restore unspent index
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight)));
} else {
}
else if (prevout.scriptPubKey.IsPayToPublicKey()) {
vector<unsigned char> hashBytes(prevout.scriptPubKey.begin()+1, prevout.scriptPubKey.begin()+34);
// undo spending activity
addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->nHeight, i, hash, j, true), prevout.nValue * -1));
// restore unspent index
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight)));
}
else if (prevout.scriptPubKey.IsPayToCryptoCondition()) {
vector<unsigned char> hashBytes(prevout.scriptPubKey.begin(), prevout.scriptPubKey.end());
// undo spending activity
addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->nHeight, i, hash, j, true), prevout.nValue * -1));
// restore unspent index
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight)));
}
else {
continue;
}
}
}
}
else if (tx.IsCoinImport())
{
RemoveImportTombstone(tx, view);
}
}
// set the old best anchor back
view.PopAnchor(blockUndo.old_tree_root);
@@ -2486,6 +2670,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
return AbortNode(state, "Failed to write address unspent index");
}
}
return fClean;
}
@@ -2586,6 +2771,7 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const
}
}
static int64_t nTimeVerify = 0;
static int64_t nTimeConnect = 0;
static int64_t nTimeIndex = 0;
@@ -2595,7 +2781,8 @@ static int64_t nTimeTotal = 0;
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck,bool fCheckPOW)
{
const CChainParams& chainparams = Params();
if ( KOMODO_STOPAT != 0 && pindex->nHeight > KOMODO_STOPAT )
return(false);
//fprintf(stderr,"connectblock ht.%d\n",(int32_t)pindex->nHeight);
AssertLockHeld(cs_main);
bool fExpensiveChecks = true;
@@ -2658,6 +2845,14 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
CBlockUndo blockundo;
if ( ASSETCHAINS_CC != 0 )
{
if ( scriptcheckqueue.IsIdle() == 0 )
{
fprintf(stderr,"scriptcheckqueue isnt idle\n");
sleep(1);
}
}
CCheckQueueControl<CScriptCheck> control(fExpensiveChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL);
int64_t nTimeStart = GetTimeMicros();
@@ -2705,7 +2900,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return state.DoS(100, error("ConnectBlock(): too many sigops"),
REJECT_INVALID, "bad-blk-sigops");
//fprintf(stderr,"ht.%d vout0 t%u\n",pindex->nHeight,tx.nLockTime);
if (!tx.IsCoinBase())
if (!tx.IsMint())
{
if (!view.HaveInputs(tx))
{
@@ -2728,10 +2923,20 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (prevout.scriptPubKey.IsPayToScriptHash()) {
hashBytes = uint160(vector <unsigned char>(prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22));
addressType = 2;
} else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
}
else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
hashBytes = uint160(vector <unsigned char>(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23));
addressType = 1;
} else {
}
else if (prevout.scriptPubKey.IsPayToPublicKey()) {
hashBytes = Hash160(vector <unsigned char>(prevout.scriptPubKey.begin()+1, prevout.scriptPubKey.begin()+34));
addressType = 1;
}
else if (prevout.scriptPubKey.IsPayToCryptoCondition()) {
hashBytes = Hash160(vector <unsigned char>(prevout.scriptPubKey.begin(), prevout.scriptPubKey.end()));
addressType = 1;
}
else {
hashBytes.SetNull();
addressType = 0;
}
@@ -2765,7 +2970,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (!tx.IsCoinBase())
{
nFees += view.GetValueIn(chainActive.Tip()->nHeight,&interest,tx,chainActive.Tip()->nTime) - tx.GetValueOut();
nFees += view.GetValueIn(chainActive.LastTip()->nHeight,&interest,tx,chainActive.LastTip()->nTime) - tx.GetValueOut();
sum += interest;
std::vector<CScriptCheck> vChecks;
@@ -2777,7 +2982,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (fAddressIndex) {
for (unsigned int k = 0; k < tx.vout.size(); k++) {
const CTxOut &out = tx.vout[k];
//fprintf(stderr,"add %d vouts\n",(int32_t)tx.vout.size());
if (out.scriptPubKey.IsPayToScriptHash()) {
vector<unsigned char> hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22);
@@ -2787,7 +2992,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
// record unspent output
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
} else if (out.scriptPubKey.IsPayToPublicKeyHash()) {
}
else if (out.scriptPubKey.IsPayToPublicKeyHash()) {
vector<unsigned char> hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23);
// record receiving activity
@@ -2796,7 +3002,28 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
// record unspent output
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
} else {
}
else if (out.scriptPubKey.IsPayToPublicKey()) {
vector<unsigned char> hashBytes(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34);
// record receiving activity
addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
// record unspent output
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
}
else if (out.scriptPubKey.IsPayToCryptoCondition()) {
vector<unsigned char> hashBytes(out.scriptPubKey.begin(), out.scriptPubKey.end());
// record receiving activity
addressIndex.push_back(make_pair(CAddressIndexKey(1, Hash160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
// record unspent output
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, Hash160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
}
else {
continue;
}
@@ -2856,7 +3083,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)",
block.vtx[0].GetValueOut(), blockReward),
REJECT_INVALID, "bad-cb-amount");
} else if ( NOTARY_PUBKEY33[0] != 0 )
} else if ( IS_KOMODO_NOTARY != 0 )
fprintf(stderr,"allow nHeight.%d coinbase %.8f vs %.8f interest %.8f\n",(int32_t)pindex->nHeight,dstr(block.vtx[0].GetValueOut()),dstr(blockReward),dstr(sum));
}
if (!control.Wait())
@@ -2896,6 +3123,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
pindex->RaiseValidity(BLOCK_VALID_SCRIPTS);
setDirtyBlockIndex.insert(pindex);
}
ConnectNotarisations(block, pindex->nHeight);
if (fTxIndex)
if (!pblocktree->WriteTxIndex(vPos))
@@ -3083,10 +3312,19 @@ void static UpdateTip(CBlockIndex *pindexNew) {
nTimeBestReceived = GetTime();
mempool.AddTransactionsUpdated(1);
KOMODO_NEWBLOCKS++;
double progress;
if ( ASSETCHAINS_SYMBOL[0] == 0 ) {
progress = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.LastTip());
} else {
int32_t longestchain = komodo_longestchain();
progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 1.0;
}
LogPrintf("%s: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f cache=%.1fMiB(%utx)\n", __func__,
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx,
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
chainActive.LastTip()->GetBlockHash().ToString(), chainActive.Height(),
log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.LastTip()->nChainTx,
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.LastTip()->GetBlockTime()), progress,
pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
cvBlockChange.notify_all();
@@ -3133,6 +3371,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
if (!DisconnectBlock(block, state, pindexDelete, view))
return error("DisconnectTip(): DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString());
assert(view.Flush());
DisconnectNotarisations(block);
}
LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
uint256 anchorAfterDisconnect = pcoinsTip->GetBestAnchor();
@@ -3149,7 +3388,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
list<CTransaction> removed;
CValidationState stateDummy;
// don't keep staking or invalid transactions
if (tx.IsCoinBase() || ((i == (block.vtx.size() - 1)) && block.IsVerusPOSBlock()) || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL))
if (tx.IsCoinBase() || ((i == (block.vtx.size() - 1)) && (block.IsVerusPOSBlock() || komodo_isPoS((CBlock *)&block) != 0)) || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL))
{
mempool.remove(tx, removed, true);
}
@@ -3165,13 +3404,15 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
UpdateTip(pindexDelete->pprev);
// Get the current commitment tree
ZCIncrementalMerkleTree newTree;
assert(pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), newTree));
// Let wallets know transactions went from 1-confirmed to
// 0-confirmed or conflicted:
for (int i = 0; i < block.vtx.size(); i++)
{
CTransaction &tx = block.vtx[i];
if ((i == (block.vtx.size() - 1) && block.IsVerusPOSBlock()))
if ((i == (block.vtx.size() - 1) && (block.IsVerusPOSBlock() || komodo_isPoS((CBlock *)&block) != 0)))
{
EraseFromWallets(tx.GetHash());
}
@@ -3180,8 +3421,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
SyncWithWallets(tx, NULL);
}
}
// Update cached incremental witnesses
//fprintf(stderr,"chaintip false\n");
GetMainSignals().ChainTip(pindexDelete, &block, newTree, false);
return true;
}
@@ -3263,7 +3503,11 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001);
LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001);
if ( ASSETCHAINS_SYMBOL[0] == 0 )
if ( KOMODO_LONGESTCHAIN != 0 && pindexNew->nHeight >= KOMODO_LONGESTCHAIN )
KOMODO_INSYNC = 1;
else KOMODO_INSYNC = 0;
//fprintf(stderr,"connect.%d insync.%d\n",(int32_t)pindexNew->nHeight,KOMODO_INSYNC);
if ( ASSETCHAINS_SYMBOL[0] == 0 && KOMODO_INSYNC != 0 )
komodo_broadcast(pblock,8);
return true;
}
@@ -3331,7 +3575,7 @@ static void PruneBlockIndexCandidates() {
// Note that we can't delete the current block itself, as we may need to return to it later in case a
// reorganization to a better block fails.
std::set<CBlockIndex*, CBlockIndexWorkComparator>::iterator it = setBlockIndexCandidates.begin();
while (it != setBlockIndexCandidates.end() && setBlockIndexCandidates.value_comp()(*it, chainActive.Tip())) {
while (it != setBlockIndexCandidates.end() && setBlockIndexCandidates.value_comp()(*it, chainActive.LastTip())) {
setBlockIndexCandidates.erase(it++);
}
// Either the current tip or a successor of it we're working towards is left in setBlockIndexCandidates.
@@ -3383,8 +3627,8 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
if ( KOMODO_REWIND != 0 )
{
CBlockIndex *tipindex;
fprintf(stderr,">>>>>>>>>>> rewind start ht.%d -> KOMODO_REWIND.%d\n",chainActive.Tip()->nHeight,KOMODO_REWIND);
while ( KOMODO_REWIND > 0 && (tipindex= chainActive.Tip()) != 0 && tipindex->nHeight > KOMODO_REWIND )
fprintf(stderr,">>>>>>>>>>> rewind start ht.%d -> KOMODO_REWIND.%d\n",chainActive.LastTip()->nHeight,KOMODO_REWIND);
while ( KOMODO_REWIND > 0 && (tipindex= chainActive.LastTip()) != 0 && tipindex->nHeight > KOMODO_REWIND )
{
fBlocksDisconnected = true;
fprintf(stderr,"%d ",(int32_t)tipindex->nHeight);
@@ -3798,9 +4042,9 @@ bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,
for (i=31; i>=0; i--)
fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
fprintf(stderr," <- CheckBlockHeader\n");
if ( chainActive.Tip() != 0 )
if ( chainActive.LastTip() != 0 )
{
hash = chainActive.Tip()->GetBlockHash();
hash = chainActive.LastTip()->GetBlockHash();
for (i=31; i>=0; i--)
fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
fprintf(stderr," <- chainTip\n");
@@ -3822,7 +4066,7 @@ bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,
{
if (blockhdr.GetBlockTime() < GetAdjustedTime() + 600)
*futureblockp = 1;
LogPrintf("CheckBlockHeader block from future %d error",blockhdr.GetBlockTime() - GetAdjustedTime());
//LogPrintf("CheckBlockHeader block from future %d error",blockhdr.GetBlockTime() - GetAdjustedTime());
return false; //state.Invalid(error("CheckBlockHeader(): block timestamp too far in the future"),REJECT_INVALID, "time-too-new");
}
}
@@ -3853,9 +4097,7 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C
uint8_t pubkey33[33]; uint256 hash;
// These are checks that are independent of context.
hash = block.GetHash();
// Check that the header is valid (particularly PoW). This is mostly
// redundant with the call in AcceptBlockHeader.
// Check that the header is valid (particularly PoW). This is mostly redundant with the call in AcceptBlockHeader.
if (!CheckBlockHeader(futureblockp,height,pindex,block,state,fCheckPOW))
{
if ( *futureblockp == 0 )
@@ -3915,6 +4157,21 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C
REJECT_INVALID, "bad-cb-multiple");
// Check transactions
if ( ASSETCHAINS_CC != 0 ) // CC contracts might refer to transactions in the current block, from a CC spend within the same block and out of order
{
CValidationState stateDummy;
//fprintf(stderr,"put block's tx into mempool\n");
for (int i = 0; i < block.vtx.size(); i++)
{
const CTransaction &tx = block.vtx[i];
if (tx.IsCoinBase() != 0 )
continue;
else if ( ASSETCHAINS_STAKED != 0 && (i == (block.vtx.size() - 1)) && komodo_isPoS((CBlock *)&block) != 0 )
continue;
AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL);
}
//fprintf(stderr,"done putting block's tx into mempool\n");
}
BOOST_FOREACH(const CTransaction& tx, block.vtx)
{
if ( komodo_validate_interest(tx,height == 0 ? komodo_block2height((CBlock *)&block) : height,block.nTime,0) < 0 )
@@ -3992,16 +4249,26 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
// Don't accept any forks from the main chain prior to last checkpoint
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainParams.Checkpoints());
int32_t notarized_height;
if (pcheckpoint && nHeight > 1 && nHeight < pcheckpoint->nHeight )
return state.DoS(1, error("%s: forked chain older than last checkpoint (height %d) vs %d", __func__, nHeight,pcheckpoint->nHeight));
else if ( komodo_checkpoint(&notarized_height,nHeight,hash) < 0 )
if ( nHeight == 1 && chainActive.LastTip() != 0 && chainActive.LastTip()->nHeight > 1 )
{
CBlockIndex *heightblock = chainActive[nHeight];
if ( heightblock != 0 && heightblock->GetBlockHash() == hash )
{
//fprintf(stderr,"got a pre notarization block that matches height.%d\n",(int32_t)nHeight);
return true;
} else return state.DoS(1, error("%s: forked chain %d older than last notarized (height %d) vs %d", __func__,nHeight, notarized_height));
return state.DoS(1, error("%s: trying to change height 1 forbidden", __func__));
}
if ( nHeight != 0 )
{
if ( pcheckpoint != 0 && nHeight < pcheckpoint->nHeight )
return state.DoS(1, error("%s: forked chain older than last checkpoint (height %d) vs %d", __func__, nHeight,pcheckpoint->nHeight));
if ( komodo_checkpoint(&notarized_height,nHeight,hash) < 0 )
{
CBlockIndex *heightblock = chainActive[nHeight];
if ( heightblock != 0 && heightblock->GetBlockHash() == hash )
{
//fprintf(stderr,"got a pre notarization block that matches height.%d\n",(int32_t)nHeight);
return true;
} else return state.DoS(1, error("%s: forked chain %d older than last notarized (height %d) vs %d", __func__,nHeight, notarized_height));
}
}
}
// Reject block.nVersion < 4 blocks
@@ -4049,16 +4316,13 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
return true;
}
//static uint256 komodo_requestedhash;
//static int32_t komodo_requestedcount;
bool AcceptBlockHeader(int32_t *futureblockp,const CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex)
{
static uint256 zero;
const CChainParams& chainparams = Params();
AssertLockHeld(cs_main);
// Check for duplicate
// Check for duplicate
uint256 hash = block.GetHash();
BlockMap::iterator miSelf = mapBlockIndex.find(hash);
CBlockIndex *pindex = NULL;
@@ -4097,25 +4361,13 @@ bool AcceptBlockHeader(int32_t *futureblockp,const CBlockHeader& block, CValidat
BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
if (mi == mapBlockIndex.end())
{
//fprintf(stderr,"AcceptBlockHeader hashPrevBlock %s not found\n",block.hashPrevBlock.ToString().c_str());
/*if ( komodo_requestedhash == zero )
{
komodo_requestedhash = block.hashPrevBlock;
komodo_requestedcount = 0;
}*/
LogPrintf("AcceptBlockHeader %s\n hashPrevBlock %s not found\n", hash.ToString().c_str(), block.hashPrevBlock.ToString().c_str());
LogPrintf("AcceptBlockHeader hashPrevBlock %s not found\n",block.hashPrevBlock.ToString().c_str());
return(false);
//return state.DoS(10, error("%s: prev block not found", __func__), 0, "bad-prevblk");
}
pindexPrev = (*mi).second;
if (pindexPrev == 0 )
{
/*fprintf(stderr,"AcceptBlockHeader failed no pindexPrev %s\n",block.hashPrevBlock.ToString().c_str());
if ( komodo_requestedhash == zero )
{
komodo_requestedhash = block.hashPrevBlock;
komodo_requestedcount = 0;
}*/
LogPrintf("AcceptBlockHeader hashPrevBlock %s no pindexPrev\n",block.hashPrevBlock.ToString().c_str());
return(false);
}
@@ -4207,7 +4459,6 @@ bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, C
}
int nHeight = pindex->nHeight;
// Write block to history file
try {
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
@@ -4333,18 +4584,18 @@ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNo
bool checked; uint256 hash; int32_t futureblock=0;
auto verifier = libzcash::ProofVerifier::Disabled();
hash = pblock->GetHash();
//fprintf(stderr,"process newblock %s\n",hash.ToString().c_str());
if ( chainActive.Tip() != 0 )
komodo_currentheight_set(chainActive.Tip()->nHeight);
checked = CheckBlock(&futureblock,height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier,0);
//fprintf(stderr,"ProcessBlock %d\n",(int32_t)chainActive.LastTip()->nHeight);
{
LOCK(cs_main);
if ( chainActive.LastTip() != 0 )
komodo_currentheight_set(chainActive.LastTip()->nHeight);
checked = CheckBlock(&futureblock,height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier,0);
bool fRequested = MarkBlockAsReceived(hash);
fRequested |= fForceProcessing;
if ( checked != 0 && komodo_checkPOW(from_miner && ASSETCHAINS_STAKED == 0,pblock,height) < 0 )
if ( checked != 0 && komodo_checkPOW(0,pblock,height) < 0 ) //from_miner && ASSETCHAINS_STAKED == 0
{
checked = 0;
fprintf(stderr,"passed checkblock but failed checkPOW.%d\n",from_miner && ASSETCHAINS_STAKED == 0);
//fprintf(stderr,"passed checkblock but failed checkPOW.%d\n",from_miner && ASSETCHAINS_STAKED == 0);
}
if (!checked && futureblock == 0)
{
@@ -4373,7 +4624,8 @@ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNo
if (futureblock == 0 && !ActivateBestChain(state, pblock))
return error("%s: ActivateBestChain failed", __func__);
//fprintf(stderr,"finished ProcessBlock %d\n",(int32_t)chainActive.LastTip()->nHeight);
return true;
}
@@ -4753,11 +5005,21 @@ bool static LoadBlockIndexDB()
it->second->hashAnchorEnd = pcoinsTip->GetBestAnchor();
PruneBlockIndexCandidates();
double progress;
if ( ASSETCHAINS_SYMBOL[0] == 0 ) {
progress = Checkpoints::GuessVerificationProgress(chainparams.Checkpoints(), chainActive.Tip());
} else {
int32_t longestchain = komodo_longestchain();
// TODO: komodo_longestchain does not have the data it needs at the time LoadBlockIndexDB
// runs, which makes it return 0, so we guess 50% for now
progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 0.5;
}
LogPrintf("%s: hashBestChain=%s height=%d date=%s progress=%f\n", __func__,
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(),
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
Checkpoints::GuessVerificationProgress(chainparams.Checkpoints(), chainActive.Tip()));
chainActive.LastTip()->GetBlockHash().ToString(), chainActive.Height(),
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.LastTip()->GetBlockTime()),
progress);
EnforceNodeDeprecation(chainActive.Height(), true);
@@ -5218,10 +5480,11 @@ void static CheckBlockIndex()
// Build forward-pointing map of the entire block tree.
std::multimap<CBlockIndex*,CBlockIndex*> forward;
for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); it++) {
forward.insert(std::make_pair(it->second->pprev, it->second));
if ( it->second != 0 )
forward.insert(std::make_pair(it->second->pprev, it->second));
}
assert(forward.size() == mapBlockIndex.size());
if ( Params().NetworkIDString() != "regtest" )
assert(forward.size() == mapBlockIndex.size());
std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeGenesis = forward.equal_range(NULL);
CBlockIndex *pindex = rangeGenesis.first->second;
@@ -6047,7 +6310,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
pfrom->PushMessage("headers", vHeaders);
}
/*else if ( NOTARY_PUBKEY33[0] != 0 )
/*else if ( IS_KOMODO_NOTARY != 0 )
{
static uint32_t counter;
if ( counter++ < 3 )
@@ -6219,10 +6482,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return error("non-continuous headers sequence");
}
int32_t futureblock;
//fprintf(stderr,"headers msg nCount.%d\n",(int32_t)nCount);
if (!AcceptBlockHeader(&futureblock,header, state, &pindexLast)) {
int nDoS;
if (state.IsInvalid(nDoS))
if (state.IsInvalid(nDoS) && futureblock == 0)
{
if (nDoS > 0 && futureblock == 0)
Misbehaving(pfrom->GetId(), nDoS/nDoS);