Overview
ALT block storage should be modified to store VeriBlock related data.
1. Add PayloadsProvider.
We should add a PayloadsProvider
for the VeriBlock library. The main idea of such class is that we reuse the existing ALT blockchain database. Our library allows to use the native implementation of the database. We implement it with PayloadsProvider
class which is inherited from the altintegration::PayloadsStorage class.
Payloads provider: https://github.com/VeriBlock/vbk-ri-btc/blob/master/src/vbk/adaptors/payloads_provider.hpp. Copy this file to your project.
Block provider: https://github.com/VeriBlock/vbk-ri-btc/blob/master/src/vbk/adaptors/block_provider.hpp. Copy this file to your project.
- Note
- These adaptors rely heavily on Bitcoin structures such as
CDBWrapper
and CDBIterator
. Other blockchains should use own adaptors or other means for storing VeriBlock related data.
2. Create wrappers for the persistence API.
https://github.com/VeriBlock/vbk-ri-btc/blob/master/src/vbk/pop_service.hpp
#ifndef BITCOIN_SRC_VBK_POP_SERVICE_HPP
#define BITCOIN_SRC_VBK_POP_SERVICE_HPP
#include "pop_common.hpp"
#include <vbk/adaptors/payloads_provider.hpp>
#include <vbk/util.hpp>
class CBlockTreeDB;
class CDBBatch;
class CDBIterator;
class CDBWrapper;
namespace VeriBlock {
void InitPopContext(CDBWrapper& db);
bool hasPopData(CBlockTreeDB& db);
void saveTrees(CDBBatch* batch);
bool loadTrees(CDBWrapper& db);
}
#endif
Represents ALT block body of POP-related info.
https://github.com/VeriBlock/vbk-ri-btc/blob/master/src/vbk/pop_service.cpp
#include <chain.h>
#include <chainparams.h>
#include <consensus/validation.h>
#include <dbwrapper.h>
#include <shutdown.h>
#include <validation.h>
#include <vbk/adaptors/payloads_provider.hpp>
#include <veriblock/storage/util.hpp>
#ifdef WIN32
#include <boost/thread/interruption.hpp>
#endif
#include "pop_service.hpp"
#include <utility>
#include <vbk/adaptors/block_provider.hpp>
#include <vbk/pop_common.hpp>
namespace VeriBlock {
void InitPopContext(CDBWrapper& db)
{
auto payloads_provider = std::make_shared<PayloadsProvider>(db);
SetPop(payloads_provider);
}
bool hasPopData(CBlockTreeDB& db)
{
return db.Exists(tip_key<altintegration::BtcBlock>()) &&
db.Exists(tip_key<altintegration::VbkBlock>()) &&
db.Exists(tip_key<altintegration::AltBlock>());
}
void saveTrees(CDBBatch* batch)
{
AssertLockHeld(cs_main);
VeriBlock::BlockBatch b(*batch);
altintegration::SaveAllTrees(*GetPop().altTree, b);
}
bool loadTrees(CDBWrapper& db)
{
BlockReader reader(db);
if (!altintegration::LoadAllTrees(GetPop(), reader, state)) {
return error("%s: failed to load trees %s", __func__, state.toString());
}
return true;
}
Class that is used for storing validation state.
- Note
- You can copy provided pop_service.hpp and pop_service.cpp files and comment out everything but storage related API.
3. Initialize VeriBlock storage during ALT blockchain initialization process.
https://github.com/VeriBlock/vbk-ri-btc/blob/master/src/init.cpp
+#include <vbk/pop_service.hpp>
method Shutdown
threadGroup.interrupt_all();
threadGroup.join_all();
+ VeriBlock::StopPop();
method AppInitMain
pblocktree.reset();
pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, false, fReset));
+ VeriBlock::InitPopContext(*pblocktree);
https://github.com/VeriBlock/vbk-ri-btc/blob/master/src/txdb.cpp
#include <boost/thread.hpp>
+#include <vbk/pop_service.hpp>
method CBlockTreeDB::WriteBatchSync
}
+
+
+ VeriBlock::saveTrees(&batch);
return WriteBatch(batch, true);
https://github.com/VeriBlock/vbk-ri-btc/blob/master/src/validation.cpp
#include <warnings.h>
+#include <vbk/pop_service.hpp>
+#include <vbk/pop_common.hpp>
+#include <vbk/util.hpp>
method BlockManager::LoadBlockIndex
return false;
+ bool hasPopData = VeriBlock::hasPopData(blocktree);
+
+ if (!hasPopData) {
+ LogPrintf("BTC/VBK/ALT tips not found... skipping block index loading\n");
+ return true;
+ }
+
method BlockManager::LoadBlockIndex
if (pindex->IsValid(BLOCK_VALID_TREE) && (pindexBestHeader == nullptr || CBlockIndexWorkComparator()(pindexBestHeader, pindex)))
pindexBestHeader = pindex;
}
+
+
+ {
+ AssertLockHeld(cs_main);
+
+
+ if(!VeriBlock::loadTrees(blocktree)) {
+ return false;
+ }
}
4. Update the constructor of the TestingSetup struct.
https://github.com/VeriBlock/vbk-ri-btc/blob/master/src/test/util/setup_common.cpp
method TestingSetup::TestingSetup
pblocktree.reset(new CBlockTreeDB(1 << 20, true));
+ VeriBlock::InitPopContext(*pblocktree);
method TestingSetup::~TestingSetup
threadGroup.interrupt_all();
threadGroup.join_all();
+ VeriBlock::StopPop();
method TestChain100Setup::TestChain100Setup
+ assert(ChainActive().Tip() != nullptr);
+ assert(ChainActive().Tip()->nHeight == 100);
+ assert(BlockIndex().size() == 101);
5. Restore VeriBlock block hash from the storage - do not recalculate it if possible.
https://github.com/VeriBlock/vbk-ri-btc/blob/master/src/dbwrapper.h
+
+template <>
+{
+ leveldb::Slice slValue = piter->value();
+ try {
+ CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
+ ssValue.Xor(dbwrapper_private::GetObfuscateKey(parent));
+ std::pair<char, altintegration::VbkBlock::hash_t> key;
+ if (!GetKey(key)) return false;
+ UnserializeWithHash(ssValue, value, key.second);
+ } catch (const std::exception&) {
+ return false;
+ }
+ return true;
+}
6. Add pop_service.cpp to the makefile.
https://github.com/VeriBlock/vbk-ri-btc/blob/master/src/Makefile.am
libbitcoin_server_a_SOURCES = \
+ vbk/pop_service.hpp \
+ vbk/pop_service.cpp \
addrdb.cpp \