Merge pull request #21 from nzsquirrell/dev

Dev
This commit is contained in:
myriadcoin
2015-07-12 09:35:26 +02:00
7 changed files with 166 additions and 80 deletions
+2
View File
@@ -28,6 +28,7 @@ BITCOIN_CORE_H = \
addrman.h \
alert.h \
allocators.h \
auxpow.h \
base58.h bignum.h \
bloom.h \
chainparams.h \
@@ -108,6 +109,7 @@ version.o: obj/build.h
libbitcoin_server_a_SOURCES = \
addrman.cpp \
alert.cpp \
auxpow.cpp \
bloom.cpp \
checkpoints.cpp \
coins.cpp \
+10 -11
View File
@@ -85,6 +85,16 @@ inline std::string GetAlgoName(int Algo)
}
class CTransaction;
class CAuxPow;
template <typename Stream>
int ReadWriteAuxPow(Stream& s, const boost::shared_ptr<CAuxPow>& auxpow, int nType, int nVersion, CSerActionSerialize ser_action);
template <typename Stream>
int ReadWriteAuxPow(Stream& s, boost::shared_ptr<CAuxPow>& auxpow, int nType, int nVersion, CSerActionUnserialize ser_action);
template <typename Stream>
int ReadWriteAuxPow(Stream& s, const boost::shared_ptr<CAuxPow>& auxpow, int nType, int nVersion, CSerActionGetSerializeSize ser_action);
/** No amount larger than this (in satoshi) is valid */
static const int64_t MAX_MONEY = 2000000000 * COIN;
@@ -413,17 +423,6 @@ public:
)
};
class CAuxPow;
template <typename Stream>
int ReadWriteAuxPow(Stream& s, const boost::shared_ptr<CAuxPow>& auxpow, int nType, int nVersion, CSerActionSerialize ser_action);
template <typename Stream>
int ReadWriteAuxPow(Stream& s, boost::shared_ptr<CAuxPow>& auxpow, int nType, int nVersion, CSerActionUnserialize ser_action);
template <typename Stream>
int ReadWriteAuxPow(Stream& s, const boost::shared_ptr<CAuxPow>& auxpow, int nType, int nVersion, CSerActionGetSerializeSize ser_action);
/** Nodes collect new transactions into a block, hash them into a hash tree,
* and scan through nonce values to make the block's hash satisfy proof-of-work
* requirements. When they solve the proof-of-work, they broadcast the block
+101 -48
View File
@@ -1135,17 +1135,6 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
// CBlock and CBlockIndex
//
std::string CDiskBlockIndex::ToString() const
{
std::string str = "CDiskBlockIndex(";
str += CBlockIndex::ToString();
str += strprintf("\n hashBlock=%s, hashPrev=%s, hashParentBlock=%s)",
GetBlockHash().ToString().c_str(),
hashPrev.ToString().c_str(),
(auxpow.get() != NULL) ? auxpow->GetParentBlockHash(GetAlgo()).ToString().substr(0,20).c_str() : "-");
return str;
}
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos)
{
// Open history file to append
@@ -1190,7 +1179,8 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
}
// Check the header
if (!CheckProofOfWork(block.GetPoWHash(block.GetAlgo()), block.nBits, block.GetAlgo()))
//if (!CheckProofOfWork(block.GetPoWHash(block.GetAlgo()), block.nBits, block.GetAlgo()))
if (!block.CheckProofOfWork(mapBlockIndex[block.GetHash()]->nHeight))
return error("ReadBlockFromDisk : Errors in block header");
return true;
@@ -1533,7 +1523,7 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits, int algo)
bool CBlockHeader::CheckProofOfWork(int nHeight) const
{
int algo = GetAlgo();
if ((nHeight >= GetAuxPowStartBlock()) && (algo == ALGO_SHA256D && algo == ALGO_SCRYPT))
if ((nHeight >= GetAuxPowStartBlock()) && (algo == ALGO_SHA256D || algo == ALGO_SCRYPT))
{
// Prevent same work from being submitted twice:
// - this block must have our chain ID
@@ -1999,7 +1989,8 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
{
AssertLockHeld(cs_main);
// Check it again in case a previous version let a bad block in
if (!CheckBlock(block, state, !fJustCheck, !fJustCheck))
//if (!CheckBlock(block, state, !fJustCheck, !fJustCheck))
if (!CheckBlock(block, state, pindex->nHeight, !fJustCheck, !fJustCheck))
return false;
// verify that the view's current state corresponds to the previous block
@@ -2409,27 +2400,6 @@ bool ActivateBestChain(CValidationState &state) {
return true;
}
CBlockHeader CBlockIndex::GetBlockHeader() const
{
CBlockHeader block;
if (nVersion & BLOCK_VERSION_AUXPOW) {
CDiskBlockIndex diskblockindex;
// auxpow is not in memory, load CDiskBlockHeader
// from database to get it
pblocktree->ReadDiskBlockIndex(*phashBlock, diskblockindex);
block.auxpow = diskblockindex.auxpow;
}
block.nVersion = nVersion;
if (pprev)
block.hashPrevBlock = pprev->GetBlockHash();
block.hashMerkleRoot = hashMerkleRoot;
block.nTime = nTime;
block.nBits = nBits;
block.nNonce = nNonce;
return block;
}
bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos)
{
// Check for duplicate
@@ -2466,10 +2436,8 @@ bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos
pindexNew->nStatus = BLOCK_VALID_TRANSACTIONS | BLOCK_HAVE_DATA;
setBlockIndexValid.insert(pindexNew);
//if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew, block.auxpow)) || !pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew)))
if (!pblocktree->WriteDiskBlockIndex(CDiskBlockIndex(pindexNew, block.auxpow)) || !pblocktree->WriteBlockIndex(*pindexNew))
/* write both the immutible data (CDiskBlockIndex) and the mutable data (BlockIndex) */
//if (!pblocktree->WriteDiskBlockIndex(CDiskBlockIndex(pindexNew, block.auxpow)) || !pblocktree->WriteBlockIndex(*pindexNew))
if (!pblocktree->WriteDiskBlockIndex(CDiskBlockIndex(pindexNew, block.auxpow)) || !pblocktree->WriteBlockIndex(*pindexNew))
return state.Abort(_("Failed to write block index"));
// New best?
@@ -2590,26 +2558,66 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
return true;
}
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, int nHeight, bool fCheckPOW)
{
// Check proof of work matches claimed amount
if (fCheckPOW && !block.CheckProofOfWork(nHeight))
//if (fCheckPOW && !CheckProofOfWork(block.GetPoWHash(block.GetAlgo()), block.nBits, block.GetAlgo()))
return state.DoS(50, error("CheckBlockHeader() : proof of work failed"),
REJECT_INVALID, "high-hash");
bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bool fCheckMerkleRoot)
// Check timestamp
if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
return state.Invalid(error("CheckBlockHeader() : block timestamp too far in the future"),
REJECT_INVALID, "time-too-new");
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex);
if (pcheckpoint && block.hashPrevBlock != (chainActive.Tip() ? chainActive.Tip()->GetBlockHash() : uint256(0)))
{
// Extra checks to prevent "fill up memory by spamming with bogus blocks"
int64_t deltaTime = block.GetBlockTime() - pcheckpoint->nTime;
if (deltaTime < 0)
{
LogPrintf("CheckBlockHeader(): Height=%d, hash=%s, BlockTime=%d, Checkpoint=%d\n", nHeight, block.GetHash().GetHex().c_str(), block.GetBlockTime(), pcheckpoint->nTime);
return state.DoS(100, error("CheckBlockHeader() : block with timestamp before last checkpoint"),
REJECT_CHECKPOINT, "time-too-old");
}
CBigNum bnNewBlock;
bnNewBlock.SetCompact(block.nBits);
CBigNum bnRequired;
bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime));
if (bnNewBlock > bnRequired)
{
return state.DoS(100, error("CheckBlockHeader() : block with too little proof-of-work"),
REJECT_INVALID, "bad-diffbits");
}
}
return true;
}
bool CheckBlock(const CBlock& block, CValidationState& state, int nHeight, bool fCheckPOW, bool fCheckMerkleRoot)
{
// These are checks that are independent of context
// that can be verified before saving an orphan block.
if (!CheckBlockHeader(block, state, nHeight, fCheckPOW))
return false;
// Size limits
if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
return state.DoS(100, error("CheckBlock() : size limits failed"),
REJECT_INVALID, "bad-blk-length");
// Check proof of work matches claimed amount
if (fCheckPOW && !CheckProofOfWork(block.GetPoWHash(block.GetAlgo()), block.nBits, block.GetAlgo()))
return state.DoS(50, error("CheckBlock() : proof of work failed"),
REJECT_INVALID, "high-hash");
// if (fCheckPOW && !CheckProofOfWork(block.GetPoWHash(block.GetAlgo()), block.nBits, block.GetAlgo()))
// return state.DoS(50, error("CheckBlock() : proof of work failed"),
// REJECT_INVALID, "high-hash");
// Check timestamp
if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
return state.Invalid(error("CheckBlock() : block timestamp too far in the future"),
REJECT_INVALID, "time-too-new");
// if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
// return state.Invalid(error("CheckBlock() : block timestamp too far in the future"),
// REJECT_INVALID, "time-too-new");
// First transaction must be coinbase, the rest must not be
if (block.vtx.empty() || !block.vtx[0].IsCoinBase())
@@ -2812,6 +2820,48 @@ int64_t CBlockIndex::GetMedianTime() const
return pindex->GetMedianTimePast();
}
std::string CBlockIndex::ToString() const
{
return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
pprev, nHeight,
hashMerkleRoot.ToString().substr(0,10).c_str(),
GetBlockHash().ToString().c_str());
}
std::string CDiskBlockIndex::ToString() const
{
std::string str = "CDiskBlockIndex(";
str += CBlockIndex::ToString();
str += strprintf("\n hashBlock=%s, hashPrev=%s, hashParentBlock=%s)",
GetBlockHash().ToString().c_str(),
hashPrev.ToString().c_str(),
(auxpow.get() != NULL) ? auxpow->GetParentBlockHash(GetAlgo()).ToString().substr(0,20).c_str() : "-");
return str;
}
CBlockHeader CBlockIndex::GetBlockHeader() const
{
CBlockHeader block;
if (nVersion & BLOCK_VERSION_AUXPOW) {
CDiskBlockIndex diskblockindex;
// auxpow is not in memory, load CDiskBlockHeader
// from database to get it
pblocktree->ReadDiskBlockIndex(*phashBlock, diskblockindex);
block.auxpow = diskblockindex.auxpow;
}
block.nVersion = nVersion;
if (pprev)
block.hashPrevBlock = pprev->GetBlockHash();
block.hashMerkleRoot = hashMerkleRoot;
block.nTime = nTime;
block.nBits = nBits;
block.nNonce = nNonce;
return block;
}
void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd)
{
AssertLockHeld(cs_main);
@@ -2835,9 +2885,12 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
if (mapOrphanBlocks.count(hash))
return state.Invalid(error("ProcessBlock() : already have block (orphan) %s", hash.ToString()), 0, "duplicate");
// Preliminary checks
if (!CheckBlock(*pblock, state))
if (!CheckBlock(*pblock, state, INT_MAX))
{
if (state.CorruptionPossible())
mapAlreadyAskedFor.erase(CInv(MSG_BLOCK, hash));
return error("ProcessBlock() : CheckBlock FAILED");
}
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex);
if (pcheckpoint && pblock->hashPrevBlock != (chainActive.Tip() ? chainActive.Tip()->GetBlockHash() : uint256(0)))
@@ -3235,7 +3288,7 @@ bool VerifyDB(int nCheckLevel, int nCheckDepth)
if (!ReadBlockFromDisk(block, pindex))
return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
// check level 1: verify block validity
if (nCheckLevel >= 1 && !CheckBlock(block, state))
if (nCheckLevel >= 1 && !CheckBlock(block, state, pindex->nHeight))
return error("VerifyDB() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
// check level 2: verify undo validity
if (nCheckLevel >= 2 && pindex) {
+8 -11
View File
@@ -622,7 +622,8 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos);
// Context-independent validity checks
bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, int nHeight, bool fCheckPOW = true);
bool CheckBlock(const CBlock& block, CValidationState& state, int nHeight, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
// Store block on disk
// if dbp is provided, the file is known to already reside on disk
@@ -994,10 +995,12 @@ public:
bool CheckIndex() const
{
int algo = GetAlgo();
/* This check was considered unneccessary given the other safeguards like the genesis and checkpoints, and it breaks LoadBlockIndexGuts() after AuxPow is enabled. */
/* int algo = GetAlgo();
if (algo == ALGO_SHA256D)
return CheckProofOfWork(GetBlockHash(), nBits, algo);
else
else*/
return true;
}
@@ -1026,13 +1029,7 @@ public:
static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart,
unsigned int nRequired, unsigned int nToCheck);
std::string ToString() const
{
return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
pprev, nHeight,
hashMerkleRoot.ToString().c_str(),
GetBlockHash().ToString().c_str());
}
std::string ToString() const; //moved code to main.cpp because new method required access to auxpow
void print() const
{
@@ -1096,7 +1093,7 @@ public:
}
std::string ToString() const;
std::string ToString() const; // moved code to main.cpp
void print() const
{
+35
View File
@@ -16,6 +16,9 @@
using namespace json_spirit;
using namespace std;
// from rpcraw.cpp
void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry);
void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex);
double GetDifficulty(const CBlockIndex* blockindex, int algo)
@@ -76,6 +79,38 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
result.push_back(Pair("pow_algo", GetAlgoName(algo)));
result.push_back(Pair("pow_hash", block.GetPoWHash(algo).GetHex()));
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
if (block.nVersion & BLOCK_VERSION_AUXPOW) {
// this block includes auxpow
Object auxpow;
auxpow.push_back(Pair("size", (int)::GetSerializeSize(*block.auxpow, SER_NETWORK, PROTOCOL_VERSION)));
Object coinbasetx;
TxToJSON(*block.auxpow, 0, coinbasetx);
auxpow.push_back(Pair("coinbasetx", Value(coinbasetx)));
Array coinbaseMerkle;
BOOST_FOREACH(const uint256 &hash, block.auxpow->vMerkleBranch)
coinbaseMerkle.push_back(hash.GetHex());
auxpow.push_back(Pair("coinbaseMerkleBranch", coinbaseMerkle));
auxpow.push_back(Pair("coinbaseIndex", block.auxpow->nIndex));
Array chainMerkle;
BOOST_FOREACH(const uint256 &hash, block.auxpow->vChainMerkleBranch)
chainMerkle.push_back(hash.GetHex());
auxpow.push_back(Pair("chainMerkleBranch", chainMerkle));
auxpow.push_back(Pair("chainIndex", (boost::uint64_t)block.auxpow->nChainIndex));
Object parent_block;
parent_block.push_back(Pair("hash", block.auxpow->parentBlockHeader.GetHash().GetHex()));
parent_block.push_back(Pair("version", (boost::uint64_t)block.auxpow->parentBlockHeader.nVersion));
parent_block.push_back(Pair("previousblockhash", block.auxpow->parentBlockHeader.hashPrevBlock.GetHex()));
parent_block.push_back(Pair("merkleroot", block.auxpow->parentBlockHeader.hashMerkleRoot.GetHex()));
parent_block.push_back(Pair("time", (boost::int64_t)block.auxpow->parentBlockHeader.nTime));
parent_block.push_back(Pair("bits", HexBits(block.auxpow->parentBlockHeader.nBits)));
parent_block.push_back(Pair("nonce", (boost::uint64_t)block.auxpow->parentBlockHeader.nNonce));
auxpow.push_back(Pair("parent_block", Value(parent_block)));
result.push_back(Pair("auxpow", Value(auxpow)));
}
Array txs;
BOOST_FOREACH(const CTransaction&tx, block.vtx)
txs.push_back(tx.GetHash().GetHex());
+1 -1
View File
@@ -315,7 +315,7 @@ static const CRPCCommand vRPCCommands[] =
{ "gethashespersec", &gethashespersec, true, false, false },
{ "getwork", &getwork, true, false, true },
{ "setgenerate", &setgenerate, true, true, false },
/* Stealth */
{ "getnewstealthaddress", &getnewstealthaddress, false, false, true},
{ "liststealthaddresses", &liststealthaddresses, false, false, true},
+9 -9
View File
@@ -215,35 +215,35 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
char chType;
ssKey >> chType;
if (chType == 'b') {
// Detect pre-auxpow keys in the database and abort if found
if (slKey.size() < ssKeySet.size()) {
return error("Database key size is %d expected %d, require reindex to upgrade.", slKey.size(), ssKeySet.size());
}
ssKey >> hash;
leveldb::Slice slValue = pcursor->value();
// CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
CDataStream ssValue_immutable(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
CDiskBlockIndex diskindex;
// ssValue >> diskindex;
ssValue_immutable >> diskindex; // read all immutable data
// Construct immutable parts of block index objecty
CBlockIndex* pindexNew = InsertBlockIndex(hash);
assert(diskindex.GetBlockHash() == *pindexNew->phashBlock); // paranoia check
// // Construct block index object
// CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev);
pindexNew->nHeight = diskindex.nHeight;
// pindexNew->nFile = diskindex.nFile;
// pindexNew->nDataPos = diskindex.nDataPos;
// pindexNew->nUndoPos = diskindex.nUndoPos;
pindexNew->nFile = diskindex.nFile;
pindexNew->nDataPos = diskindex.nDataPos;
pindexNew->nUndoPos = diskindex.nUndoPos;
pindexNew->nVersion = diskindex.nVersion;
pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
pindexNew->nTime = diskindex.nTime;
pindexNew->nBits = diskindex.nBits;
pindexNew->nNonce = diskindex.nNonce;
// pindexNew->nStatus = diskindex.nStatus;
pindexNew->nStatus = diskindex.nStatus;
pindexNew->nTx = diskindex.nTx;
// if (!pindexNew->CheckIndex())
// CheckIndex need phashBlock to be set
diskindex.phashBlock = pindexNew->phashBlock;
if (!diskindex.CheckIndex())