mirror of
https://github.com/twisterarmy/twister-core.git
synced 2025-01-10 14:58:05 +00:00
add and verify proof of work in tx. remove some old stuff.
This commit is contained in:
parent
0e863844ed
commit
27ee7c328b
@ -34,6 +34,7 @@ public:
|
|||||||
nRPCPort = 28332;
|
nRPCPort = 28332;
|
||||||
//bnProofOfWorkLimit = CBigNum(~uint256(0) >> 32);
|
//bnProofOfWorkLimit = CBigNum(~uint256(0) >> 32);
|
||||||
bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1);
|
bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1);
|
||||||
|
nTxBits = 0x207fffff;
|
||||||
nSubsidyHalvingInterval = 210000;
|
nSubsidyHalvingInterval = 210000;
|
||||||
|
|
||||||
// Build the genesis block. Note that the output of the genesis coinbase cannot
|
// Build the genesis block. Note that the output of the genesis coinbase cannot
|
||||||
@ -47,6 +48,7 @@ public:
|
|||||||
const char* pszTimestamp = "The Times 14/Jul/2013 Globo caught bribing Receita Federal employee to rob R$615M tax evasion documents.";
|
const char* pszTimestamp = "The Times 14/Jul/2013 Globo caught bribing Receita Federal employee to rob R$615M tax evasion documents.";
|
||||||
CTransaction txNew;
|
CTransaction txNew;
|
||||||
txNew.message = CScript() << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
|
txNew.message = CScript() << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
|
||||||
|
txNew.nNonce = 1;
|
||||||
genesis.vtx.push_back(txNew);
|
genesis.vtx.push_back(txNew);
|
||||||
genesis.hashPrevBlock = 0;
|
genesis.hashPrevBlock = 0;
|
||||||
genesis.hashMerkleRoot = genesis.BuildMerkleTree();
|
genesis.hashMerkleRoot = genesis.BuildMerkleTree();
|
||||||
@ -54,7 +56,7 @@ public:
|
|||||||
genesis.nTime = 1231006505;
|
genesis.nTime = 1231006505;
|
||||||
//genesis.nBits = 0x1d00ffff;
|
//genesis.nBits = 0x1d00ffff;
|
||||||
genesis.nBits = 0x207fffff;
|
genesis.nBits = 0x207fffff;
|
||||||
genesis.nNonce = 2;
|
genesis.nNonce = 0;
|
||||||
|
|
||||||
hashGenesisBlock = genesis.GetHash();
|
hashGenesisBlock = genesis.GetHash();
|
||||||
printf("hashGenesisBlock %s\n", hashGenesisBlock.ToString().c_str());
|
printf("hashGenesisBlock %s\n", hashGenesisBlock.ToString().c_str());
|
||||||
@ -148,6 +150,7 @@ public:
|
|||||||
pchMessageStart[3] = 0xda;
|
pchMessageStart[3] = 0xda;
|
||||||
nSubsidyHalvingInterval = 150;
|
nSubsidyHalvingInterval = 150;
|
||||||
bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1);
|
bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1);
|
||||||
|
nTxBits = 0x207fffff;
|
||||||
genesis.nTime = 1296688602;
|
genesis.nTime = 1296688602;
|
||||||
genesis.nBits = 0x207fffff;
|
genesis.nBits = 0x207fffff;
|
||||||
genesis.nNonce = 2;
|
genesis.nNonce = 2;
|
||||||
|
@ -54,6 +54,7 @@ public:
|
|||||||
const vector<unsigned char>& AlertKey() const { return vAlertPubKey; }
|
const vector<unsigned char>& AlertKey() const { return vAlertPubKey; }
|
||||||
int GetDefaultPort() const { return nDefaultPort; }
|
int GetDefaultPort() const { return nDefaultPort; }
|
||||||
const CBigNum& ProofOfWorkLimit() const { return bnProofOfWorkLimit; }
|
const CBigNum& ProofOfWorkLimit() const { return bnProofOfWorkLimit; }
|
||||||
|
unsigned int txBits() const { return nTxBits; }
|
||||||
int SubsidyHalvingInterval() const { return nSubsidyHalvingInterval; }
|
int SubsidyHalvingInterval() const { return nSubsidyHalvingInterval; }
|
||||||
virtual const CBlock& GenesisBlock() const = 0;
|
virtual const CBlock& GenesisBlock() const = 0;
|
||||||
virtual bool RequireRPCPassword() const { return true; }
|
virtual bool RequireRPCPassword() const { return true; }
|
||||||
@ -73,6 +74,7 @@ protected:
|
|||||||
int nDefaultPort;
|
int nDefaultPort;
|
||||||
int nRPCPort;
|
int nRPCPort;
|
||||||
CBigNum bnProofOfWorkLimit;
|
CBigNum bnProofOfWorkLimit;
|
||||||
|
unsigned int nTxBits;
|
||||||
int nSubsidyHalvingInterval;
|
int nSubsidyHalvingInterval;
|
||||||
string strDataDir;
|
string strDataDir;
|
||||||
vector<CDNSSeedData> vSeeds;
|
vector<CDNSSeedData> vSeeds;
|
||||||
|
@ -81,17 +81,16 @@ uint256 CTransaction::GetHash() const
|
|||||||
std::string CTransaction::ToString() const
|
std::string CTransaction::ToString() const
|
||||||
{
|
{
|
||||||
std::string str;
|
std::string str;
|
||||||
str += strprintf("CTransaction(hash=%s, ver=%d, message.size=%"PRIszu", userID.size=%"PRIszu", pubKey.size=%"PRIszu")\n",
|
str += strprintf("CTransaction(hash=%s, ver=%d, message.size=%"PRIszu", userName.size=%"PRIszu", pubKey.size=%"PRIszu")\n",
|
||||||
GetHash().ToString().substr(0,10).c_str(),
|
GetHash().ToString().substr(0,10).c_str(),
|
||||||
nVersion,
|
nVersion,
|
||||||
message.size(),
|
message.size(),
|
||||||
userID.size(),
|
userName.size(),
|
||||||
pubKey.size());
|
pubKey.size());
|
||||||
if( message.size() ) {
|
if( message.size() ) {
|
||||||
str += " message: " + message.ToString() + "\n";
|
str += " message: " + message.ToString() + "\n";
|
||||||
} else {
|
} else {
|
||||||
str += " userName: " + userName.ToString() + "\n";
|
str += " userName: " + userName.ToString() + "\n";
|
||||||
str += " userID: " + userID.ToString() + "\n";
|
|
||||||
str += " pubKey: " + pubKey.ToString() + "\n";
|
str += " pubKey: " + pubKey.ToString() + "\n";
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
|
15
src/core.h
15
src/core.h
@ -182,8 +182,8 @@ public:
|
|||||||
int nVersion;
|
int nVersion;
|
||||||
CScript message;
|
CScript message;
|
||||||
CScript userName;
|
CScript userName;
|
||||||
CScript userID;
|
|
||||||
CScript pubKey;
|
CScript pubKey;
|
||||||
|
unsigned int nNonce;
|
||||||
|
|
||||||
CTransaction()
|
CTransaction()
|
||||||
{
|
{
|
||||||
@ -196,8 +196,8 @@ public:
|
|||||||
nVersion = this->nVersion;
|
nVersion = this->nVersion;
|
||||||
READWRITE(message);
|
READWRITE(message);
|
||||||
READWRITE(userName);
|
READWRITE(userName);
|
||||||
READWRITE(userID);
|
|
||||||
READWRITE(pubKey);
|
READWRITE(pubKey);
|
||||||
|
READWRITE(nNonce);
|
||||||
)
|
)
|
||||||
|
|
||||||
void SetNull()
|
void SetNull()
|
||||||
@ -205,20 +205,20 @@ public:
|
|||||||
nVersion = CTransaction::CURRENT_VERSION;
|
nVersion = CTransaction::CURRENT_VERSION;
|
||||||
message.clear();
|
message.clear();
|
||||||
userName.clear();
|
userName.clear();
|
||||||
userID.clear();
|
|
||||||
pubKey.clear();
|
pubKey.clear();
|
||||||
|
nNonce = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsNull() const
|
bool IsNull() const
|
||||||
{
|
{
|
||||||
return (message.empty() && userName.empty() && userID.empty() && pubKey.empty());
|
return (message.empty() && userName.empty() && pubKey.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 GetHash() const;
|
uint256 GetHash() const;
|
||||||
|
|
||||||
bool IsSpamMessage() const
|
bool IsSpamMessage() const
|
||||||
{
|
{
|
||||||
return (!message.empty() && userID.empty() && pubKey.empty());
|
return (!message.empty() && userName.empty() && pubKey.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator==(const CTransaction& a, const CTransaction& b)
|
friend bool operator==(const CTransaction& a, const CTransaction& b)
|
||||||
@ -226,7 +226,6 @@ public:
|
|||||||
return (a.nVersion == b.nVersion &&
|
return (a.nVersion == b.nVersion &&
|
||||||
a.message == b.message &&
|
a.message == b.message &&
|
||||||
a.userName == b.userName &&
|
a.userName == b.userName &&
|
||||||
a.userID == b.userID &&
|
|
||||||
a.pubKey == b.pubKey);
|
a.pubKey == b.pubKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,6 +547,7 @@ public:
|
|||||||
// header
|
// header
|
||||||
static const int CURRENT_VERSION=2;
|
static const int CURRENT_VERSION=2;
|
||||||
int nVersion;
|
int nVersion;
|
||||||
|
int nHeight;
|
||||||
uint256 hashPrevBlock;
|
uint256 hashPrevBlock;
|
||||||
uint256 hashMerkleRoot;
|
uint256 hashMerkleRoot;
|
||||||
unsigned int nTime;
|
unsigned int nTime;
|
||||||
@ -563,6 +563,7 @@ public:
|
|||||||
(
|
(
|
||||||
READWRITE(this->nVersion);
|
READWRITE(this->nVersion);
|
||||||
nVersion = this->nVersion;
|
nVersion = this->nVersion;
|
||||||
|
READWRITE(nHeight);
|
||||||
READWRITE(hashPrevBlock);
|
READWRITE(hashPrevBlock);
|
||||||
READWRITE(hashMerkleRoot);
|
READWRITE(hashMerkleRoot);
|
||||||
READWRITE(nTime);
|
READWRITE(nTime);
|
||||||
@ -573,6 +574,7 @@ public:
|
|||||||
void SetNull()
|
void SetNull()
|
||||||
{
|
{
|
||||||
nVersion = CBlockHeader::CURRENT_VERSION;
|
nVersion = CBlockHeader::CURRENT_VERSION;
|
||||||
|
nHeight = 0;
|
||||||
hashPrevBlock = 0;
|
hashPrevBlock = 0;
|
||||||
hashMerkleRoot = 0;
|
hashMerkleRoot = 0;
|
||||||
nTime = 0;
|
nTime = 0;
|
||||||
@ -631,6 +633,7 @@ public:
|
|||||||
{
|
{
|
||||||
CBlockHeader block;
|
CBlockHeader block;
|
||||||
block.nVersion = nVersion;
|
block.nVersion = nVersion;
|
||||||
|
block.nHeight = nHeight;
|
||||||
block.hashPrevBlock = hashPrevBlock;
|
block.hashPrevBlock = hashPrevBlock;
|
||||||
block.hashMerkleRoot = hashMerkleRoot;
|
block.hashMerkleRoot = hashMerkleRoot;
|
||||||
block.nTime = nTime;
|
block.nTime = nTime;
|
||||||
|
184
src/main.cpp
184
src/main.cpp
@ -476,11 +476,6 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsFinalTx(tx)) {
|
|
||||||
reason = "non-final";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extremely large transactions with lots of inputs can cost the network
|
// Extremely large transactions with lots of inputs can cost the network
|
||||||
// almost as much to process as they cost the sender in fees, because
|
// almost as much to process as they cost the sender in fees, because
|
||||||
// computing signature hashes is O(ninputs*txsize). Limiting transactions
|
// computing signature hashes is O(ninputs*txsize). Limiting transactions
|
||||||
@ -491,52 +486,6 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [MF]
|
|
||||||
BOOST_FOREACH(const CTxIn& txin, tx.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) {
|
|
||||||
reason = "scriptsig-size";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!txin.scriptSig.IsPushOnly()) {
|
|
||||||
reason = "scriptsig-not-pushonly";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BOOST_FOREACH(const CTxOut& txout, tx.vout) {
|
|
||||||
if (!::IsStandard(txout.scriptPubKey)) {
|
|
||||||
reason = "scriptpubkey";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (txout.IsDust(CTransaction::nMinRelayTxFee)) {
|
|
||||||
reason = "dust";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64 nBlockTime)
|
|
||||||
{
|
|
||||||
/* [MF]
|
|
||||||
// Time based nLockTime implemented in 0.1.6
|
|
||||||
if (tx.nLockTime == 0)
|
|
||||||
return true;
|
|
||||||
if (nBlockHeight == 0)
|
|
||||||
nBlockHeight = nBestHeight;
|
|
||||||
if (nBlockTime == 0)
|
|
||||||
nBlockTime = GetAdjustedTime();
|
|
||||||
if ((int64)tx.nLockTime < ((int64)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64)nBlockHeight : nBlockTime))
|
|
||||||
return true;
|
|
||||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
|
||||||
if (!txin.IsFinal())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
*/
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -709,88 +658,32 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
|
|||||||
|
|
||||||
bool CheckTransaction(const CTransaction& tx, CValidationState &state)
|
bool CheckTransaction(const CTransaction& tx, CValidationState &state)
|
||||||
{
|
{
|
||||||
/* [MF]
|
|
||||||
// Basic checks that don't depend on any context
|
// Basic checks that don't depend on any context
|
||||||
if (tx.vin.empty())
|
if (tx.IsSpamMessage()) {
|
||||||
return state.DoS(10, error("CheckTransaction() : vin empty"));
|
if (!tx.userName.empty())
|
||||||
if (tx.vout.empty())
|
return state.DoS(10, error("CheckTransaction() : username not empty in spam message"));
|
||||||
return state.DoS(10, error("CheckTransaction() : vout empty"));
|
if (!tx.pubKey.empty())
|
||||||
|
return state.DoS(10, error("CheckTransaction() : pubKey empty not empty in spam message"));
|
||||||
|
if (tx.message.size() > MAX_SPAM_MSG_SIZE)
|
||||||
|
return state.DoS(100, error("CheckTransaction() : spam message too big"));
|
||||||
|
} else {
|
||||||
|
if (tx.userName.empty())
|
||||||
|
return state.DoS(10, error("CheckTransaction() : username empty"));
|
||||||
|
if (tx.userName.size() > MAX_USERNAME_SIZE)
|
||||||
|
return state.DoS(100, error("CheckTransaction() : username too big"));
|
||||||
|
if (tx.pubKey.empty())
|
||||||
|
return state.DoS(10, error("CheckTransaction() : pubKey empty"));
|
||||||
|
}
|
||||||
// Size limits
|
// Size limits
|
||||||
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
|
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
|
||||||
return state.DoS(100, error("CTransaction::CheckTransaction() : size limits failed"));
|
return state.DoS(100, error("CTransaction::CheckTransaction() : size limits failed"));
|
||||||
|
// Check proof of work matches claimed amount
|
||||||
|
if (!CheckProofOfWork(tx.GetHash(), Params().txBits()) )
|
||||||
|
return state.DoS(50, error("CheckTransaction() : proof of work failed"));
|
||||||
|
|
||||||
// Check for negative or overflow output values
|
|
||||||
int64 nValueOut = 0;
|
|
||||||
BOOST_FOREACH(const CTxOut& txout, tx.vout)
|
|
||||||
{
|
|
||||||
if (txout.nValue < 0)
|
|
||||||
return state.DoS(100, error("CheckTransaction() : txout.nValue negative"));
|
|
||||||
if (txout.nValue > MAX_MONEY)
|
|
||||||
return state.DoS(100, error("CheckTransaction() : txout.nValue too high"));
|
|
||||||
nValueOut += txout.nValue;
|
|
||||||
if (!MoneyRange(nValueOut))
|
|
||||||
return state.DoS(100, error("CTransaction::CheckTransaction() : txout total out of range"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for duplicate inputs
|
|
||||||
set<COutPoint> vInOutPoints;
|
|
||||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
|
||||||
{
|
|
||||||
if (vInOutPoints.count(txin.prevout))
|
|
||||||
return state.DoS(100, error("CTransaction::CheckTransaction() : duplicate inputs"));
|
|
||||||
vInOutPoints.insert(txin.prevout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tx.IsCoinBase())
|
|
||||||
{
|
|
||||||
if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
|
|
||||||
return state.DoS(100, error("CheckTransaction() : coinbase script size"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
|
||||||
if (txin.prevout.IsNull())
|
|
||||||
return state.DoS(10, error("CheckTransaction() : prevout is null"));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 GetMinFee(const CTransaction& tx, bool fAllowFree, enum GetMinFee_mode mode)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
// Base fee is either nMinTxFee or nMinRelayTxFee
|
|
||||||
int64 nBaseFee = (mode == GMF_RELAY) ? tx.nMinRelayTxFee : tx.nMinTxFee;
|
|
||||||
|
|
||||||
unsigned int nBytes = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
|
|
||||||
int64 nMinFee = (1 + (int64)nBytes / 1000) * nBaseFee;
|
|
||||||
|
|
||||||
if (fAllowFree)
|
|
||||||
{
|
|
||||||
// There is a free transaction area in blocks created by most miners,
|
|
||||||
// * If we are relaying we allow transactions up to DEFAULT_BLOCK_PRIORITY_SIZE - 1000
|
|
||||||
// to be considered to fall into this category
|
|
||||||
// * If we are creating a transaction we allow transactions up to DEFAULT_BLOCK_PRIORITY_SIZE - 17000
|
|
||||||
// (= 10000) to be considered safe and assume they can likely make it into this section
|
|
||||||
if (nBytes < (mode == GMF_SEND ? (DEFAULT_BLOCK_PRIORITY_SIZE - 17000) : (DEFAULT_BLOCK_PRIORITY_SIZE - 1000)))
|
|
||||||
nMinFee = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// To limit dust spam, require base fee if any output is less than 0.01
|
|
||||||
if (nMinFee < nBaseFee)
|
|
||||||
{
|
|
||||||
BOOST_FOREACH(const CTxOut& txout, tx.vout)
|
|
||||||
if (txout.nValue < CENT)
|
|
||||||
nMinFee = nBaseFee;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!MoneyRange(nMinFee))
|
|
||||||
nMinFee = MAX_MONEY;
|
|
||||||
return nMinFee;
|
|
||||||
*/
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins)
|
void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
@ -817,12 +710,6 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFr
|
|||||||
if (tx.IsSpamMessage())
|
if (tx.IsSpamMessage())
|
||||||
return state.DoS(100, error("CTxMemPool::accept() : coinbase as individual tx"));
|
return state.DoS(100, error("CTxMemPool::accept() : coinbase as individual tx"));
|
||||||
|
|
||||||
/*
|
|
||||||
// To help v0.1.5 clients who would see it as a negative number
|
|
||||||
if ((int64)tx.nLockTime > std::numeric_limits<int>::max())
|
|
||||||
return error("CTxMemPool::accept() : not accepting nLockTime beyond 2038 yet");
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Rather not work on nonstandard transactions (unless -testnet)
|
// Rather not work on nonstandard transactions (unless -testnet)
|
||||||
string reason;
|
string reason;
|
||||||
if (!TestNet() && !IsStandardTx(tx, reason))
|
if (!TestNet() && !IsStandardTx(tx, reason))
|
||||||
@ -839,7 +726,7 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFr
|
|||||||
|
|
||||||
// Check for conflicts with in-memory transactions
|
// Check for conflicts with in-memory transactions
|
||||||
CTransaction* ptxOld = NULL;
|
CTransaction* ptxOld = NULL;
|
||||||
/* [MF]
|
/*
|
||||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||||
{
|
{
|
||||||
COutPoint outpoint = tx.vin[i].prevout;
|
COutPoint outpoint = tx.vin[i].prevout;
|
||||||
@ -910,16 +797,8 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFr
|
|||||||
// you should add code here to check that the transaction does a
|
// you should add code here to check that the transaction does a
|
||||||
// reasonable number of ECDSA signature verifications.
|
// reasonable number of ECDSA signature verifications.
|
||||||
|
|
||||||
int64 nFees = view.GetValueIn(tx)-GetValueOut(tx);
|
|
||||||
unsigned int nSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
|
unsigned int nSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
|
||||||
// Don't accept it if it can't get into a block
|
|
||||||
int64 txMinFee = GetMinFee(tx, true, GMF_RELAY);
|
|
||||||
if (fLimitFree && nFees < txMinFee)
|
|
||||||
return error("CTxMemPool::accept() : not enough fees %s, %"PRI64d" < %"PRI64d,
|
|
||||||
hash.ToString().c_str(),
|
|
||||||
nFees, txMinFee);
|
|
||||||
|
|
||||||
// Continuously rate-limit free transactions
|
// Continuously rate-limit free 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.
|
||||||
@ -2341,11 +2220,6 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp)
|
|||||||
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
|
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
|
||||||
return state.Invalid(error("AcceptBlock() : block's timestamp is too early"));
|
return state.Invalid(error("AcceptBlock() : block's timestamp is too early"));
|
||||||
|
|
||||||
// Check that all transactions are finalized
|
|
||||||
BOOST_FOREACH(const CTransaction& tx, block.vtx)
|
|
||||||
if (!IsFinalTx(tx, nHeight, block.GetBlockTime()))
|
|
||||||
return state.DoS(10, error("AcceptBlock() : contains a non-final transaction"));
|
|
||||||
|
|
||||||
// Check that the block chain matches the known block chain up to a checkpoint
|
// Check that the block chain matches the known block chain up to a checkpoint
|
||||||
if (!Checkpoints::CheckBlock(nHeight, hash))
|
if (!Checkpoints::CheckBlock(nHeight, hash))
|
||||||
return state.DoS(100, error("AcceptBlock() : rejected by checkpoint lock-in at %d", nHeight));
|
return state.DoS(100, error("AcceptBlock() : rejected by checkpoint lock-in at %d", nHeight));
|
||||||
@ -2353,25 +2227,13 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp)
|
|||||||
// Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded:
|
// Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded:
|
||||||
if (block.nVersion < 2)
|
if (block.nVersion < 2)
|
||||||
{
|
{
|
||||||
if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 950, 1000)) ||
|
return state.Invalid(error("AcceptBlock() : rejected nVersion=1 block"));
|
||||||
(TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 75, 100)))
|
|
||||||
{
|
|
||||||
return state.Invalid(error("AcceptBlock() : rejected nVersion=1 block"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
|
// Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
|
||||||
if (block.nVersion >= 2)
|
if (block.nVersion >= 2)
|
||||||
{
|
{
|
||||||
// if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet):
|
if( nHeight != block.nHeight )
|
||||||
if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 750, 1000)) ||
|
return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"));
|
||||||
(TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 51, 100)))
|
|
||||||
{
|
|
||||||
CScript expect = CScript() << nHeight;
|
|
||||||
/* [MF]
|
|
||||||
if (!std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin()))
|
|
||||||
return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"));
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4362,7 +4224,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
|
|||||||
for (map<uint256, CTransaction>::iterator mi = mempool.mapTx.begin(); mi != mempool.mapTx.end(); ++mi)
|
for (map<uint256, CTransaction>::iterator mi = mempool.mapTx.begin(); mi != mempool.mapTx.end(); ++mi)
|
||||||
{
|
{
|
||||||
CTransaction& tx = (*mi).second;
|
CTransaction& tx = (*mi).second;
|
||||||
if (tx.IsSpamMessage() || !IsFinalTx(tx))
|
if (tx.IsSpamMessage())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
COrphan* porphan = NULL;
|
COrphan* porphan = NULL;
|
||||||
|
14
src/main.h
14
src/main.h
@ -59,6 +59,10 @@ static const int fHaveUPnP = true;
|
|||||||
#else
|
#else
|
||||||
static const int fHaveUPnP = false;
|
static const int fHaveUPnP = false;
|
||||||
#endif
|
#endif
|
||||||
|
/** The maximum size for spam messages */
|
||||||
|
static const unsigned int MAX_SPAM_MSG_SIZE = 140;
|
||||||
|
/** The maximum size for username */
|
||||||
|
static const unsigned int MAX_USERNAME_SIZE = 16;
|
||||||
|
|
||||||
|
|
||||||
extern CScript COINBASE_FLAGS;
|
extern CScript COINBASE_FLAGS;
|
||||||
@ -262,14 +266,6 @@ struct CDiskTxPos : public CDiskBlockPos
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
enum GetMinFee_mode
|
|
||||||
{
|
|
||||||
GMF_RELAY,
|
|
||||||
GMF_SEND,
|
|
||||||
};
|
|
||||||
|
|
||||||
int64 GetMinFee(const CTransaction& tx, bool fAllowFree, enum GetMinFee_mode mode);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check transaction inputs, and make sure any
|
// Check transaction inputs, and make sure any
|
||||||
// pay-to-script-hash transactions are evaluating IsStandard scripts
|
// pay-to-script-hash transactions are evaluating IsStandard scripts
|
||||||
@ -328,8 +324,6 @@ bool CheckTransaction(const CTransaction& tx, CValidationState& state);
|
|||||||
*/
|
*/
|
||||||
bool IsStandardTx(const CTransaction& tx, std::string& reason);
|
bool IsStandardTx(const CTransaction& tx, std::string& reason);
|
||||||
|
|
||||||
bool IsFinalTx(const CTransaction &tx, int nBlockHeight = 0, int64 nBlockTime = 0);
|
|
||||||
|
|
||||||
/** Amount of bitcoins spent by the transaction.
|
/** Amount of bitcoins spent by the transaction.
|
||||||
@return sum of all outputs (note: does not include fees)
|
@return sum of all outputs (note: does not include fees)
|
||||||
*/
|
*/
|
||||||
|
@ -408,7 +408,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
|
|||||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||||
{
|
{
|
||||||
const CWalletTx& wtx = (*it).second;
|
const CWalletTx& wtx = (*it).second;
|
||||||
if (wtx.IsSpamMessage() || !IsFinalTx(wtx))
|
if (wtx.IsSpamMessage())
|
||||||
continue;
|
continue;
|
||||||
/*
|
/*
|
||||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||||
@ -455,7 +455,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
|
|||||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||||
{
|
{
|
||||||
const CWalletTx& wtx = (*it).second;
|
const CWalletTx& wtx = (*it).second;
|
||||||
if (wtx.IsSpamMessage() || !IsFinalTx(wtx))
|
if (wtx.IsSpamMessage())
|
||||||
continue;
|
continue;
|
||||||
/*
|
/*
|
||||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||||
@ -480,9 +480,6 @@ int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinD
|
|||||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||||
{
|
{
|
||||||
const CWalletTx& wtx = (*it).second;
|
const CWalletTx& wtx = (*it).second;
|
||||||
if (!IsFinalTx(wtx))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int64 nReceived, nSent, nFee;
|
int64 nReceived, nSent, nFee;
|
||||||
wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee);
|
wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee);
|
||||||
|
|
||||||
@ -841,7 +838,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
|
|||||||
{
|
{
|
||||||
const CWalletTx& wtx = (*it).second;
|
const CWalletTx& wtx = (*it).second;
|
||||||
|
|
||||||
if (wtx.IsSpamMessage() || !IsFinalTx(wtx))
|
if (wtx.IsSpamMessage())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int nDepth = wtx.GetDepthInMainChain();
|
int nDepth = wtx.GetDepthInMainChain();
|
||||||
|
@ -971,29 +971,12 @@ int64 CWallet::GetBalance() const
|
|||||||
int64 CWallet::GetUnconfirmedBalance() const
|
int64 CWallet::GetUnconfirmedBalance() const
|
||||||
{
|
{
|
||||||
int64 nTotal = 0;
|
int64 nTotal = 0;
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
|
||||||
{
|
|
||||||
const CWalletTx* pcoin = &(*it).second;
|
|
||||||
if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed())
|
|
||||||
nTotal += pcoin->GetAvailableCredit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nTotal;
|
return nTotal;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 CWallet::GetImmatureBalance() const
|
int64 CWallet::GetImmatureBalance() const
|
||||||
{
|
{
|
||||||
int64 nTotal = 0;
|
int64 nTotal = 0;
|
||||||
{
|
|
||||||
LOCK(cs_wallet);
|
|
||||||
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
|
||||||
{
|
|
||||||
const CWalletTx* pcoin = &(*it).second;
|
|
||||||
nTotal += pcoin->GetImmatureCredit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nTotal;
|
return nTotal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1008,9 +991,6 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed) const
|
|||||||
{
|
{
|
||||||
const CWalletTx* pcoin = &(*it).second;
|
const CWalletTx* pcoin = &(*it).second;
|
||||||
|
|
||||||
if (!IsFinalTx(*pcoin))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (fOnlyConfirmed && !pcoin->IsConfirmed())
|
if (fOnlyConfirmed && !pcoin->IsConfirmed())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1705,7 +1685,7 @@ std::map<CTxDestination, int64> CWallet::GetAddressBalances()
|
|||||||
{
|
{
|
||||||
CWalletTx *pcoin = &walletEntry.second;
|
CWalletTx *pcoin = &walletEntry.second;
|
||||||
|
|
||||||
if (!IsFinalTx(*pcoin) || !pcoin->IsConfirmed())
|
if (!pcoin->IsConfirmed())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (pcoin->IsSpamMessage() && pcoin->GetBlocksToMaturity() > 0)
|
if (pcoin->IsSpamMessage() && pcoin->GetBlocksToMaturity() > 0)
|
||||||
|
@ -660,9 +660,6 @@ public:
|
|||||||
|
|
||||||
bool IsConfirmed() const
|
bool IsConfirmed() const
|
||||||
{
|
{
|
||||||
// Quick answer in most cases
|
|
||||||
if (!IsFinalTx(*this))
|
|
||||||
return false;
|
|
||||||
if (GetDepthInMainChain() >= 1)
|
if (GetDepthInMainChain() >= 1)
|
||||||
return true;
|
return true;
|
||||||
if (!IsFromMe()) // using wtx's cached debit
|
if (!IsFromMe()) // using wtx's cached debit
|
||||||
@ -678,8 +675,6 @@ public:
|
|||||||
{
|
{
|
||||||
const CMerkleTx* ptx = vWorkQueue[i];
|
const CMerkleTx* ptx = vWorkQueue[i];
|
||||||
|
|
||||||
if (!IsFinalTx(*ptx))
|
|
||||||
return false;
|
|
||||||
if (ptx->GetDepthInMainChain() >= 1)
|
if (ptx->GetDepthInMainChain() >= 1)
|
||||||
continue;
|
continue;
|
||||||
if (!pwallet->IsFromMe(*ptx))
|
if (!pwallet->IsFromMe(*ptx))
|
||||||
|
Loading…
Reference in New Issue
Block a user