Use fully static linkage #364

Closed
bvbfan wants to merge 78 commits from static_link into master
13 changed files with 104 additions and 50 deletions
Showing only changes of commit 8743a93c9f - Show all commits

View file

@ -56,8 +56,8 @@ public:
{
static_assert(BITS/32 > 0 && BITS%32 == 0, "Template parameter BITS must be a positive multiple of 32.");
pn[0] = (unsigned int)b;
pn[1] = (unsigned int)(b >> 32);
pn[0] = uint32_t(b);
pn[1] = uint32_t(b >> 32U);
for (int i = 2; i < WIDTH; i++)
pn[i] = 0;
}

View file

@ -72,12 +72,18 @@ void CBaseBlob<BITS>::SetNull()
}
template<uint32_t BITS>
std::string CBaseBlob<BITS>::GetHex() const
std::string CBaseBlob<BITS>::GetHex(bool reverse) const
{
std::stringstream ss;
ss << std::hex;
if (reverse) {
for (auto it = data.rbegin(); it != data.rend(); ++it)
ss << std::setw(2) << std::setfill('0') << uint32_t(*it);
}
else {
for (auto it = data.begin(); it != data.end(); ++it)
ss << std::setw(2) << std::setfill('0') << uint32_t(*it);
}
return ss.str();
}

View file

@ -38,7 +38,7 @@ public:
bool IsNull() const;
void SetNull();
std::string GetHex() const;
std::string GetHex(bool reverse=true) const;
void SetHex(const char* psz);
void SetHex(const std::string& str);

View file

@ -49,10 +49,22 @@ namespace sqlite
inline uint256 get_col_from_db(sqlite3_stmt* stmt, int inx, result_type<uint256>) {
uint256 ret;
// I think we need this, but I lost my specific test case:
// auto type = sqlite3_column_type(stmt, inx);
// if (type == SQLITE_NULL)
// return ret;
//
// if (type == SQLITE_INTEGER) {
// auto integer = sqlite3_column_int64(stmt, inx);
// return uint256(integer);
// }
// assert(type == SQLITE_BLOB);
auto ptr = sqlite3_column_blob(stmt, inx);
if (!ptr) return ret;
int bytes = sqlite3_column_bytes(stmt, inx);
assert(bytes > 0 && bytes <= int(ret.size()));
assert(bytes <= ret.size());
std::memcpy(ret.begin(), ptr, bytes);
return ret;
}

View file

@ -77,34 +77,19 @@ CClaimTrie::CClaimTrie(std::size_t cacheBytes, bool fWipe, int height,
"parent BLOB REFERENCES node(name) DEFERRABLE INITIALLY DEFERRED, "
"hash BLOB)";
db << "CREATE INDEX IF NOT EXISTS node_hash_len_name ON node (hash, LENGTH(name) DESC)";
// db << "CREATE UNIQUE INDEX IF NOT EXISTS node_parent_name ON node (parent, name)"; // no apparent gain
db << "CREATE INDEX IF NOT EXISTS node_parent ON node (parent)";
db << "CREATE TABLE IF NOT EXISTS takeover (name BLOB NOT NULL, height INTEGER NOT NULL, "
"claimID BLOB, PRIMARY KEY(name, height DESC));";
db << "CREATE INDEX IF NOT EXISTS takeover_height ON takeover (height)";
db << "CREATE TABLE IF NOT EXISTS claim (claimID BLOB NOT NULL PRIMARY KEY, name BLOB NOT NULL, "
"nodeName BLOB NOT NULL REFERENCES node(name) DEFERRABLE INITIALLY DEFERRED, "
"txID BLOB NOT NULL, txN INTEGER NOT NULL, originalHeight INTEGER NOT NULL, updateHeight INTEGER NOT NULL, "
"validHeight INTEGER NOT NULL, activationHeight INTEGER NOT NULL, "
"expirationHeight INTEGER NOT NULL, amount INTEGER NOT NULL);";
db << "CREATE INDEX IF NOT EXISTS claim_activationHeight ON claim (activationHeight)";
db << "CREATE INDEX IF NOT EXISTS claim_expirationHeight ON claim (expirationHeight)";
db << "CREATE INDEX IF NOT EXISTS claim_nodeName ON claim (nodeName)";
db << "CREATE TABLE IF NOT EXISTS support (txID BLOB NOT NULL, txN INTEGER NOT NULL, "
"supportedClaimID BLOB NOT NULL, name BLOB NOT NULL, nodeName BLOB NOT NULL, "
"blockHeight INTEGER NOT NULL, validHeight INTEGER NOT NULL, activationHeight INTEGER NOT NULL, "
"expirationHeight INTEGER NOT NULL, amount INTEGER NOT NULL, PRIMARY KEY(txID, txN));";
db << "CREATE INDEX IF NOT EXISTS support_supportedClaimID ON support (supportedClaimID)";
db << "CREATE INDEX IF NOT EXISTS support_activationHeight ON support (activationHeight)";
db << "CREATE INDEX IF NOT EXISTS support_expirationHeight ON support (expirationHeight)";
db << "CREATE INDEX IF NOT EXISTS support_nodeName ON support (nodeName)";
db << "CREATE TABLE IF NOT EXISTS takeover (name BLOB NOT NULL, height INTEGER NOT NULL, "
"claimID BLOB, PRIMARY KEY(name, height DESC));";
if (fWipe) {
db << "DELETE FROM node";
@ -113,6 +98,21 @@ CClaimTrie::CClaimTrie(std::size_t cacheBytes, bool fWipe, int height,
db << "DELETE FROM takeover";
}
db << "CREATE INDEX IF NOT EXISTS node_hash_len_name ON node (hash, LENGTH(name) DESC)";
// db << "CREATE UNIQUE INDEX IF NOT EXISTS node_parent_name ON node (parent, name)"; // no apparent gain
db << "CREATE INDEX IF NOT EXISTS node_parent ON node (parent)";
db << "CREATE INDEX IF NOT EXISTS takeover_height ON takeover (height)";
db << "CREATE INDEX IF NOT EXISTS claim_activationHeight ON claim (activationHeight)";
db << "CREATE INDEX IF NOT EXISTS claim_expirationHeight ON claim (expirationHeight)";
db << "CREATE INDEX IF NOT EXISTS claim_nodeName ON claim (nodeName)";
db << "CREATE INDEX IF NOT EXISTS support_supportedClaimID ON support (supportedClaimID)";
db << "CREATE INDEX IF NOT EXISTS support_activationHeight ON support (activationHeight)";
db << "CREATE INDEX IF NOT EXISTS support_expirationHeight ON support (expirationHeight)";
db << "CREATE INDEX IF NOT EXISTS support_nodeName ON support (nodeName)";
db << "INSERT OR IGNORE INTO node(name, hash) VALUES(x'', ?)" << one; // ensure that we always have our root node
}
@ -457,9 +457,7 @@ bool CClaimTrieCacheBase::validateDb(int height, const uint256& rootHash)
{
base->nNextHeight = nNextHeight = height + 1;
logPrint << "Checking claim trie consistency... " << Clog::flush;
if (checkConsistency()) {
logPrint << "consistent" << Clog::endl;
if (rootHash != getMerkleHash()) {
logPrint << "CClaimTrieCacheBase::" << __func__ << "(): the block's root claim hash doesn't match the persisted claim root hash." << Clog::endl;
return false;
@ -470,7 +468,6 @@ bool CClaimTrieCacheBase::validateDb(int height, const uint256& rootHash)
return true;
}
logPrint << "inconsistent!" << Clog::endl;
return false;
}
@ -650,7 +647,6 @@ bool CClaimTrieCacheBase::removeClaim(const uint160& claimId, const COutPoint& o
*it >> nodeName >> originalHeight >> validHeight;
}
ensureTransacting();
db << "DELETE FROM claim WHERE claimID = ? AND txID = ? AND txN = ?"
@ -683,13 +679,18 @@ bool CClaimTrieCacheBase::removeClaim(const uint160& claimId, const COutPoint& o
bool CClaimTrieCacheBase::removeSupport(const COutPoint& outPoint, std::string& nodeName, int& validHeight)
{
ensureTransacting();
auto query = db << "SELECT nodeName, activationHeight FROM support WHERE txID = ? AND txN = ? AND expirationHeight >= ?"
{
auto query = db << "SELECT nodeName, activationHeight FROM support "
"WHERE txID = ? AND txN = ? AND expirationHeight >= ?"
<< outPoint.hash << outPoint.n << nNextHeight;
auto it = query.begin();
if (it == query.end()) return false;
if (it == query.end())
return false;
*it >> nodeName >> validHeight;
}
ensureTransacting();
db << "DELETE FROM support WHERE txID = ? AND txN = ?" << outPoint.hash << outPoint.n;
if (!db.rows_modified())
return false;
@ -925,7 +926,7 @@ std::vector<uint160> CClaimTrieCacheBase::getActivatedClaims(int height) {
}
std::vector<uint160> CClaimTrieCacheBase::getClaimsWithActivatedSupports(int height) {
std::vector<uint160> ret;
auto query = db << "SELECT DISTINCT supportedClaimID FROM support WHERE activationHeight = ?1 AND updateHeight < ?1" << height;
auto query = db << "SELECT DISTINCT supportedClaimID FROM support WHERE activationHeight = ?1 AND blockHeight < ?1" << height;
for (auto&& row: query) {
ret.emplace_back();
row >> ret.back();
@ -943,7 +944,7 @@ std::vector<uint160> CClaimTrieCacheBase::getExpiredClaims(int height) {
}
std::vector<uint160> CClaimTrieCacheBase::getClaimsWithExpiredSupports(int height) {
std::vector<uint160> ret;
auto query = db << "SELECT DISTINCT supportedClaimID FROM support WHERE expirationHeight = ?1 AND updateHeight < ?1" << height;
auto query = db << "SELECT DISTINCT supportedClaimID FROM support WHERE expirationHeight = ?1 AND blockHeight < ?1" << height;
for (auto&& row: query) {
ret.emplace_back();
row >> ret.back();

View file

@ -1,5 +1,6 @@
#include <uints.h>
#include <cstring>
uint160::uint160(const std::vector<uint8_t>& vec) : CBaseBlob<160>(vec)
{
@ -9,6 +10,10 @@ uint256::uint256(const std::vector<uint8_t>& vec) : CBaseBlob<256>(vec)
{
}
uint256::uint256(int64_t value) : CBaseBlob<256>() {
std::memcpy(this->begin(), &value, sizeof(value)); // TODO: fix the endianness here
}
uint160 uint160S(const char* str)
{
uint160 s;

View file

@ -25,6 +25,7 @@ public:
uint256() = default;
explicit uint256(const std::vector<uint8_t>& vec);
explicit uint256(int64_t value);
uint256(uint256&&) = default;
uint256& operator=(uint256&&) = default;

View file

@ -1543,8 +1543,9 @@ bool AppInitMain()
}
auto tip = chainActive.Tip();
LogPrintf("Checking existing claim trie consistency...\n");
if (tip && !CClaimTrieCache(pclaimTrie).validateDb(tip->nHeight, tip->hashClaimTrie)) {
strLoadError = _("Error validating the claim trie from disk");
strLoadError = _("Error validating the stored claim trie");
break;
}

View file

@ -434,7 +434,7 @@ boost::test_tools::predicate_result ClaimTrieChainFixture::best_claim_effective_
bool ClaimTrieChainFixture::getClaimById(const uint160 &claimId, std::string &name, CClaimValue &value)
{
auto query = db << "SELECT nodeName, claimID, txID, txN, amount, validHeight, blockHeight "
auto query = db << "SELECT nodeName, claimID, txID, txN, amount, validHeight, updateHeight "
"FROM claim WHERE claimID = ?" << claimId;
auto hit = false;
for (auto&& row: query) {

View file

@ -280,4 +280,20 @@ BOOST_AUTO_TEST_CASE( operator_with_self )
BOOST_CHECK(v == UintToArith256(uint256S("0")));
}
BOOST_AUTO_TEST_CASE( bit64_all_ways )
{
std::vector<int64_t> tests = { 0, 1, -1, 42, 1LL << 33U, std::numeric_limits<int64_t>::max(),
std::numeric_limits<int64_t>::lowest() };
for (auto test: tests) {
auto a = uint256(test);
auto b = arith_uint256(uint64_t(test));
auto c = ArithToUint256(b);
auto d = UintToArith256(a);
BOOST_CHECK(a == c);
BOOST_CHECK(b == d);
BOOST_CHECK_EQUAL(a.GetHex(false), c.GetHex(false));
}
}
BOOST_AUTO_TEST_SUITE_END()

View file

@ -53,7 +53,7 @@ CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe)
bool CCoinsViewDB::GetCoin(const COutPoint &outpoint, Coin &coin) const {
auto query = db << "SELECT isCoinbase, blockHeight, amount, script FROM unspent "
"WHERE txID = ? and txN = ?" << outpoint.hash << outpoint.n;
"WHERE txID = ? AND txN = ?" << outpoint.hash << outpoint.n;
for (auto&& row: query) {
uint32_t coinbase = 0, height = 0;
row >> coinbase >> height >> coin.out.nValue >> coin.out.scriptPubKey;
@ -66,10 +66,8 @@ bool CCoinsViewDB::GetCoin(const COutPoint &outpoint, Coin &coin) const {
bool CCoinsViewDB::HaveCoin(const COutPoint &outpoint) const {
auto query = db << "SELECT 1 FROM unspent "
"WHERE txID = ? and txN = ?" << outpoint.hash << outpoint.n;
for (auto&& row: query)
return true;
return false;
"WHERE txID = ? AND txN = ?" << outpoint.hash << outpoint.n;
return query.begin() != query.end();
}
uint256 CCoinsViewDB::GetBestBlock() const {
@ -113,20 +111,26 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, boo
db << "BEGIN";
db << "INSERT OR REPLACE INTO marker VALUES('head_block', ?)" << hashBlock;
auto dbd = db << "DELETE FROM unspent WHERE txID = ? AND txN = ?";
auto dbi = db << "INSERT OR REPLACE INTO unspent VALUES(?,?,?,?,?,?,?)";
for (auto it = mapCoins.begin(); it != mapCoins.end();) {
if (it->second.flags & CCoinsCacheEntry::DIRTY) {
if (it->second.coin.IsSpent()) {
// at present the "IsSpent" flag is used for both "spent" and "block going backwards"
db << "DELETE FROM unspent WHERE txID = ? AND txN = ?" << it->first.hash << it->first.n;
dbd << it->first.hash << it->first.n;
dbd++;
}
else {
CTxDestination address;
std::string destination;
if (ExtractDestination(it->second.coin.out.scriptPubKey, address))
destination = EncodeDestination(address);
db << "INSERT OR REPLACE INTO unspent VALUES(?,?,?,?,?,?,?)" << it->first.hash << it->first.n
<< it->second.coin.fCoinBase << it->second.coin.nHeight
uint32_t isCoinBase = it->second.coin.fCoinBase; // bit-field
uint32_t coinHeight = it->second.coin.nHeight; // bit-field
dbi << it->first.hash << it->first.n << isCoinBase << coinHeight
<< it->second.coin.out.nValue << it->second.coin.out.scriptPubKey << destination;
dbi++;
}
changed++;
}
@ -141,6 +145,8 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, boo
}
}
}
dbd.used(true);
dbi.used(true);
db << "INSERT OR REPLACE INTO marker VALUES('best_block', ?)" << hashBlock;
db << "DELETE FROM marker WHERE name = 'head_block'";
@ -201,9 +207,6 @@ CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe)
"nonce INTEGER NOT NULL "
")";
db << "CREATE UNIQUE INDEX IF NOT EXISTS block_info_height ON block_info (height)";
db << "CREATE UNIQUE INDEX IF NOT EXISTS block_file_data_pos ON block_info (file, dataPos)";
db << "CREATE TABLE IF NOT EXISTS tx_to_block ("
"txID BLOB NOT NULL PRIMARY KEY, "
"file INTEGER NOT NULL, "
@ -220,6 +223,9 @@ CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe)
db << "DELETE FROM tx_to_block";
db << "DELETE FROM flag";
}
// not unique because we actually want to store forks:
db << "CREATE INDEX IF NOT EXISTS block_info_height ON block_info (height)";
}
bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {

View file

@ -2493,6 +2493,12 @@ bool CChainState::ConnectTip(CValidationState& state, const CChainParams& chainp
assert(flushed);
flushed = trieCache.flush();
assert(flushed);
// for verifying that rollback code works:
// auto result = DisconnectBlock(blockConnecting, pindexNew, view, trieCache);
// assert(result == DisconnectResult::DISCONNECT_OK);
// assert(trieCache.getMerkleHash() == pindexNew->pprev->hashClaimTrie);
// LogPrintf("Verified %d!\n", pindexNew->nHeight);
}
int64_t nTime4 = GetTimeMicros(); nTimeFlush += nTime4 - nTime3;
LogPrint(BCLog::BENCH, " - Flush: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime4 - nTime3) * MILLI, nTimeFlush * MICRO, nTimeFlush * MILLI / nBlocksTotal);

View file

@ -102,7 +102,7 @@ static const int MAX_BLOCKTXN_DEPTH = 10;
* want to make this a per-peer adaptive value at some point. */
static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
/** Time to wait (in seconds) between writing blocks/block index to disk. */
static const unsigned int DATABASE_WRITE_INTERVAL = 60 * 60;
static const unsigned int DATABASE_WRITE_INTERVAL = 15 * 60;
/** Time to wait (in seconds) between flushing chainstate to disk. */
static const unsigned int DATABASE_FLUSH_INTERVAL = 24 * 60 * 60;
/** Maximum length of reject messages. */