Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add vault history DB and listvaulthistory RPC call #898

Merged
merged 12 commits into from
Nov 24, 2021
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ DEFI_CORE_H = \
masternodes/undo.h \
masternodes/undos.h \
masternodes/vault.h \
masternodes/vaulthistory.h \
memusage.h \
merkleblock.h \
miner.h \
Expand Down Expand Up @@ -404,6 +405,7 @@ libdefi_server_a_SOURCES = \
masternodes/skipped_txs.cpp \
masternodes/undos.cpp \
masternodes/vault.cpp \
masternodes/vaulthistory.cpp \
miner.cpp \
net.cpp \
net_processing.cpp \
Expand Down
11 changes: 9 additions & 2 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <masternodes/accountshistory.h>
#include <masternodes/anchors.h>
#include <masternodes/masternodes.h>
#include <masternodes/vaulthistory.h>
#include <miner.h>
#include <net.h>
#include <net_permissions.h>
Expand Down Expand Up @@ -417,7 +418,8 @@ void SetupServerArgs()
hidden_args.emplace_back("-sysperms");
#endif
gArgs.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-acindex", strprintf("Maintain a full account history index, tracking all accounts balances changes. Used by the listaccounthistory and accounthistorycount rpc calls (default: %u)", false), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-acindex", strprintf("Maintain a full account history index, tracking all accounts balances changes. Used by the listaccounthistory and accounthistorycount rpc calls (default: %u)", DEFAULT_ACINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-vaultindex", strprintf("Maintain a full vault history index, tracking all vault changes. Used by the getvaulthistory rpc call (default: %u)", DEFAULT_VAULTINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-blockfilterindex=<type>",
strprintf("Maintain an index of compact filters by block (default: %s, values: %s).", DEFAULT_BLOCKFILTERINDEX, ListBlockFilterTypes()) +
" If <type> is not supplied or if <type> = 1, indexes for all known types are enabled.",
Expand Down Expand Up @@ -461,7 +463,6 @@ void SetupServerArgs()
gArgs.AddArg("-anchorquorum", "Min quorum size (regtest only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-spv", "Enable SPV to bitcoin blockchain (default: 1)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-spv_resync", "Flag to reset spv database and resync from zero block (default: 0)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-spv_rescan", "Block height to rescan from (default: 0 = off)", ArgsManager::ALLOW_INT, OptionsCategory::OPTIONS);
gArgs.AddArg("-amkheight", "AMK fork activation height (regtest only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-bayfrontheight", "Bayfront fork activation height (regtest only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-bayfrontgardensheight", "Bayfront Gardens fork activation height (regtest only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
Expand Down Expand Up @@ -1630,6 +1631,12 @@ bool AppInitMain(InitInterfaces& interfaces)
pburnHistoryDB.reset();
pburnHistoryDB = MakeUnique<CBurnHistoryStorage>(GetDataDir() / "burn", nCustomCacheSize, false, fReset || fReindexChainState);

// Create vault history DB
pvaultHistoryDB.reset();
if (gArgs.GetBoolArg("-vaultindex", DEFAULT_VAULTINDEX)) {
pvaultHistoryDB = MakeUnique<CVaultHistoryStorage>(GetDataDir() / "vault", nCustomCacheSize, false, fReset || fReindexChainState);
}

// If necessary, upgrade from older database format.
// This is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
if (!::ChainstateActive().CoinsDB().Upgrade()) {
Expand Down
154 changes: 112 additions & 42 deletions src/masternodes/accountshistory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <masternodes/accountshistory.h>
#include <masternodes/accounts.h>
#include <masternodes/masternodes.h>
#include <masternodes/vaulthistory.h>
#include <key_io.h>

void CAccountsHistoryView::ForEachAccountHistory(std::function<bool(AccountHistoryKey const &, CLazySerialize<AccountHistoryValue>)> callback, AccountHistoryKey const & start)
Expand Down Expand Up @@ -34,94 +35,102 @@ CBurnHistoryStorage::CBurnHistoryStorage(const fs::path& dbName, std::size_t cac
{
}

CAccountsHistoryWriter::CAccountsHistoryWriter(CCustomCSView & storage, uint32_t height, uint32_t txn, const uint256& txid, uint8_t type, CAccountsHistoryView* historyView, CAccountsHistoryView* burnView)
: CStorageView(new CFlushableStorageKV(static_cast<CStorageKV&>(storage.GetStorage()))), height(height), txn(txn), txid(txid), type(type), historyView(historyView), burnView(burnView)
CAccountsHistoryWriter::CAccountsHistoryWriter(CCustomCSView & storage, uint32_t height, uint32_t txn, const uint256& txid, uint8_t type,
CHistoryWriters* writers, const uint256& vaultID)
: CStorageView(new CFlushableStorageKV(static_cast<CStorageKV&>(storage.GetStorage()))), height(height), txn(txn),
txid(txid), type(type), writers(writers), vaultID(vaultID)
{
}

Res CAccountsHistoryWriter::AddBalance(CScript const & owner, CTokenAmount amount)
{
auto res = CCustomCSView::AddBalance(owner, amount);
if (historyView && res.ok && amount.nValue != 0) {
diffs[owner][amount.nTokenId] += amount.nValue;
}
if (burnView && res.ok && amount.nValue != 0 && owner == Params().GetConsensus().burnAddress) {
burnDiffs[owner][amount.nTokenId] += amount.nValue;
if (writers && amount.nValue != 0 && res.ok) {
writers->AddBalance(owner, amount, vaultID);
}
return res;
}

Res CAccountsHistoryWriter::AddFeeBurn(CScript const & owner, CAmount amount)
{
if (burnView && amount != 0) {
burnDiffs[owner][DCT_ID{0}] += amount;
}
return Res::Ok();
return res;
}

Res CAccountsHistoryWriter::SubBalance(CScript const & owner, CTokenAmount amount)
{
auto res = CCustomCSView::SubBalance(owner, amount);
if (historyView && res.ok && amount.nValue != 0) {
diffs[owner][amount.nTokenId] -= amount.nValue;
}
if (burnView && res.ok && amount.nValue != 0 && owner == Params().GetConsensus().burnAddress) {
burnDiffs[owner][amount.nTokenId] -= amount.nValue;
if (writers && res.ok && amount.nValue != 0) {
writers->SubBalance(owner, amount, vaultID);
}

return res;
}

bool CAccountsHistoryWriter::Flush()
{
if (historyView) {
for (const auto& diff : diffs) {
historyView->WriteAccountHistory({diff.first, height, txn}, {txid, type, diff.second});
}
}
if (burnView) {
for (const auto& diff : burnDiffs) {
burnView->WriteAccountHistory({diff.first, height, txn}, {txid, type, diff.second});
}
if (writers) {
writers->Flush(height, txid, txn, type);
}
return CCustomCSView::Flush();
}

CAccountsHistoryEraser::CAccountsHistoryEraser(CCustomCSView & storage, uint32_t height, uint32_t txn, CAccountsHistoryView* historyView, CAccountsHistoryView* burnView)
: CStorageView(new CFlushableStorageKV(static_cast<CStorageKV&>(storage.GetStorage()))), height(height), txn(txn), historyView(historyView), burnView(burnView)
CAccountsHistoryEraser::CAccountsHistoryEraser(CCustomCSView & storage, uint32_t height, uint32_t txn, CHistoryErasers& erasers, const uint256& vaultID)
: CStorageView(new CFlushableStorageKV(static_cast<CStorageKV&>(storage.GetStorage()))), height(height), txn(txn),
erasers(erasers), vaultID(vaultID)
{
}

Res CAccountsHistoryEraser::AddBalance(CScript const & owner, CTokenAmount)
{
if (historyView) {
accounts.insert(owner);
}
if (burnView && owner == Params().GetConsensus().burnAddress) {
burnAccounts.insert(owner);
}
erasers.AddBalance(owner, vaultID);
return Res::Ok();
}

Res CAccountsHistoryEraser::SubBalance(CScript const & owner, CTokenAmount)
{
erasers.SubBalance(owner, vaultID);
return Res::Ok();
}

bool CAccountsHistoryEraser::Flush()
{
erasers.Flush(height, txn);
return Res::Ok(); // makes sure no changes are applyed to underlaying view
}

CHistoryErasers::CHistoryErasers(CAccountHistoryStorage* historyView, CBurnHistoryStorage* burnView, CVaultHistoryStorage* vaultView)
: historyView(historyView), burnView(burnView), vaultView(vaultView) {}

void CHistoryErasers::AddBalance(const CScript& owner, const uint256& vaultID)
{
if (historyView) {
accounts.insert(owner);
}
if (burnView && owner == Params().GetConsensus().burnAddress) {
burnAccounts.insert(owner);
}
return Res::Ok();
if (vaultView && !vaultID.IsNull()) {
vaults.insert(vaultID);
}
}

Res CAccountsHistoryEraser::SubFeeBurn(CScript const & owner)
void CHistoryErasers::SubFeeBurn(const CScript& owner)
{
if (burnView) {
burnAccounts.insert(owner);
}
return Res::Ok();
}

bool CAccountsHistoryEraser::Flush()
void CHistoryErasers::SubBalance(const CScript& owner, const uint256& vaultID)
{
if (historyView) {
accounts.insert(owner);
}
if (burnView && owner == Params().GetConsensus().burnAddress) {
burnAccounts.insert(owner);
}
if (vaultView && !vaultID.IsNull()) {
vaults.insert(vaultID);
}
}

void CHistoryErasers::Flush(const uint32_t height, const uint32_t txn)
{
if (historyView) {
for (const auto& account : accounts) {
Expand All @@ -133,7 +142,68 @@ bool CAccountsHistoryEraser::Flush()
burnView->EraseAccountHistory({account, height, txn});
}
}
return Res::Ok(); // makes sure no changes are applyed to underlaying view
if (vaultView) {
for (const auto& vault : vaults) {
vaultView->EraseVaultHistory({vault, height, txn});
}
}
}

CHistoryWriters::CHistoryWriters(CAccountHistoryStorage* historyView, CBurnHistoryStorage* burnView, CVaultHistoryStorage* vaultView)
: historyView(historyView), burnView(burnView), vaultView(vaultView) {}

void CHistoryWriters::AddBalance(const CScript& owner, const CTokenAmount amount, const uint256& vaultID)
{
if (historyView) {
diffs[owner][amount.nTokenId] += amount.nValue;
}
if (burnView && owner == Params().GetConsensus().burnAddress) {
burnDiffs[owner][amount.nTokenId] += amount.nValue;
}
if (vaultView && !vaultID.IsNull()) {
vaultDiffs[vaultID][owner][amount.nTokenId] += amount.nValue;
}
}

void CHistoryWriters::AddFeeBurn(const CScript& owner, const CAmount amount)
{
if (burnView && amount != 0) {
burnDiffs[owner][DCT_ID{0}] += amount;
}
}

void CHistoryWriters::SubBalance(const CScript& owner, const CTokenAmount amount, const uint256& vaultID)
{
if (historyView) {
diffs[owner][amount.nTokenId] -= amount.nValue;
}
if (burnView && owner == Params().GetConsensus().burnAddress) {
burnDiffs[owner][amount.nTokenId] -= amount.nValue;
}
if (vaultView && !vaultID.IsNull()) {
vaultDiffs[vaultID][owner][amount.nTokenId] -= amount.nValue;
}
}

void CHistoryWriters::Flush(const uint32_t height, const uint256& txid, const uint32_t txn, const uint8_t type)
{
if (historyView) {
for (const auto& diff : diffs) {
historyView->WriteAccountHistory({diff.first, height, txn}, {txid, type, diff.second});
}
}
if (burnView) {
for (const auto& diff : burnDiffs) {
burnView->WriteAccountHistory({diff.first, height, txn}, {txid, type, diff.second});
}
}
if (vaultView) {
for (const auto& diff : vaultDiffs) {
for (const auto& addresses : diff.second) {
vaultView->WriteVaultHistory({diff.first, height, txn, addresses.first}, {txid, type, addresses.second});
}
}
}
}

std::unique_ptr<CAccountHistoryStorage> paccountHistoryDB;
Expand Down
58 changes: 46 additions & 12 deletions src/masternodes/accountshistory.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
#include <script/script.h>
#include <uint256.h>

class CVaultHistoryView;
class CVaultHistoryStorage;

struct AccountHistoryKey {
CScript owner;
uint32_t blockHeight;
Expand Down Expand Up @@ -77,39 +80,70 @@ class CBurnHistoryStorage : public CAccountsHistoryView
CBurnHistoryStorage(const fs::path& dbName, std::size_t cacheSize, bool fMemory = false, bool fWipe = false);
};

class CHistoryWriters {
CAccountHistoryStorage* historyView;
CBurnHistoryStorage* burnView;
CVaultHistoryStorage* vaultView;
std::map<CScript, TAmounts> diffs;
std::map<CScript, TAmounts> burnDiffs;
std::map<uint256, std::map<CScript,TAmounts>> vaultDiffs;

public:
CHistoryWriters(CAccountHistoryStorage* historyView, CBurnHistoryStorage* burnView, CVaultHistoryStorage* vaultView);

void AddBalance(const CScript& owner, const CTokenAmount amount, const uint256& vaultID);
void AddFeeBurn(const CScript& owner, const CAmount amount);
void SubBalance(const CScript& owner, const CTokenAmount amount, const uint256& vaultID);
void Flush(const uint32_t height, const uint256& txid, const uint32_t txn, const uint8_t type);
};

class CHistoryErasers {
CAccountHistoryStorage* historyView;
CBurnHistoryStorage* burnView;
CVaultHistoryStorage* vaultView;
std::set<CScript> accounts;
std::set<CScript> burnAccounts;
std::set<uint256> vaults;

public:
CHistoryErasers(CAccountHistoryStorage* historyView, CBurnHistoryStorage* burnView, CVaultHistoryStorage* vaultView);

void AddBalance(const CScript& owner, const uint256& vaultID);
void SubFeeBurn(const CScript& owner);
void SubBalance(const CScript& owner, const uint256& vaultID);
void Flush(const uint32_t height, const uint32_t txn);
};

class CAccountsHistoryWriter : public CCustomCSView
{
const uint32_t height;
const uint32_t txn;
const uint256 txid;
const uint8_t type;
std::map<CScript, TAmounts> diffs;
std::map<CScript, TAmounts> burnDiffs;
CAccountsHistoryView* historyView;
CAccountsHistoryView* burnView;
CHistoryWriters* writers;

public:
CAccountsHistoryWriter(CCustomCSView & storage, uint32_t height, uint32_t txn, const uint256& txid, uint8_t type, CAccountsHistoryView* historyView, CAccountsHistoryView* burnView);
uint256 vaultID;

CAccountsHistoryWriter(CCustomCSView & storage, uint32_t height, uint32_t txn, const uint256& txid, uint8_t type,
CHistoryWriters* writers, const uint256& vaultID = uint256());
Res AddBalance(CScript const & owner, CTokenAmount amount) override;
Res SubBalance(CScript const & owner, CTokenAmount amount) override;
Res AddFeeBurn(CScript const & owner, CAmount amount);
bool Flush();
};

class CAccountsHistoryEraser : public CCustomCSView
{
const uint32_t height;
const uint32_t txn;
std::set<CScript> accounts;
std::set<CScript> burnAccounts;
CAccountsHistoryView* historyView;
CAccountsHistoryView* burnView;
CHistoryErasers& erasers;

public:
CAccountsHistoryEraser(CCustomCSView & storage, uint32_t height, uint32_t txn, CAccountsHistoryView* historyView, CAccountsHistoryView* burnView);
uint256 vaultID;

CAccountsHistoryEraser(CCustomCSView & storage, uint32_t height, uint32_t txn, CHistoryErasers& erasers, const uint256& vaultID = uint256());
Res AddBalance(CScript const & owner, CTokenAmount amount) override;
Res SubBalance(CScript const & owner, CTokenAmount amount) override;
Res SubFeeBurn(CScript const & owner);
bool Flush();
};

Expand Down
10 changes: 10 additions & 0 deletions src/masternodes/masternodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,16 @@ class CCollateralLoans { // in USD

uint32_t ratio() const;
CAmount precisionRatio() const;

ADD_SERIALIZE_METHODS;

template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(totalCollaterals);
READWRITE(totalLoans);
READWRITE(collaterals);
READWRITE(loans);
}
};

template<typename T>
Expand Down
Loading