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 interrupt-block, stop-block, refactor stats, explicit validity checks #1261

Merged
merged 22 commits into from
May 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
dd2c9f4
Token Lock
Bushstar May 13, 2022
7423960
Token Split
Bushstar May 17, 2022
e327801
Fix setting ATTRIBUTES by Gov height
Bushstar May 17, 2022
b980af0
Move loan and collateral token to Gov var
Bushstar May 18, 2022
0d6f7b9
Move FCR to GW
Bushstar May 18, 2022
449f287
tests: remove redundant line
Bushstar May 18, 2022
bdc2d35
Merge branch 'master' into token-splits-port
Bushstar May 22, 2022
3025805
Set time in attrs when applying by height
Bushstar May 22, 2022
9ede7a7
Token split support multiple pool and pool created in the block
Bushstar May 22, 2022
f1fdc8c
Migrate all keys on token split
Bushstar May 22, 2022
045b836
Do not fail when vault has interest but no loan tokens
Bushstar May 22, 2022
45d386b
Return false on error from get internal price
Bushstar May 22, 2022
db06a56
tests: Update error text
Bushstar May 22, 2022
651a1a4
Add SetValue and EraseKey to attrs
Bushstar May 22, 2022
92dd59c
Merge branch 'master' into token-splits-port
prasannavl May 22, 2022
48f01ee
Add interrupt-block, refactor stats, explicit validity checks
prasannavl May 22, 2022
5288304
Add interrupt block to lint
prasannavl May 22, 2022
51d293b
Add stop-block, refactor logic, fix lints
prasannavl May 22, 2022
9e33b92
Swap order of stop and interrupt
prasannavl May 22, 2022
3dcd5dd
Merge branch 'master' into pvl/master_post_split_finishes
prasannavl May 23, 2022
fea0b90
Update init.cpp
prasannavl May 23, 2022
06c07c1
Merge branch 'master' into pvl/master_post_split_finishes
prasannavl May 23, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ src/univalue/gen
Makefile
!depends/Makefile
background.tiff*
configure~

# Qt Creator
Makefile.am.user
Expand Down
37 changes: 34 additions & 3 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ void SetupServerArgs()

// Hidden Options
std::vector<std::string> hidden_args = {
"-dbcrashratio", "-forcecompactdb",
"-dbcrashratio", "-forcecompactdb", "-interrupt-block=<hash|height>", "-stop-block=<hash|height>",
// GUI args. These will be overwritten by SetupUIArgs for the GUI
"-choosedatadir", "-lang=<lang>", "-min", "-resetguisettings", "-splash"};

Expand Down Expand Up @@ -809,6 +809,8 @@ static bool InitSanityCheck()

static bool AppInitServers()
{
if (!gArgs.GetBoolArg("-rpcstats", DEFAULT_RPC_STATS))
statsRPC.setActive(false);
RPCServer::OnStarted(&OnRPCStarted);
RPCServer::OnStopped(&OnRPCStopped);
if (!InitHTTPServer())
Expand Down Expand Up @@ -1285,6 +1287,34 @@ void SetupAnchorSPVDatabases(bool resync) {
}
}

bool SetupInterruptArg(const std::string &argName, std::string &hashStore, int &heightStore) {
// Experimental: Block height or hash to invalidate on and stop sync
auto val = gArgs.GetArg(argName, "");
auto flagName = argName.substr(1);
if (val.empty())
return false;
if (val.size() == 64) {
hashStore = val;
LogPrintf("flag: %s hash: %s\n", flagName, hashStore);
} else {
std::stringstream ss(val);
ss >> heightStore;
if (heightStore) {
LogPrintf("flag: %s height: %d\n", flagName, heightStore);
} else {
LogPrintf("%s: invalid hash or height provided: %s\n", flagName, val);
}
}
return true;
}

void SetupInterrupts() {
auto isSet = false;
isSet = SetupInterruptArg("-interrupt-block", fInterruptBlockHash, fInterruptBlockHeight) || isSet;
isSet = SetupInterruptArg("-stop-block", fStopBlockHash, fStopBlockHeight) || isSet;
fStopOrInterrupt = isSet;
}

bool AppInitMain(InitInterfaces& interfaces)
{
const CChainParams& chainparams = Params();
Expand Down Expand Up @@ -1500,6 +1530,9 @@ bool AppInitMain(InitInterfaces& interfaces)
nMaxOutboundLimit = gArgs.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET)*1024*1024;
}

// Setup interrupts
SetupInterrupts();

// ********************************************************* Step 7: load block chain

fReindex = gArgs.GetBoolArg("-reindex", false);
Expand Down Expand Up @@ -2069,7 +2102,5 @@ bool AppInitMain(InitInterfaces& interfaces)
));
}

if (!gArgs.GetBoolArg("-rpcstats", DEFAULT_RPC_STATS)) statsRPC.setActive(false);

return true;
}
31 changes: 24 additions & 7 deletions src/masternodes/mn_checks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4239,21 +4239,38 @@ Res SwapToDFIOverUSD(CCustomCSView & mnview, DCT_ID tokenId, CAmount amount, CS
bool IsVaultPriceValid(CCustomCSView& mnview, const CVaultId& vaultId, uint32_t height)
{
if (auto collaterals = mnview.GetVaultCollaterals(vaultId))
for (const auto& collateral : collaterals->balances)
if (auto collateralToken = mnview.HasLoanCollateralToken({collateral.first, height}))
if (auto fixedIntervalPrice = mnview.GetFixedIntervalPrice(collateralToken->fixedIntervalPriceId))
if (!fixedIntervalPrice.val->isLive(mnview.GetPriceDeviation()))
for (const auto& collateral : collaterals->balances) {
if (auto collateralToken = mnview.HasLoanCollateralToken({collateral.first, height})) {
if (auto fixedIntervalPrice = mnview.GetFixedIntervalPrice(collateralToken->fixedIntervalPriceId)) {
if (!fixedIntervalPrice.val->isLive(mnview.GetPriceDeviation())) {
return false;
}
} else {
// No fixed interval prices available. Should not have happened.
return false;
}
} else {
// Not a collateral token. Should not have happened.
return false;
}
}

if (auto loans = mnview.GetLoanTokens(vaultId))
for (const auto& loan : loans->balances)
if (auto loanToken = mnview.GetLoanTokenByID(loan.first))
for (const auto& loan : loans->balances) {
if (auto loanToken = mnview.GetLoanTokenByID(loan.first)) {
if (auto fixedIntervalPrice = mnview.GetFixedIntervalPrice(loanToken->fixedIntervalPriceId)) {
if (!fixedIntervalPrice.val->isLive(mnview.GetPriceDeviation()))
if (!fixedIntervalPrice.val->isLive(mnview.GetPriceDeviation())) {
return false;
}
} else {
// No fixed interval prices available. Should not have happened.
return false;
}
} else {
// Not a loan token. Should not have happened.
return false;
}
}
return true;
}

Expand Down
48 changes: 47 additions & 1 deletion src/rpc/stats.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,54 @@
#include <rpc/stats.h>

#include <rpc/server.h>
#include <rpc/util.h>

bool CRPCStats::isActive() { return active.load(); }
void CRPCStats::setActive(bool isActive) { active.store(isActive); }

std::optional<RPCStats> CRPCStats::get(const std::string& name) {
CLockFreeGuard lock(lock_stats);

auto it = map.find(name);
if (it == map.end()) {
return {};
}
return it->second;
}

std::map<std::string, RPCStats> CRPCStats::getMap() {
CLockFreeGuard lock(lock_stats);
return map;
}

void CRPCStats::save() {
fs::path statsPath = GetDataDir() / DEFAULT_STATSFILE;
fsbridge::ofstream file(statsPath);

file << toJSON().write() << '\n';
file.close();
}

void CRPCStats::load() {
fs::path statsPath = GetDataDir() / DEFAULT_STATSFILE;
fsbridge::ifstream file(statsPath);
if (!file.is_open()) return;

std::string line;
file >> line;

if (!line.size()) return;

UniValue arr(UniValue::VARR);
arr.read((const std::string)line);

CLockFreeGuard lock(lock_stats);
for (const auto &val : arr.getValues()) {
auto name = val["name"].get_str();
map[name] = RPCStats::fromJSON(val);
}
file.close();
}

UniValue RPCStats::toJSON() {
UniValue stats(UniValue::VOBJ),
latencyObj(UniValue::VOBJ),
Expand Down
65 changes: 11 additions & 54 deletions src/rpc/stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <univalue.h>
#include <util/time.h>
#include <util/system.h>

#include <optional>
#include <boost/circular_buffer.hpp>

const char * const DEFAULT_STATSFILE = "stats.log";
Expand Down Expand Up @@ -39,9 +39,10 @@ struct RPCStats {

RPCStats() : history(RPC_STATS_HISTORY_SIZE) {}

RPCStats(const std::string& name, int64_t latency, int64_t payload) : name(name), latency(latency), payload(payload), history(RPC_STATS_HISTORY_SIZE) {
lastUsedTime = GetSystemTimeInSeconds();
count = 1;
RPCStats(const std::string& name, int64_t latency, int64_t payload) :
name(name), latency(latency), payload(payload), history(RPC_STATS_HISTORY_SIZE) {
lastUsedTime = GetSystemTimeInSeconds();
count = 1;
};

UniValue toJSON();
Expand All @@ -59,58 +60,14 @@ class CRPCStats
std::atomic_bool active{DEFAULT_RPC_STATS};

public:
bool isActive() {
return active.load();
}
void setActive(bool isActive) {
active.store(isActive);
}

bool isActive();
void setActive(bool isActive);
void add(const std::string& name, const int64_t latency, const int64_t payload);

std::optional<RPCStats> get(const std::string& name) {
CLockFreeGuard lock(lock_stats);

auto it = map.find(name);
if (it == map.end()) {
return {};
}
return it->second;
};
std::map<std::string, RPCStats> getMap() {
CLockFreeGuard lock(lock_stats);
return map;
};
std::optional<RPCStats> get(const std::string& name);
std::map<std::string, RPCStats> getMap();
UniValue toJSON();

void save() {
fs::path statsPath = GetDataDir() / DEFAULT_STATSFILE;
fsbridge::ofstream file(statsPath);

file << toJSON().write() << '\n';
file.close();
};

void load() {
fs::path statsPath = GetDataDir() / DEFAULT_STATSFILE;
fsbridge::ifstream file(statsPath);
if (!file.is_open()) return;

std::string line;
file >> line;

if (!line.size()) return;

UniValue arr(UniValue::VARR);
arr.read((const std::string)line);

CLockFreeGuard lock(lock_stats);
for (const auto &val : arr.getValues()) {
auto name = val["name"].get_str();
map[name] = RPCStats::fromJSON(val);
}
file.close();
};
void save();
void load();
};

extern CRPCStats statsRPC;
Expand Down
39 changes: 38 additions & 1 deletion src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,13 @@ bool fHavePruned = false;
bool fPruneMode = false;
bool fRequireStandard = true;
bool fCheckBlockIndex = false;

bool fStopOrInterrupt = false;
std::string fInterruptBlockHash = "";
int fInterruptBlockHeight = 0;
std::string fStopBlockHash = "";
int fStopBlockHeight = 0;

size_t nCoinCacheUsage = 5000 * 300;
size_t nCustomMemUsage = nDefaultDbCache << 10;
uint64_t nPruneTarget = 0;
Expand Down Expand Up @@ -2304,6 +2311,33 @@ bool ApplyGovVars(CCustomCSView& cache, const CBlockIndex& pindex, const std::ma
return false;
}

bool StopOrInterruptConnect(const CBlockIndex *pIndex, CValidationState& state) {
if (!fStopOrInterrupt)
return false;

const auto checkMatch = [](const CBlockIndex *index, const int height, const std::string& hash) {
return height == index->nHeight || (!hash.empty() && hash == index->phashBlock->ToString());
};

// Stop is processed first. So, if a block has both stop and interrupt
// stop will take priority.
if (checkMatch(pIndex, fStopBlockHeight, fStopBlockHash)) {
StartShutdown();
return true;
}

if (checkMatch(pIndex, fInterruptBlockHeight, fInterruptBlockHash)) {
state.Invalid(
ValidationInvalidReason::CONSENSUS,
error("ConnectBlock(): user interrupt"),
REJECT_INVALID,
"user-interrupt-request");
return true;
}

return false;
}

/** Apply the effects of this block (with given index) on the UTXO set represented by coins.
* Validity checks that depend on the UTXO set are also done; ConnectBlock()
* can fail if those validity checks fail (among other reasons). */
Expand All @@ -2315,6 +2349,10 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
assert(*pindex->phashBlock == block.GetHash());
int64_t nTimeStart = GetTimeMicros();

// Interrupt on hash or height requested. Invalidate the block.
if (StopOrInterruptConnect(pindex, state))
return false;

// Reset phanton TX to block TX count
nPhantomBurnTx = block.vtx.size();

Expand Down Expand Up @@ -4218,7 +4256,6 @@ void CChainState::ProcessTokenSplits(const CBlock& block, const CBlockIndex* pin
}

view.SetVariable(*attributes);

view.Flush();
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,13 @@ extern int nScriptCheckThreads;
extern bool fRequireStandard;
extern bool fCheckBlockIndex;
extern bool fCheckpointsEnabled;

extern bool fStopOrInterrupt;
extern std::string fInterruptBlockHash;
extern int fInterruptBlockHeight;
extern std::string fStopBlockHash;
extern int fStopBlockHeight;

extern size_t nCoinCacheUsage;
extern size_t nCustomMemUsage;
/** A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) */
Expand Down
2 changes: 1 addition & 1 deletion test/lint/check-doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
CMD_GREP_WALLET_HIDDEN_ARGS = r"git grep --function-context 'void DummyWalletInit::AddWalletOptions' -- {}".format(CMD_ROOT_DIR)
CMD_GREP_DOCS = r"git grep --perl-regexp '{}' {}".format(REGEX_DOC, CMD_ROOT_DIR)
# list unsupported, deprecated and duplicate args as they need no documentation
SET_DOC_OPTIONAL = set(['-h', '-help', '-dbcrashratio', '-forcecompactdb'])
SET_DOC_OPTIONAL = set(['-h', '-help', '-dbcrashratio', '-forcecompactdb', '-interrupt-block', '-stop-block'])


def lint_missing_argument_documentation():
Expand Down