Browse Source

Updates from to main.cpp from kmd master 1f874d46c5ddd24c0fd32ae6800f16d8006b9059

pull/51/head
Duke Leto 5 years ago
parent
commit
c1d1554dfc
  1. 327
      src/main.cpp

327
src/main.cpp

@ -940,20 +940,34 @@ bool IsStandardTx(const CTransaction& tx, string& reason, const int nHeight)
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
{
int32_t i;
if (tx.nLockTime == 0)
if (tx.nLockTime == 0)
return true;
if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
return true;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
if ( txin.nSequence == 0xfffffffe && (((int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD && (int64_t)tx.nLockTime > nBlockTime) || ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD && (int64_t)tx.nLockTime > nBlockHeight)) )
if ( !komodo_hardfork_active(nBlockTime) && txin.nSequence == 0xfffffffe &&
//if ( (nBlockTime <= ASSETCHAINS_STAKED_HF_TIMESTAMP ) && txin.nSequence == 0xfffffffe &&
(
((int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD && (int64_t)tx.nLockTime > nBlockTime) ||
((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD && (int64_t)tx.nLockTime > nBlockHeight)
)
)
{
}
//else if ( nBlockTime > ASSETCHAINS_STAKED_HF_TIMESTAMP && txin.nSequence == 0xfffffffe &&
else if ( komodo_hardfork_active(nBlockTime) && txin.nSequence == 0xfffffffe &&
(
((int64_t)tx.nLockTime >= LOCKTIME_THRESHOLD && (int64_t)tx.nLockTime <= nBlockTime) ||
((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD && (int64_t)tx.nLockTime <= nBlockHeight))
)
{
}
else if (!txin.IsFinal())
{
//printf("non-final txin seq.%x locktime.%u vs nTime.%u\n",txin.nSequence,(uint32_t)tx.nLockTime,(uint32_t)nBlockTime);
LogPrintf("non-final txin seq.%x locktime.%u vs nTime.%u\n",txin.nSequence,(uint32_t)tx.nLockTime,(uint32_t)nBlockTime);
return false;
}
}
@ -1160,6 +1174,7 @@ bool ContextualCheckTransaction(int32_t slowflag,const CBlock *block, CBlockInde
if (tx.fOverwintered && tx.nVersionGroupId != SAPLING_VERSION_GROUP_ID)
{
//return state.DoS(dosLevel, error("CheckTransaction(): invalid Sapling tx version"),REJECT_INVALID, "bad-sapling-tx-version-group-id");
if ( 0 )
{
string strHex = EncodeHexTx(tx);
fprintf(stderr,"invalid Sapling rawtx.%s\n",strHex.c_str());
@ -1332,7 +1347,7 @@ bool ContextualCheckTransaction(int32_t slowflag,const CBlock *block, CBlockInde
}
bool CheckTransaction(uint32_t tiptime,const CTransaction& tx, CValidationState &state,
libzcash::ProofVerifier& verifier)
libzcash::ProofVerifier& verifier,int32_t txIndex, int32_t numTxs)
{
static uint256 array[64]; static int32_t numbanned,indallvouts; int32_t j,k,n;
if ( *(int32_t *)&array[0] == 0 )
@ -1732,7 +1747,7 @@ CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF
}
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,bool* pfMissingInputs, bool fRejectAbsurdFee, int dosLevel, bool fSkipExpiry)
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,bool* pfMissingInputs, bool fRejectAbsurdFee, int dosLevel)
{
AssertLockHeld(cs_main);
if (pfMissingInputs)
@ -1743,14 +1758,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
if ( nextBlockHeight <= 1 || chainActive.LastTip() == 0 )
tiptime = (uint32_t)time(NULL);
else tiptime = (uint32_t)chainActive.LastTip()->nTime;
// is it already in the memory pool?
uint256 hash = tx.GetHash();
if (pool.exists(hash))
{
//fprintf(stderr,"already in mempool\n");
return state.Invalid(false, REJECT_DUPLICATE, "already in mempool");
}
//fprintf(stderr,"addmempool 0\n");
// Node operator can choose to reject tx by number of transparent inputs
static_assert(std::numeric_limits<size_t>::max() >= std::numeric_limits<int64_t>::max(), "size_t too small");
@ -1766,21 +1773,21 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
}
}
//fprintf(stderr,"addmempool 1\n");
auto verifier = libzcash::ProofVerifier::Strict();
if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,chainActive.LastTip()->GetHeight()+1,chainActive.LastTip()->GetMedianTimePast() + 777,0) < 0 )
{
//fprintf(stderr,"AcceptToMemoryPool komodo_validate_interest failure\n");
fprintf(stderr,"AcceptToMemoryPool komodo_validate_interest failure\n");
return error("AcceptToMemoryPool: komodo_validate_interest failed");
}
if (!CheckTransaction(tiptime,tx, state, verifier))
if (!CheckTransaction(tiptime,tx, state, verifier, 0, 0))
{
return error("AcceptToMemoryPool: CheckTransaction failed");
}
// DoS level set to 10 to be more forgiving.
// Check transaction contextually against the set of consensus rules which apply in the next block to be mined.
if (!fSkipExpiry && !ContextualCheckTransaction(0,0,0,tx, state, nextBlockHeight, (dosLevel == -1) ? 10 : dosLevel))
if (!ContextualCheckTransaction(0,0,0,tx, state, nextBlockHeight, (dosLevel == -1) ? 10 : dosLevel))
{
return error("AcceptToMemoryPool: ContextualCheckTransaction failed");
}
@ -1791,26 +1798,34 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
fprintf(stderr,"AcceptToMemoryPool coinbase as individual tx\n");
return state.DoS(100, error("AcceptToMemoryPool: coinbase as individual tx"),REJECT_INVALID, "coinbase");
}
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
string reason;
if (!fSkipExpiry && Params().RequireStandard() && !IsStandardTx(tx, reason, nextBlockHeight))
if (Params().RequireStandard() && !IsStandardTx(tx, reason, nextBlockHeight))
{
//
//fprintf(stderr,"AcceptToMemoryPool reject nonstandard transaction: %s\nscriptPubKey: %s\n",reason.c_str(),tx.vout[0].scriptPubKey.ToString().c_str());
return state.DoS(0,error("AcceptToMemoryPool: nonstandard transaction: %s", reason),REJECT_NONSTANDARD, reason);
}
// Only accept nLockTime-using transactions that can be mined in the next
// block; we don't want our mempool filled up with transactions that can't
// be mined yet.
if (!fSkipExpiry && !CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
{
//fprintf(stderr,"AcceptToMemoryPool reject non-final\n");
return state.DoS(0, false, REJECT_NONSTANDARD, "non-final");
}
//fprintf(stderr,"addmempool 3\n");
// is it already in the memory pool?
uint256 hash = tx.GetHash();
if (pool.exists(hash))
{
//fprintf(stderr,"already in mempool\n");
return state.Invalid(false, REJECT_DUPLICATE, "already in mempool");
}
// Check for conflicts with in-memory transactions
if (!fSkipExpiry)
{
LOCK(pool.cs); // protect pool.mapNextTx
for (unsigned int i = 0; i < tx.vin.size(); i++)
@ -1837,7 +1852,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
}
}
//fprintf(stderr,"addmempool 4\n");
{
CCoinsView dummy;
CCoinsViewCache view(&dummy);
@ -1861,7 +1875,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
if (ExistsImportTombstone(tx, view))
return state.Invalid(false, REJECT_DUPLICATE, "import tombstone exists");
}
else if (!fSkipExpiry)
else
{
// do all inputs exist?
// Note that this does not check for the presence of actual outputs (see the next check for that),
@ -1873,10 +1887,13 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
if (pfMissingInputs)
*pfMissingInputs = true;
//fprintf(stderr,"missing inputs\n");
return state.DoS(0, error("AcceptToMemoryPool: tx inputs not found"),REJECT_INVALID, "bad-txns-inputs-missing");
return false;
/*
https://github.com/zcash/zcash/blob/master/src/main.cpp#L1490
state.DoS(0, error("AcceptToMemoryPool: tx inputs not found"),REJECT_INVALID, "bad-txns-inputs-missing");
*/
}
}
// are the actual inputs available?
if (!view.HaveInputs(tx))
{
@ -1884,59 +1901,50 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent");
}
}
// are the joinsplit's requirements met?
if (!view.HaveJoinSplitRequirements(tx))
{
//fprintf(stderr,"accept failure.2\n");
return state.Invalid(error("AcceptToMemoryPool: joinsplit requirements not met"),REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met");
}
// Bring the best block into scope
view.GetBestBlock();
if (!fSkipExpiry)
nValueIn = view.GetValueIn(chainActive.LastTip()->GetHeight(),&interest,tx,chainActive.LastTip()->nTime);
nValueIn = view.GetValueIn(chainActive.LastTip()->GetHeight(),&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
view.SetBackend(dummy);
}
// Check for non-standard pay-to-script-hash in inputs
if (!fSkipExpiry && Params().RequireStandard() && !AreInputsStandard(tx, view, consensusBranchId))
if (Params().RequireStandard() && !AreInputsStandard(tx, view, consensusBranchId))
return error("AcceptToMemoryPool: reject nonstandard transaction input");
// Check that the transaction doesn't have an excessive number of
// sigops, making it impossible to mine. Since the coinbase transaction
// itself can contain sigops MAX_STANDARD_TX_SIGOPS is less than
// MAX_BLOCK_SIGOPS; we still consider this an invalid rather than
// merely non-standard transaction.
unsigned int nSigOps = GetLegacySigOpCount(tx);
if (!fSkipExpiry)
nSigOps += GetP2SHSigOpCount(tx, view);
nSigOps += GetP2SHSigOpCount(tx, view);
if (nSigOps > MAX_STANDARD_TX_SIGOPS)
{
fprintf(stderr,"accept failure.4\n");
return state.DoS(1, error("AcceptToMemoryPool: too many sigops %s, %d > %d", hash.ToString(), nSigOps, MAX_STANDARD_TX_SIGOPS),REJECT_NONSTANDARD, "bad-txns-too-many-sigops");
}
CAmount nValueOut = tx.GetValueOut();
double dPriority = 0;
CAmount nFees = 0;
if (!fSkipExpiry)
{
dPriority = view.GetPriority(tx, chainActive.Height());
nFees = nValueIn-nValueOut;
}
CAmount nFees = nValueIn-nValueOut;
double dPriority = view.GetPriority(tx, chainActive.Height());
if ( nValueOut > 777777*COIN && KOMODO_VALUETOOBIG(nValueOut - 777777*COIN) != 0 ) // some room for blockreward and txfees
return state.DoS(100, error("AcceptToMemoryPool: GetValueOut too big"),REJECT_INVALID,"tx valueout is too big");
// Keep track of transactions that spend a coinbase, which we re-scan
// during reorgs to ensure COINBASE_MATURITY is still met.
bool fSpendsCoinbase = false;
if (!fSkipExpiry && !tx.IsCoinImport() && !tx.IsPegsImport()) {
if (!tx.IsCoinImport() && !tx.IsPegsImport()) {
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
const CCoins *coins = view.AccessCoins(txin.prevout.hash);
if (coins->IsCoinBase()) {
@ -1945,15 +1953,15 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
}
}
}
//fprintf(stderr,"addmempool 5\n");
// Grab the branch ID we expect this transaction to commit to. We don't
// yet know if it does, but if the entry gets added to the mempool, then
// it has passed ContextualCheckInputs and therefore this is correct.
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), mempool.HasNoInputsOf(tx), fSpendsCoinbase, consensusBranchId);
unsigned int nSize = entry.GetTxSize();
// Accept a tx if it contains joinsplits and has at least the default fee specified by z_sendmany.
if (tx.vjoinsplit.size() > 0 && nFees >= ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE) {
// In future we will we have more accurate and dynamic computation of fees for tx with joinsplits.
@ -1966,17 +1974,17 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
return state.DoS(0, error("AcceptToMemoryPool: not enough fees %s, %d < %d",hash.ToString(), nFees, txMinFee),REJECT_INSUFFICIENTFEE, "insufficient fee");
}
}
// Require that free transactions have sufficient priority to be mined in the next block.
if (GetBoolArg("-relaypriority", false) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(view.GetPriority(tx, chainActive.Height() + 1))) {
fprintf(stderr,"accept failure.6\n");
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient priority");
}
// Continuously rate-limit free (really, very-low-fee) transactions
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
// be annoying or make others' transactions take longer to confirm.
if ( !fSkipExpiry && fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize) && !tx.IsCoinImport() && !tx.IsPegsImport())
if (fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize) && !tx.IsCoinImport() && !tx.IsPegsImport())
{
static CCriticalSection csFreeLimiter;
static double dFreeCount;
@ -1998,8 +2006,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
dFreeCount += nSize;
}
if (!fSkipExpiry && !tx.IsCoinImport() && !tx.IsPegsImport() && fRejectAbsurdFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000 && nFees > nValueOut/19)
if (!tx.IsCoinImport() && !tx.IsPegsImport() && fRejectAbsurdFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000 && nFees > nValueOut/19)
{
string errmsg = strprintf("absurdly high fees %s, %d > %d",
hash.ToString(),
@ -2012,12 +2020,12 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
PrecomputedTransactionData txdata(tx);
if (!fSkipExpiry && !ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
{
//fprintf(stderr,"accept failure.9\n");
return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString());
}
// Check again against just the consensus-critical mandatory script
// verification flags, in case of bugs in the standard flags that cause
// transactions to pass as valid when they're actually invalid. For
@ -2034,7 +2042,8 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
KOMODO_CONNECTING = (1<<30) + (int32_t)chainActive.LastTip()->GetHeight() + 1;
}
//fprintf(stderr,"addmempool 7\n");
if (!fSkipExpiry && !ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
{
if ( flag != 0 )
KOMODO_CONNECTING = -1;
@ -2043,24 +2052,36 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
if ( flag != 0 )
KOMODO_CONNECTING = -1;
// Store transaction in memory
pool.addUnchecked(hash, entry, !IsInitialBlockDownload());
if (!fSkipExpiry && !tx.IsCoinImport())
{
// Add memory address index
if (fAddressIndex) {
pool.addAddressIndex(entry, view);
}
LOCK(pool.cs);
// Store transaction in memory
pool.addUnchecked(hash, entry, !IsInitialBlockDownload());
if (!tx.IsCoinImport())
{
// Add memory address index
if (fAddressIndex) {
pool.addAddressIndex(entry, view);
}
// Add memory spent index
if (fSpentIndex) {
pool.addSpentIndex(entry, view);
// Add memory spent index
if (fSpentIndex) {
pool.addSpentIndex(entry, view);
}
}
}
}
//SyncWithWallets(tx,NULL);
// This should be here still?
//SyncWithWallets(tx, NULL);
return true;
}
bool CCTxFixAcceptToMemPoolUnchecked(CTxMemPool& pool, const CTransaction &tx)
{
// called from CheckBlock which is in cs_main and mempool.cs locks already.
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
CTxMemPoolEntry entry(tx, 0, GetTime(), 0, chainActive.Height(), mempool.HasNoInputsOf(tx), false, consensusBranchId);
//fprintf(stderr, "adding %s to mempool from block %d\n",tx.GetHash().ToString().c_str(),chainActive.GetHeight());
pool.addUnchecked(tx.GetHash(), entry, false);
return true;
}
@ -2127,59 +2148,6 @@ struct CompareBlocksByHeightMain
}
};
bool RemoveOrphanedBlocks(int32_t notarized_height)
{
LOCK(cs_main);
std::vector<const CBlockIndex*> prunedblocks;
std::set<const CBlockIndex*, CompareBlocksByHeightMain> setTips;
int32_t m=0,n = 0;
// get notarised timestamp and use this as a backup incase the forked block has no height.
// we -600 to make sure the time is within future block constraints.
uint32_t notarized_timestamp = komodo_heightstamp(notarized_height)-600;
// Most of this code is a direct copy from GetChainTips RPC. Which gives a return of all
// blocks that are not in the main chain.
BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
{
n++;
setTips.insert(item.second);
}
n = 0;
BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
{
const CBlockIndex* pprev=0;
n++;
if ( item.second != 0 )
pprev = item.second->pprev;
if (pprev)
setTips.erase(pprev);
}
const CBlockIndex *forked;
BOOST_FOREACH(const CBlockIndex* block, setTips)
{
// We skip anything over notarised height to avoid breaking normal consensus rules.
if ( block->GetHeight() > notarized_height || block->nTime > notarized_timestamp )
continue;
// We can also check if the block is in the active chain as a backup test.
forked = chainActive.FindFork(block);
// Here we save each forked block to a vector for removal later.
if ( forked != 0 )
prunedblocks.push_back(block);
}
if (prunedblocks.size() > 0 && pblocktree->EraseBatchSync(prunedblocks))
{
// Blocks cleared from disk succesfully, using internal DB batch erase function. Which exists, but has never been used before.
// We need to try and clear the block index from mapBlockIndex now, otherwise node will need a restart.
BOOST_FOREACH(const CBlockIndex* block, prunedblocks)
{
m++;
mapBlockIndex.erase(block->GetBlockHash());
}
fprintf(stderr, "%s removed %d orphans from %d blocks before %d\n",ASSETCHAINS_SYMBOL,m,n, notarized_height);
return true;
}
return false;
}
/*uint64_t myGettxout(uint256 hash,int32_t n)
{
CCoins coins;
@ -2199,7 +2167,12 @@ bool myAddtomempool(CTransaction &tx, CValidationState *pstate, bool fSkipExpiry
pstate = &state;
CTransaction Ltx; bool fMissingInputs,fOverrideFees = false;
if ( mempool.lookup(tx.GetHash(),Ltx) == 0 )
return(AcceptToMemoryPool(mempool, *pstate, tx, false, &fMissingInputs, !fOverrideFees, -1, fSkipExpiry));
{
if ( !fSkipExpiry )
return(AcceptToMemoryPool(mempool, *pstate, tx, false, &fMissingInputs, !fOverrideFees, -1));
else
return(CCTxFixAcceptToMemPoolUnchecked(mempool,tx));
}
else return(true);
}
@ -3413,9 +3386,10 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
auto verifier = libzcash::ProofVerifier::Strict();
auto disabledVerifier = libzcash::ProofVerifier::Disabled();
int32_t futureblock;
CAmount blockReward = 0; uint64_t notarypaycheque = 0;
CAmount blockReward = GetBlockSubsidy(pindex->GetHeight(), chainparams.GetConsensus());
uint64_t notarypaycheque = 0;
// Check it again to verify JoinSplit proofs, and in case a previous version let a bad block in
if (!CheckBlock(&futureblock,pindex->GetHeight(),pindex,block, state, fExpensiveChecks ? verifier : disabledVerifier, fCheckPOW, !fJustCheck) || futureblock != 0 )
if ( !CheckBlock(&futureblock,pindex->GetHeight(),pindex,block, state, fExpensiveChecks ? verifier : disabledVerifier, fCheckPOW, !fJustCheck) || futureblock != 0 )
{
//fprintf(stderr,"checkblock failure in connectblock futureblock.%d\n",futureblock);
return false;
@ -3532,7 +3506,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
CAmount nFees = 0;
int nInputs = 0;
uint64_t valueout;
int64_t voutsum = 0,prevsum=0,interest,sum = 0;
int64_t voutsum = 0, prevsum = 0, interest, sum = 0, stakeTxValue = 0;
unsigned int nSigOps = 0;
CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
std::vector<std::pair<uint256, CDiskTxPos> > vPos;
@ -3731,7 +3705,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
int64_t nTime1 = GetTimeMicros(); nTimeConnect += nTime1 - nTimeStart;
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);
blockReward += nFees + GetBlockSubsidy(pindex->GetHeight(), chainparams.GetConsensus()) + sum;
blockReward += nFees + sum;
if ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 ) //ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 &&
{
uint64_t checktoshis;
@ -4016,6 +3990,9 @@ void static UpdateTip(CBlockIndex *pindexNew) {
pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
cvBlockChange.notify_all();
/*
// https://github.com/zcash/zcash/issues/3992 -> https://github.com/zcash/zcash/commit/346d11d3eb2f8162df0cb00b1d1f49d542495198
// Check the version of the last 100 blocks to see if we need to upgrade:
static bool fWarned = false;
@ -4039,6 +4016,7 @@ void static UpdateTip(CBlockIndex *pindexNew) {
fWarned = true;
}
}
*/
}
/**
@ -4127,17 +4105,15 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
for (int i = 0; i < block.vtx.size(); i++)
{
CTransaction &tx = block.vtx[i];
if ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block,pindexDelete->GetHeight(),true) != 0)))
//if ((i == (block.vtx.size() - 1)) && ((ASSETCHAINS_LWMAPOS && block.IsVerusPOSBlock()) || (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block) != 0))))
if ( komodo_newStakerActive(0, pindexDelete->nTime) == 0 && i == block.vtx.size()-1 && komodo_isPoS((CBlock *)&block,pindexDelete->GetHeight(),0) != 0 )
{
#ifdef ENABLE_WALLET
if ( !GetBoolArg("-disablewallet", false) && KOMODO_NSPV_FULLNODE )
pwalletMain->EraseFromWallet(tx.GetHash());
// new staking tx cannot be accepted to mempool and expires in 1 block, so no need for this! :D
if ( !GetBoolArg("-disablewallet", false) && KOMODO_NSPV_FULLNODE )
pwalletMain->EraseFromWallet(tx.GetHash());
#endif
}
else
{
SyncWithWallets(tx, NULL);
}
} else SyncWithWallets(tx, NULL);
}
// Update cached incremental witnesses
GetMainSignals().ChainTip(pindexDelete, &block, newSproutTree, newSaplingTree, false);
@ -4232,8 +4208,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
pblock = &block;
}
KOMODO_CONNECTING = (int32_t)pindexNew->GetHeight();
fprintf(stderr,"%s connecting ht.%d maxsize.%d vs %d\n",ASSETCHAINS_SYMBOL,(int32_t)pindexNew->GetHeight(),MAX_BLOCK_SIZE(pindexNew->GetHeight()),(int32_t)::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
//fprintf(stderr,"%s connecting ht.%d maxsize.%d vs %d\n",ASSETCHAINS_SYMBOL,(int32_t)pindexNew->GetHeight(),MAX_BLOCK_SIZE(pindexNew->GetHeight()),(int32_t)::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
// Get the current commitment tree
SproutMerkleTree oldSproutTree;
SaplingMerkleTree oldSaplingTree;
@ -4417,7 +4392,6 @@ static void PruneBlockIndexCandidates() {
* pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
*/
static bool ActivateBestChainStep(bool fSkipdpow, CValidationState &state, CBlockIndex *pindexMostWork, CBlock *pblock) {
//fprintf(stderr,"%s: fSkipdpow=%d\n", __FUNCTION__, fSkipdpow);
AssertLockHeld(cs_main);
bool fInvalidFound = false;
const CBlockIndex *pindexOldTip = chainActive.Tip();
@ -4429,9 +4403,37 @@ static bool ActivateBestChainStep(bool fSkipdpow, CValidationState &state, CBloc
notarizedht = komodo_notarized_height(&prevMoMheight,&notarizedhash,&txid);
if ( !fSkipdpow && pindexFork != 0 && pindexOldTip->GetHeight() > notarizedht && pindexFork->GetHeight() < notarizedht )
{
fprintf(stderr,"pindexOldTip->GetHeight().%d > notarizedht %d && pindexFork->GetHeight().%d is < notarizedht %d, so ignore it\n",(int32_t)pindexOldTip->GetHeight(),notarizedht,(int32_t)pindexFork->GetHeight(),notarizedht);
LogPrintf("pindexOldTip->GetHeight().%d > notarizedht %d && pindexFork->GetHeight().%d is < notarizedht %d, so ignore it\n",(int32_t)pindexOldTip->GetHeight(),notarizedht,(int32_t)pindexFork->GetHeight(),notarizedht);
// *** DEBUG ***
if (1)
{
const CBlockIndex *pindexLastNotarized = mapBlockIndex[notarizedhash];
auto msg = "- " + strprintf(_("Current tip : %s, height %d, work %s"),
pindexOldTip->phashBlock->GetHex(), pindexOldTip->GetHeight(), pindexOldTip->chainPower.chainWork.GetHex()) + "\n" +
"- " + strprintf(_("New tip : %s, height %d, work %s"),
pindexMostWork->phashBlock->GetHex(), pindexMostWork->GetHeight(), pindexMostWork->chainPower.chainWork.GetHex()) + "\n" +
"- " + strprintf(_("Fork point : %s, height %d"),
pindexFork->phashBlock->GetHex(), pindexFork->GetHeight()) + "\n" +
"- " + strprintf(_("Last ntrzd : %s, height %d"),
pindexLastNotarized->phashBlock->GetHex(), pindexLastNotarized->GetHeight());
LogPrintf("[ Debug ]\n%s\n",msg);
int nHeight = pindexFork ? pindexFork->GetHeight() : -1;
int nTargetHeight = std::min(nHeight + 32, pindexMostWork->GetHeight());
LogPrintf("[ Debug ] nHeight = %d, nTargetHeight = %d\n", nHeight, nTargetHeight);
CBlockIndex *pindexIter = pindexMostWork->GetAncestor(nTargetHeight);
while (pindexIter && pindexIter->GetHeight() != nHeight) {
LogPrintf("[ Debug -> New blocks list ] %s, height %d\n", pindexIter->phashBlock->GetHex(), pindexIter->GetHeight());
pindexIter = pindexIter->pprev;
}
}
CValidationState tmpstate;
InvalidateBlock(tmpstate,pindexMostWork); // trying to invalidate longest chain, which tried to reorg notarized chain (in case of fork point below last notarized block)
return state.DoS(100, error("ActivateBestChainStep(): pindexOldTip->GetHeight().%d > notarizedht %d && pindexFork->GetHeight().%d is < notarizedht %d, so ignore it",(int32_t)pindexOldTip->GetHeight(),notarizedht,(int32_t)pindexFork->GetHeight(),notarizedht),
REJECT_INVALID, "past-notarized-height");
REJECT_INVALID, "past-notarized-height");
}
// - On ChainDB initialization, pindexOldTip will be null, so there are no removable blocks.
// - If pindexMostWork is in a chain that doesn't have the same genesis block as our chain,
@ -4553,7 +4555,6 @@ static bool ActivateBestChainStep(bool fSkipdpow, CValidationState &state, CBloc
* that is already loaded (to avoid loading it again from disk).
*/
bool ActivateBestChain(bool fSkipdpow, CValidationState &state, CBlock *pblock) {
//fprintf(stderr,"%s: fSkipdpow=%d\n", __FUNCTION__, fSkipdpow);
CBlockIndex *pindexNewTip = NULL;
CBlockIndex *pindexMostWork = NULL;
const CChainParams& chainParams = Params();
@ -4762,8 +4763,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
sproutValue += js.vpub_old;
sproutValue -= js.vpub_new;
}
}
}
pindexNew->nSproutValue = sproutValue;
pindexNew->nChainSproutValue = boost::none;
pindexNew->nSaplingValue = saplingValue;
@ -4773,7 +4773,6 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
pindexNew->nUndoPos = 0;
pindexNew->nStatus |= BLOCK_HAVE_DATA;
pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS);
setDirtyBlockIndex.insert(pindexNew);
if (pindexNew->pprev == NULL || pindexNew->pprev->nChainTx) {
@ -4786,10 +4785,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
CBlockIndex *pindex = queue.front();
queue.pop_front();
pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx;
if (pindex->pprev) {
pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx;
if (pindex->pprev->nChainSproutValue && pindex->nSproutValue) {
pindex->nChainSproutValue = *pindex->pprev->nChainSproutValue + *pindex->nSproutValue;
} else {
@ -5073,7 +5069,7 @@ bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,
}
int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtime);
int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height);
int32_t komodo_checkPOW(int64_t stakeTxValue,int32_t slowflag,CBlock *pblock,int32_t height);
bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const CBlock& block, CValidationState& state,
libzcash::ProofVerifier& verifier,
@ -5105,9 +5101,24 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C
fprintf(stderr," failed hash ht.%d\n",height);
return state.DoS(50, error("CheckBlock: proof of work failed"),REJECT_INVALID, "high-hash");
}
if ( komodo_checkPOW(1,(CBlock *)&block,height) < 0 ) // checks Equihash
if ( ASSETCHAINS_STAKED == 0 && komodo_checkPOW(0,1,(CBlock *)&block,height) < 0 ) // checks Equihash
return state.DoS(100, error("CheckBlock: failed slow_checkPOW"),REJECT_INVALID, "failed-slow_checkPOW");
}
if ( height > nDecemberHardforkHeight && ASSETCHAINS_SYMBOL[0] == 0 ) // December 2019 hardfork
{
int32_t notaryid;
int32_t special = komodo_chosennotary(&notaryid,height,pubkey33,tiptime);
if (notaryid > 0) {
CScript merkleroot = CScript();
CBlock blockcopy = block; // block shouldn't be changed below, so let's make it's copy
CBlock *pblockcopy = (CBlock *)&blockcopy;
if (!komodo_checkopret(pblockcopy, merkleroot)) {
fprintf(stderr, "failed or missing merkleroot expected.%s != merkleroot.%s\n", komodo_makeopret(pblockcopy, false).ToString().c_str(), merkleroot.ToString().c_str());
return state.DoS(100, error("CheckBlock: failed or missing merkleroot opret in easy-mined"),REJECT_INVALID, "failed-merkle-opret-in-easy-mined");
}
}
}
// Check the merkle root.
if (fCheckMerkleRoot) {
bool mutated;
@ -5177,10 +5188,9 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C
list<CTransaction> removed;
for (i=0; i<block.vtx.size(); i++)
{
CValidationState state;
CTransaction Tx;
CValidationState state; CTransaction Tx;
const CTransaction &tx = (CTransaction)block.vtx[i];
if (tx.IsCoinBase() || !tx.vjoinsplit.empty() || !tx.vShieldedSpend.empty() || ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED && komodo_isPoS((CBlock *)&block,height,true) != 0)))
if ( tx.IsCoinBase() || !tx.vjoinsplit.empty() || !tx.vShieldedSpend.empty() || (i == block.vtx.size()-1 && komodo_isPoS((CBlock *)&block,height,0) != 0) )
continue;
Tx = tx;
if ( myAddtomempool(Tx, &state, true) == false ) // happens with out of order tx in block on resync
@ -5215,8 +5225,11 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C
{
const CTransaction& tx = block.vtx[i];
if ( komodo_validate_interest(tx,height == 0 ? komodo_block2height((CBlock *)&block) : height,block.nTime,0) < 0 )
{
fprintf(stderr, "validate intrest failed for txnum.%i tx.%s\n", i, tx.ToString().c_str());
return error("CheckBlock: komodo_validate_interest failed");
if (!CheckTransaction(tiptime,tx, state, verifier))
}
if (!CheckTransaction(tiptime,tx, state, verifier, i, (int32_t)block.vtx.size()))
return error("CheckBlock: CheckTransaction failed");
}
@ -5737,7 +5750,7 @@ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNo
}
}
fRequested |= fForceProcessing;
if ( checked != 0 && komodo_checkPOW(0,pblock,height) < 0 ) //from_miner && ASSETCHAINS_STAKED == 0
if ( checked != 0 && komodo_checkPOW(0,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);
@ -6043,9 +6056,9 @@ bool static LoadBlockIndexDB()
vSortedByHeight.push_back(make_pair(pindex->GetHeight(), pindex));
//komodo_pindex_init(pindex,(int32_t)pindex->GetHeight());
}
fprintf(stderr,"load blockindexDB paired %u\n",(uint32_t)time(NULL));
//fprintf(stderr,"load blockindexDB paired %u\n",(uint32_t)time(NULL));
sort(vSortedByHeight.begin(), vSortedByHeight.end());
fprintf(stderr,"load blockindexDB sorted %u\n",(uint32_t)time(NULL));
//fprintf(stderr,"load blockindexDB sorted %u\n",(uint32_t)time(NULL));
BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight)
{
CBlockIndex* pindex = item.second;

Loading…
Cancel
Save