extern CCriticalSection cs_main;
extern std::map<uint256, CBlockIndex*> mapBlockIndex;
+extern std::set<std::pair<COutPoint, unsigned int> > setStakeSeen;
extern uint256 hashGenesisBlock;
extern CBlockIndex* pindexGenesisBlock;
extern int nBestHeight;
extern int64 nTimeBestReceived;
extern CCriticalSection cs_setpwalletRegistered;
extern std::set<CWallet*> setpwalletRegistered;
+extern std::map<uint256, CBlock*> mapOrphanBlocks;
// Settings
extern int fGenerateBitcoins;
bool ProcessMessages(CNode* pfrom);
bool SendMessages(CNode* pto, bool fSendTrickle);
void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
-CBlock* CreateNewBlock(CWallet* pwallet);
+CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfWorkOnly=false);
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
int GetNumBlocksOfPeers();
bool IsInitialBlockDownload();
std::string GetWarnings(std::string strFor);
-
+bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew);
+uint256 WantedByOrphan(const CBlock* pblockOrphan);
+const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake);
return (nValue == -1);
}
- bool IsCoinStake() const
+ bool SetEmpty()
+ {
+ nValue = 0;
+ scriptPubKey.clear();
+ }
+
+ bool IsEmpty() const
{
return (nValue == 0 && scriptPubKey.empty());
}
std::string ToString() const
{
- if (IsCoinStake()) return "CTxOut(coinstake)";
+ if (IsEmpty()) return "CTxOut(empty)";
if (scriptPubKey.size() < 6)
return "CTxOut(error)";
return strprintf("CTxOut(nValue=%s, scriptPubKey=%s)", FormatMoney(nValue).c_str(), scriptPubKey.ToString().substr(0,30).c_str());
bool IsCoinStake() const
{
// ppcoin: the coin stake transaction is marked with the first output empty
- return (vout.size() == 2 && vout[0].IsCoinStake());
+ return (vin.size() > 0 && vout.size() == 2 && vout[0].IsEmpty());
}
int GetSigOpCount() const
std::string ToString() const
{
std::string str;
- str += strprintf("CTransaction(hash=%s, nTime=%d, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n",
+ str += IsCoinBase()? "Coinbase" : (IsCoinStake()? "Coinstake" : "CTransaction");
+ str += strprintf("(hash=%s, nTime=%d, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n",
GetHash().ToString().substr(0,10).c_str(),
nTime,
nVersion,
public:
bool RemoveFromMemoryPool();
bool GetCoinAge(CTxDB& txdb, uint64& nCoinAge) const; // ppcoin: get transaction coin age
- bool CheckProofOfStake(CTxDB& txdb, unsigned int nBits) const;
+ bool CheckProofOfStake(unsigned int nBits) const;
};
return !IsProofOfStake();
}
+ std::pair<COutPoint, unsigned int> GetProofOfStake() const
+ {
+ return IsProofOfStake()? std::make_pair(vtx[1].vin[0].prevout, vtx[1].nTime) : std::make_pair(COutPoint(), (unsigned int)0);
+ }
+
// ppcoin: get max transaction timestamp
int64 GetMaxTransactionTime() const
{
filein >> *this;
// Check the header
- if (!CheckProofOfWork(GetHash(), nBits))
+ if (fReadTransactions && IsProofOfWork() && !CheckProofOfWork(GetHash(), nBits))
return error("CBlock::ReadFromDisk() : errors in block header");
return true;
bool SignBlock(const CKeyStore& keystore)
{
std::vector<std::pair<opcodetype, valtype> > vSolution;
+ const CTxOut& txout = IsProofOfStake()? vtx[1].vout[1] : vtx[0].vout[0];
- if (!Solver(vtx[0].vout[0].scriptPubKey, vSolution))
+ if (!Solver(txout.scriptPubKey, vSolution))
return false;
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
{
return vchBlockSig.empty();
std::vector<std::pair<opcodetype, valtype> > vSolution;
+ const CTxOut& txout = IsProofOfStake()? vtx[1].vout[1] : vtx[0].vout[0];
- if (!Solver(vtx[0].vout[0].scriptPubKey, vSolution))
+ if (!Solver(txout.scriptPubKey, vSolution))
return false;
BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
{
unsigned int nBlockPos;
uint64 nChainTrust;// ppcoin: trust score of chain, in the unit of coin-days
int nHeight;
- int nCheckpoint; // ppcoin: chain auto checkpoint height
bool fProofOfStake; // ppcoin: is the block of proof-of-stake type
+ COutPoint prevoutStake;
+ unsigned int nStakeTime;
// block header
int nVersion;
nBlockPos = 0;
nHeight = 0;
nChainTrust = 0;
- nCheckpoint = 0;
fProofOfStake = true;
+ prevoutStake.SetNull();
+ nStakeTime = 0;
nVersion = 0;
hashMerkleRoot = 0;
nBlockPos = nBlockPosIn;
nHeight = 0;
nChainTrust = 0;
- nCheckpoint = 0;
fProofOfStake = block.IsProofOfStake();
+ if (fProofOfStake)
+ {
+ prevoutStake = block.vtx[1].vin[0].prevout;
+ nStakeTime = block.vtx[1].nTime;
+ }
+ else
+ {
+ prevoutStake.SetNull();
+ nStakeTime = 0;
+ }
nVersion = block.nVersion;
hashMerkleRoot = block.hashMerkleRoot;
bool CheckIndex() const
{
- return CheckProofOfWork(GetBlockHash(), nBits);
+ return IsProofOfWork() ? CheckProofOfWork(GetBlockHash(), nBits) : true;
}
bool EraseBlockFromDisk()
std::string ToString() const
{
- return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nChainTrust=%"PRI64d" nHeight=%d, nCheckpoint=%d, fProofOfStake=%d merkle=%s, hashBlock=%s)",
- pprev, pnext, nFile, nBlockPos, nChainTrust, nHeight, nCheckpoint, fProofOfStake,
+ return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nChainTrust=%"PRI64d" nHeight=%d, fProofOfStake=%d prevoutStake=(%s), nStakeTime=%d merkle=%s, hashBlock=%s)",
+ pprev, pnext, nFile, nBlockPos, nChainTrust, nHeight,
+ fProofOfStake, prevoutStake.ToString().c_str(), nStakeTime,
hashMerkleRoot.ToString().substr(0,10).c_str(),
GetBlockHash().ToString().substr(0,20).c_str());
}
READWRITE(nBlockPos);
READWRITE(nChainTrust);
READWRITE(nHeight);
- READWRITE(nCheckpoint);
READWRITE(fProofOfStake);
+ if (fProofOfStake)
+ {
+ READWRITE(prevoutStake);
+ READWRITE(nStakeTime);
+ }
+ else if (fRead)
+ {
+ const_cast<CDiskBlockIndex*>(this)->prevoutStake.SetNull();
+ const_cast<CDiskBlockIndex*>(this)->nStakeTime = 0;
+ }
// block header
READWRITE(this->nVersion);