Updates from to main.cpp from kmd master 1f874d46c5ddd24c0fd32ae6800f16d8006b9059
This commit is contained in:
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)
|
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
|
||||||
{
|
{
|
||||||
int32_t i;
|
if (tx.nLockTime == 0)
|
||||||
if (tx.nLockTime == 0)
|
|
||||||
return true;
|
return true;
|
||||||
if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
|
if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
|
||||||
return true;
|
return true;
|
||||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
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())
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1160,6 +1174,7 @@ bool ContextualCheckTransaction(int32_t slowflag,const CBlock *block, CBlockInde
|
|||||||
if (tx.fOverwintered && tx.nVersionGroupId != SAPLING_VERSION_GROUP_ID)
|
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");
|
//return state.DoS(dosLevel, error("CheckTransaction(): invalid Sapling tx version"),REJECT_INVALID, "bad-sapling-tx-version-group-id");
|
||||||
|
if ( 0 )
|
||||||
{
|
{
|
||||||
string strHex = EncodeHexTx(tx);
|
string strHex = EncodeHexTx(tx);
|
||||||
fprintf(stderr,"invalid Sapling rawtx.%s\n",strHex.c_str());
|
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,
|
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;
|
static uint256 array[64]; static int32_t numbanned,indallvouts; int32_t j,k,n;
|
||||||
if ( *(int32_t *)&array[0] == 0 )
|
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);
|
AssertLockHeld(cs_main);
|
||||||
if (pfMissingInputs)
|
if (pfMissingInputs)
|
||||||
@@ -1743,14 +1758,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||||||
if ( nextBlockHeight <= 1 || chainActive.LastTip() == 0 )
|
if ( nextBlockHeight <= 1 || chainActive.LastTip() == 0 )
|
||||||
tiptime = (uint32_t)time(NULL);
|
tiptime = (uint32_t)time(NULL);
|
||||||
else tiptime = (uint32_t)chainActive.LastTip()->nTime;
|
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");
|
//fprintf(stderr,"addmempool 0\n");
|
||||||
// Node operator can choose to reject tx by number of transparent inputs
|
// 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");
|
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");
|
//fprintf(stderr,"addmempool 1\n");
|
||||||
|
|
||||||
auto verifier = libzcash::ProofVerifier::Strict();
|
auto verifier = libzcash::ProofVerifier::Strict();
|
||||||
if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,chainActive.LastTip()->GetHeight()+1,chainActive.LastTip()->GetMedianTimePast() + 777,0) < 0 )
|
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");
|
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");
|
return error("AcceptToMemoryPool: CheckTransaction failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoS level set to 10 to be more forgiving.
|
// 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.
|
// 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");
|
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");
|
fprintf(stderr,"AcceptToMemoryPool coinbase as individual tx\n");
|
||||||
return state.DoS(100, error("AcceptToMemoryPool: coinbase as individual tx"),REJECT_INVALID, "coinbase");
|
return state.DoS(100, error("AcceptToMemoryPool: coinbase as individual tx"),REJECT_INVALID, "coinbase");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
|
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
|
||||||
string reason;
|
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());
|
//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);
|
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
|
// 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
|
// block; we don't want our mempool filled up with transactions that can't
|
||||||
// be mined yet.
|
// 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");
|
//fprintf(stderr,"AcceptToMemoryPool reject non-final\n");
|
||||||
return state.DoS(0, false, REJECT_NONSTANDARD, "non-final");
|
return state.DoS(0, false, REJECT_NONSTANDARD, "non-final");
|
||||||
}
|
}
|
||||||
//fprintf(stderr,"addmempool 3\n");
|
//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
|
// Check for conflicts with in-memory transactions
|
||||||
if (!fSkipExpiry)
|
|
||||||
{
|
{
|
||||||
LOCK(pool.cs); // protect pool.mapNextTx
|
LOCK(pool.cs); // protect pool.mapNextTx
|
||||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
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");
|
//fprintf(stderr,"addmempool 4\n");
|
||||||
|
|
||||||
{
|
{
|
||||||
CCoinsView dummy;
|
CCoinsView dummy;
|
||||||
CCoinsViewCache view(&dummy);
|
CCoinsViewCache view(&dummy);
|
||||||
@@ -1861,7 +1875,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||||||
if (ExistsImportTombstone(tx, view))
|
if (ExistsImportTombstone(tx, view))
|
||||||
return state.Invalid(false, REJECT_DUPLICATE, "import tombstone exists");
|
return state.Invalid(false, REJECT_DUPLICATE, "import tombstone exists");
|
||||||
}
|
}
|
||||||
else if (!fSkipExpiry)
|
else
|
||||||
{
|
{
|
||||||
// do all inputs exist?
|
// do all inputs exist?
|
||||||
// Note that this does not check for the presence of actual outputs (see the next check for that),
|
// 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)
|
if (pfMissingInputs)
|
||||||
*pfMissingInputs = true;
|
*pfMissingInputs = true;
|
||||||
//fprintf(stderr,"missing inputs\n");
|
//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?
|
// are the actual inputs available?
|
||||||
if (!view.HaveInputs(tx))
|
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");
|
return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// are the joinsplit's requirements met?
|
// are the joinsplit's requirements met?
|
||||||
if (!view.HaveJoinSplitRequirements(tx))
|
if (!view.HaveJoinSplitRequirements(tx))
|
||||||
{
|
{
|
||||||
//fprintf(stderr,"accept failure.2\n");
|
//fprintf(stderr,"accept failure.2\n");
|
||||||
return state.Invalid(error("AcceptToMemoryPool: joinsplit requirements not met"),REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met");
|
return state.Invalid(error("AcceptToMemoryPool: joinsplit requirements not met"),REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bring the best block into scope
|
// Bring the best block into scope
|
||||||
view.GetBestBlock();
|
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 )
|
if ( 0 && interest != 0 )
|
||||||
fprintf(stderr,"add interest %.8f\n",(double)interest/COIN);
|
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
|
// we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool
|
||||||
view.SetBackend(dummy);
|
view.SetBackend(dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for non-standard pay-to-script-hash in inputs
|
// 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");
|
return error("AcceptToMemoryPool: reject nonstandard transaction input");
|
||||||
|
|
||||||
// Check that the transaction doesn't have an excessive number of
|
// Check that the transaction doesn't have an excessive number of
|
||||||
// sigops, making it impossible to mine. Since the coinbase transaction
|
// sigops, making it impossible to mine. Since the coinbase transaction
|
||||||
// itself can contain sigops MAX_STANDARD_TX_SIGOPS is less than
|
// itself can contain sigops MAX_STANDARD_TX_SIGOPS is less than
|
||||||
// MAX_BLOCK_SIGOPS; we still consider this an invalid rather than
|
// MAX_BLOCK_SIGOPS; we still consider this an invalid rather than
|
||||||
// merely non-standard transaction.
|
// merely non-standard transaction.
|
||||||
unsigned int nSigOps = GetLegacySigOpCount(tx);
|
unsigned int nSigOps = GetLegacySigOpCount(tx);
|
||||||
if (!fSkipExpiry)
|
nSigOps += GetP2SHSigOpCount(tx, view);
|
||||||
nSigOps += GetP2SHSigOpCount(tx, view);
|
|
||||||
if (nSigOps > MAX_STANDARD_TX_SIGOPS)
|
if (nSigOps > MAX_STANDARD_TX_SIGOPS)
|
||||||
{
|
{
|
||||||
fprintf(stderr,"accept failure.4\n");
|
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");
|
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();
|
CAmount nValueOut = tx.GetValueOut();
|
||||||
double dPriority = 0;
|
CAmount nFees = nValueIn-nValueOut;
|
||||||
CAmount nFees = 0;
|
double dPriority = view.GetPriority(tx, chainActive.Height());
|
||||||
|
|
||||||
if (!fSkipExpiry)
|
|
||||||
{
|
|
||||||
dPriority = view.GetPriority(tx, chainActive.Height());
|
|
||||||
nFees = nValueIn-nValueOut;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( nValueOut > 777777*COIN && KOMODO_VALUETOOBIG(nValueOut - 777777*COIN) != 0 ) // some room for blockreward and txfees
|
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");
|
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
|
// Keep track of transactions that spend a coinbase, which we re-scan
|
||||||
// during reorgs to ensure COINBASE_MATURITY is still met.
|
// during reorgs to ensure COINBASE_MATURITY is still met.
|
||||||
bool fSpendsCoinbase = false;
|
bool fSpendsCoinbase = false;
|
||||||
if (!fSkipExpiry && !tx.IsCoinImport() && !tx.IsPegsImport()) {
|
if (!tx.IsCoinImport() && !tx.IsPegsImport()) {
|
||||||
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
|
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
|
||||||
const CCoins *coins = view.AccessCoins(txin.prevout.hash);
|
const CCoins *coins = view.AccessCoins(txin.prevout.hash);
|
||||||
if (coins->IsCoinBase()) {
|
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
|
// 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
|
// yet know if it does, but if the entry gets added to the mempool, then
|
||||||
// it has passed ContextualCheckInputs and therefore this is correct.
|
// it has passed ContextualCheckInputs and therefore this is correct.
|
||||||
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
|
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
|
||||||
|
|
||||||
CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), mempool.HasNoInputsOf(tx), fSpendsCoinbase, consensusBranchId);
|
CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), mempool.HasNoInputsOf(tx), fSpendsCoinbase, consensusBranchId);
|
||||||
unsigned int nSize = entry.GetTxSize();
|
unsigned int nSize = entry.GetTxSize();
|
||||||
|
|
||||||
// Accept a tx if it contains joinsplits and has at least the default fee specified by z_sendmany.
|
// 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) {
|
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.
|
// 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");
|
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.
|
// 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))) {
|
if (GetBoolArg("-relaypriority", false) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(view.GetPriority(tx, chainActive.Height() + 1))) {
|
||||||
fprintf(stderr,"accept failure.6\n");
|
fprintf(stderr,"accept failure.6\n");
|
||||||
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient priority");
|
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient priority");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Continuously rate-limit free (really, very-low-fee) transactions
|
// Continuously rate-limit free (really, very-low-fee) transactions
|
||||||
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
|
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
|
||||||
// be annoying or make others' transactions take longer to confirm.
|
// 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 CCriticalSection csFreeLimiter;
|
||||||
static double dFreeCount;
|
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);
|
LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
|
||||||
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",
|
string errmsg = strprintf("absurdly high fees %s, %d > %d",
|
||||||
hash.ToString(),
|
hash.ToString(),
|
||||||
@@ -2012,12 +2020,12 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||||||
// Check against previous transactions
|
// Check against previous transactions
|
||||||
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
|
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
|
||||||
PrecomputedTransactionData txdata(tx);
|
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");
|
//fprintf(stderr,"accept failure.9\n");
|
||||||
return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString());
|
return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check again against just the consensus-critical mandatory script
|
// Check again against just the consensus-critical mandatory script
|
||||||
// verification flags, in case of bugs in the standard flags that cause
|
// verification flags, in case of bugs in the standard flags that cause
|
||||||
// transactions to pass as valid when they're actually invalid. For
|
// 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;
|
KOMODO_CONNECTING = (1<<30) + (int32_t)chainActive.LastTip()->GetHeight() + 1;
|
||||||
}
|
}
|
||||||
//fprintf(stderr,"addmempool 7\n");
|
//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 )
|
if ( flag != 0 )
|
||||||
KOMODO_CONNECTING = -1;
|
KOMODO_CONNECTING = -1;
|
||||||
@@ -2043,24 +2052,36 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||||||
if ( flag != 0 )
|
if ( flag != 0 )
|
||||||
KOMODO_CONNECTING = -1;
|
KOMODO_CONNECTING = -1;
|
||||||
|
|
||||||
// Store transaction in memory
|
|
||||||
pool.addUnchecked(hash, entry, !IsInitialBlockDownload());
|
|
||||||
|
|
||||||
if (!fSkipExpiry && !tx.IsCoinImport())
|
|
||||||
{
|
{
|
||||||
// Add memory address index
|
LOCK(pool.cs);
|
||||||
if (fAddressIndex) {
|
// Store transaction in memory
|
||||||
pool.addAddressIndex(entry, view);
|
pool.addUnchecked(hash, entry, !IsInitialBlockDownload());
|
||||||
}
|
if (!tx.IsCoinImport())
|
||||||
|
{
|
||||||
|
// Add memory address index
|
||||||
|
if (fAddressIndex) {
|
||||||
|
pool.addAddressIndex(entry, view);
|
||||||
|
}
|
||||||
|
|
||||||
// Add memory spent index
|
// Add memory spent index
|
||||||
if (fSpentIndex) {
|
if (fSpentIndex) {
|
||||||
pool.addSpentIndex(entry, view);
|
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;
|
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)
|
/*uint64_t myGettxout(uint256 hash,int32_t n)
|
||||||
{
|
{
|
||||||
CCoins coins;
|
CCoins coins;
|
||||||
@@ -2199,7 +2167,12 @@ bool myAddtomempool(CTransaction &tx, CValidationState *pstate, bool fSkipExpiry
|
|||||||
pstate = &state;
|
pstate = &state;
|
||||||
CTransaction Ltx; bool fMissingInputs,fOverrideFees = false;
|
CTransaction Ltx; bool fMissingInputs,fOverrideFees = false;
|
||||||
if ( mempool.lookup(tx.GetHash(),Ltx) == 0 )
|
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);
|
else return(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3413,9 +3386,10 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
|||||||
auto verifier = libzcash::ProofVerifier::Strict();
|
auto verifier = libzcash::ProofVerifier::Strict();
|
||||||
auto disabledVerifier = libzcash::ProofVerifier::Disabled();
|
auto disabledVerifier = libzcash::ProofVerifier::Disabled();
|
||||||
int32_t futureblock;
|
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
|
// 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);
|
//fprintf(stderr,"checkblock failure in connectblock futureblock.%d\n",futureblock);
|
||||||
return false;
|
return false;
|
||||||
@@ -3532,7 +3506,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
|||||||
CAmount nFees = 0;
|
CAmount nFees = 0;
|
||||||
int nInputs = 0;
|
int nInputs = 0;
|
||||||
uint64_t valueout;
|
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;
|
unsigned int nSigOps = 0;
|
||||||
CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
|
CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
|
||||||
std::vector<std::pair<uint256, CDiskTxPos> > vPos;
|
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;
|
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);
|
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 &&
|
if ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 ) //ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 &&
|
||||||
{
|
{
|
||||||
uint64_t checktoshis;
|
uint64_t checktoshis;
|
||||||
@@ -4016,6 +3990,9 @@ void static UpdateTip(CBlockIndex *pindexNew) {
|
|||||||
pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
|
pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
|
||||||
|
|
||||||
cvBlockChange.notify_all();
|
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:
|
// Check the version of the last 100 blocks to see if we need to upgrade:
|
||||||
static bool fWarned = false;
|
static bool fWarned = false;
|
||||||
@@ -4039,6 +4016,7 @@ void static UpdateTip(CBlockIndex *pindexNew) {
|
|||||||
fWarned = true;
|
fWarned = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -4127,17 +4105,15 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
|
|||||||
for (int i = 0; i < block.vtx.size(); i++)
|
for (int i = 0; i < block.vtx.size(); i++)
|
||||||
{
|
{
|
||||||
CTransaction &tx = block.vtx[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
|
#ifdef ENABLE_WALLET
|
||||||
if ( !GetBoolArg("-disablewallet", false) && KOMODO_NSPV_FULLNODE )
|
// new staking tx cannot be accepted to mempool and expires in 1 block, so no need for this! :D
|
||||||
pwalletMain->EraseFromWallet(tx.GetHash());
|
if ( !GetBoolArg("-disablewallet", false) && KOMODO_NSPV_FULLNODE )
|
||||||
|
pwalletMain->EraseFromWallet(tx.GetHash());
|
||||||
#endif
|
#endif
|
||||||
}
|
} else SyncWithWallets(tx, NULL);
|
||||||
else
|
|
||||||
{
|
|
||||||
SyncWithWallets(tx, NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Update cached incremental witnesses
|
// Update cached incremental witnesses
|
||||||
GetMainSignals().ChainTip(pindexDelete, &block, newSproutTree, newSaplingTree, false);
|
GetMainSignals().ChainTip(pindexDelete, &block, newSproutTree, newSaplingTree, false);
|
||||||
@@ -4232,8 +4208,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
|
|||||||
pblock = █
|
pblock = █
|
||||||
}
|
}
|
||||||
KOMODO_CONNECTING = (int32_t)pindexNew->GetHeight();
|
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
|
// Get the current commitment tree
|
||||||
SproutMerkleTree oldSproutTree;
|
SproutMerkleTree oldSproutTree;
|
||||||
SaplingMerkleTree oldSaplingTree;
|
SaplingMerkleTree oldSaplingTree;
|
||||||
@@ -4417,7 +4392,6 @@ static void PruneBlockIndexCandidates() {
|
|||||||
* pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
|
* pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
|
||||||
*/
|
*/
|
||||||
static bool ActivateBestChainStep(bool fSkipdpow, CValidationState &state, CBlockIndex *pindexMostWork, CBlock *pblock) {
|
static bool ActivateBestChainStep(bool fSkipdpow, CValidationState &state, CBlockIndex *pindexMostWork, CBlock *pblock) {
|
||||||
//fprintf(stderr,"%s: fSkipdpow=%d\n", __FUNCTION__, fSkipdpow);
|
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
bool fInvalidFound = false;
|
bool fInvalidFound = false;
|
||||||
const CBlockIndex *pindexOldTip = chainActive.Tip();
|
const CBlockIndex *pindexOldTip = chainActive.Tip();
|
||||||
@@ -4429,9 +4403,37 @@ static bool ActivateBestChainStep(bool fSkipdpow, CValidationState &state, CBloc
|
|||||||
notarizedht = komodo_notarized_height(&prevMoMheight,¬arizedhash,&txid);
|
notarizedht = komodo_notarized_height(&prevMoMheight,¬arizedhash,&txid);
|
||||||
if ( !fSkipdpow && pindexFork != 0 && pindexOldTip->GetHeight() > notarizedht && pindexFork->GetHeight() < notarizedht )
|
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),
|
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.
|
// - 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,
|
// - 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).
|
* that is already loaded (to avoid loading it again from disk).
|
||||||
*/
|
*/
|
||||||
bool ActivateBestChain(bool fSkipdpow, CValidationState &state, CBlock *pblock) {
|
bool ActivateBestChain(bool fSkipdpow, CValidationState &state, CBlock *pblock) {
|
||||||
//fprintf(stderr,"%s: fSkipdpow=%d\n", __FUNCTION__, fSkipdpow);
|
|
||||||
CBlockIndex *pindexNewTip = NULL;
|
CBlockIndex *pindexNewTip = NULL;
|
||||||
CBlockIndex *pindexMostWork = NULL;
|
CBlockIndex *pindexMostWork = NULL;
|
||||||
const CChainParams& chainParams = Params();
|
const CChainParams& chainParams = Params();
|
||||||
@@ -4762,8 +4763,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
|
|||||||
sproutValue += js.vpub_old;
|
sproutValue += js.vpub_old;
|
||||||
sproutValue -= js.vpub_new;
|
sproutValue -= js.vpub_new;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pindexNew->nSproutValue = sproutValue;
|
pindexNew->nSproutValue = sproutValue;
|
||||||
pindexNew->nChainSproutValue = boost::none;
|
pindexNew->nChainSproutValue = boost::none;
|
||||||
pindexNew->nSaplingValue = saplingValue;
|
pindexNew->nSaplingValue = saplingValue;
|
||||||
@@ -4773,7 +4773,6 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
|
|||||||
pindexNew->nUndoPos = 0;
|
pindexNew->nUndoPos = 0;
|
||||||
pindexNew->nStatus |= BLOCK_HAVE_DATA;
|
pindexNew->nStatus |= BLOCK_HAVE_DATA;
|
||||||
pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS);
|
pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS);
|
||||||
|
|
||||||
setDirtyBlockIndex.insert(pindexNew);
|
setDirtyBlockIndex.insert(pindexNew);
|
||||||
|
|
||||||
if (pindexNew->pprev == NULL || pindexNew->pprev->nChainTx) {
|
if (pindexNew->pprev == NULL || pindexNew->pprev->nChainTx) {
|
||||||
@@ -4786,10 +4785,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
|
|||||||
CBlockIndex *pindex = queue.front();
|
CBlockIndex *pindex = queue.front();
|
||||||
queue.pop_front();
|
queue.pop_front();
|
||||||
pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx;
|
pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx;
|
||||||
|
|
||||||
if (pindex->pprev) {
|
if (pindex->pprev) {
|
||||||
pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx;
|
|
||||||
|
|
||||||
if (pindex->pprev->nChainSproutValue && pindex->nSproutValue) {
|
if (pindex->pprev->nChainSproutValue && pindex->nSproutValue) {
|
||||||
pindex->nChainSproutValue = *pindex->pprev->nChainSproutValue + *pindex->nSproutValue;
|
pindex->nChainSproutValue = *pindex->pprev->nChainSproutValue + *pindex->nSproutValue;
|
||||||
} else {
|
} 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_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,
|
bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const CBlock& block, CValidationState& state,
|
||||||
libzcash::ProofVerifier& verifier,
|
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);
|
fprintf(stderr," failed hash ht.%d\n",height);
|
||||||
return state.DoS(50, error("CheckBlock: proof of work failed"),REJECT_INVALID, "high-hash");
|
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");
|
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(¬aryid,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.
|
// Check the merkle root.
|
||||||
if (fCheckMerkleRoot) {
|
if (fCheckMerkleRoot) {
|
||||||
bool mutated;
|
bool mutated;
|
||||||
@@ -5177,10 +5188,9 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C
|
|||||||
list<CTransaction> removed;
|
list<CTransaction> removed;
|
||||||
for (i=0; i<block.vtx.size(); i++)
|
for (i=0; i<block.vtx.size(); i++)
|
||||||
{
|
{
|
||||||
CValidationState state;
|
CValidationState state; CTransaction Tx;
|
||||||
CTransaction Tx;
|
|
||||||
const CTransaction &tx = (CTransaction)block.vtx[i];
|
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;
|
continue;
|
||||||
Tx = tx;
|
Tx = tx;
|
||||||
if ( myAddtomempool(Tx, &state, true) == false ) // happens with out of order tx in block on resync
|
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];
|
const CTransaction& tx = block.vtx[i];
|
||||||
if ( komodo_validate_interest(tx,height == 0 ? komodo_block2height((CBlock *)&block) : height,block.nTime,0) < 0 )
|
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");
|
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");
|
return error("CheckBlock: CheckTransaction failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5737,7 +5750,7 @@ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fRequested |= fForceProcessing;
|
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;
|
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);
|
||||||
@@ -6043,9 +6056,9 @@ bool static LoadBlockIndexDB()
|
|||||||
vSortedByHeight.push_back(make_pair(pindex->GetHeight(), pindex));
|
vSortedByHeight.push_back(make_pair(pindex->GetHeight(), pindex));
|
||||||
//komodo_pindex_init(pindex,(int32_t)pindex->GetHeight());
|
//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());
|
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)
|
BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight)
|
||||||
{
|
{
|
||||||
CBlockIndex* pindex = item.second;
|
CBlockIndex* pindex = item.second;
|
||||||
|
|||||||
Reference in New Issue
Block a user