}
// ask wallets to resend their transactions
-void ResendWalletTransactions()
+void ResendWalletTransactions(bool fForce)
{
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
- pwallet->ResendWalletTransactions();
+ pwallet->ResendWalletTransactions(fForce);
}
bool CTransaction::IsStandard() const
{
- if (nVersion > CTransaction::CURRENT_VERSION)
+ if (nVersion > CTransaction::CURRENT_VERSION) {
return false;
+ }
BOOST_FOREACH(const CTxIn& txin, vin)
{
// Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG
// pay-to-script-hash, which is 3 ~80-byte signatures, 3
// ~65-byte public keys, plus a few script ops.
- if (txin.scriptSig.size() > 500)
+ if (txin.scriptSig.size() > 500) {
return false;
- if (!txin.scriptSig.IsPushOnly())
+ }
+ if (!txin.scriptSig.IsPushOnly()) {
return false;
+ }
+ if (fEnforceCanonical && !txin.scriptSig.HasCanonicalPushes()) {
+ return false;
+ }
}
+
+ unsigned int nDataOut = 0;
+ txnouttype whichType;
BOOST_FOREACH(const CTxOut& txout, vout) {
- if (!::IsStandard(txout.scriptPubKey))
- return false;
- if (txout.nValue == 0)
+ if (!::IsStandard(txout.scriptPubKey, whichType)) {
return false;
+ }
+ if (whichType == TX_NULL_DATA)
+ nDataOut++;
+ else {
+ if (txout.nValue == 0) {
+ return false;
+ }
+ if (fEnforceCanonical && !txout.scriptPubKey.HasCanonicalPushes()) {
+ return false;
+ }
+ }
}
+
+ // only one OP_RETURN txout is permitted
+ if (nDataOut > 1) {
+ return false;
+ }
+
return true;
}
if (!fTestNet && !IsCoinBase() && !txout.IsEmpty() && nTime < OUTPUT_SWITCH_TIME && txout.nValue < MIN_TXOUT_AMOUNT)
return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue below minimum"));
+ if (txout.nValue < 0)
+ return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue is negative"));
if (txout.nValue > MAX_MONEY)
return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue too high"));
nValueOut += txout.nValue;
vtxid.push_back((*mi).first);
}
-
-
-
+// Return depth of transaction in blockchain:
+// -1 : not in blockchain, and not in memory pool (conflicted transaction)
+// 0 : in memory pool, waiting to be included in a block
+// >=1 : this many blocks deep in the main chain
int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
{
- if (hashBlock == 0 || nIndex == -1)
- return 0;
+ bool fInMemPool = mempool.exists(GetHash());
+
+ if (hashBlock == 0 || nIndex == -1) {
+ return fInMemPool ? 0 : -1;
+ }
// Find the block it claims to be in
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
- if (mi == mapBlockIndex.end())
- return 0;
+ if (mi == mapBlockIndex.end()) {
+ return fInMemPool ? 0 : -1;
+ }
CBlockIndex* pindex = (*mi).second;
- if (!pindex || !pindex->IsInMainChain())
- return 0;
+ if (!pindex || !pindex->IsInMainChain()) {
+ return fInMemPool ? 0 : -1;
+ }
// Make sure the merkle branch connects to this block
if (!fMerkleVerified)
{
- if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
- return 0;
+ if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot) {
+ return fInMemPool ? 0 : -1;
+ }
fMerkleVerified = true;
}
return false;
}
+// entropy bit for stake modifier if chosen by modifier
+unsigned int CBlock::GetStakeEntropyBit(unsigned int nTime) const
+{
+ // Protocol switch at novacoin block #9689
+ if (nTime >= ENTROPY_SWITCH_TIME || fTestNet)
+ {
+ // Take last bit of block hash as entropy bit
+ unsigned int nEntropyBit = ((GetHash().Get64()) & 1llu);
+ if (fDebug && GetBoolArg("-printstakemodifier"))
+ printf("GetStakeEntropyBit: nTime=%u hashBlock=%s nEntropyBit=%u\n", nTime, GetHash().ToString().c_str(), nEntropyBit);
+ return nEntropyBit;
+ }
+ // Before novacoin block #9689 - old protocol
+ uint160 hashSig = Hash160(vchBlockSig);
+ if (fDebug && GetBoolArg("-printstakemodifier"))
+ printf("GetStakeEntropyBit: hashSig=%s", hashSig.ToString().c_str());
+ hashSig >>= 159; // take the first bit of the hash
+ if (fDebug && GetBoolArg("-printstakemodifier"))
+ printf(" entropybit=%"PRI64d"\n", hashSig.Get64());
+ return hashSig.Get64();
+}
+
bool CheckDiskSpace(uint64 nAdditionalBytes)
{
uint64 nFreeBytesAvailable = filesystem::space(GetDataDir()).available;
// Verify blocks in the best chain
int nCheckLevel = GetArg("-checklevel", 1);
- int nCheckDepth = GetArg( "-checkblocks", 2500);
+ int nCheckDepth = GetArg( "-checkblocks", 288);
if (nCheckDepth == 0)
nCheckDepth = 1000000000; // suffices until the year 19000
if (nCheckDepth > nBestHeight)