Skip to content

Commit

Permalink
Refactor consensus with contract based predicates (#1644) (#1668)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bushstar authored Dec 24, 2022
1 parent d8465c6 commit 03d8ed0
Show file tree
Hide file tree
Showing 35 changed files with 1,290 additions and 2,301 deletions.
37 changes: 16 additions & 21 deletions src/amount.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,18 +92,16 @@ typedef std::map<DCT_ID, CAmount> TAmounts;

inline ResVal<CAmount> SafeAdd(CAmount _a, CAmount _b) {
// check limits
if (_a < 0 || _b < 0) {
return Res::Err("negative amount");
}
Require(_a >= 0 && _b >= 0, "negative amount");

// convert to unsigned, because signed overflow is UB
const uint64_t a = (uint64_t) _a;
const uint64_t b = (uint64_t) _b;

const uint64_t sum = a + b;
// check overflow
if ((sum - a) != b || ((uint64_t)std::numeric_limits<CAmount>::max()) < sum) {
return Res::Err("overflow");
}

Require((sum - a) == b && (uint64_t)std::numeric_limits<CAmount>::max() >= sum, "overflow");
return {(CAmount) sum, Res::Ok()};
}

Expand All @@ -127,29 +125,26 @@ struct CTokenAmount { // simple std::pair is less informative

Res Add(CAmount amount) {
// safety checks
if (amount < 0) {
return Res::Err("negative amount: %s", GetDecimaleString(amount));
}
Require(amount >= 0, "negative amount: %s", GetDecimaleString(amount));

// add
auto sumRes = SafeAdd(this->nValue, amount);
if (!sumRes.ok) {
return std::move(sumRes);
}
this->nValue = *sumRes.val;
auto sumRes = SafeAdd(nValue, amount);
Require(sumRes);

nValue = *sumRes;
return Res::Ok();
}

Res Sub(CAmount amount) {
// safety checks
if (amount < 0) {
return Res::Err("negative amount: %s", GetDecimaleString(amount));
}
if (this->nValue < amount) {
return Res::Err("amount %s is less than %s", GetDecimaleString(this->nValue), GetDecimaleString(amount));
}
Require(amount >= 0, "negative amount: %s", GetDecimaleString(amount));
Require(nValue >= amount, "amount %s is less than %s", GetDecimaleString(nValue), GetDecimaleString(amount));

// sub
this->nValue -= amount;
nValue -= amount;
return Res::Ok();
}

CAmount SubWithRemainder(CAmount amount) {
// safety checks
if (amount < 0) {
Expand Down
16 changes: 4 additions & 12 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1182,9 +1182,7 @@ void ClearCheckpoints(CChainParams &params) {

Res UpdateCheckpointsFromFile(CChainParams &params, const std::string &fileName) {
std::ifstream file(fileName);
if (!file.good()) {
return Res::Err("Could not read %s. Ensure it exists and has read permissions", fileName);
}
Require(file.good(), "Could not read %s. Ensure it exists and has read permissions", fileName);

ClearCheckpoints(params);

Expand All @@ -1196,19 +1194,13 @@ Res UpdateCheckpointsFromFile(CChainParams &params, const std::string &fileName)

std::istringstream iss(trimmed);
std::string hashStr, heightStr;
if (!(iss >> heightStr >> hashStr)) {
return Res::Err("Error parsing line %s", trimmed);
}
Require((iss >> heightStr >> hashStr), "Error parsing line %s", trimmed);

uint256 hash;
if (!ParseHashStr(hashStr, hash)) {
return Res::Err("Invalid hash: %s", hashStr);
}
Require(ParseHashStr(hashStr, hash), "Invalid hash: %s", hashStr);

int32_t height;
if (!ParseInt32(heightStr, &height)) {
return Res::Err("Invalid height: %s", heightStr);
}
Require(ParseInt32(heightStr, &height), "Invalid height: %s", heightStr);

params.checkpointData.mapCheckpoints[height] = hash;
}
Expand Down
48 changes: 12 additions & 36 deletions src/masternodes/accounts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@ Res CAccountsView::AddBalance(const CScript &owner, CTokenAmount amount) {
return Res::Ok();
}
auto balance = GetBalance(owner, amount.nTokenId);
auto res = balance.Add(amount.nValue);
if (!res.ok) {
return res;
}
Require(balance.Add(amount.nValue));
return SetBalance(owner, balance);
}

Expand All @@ -48,30 +45,21 @@ Res CAccountsView::SubBalance(const CScript &owner, CTokenAmount amount) {
return Res::Ok();
}
auto balance = GetBalance(owner, amount.nTokenId);
auto res = balance.Sub(amount.nValue);
if (!res.ok) {
return res;
}
Require(balance.Sub(amount.nValue));
return SetBalance(owner, balance);
}

Res CAccountsView::AddBalances(const CScript &owner, const CBalances &balances) {
for (const auto &kv : balances.balances) {
auto res = AddBalance(owner, CTokenAmount{kv.first, kv.second});
if (!res.ok) {
return res;
}
}
for (const auto &kv : balances.balances)
Require(AddBalance(owner, CTokenAmount{kv.first, kv.second}));

return Res::Ok();
}

Res CAccountsView::SubBalances(const CScript &owner, const CBalances &balances) {
for (const auto &kv : balances.balances) {
auto res = SubBalance(owner, CTokenAmount{kv.first, kv.second});
if (!res.ok) {
return res;
}
}
for (const auto &kv : balances.balances)
Require(SubBalance(owner, CTokenAmount{kv.first, kv.second}));

return Res::Ok();
}

Expand All @@ -92,10 +80,7 @@ uint32_t CAccountsView::GetBalancesHeight(const CScript &owner) {
}

Res CAccountsView::StoreFuturesUserValues(const CFuturesUserKey &key, const CFuturesUserValue &futures) {
if (!WriteBy<ByFuturesSwapKey>(key, futures)) {
return Res::Err("Failed to store futures");
}

Require(WriteBy<ByFuturesSwapKey>(key, futures), "Failed to store futures");
return Res::Ok();
}

Expand All @@ -106,18 +91,12 @@ void CAccountsView::ForEachFuturesUserValues(
}

Res CAccountsView::EraseFuturesUserValues(const CFuturesUserKey &key) {
if (!EraseBy<ByFuturesSwapKey>(key)) {
return Res::Err("Failed to erase futures");
}

Require(EraseBy<ByFuturesSwapKey>(key), "Failed to erase futures");
return Res::Ok();
}

Res CAccountsView::StoreFuturesDUSD(const CFuturesUserKey &key, const CAmount &amount) {
if (!WriteBy<ByFuturesDUSDKey>(key, amount)) {
return Res::Err("Failed to store futures");
}

Require(WriteBy<ByFuturesDUSDKey>(key, amount), "Failed to store futures");
return Res::Ok();
}

Expand All @@ -127,9 +106,6 @@ void CAccountsView::ForEachFuturesDUSD(std::function<bool(const CFuturesUserKey
}

Res CAccountsView::EraseFuturesDUSD(const CFuturesUserKey &key) {
if (!EraseBy<ByFuturesDUSDKey>(key)) {
return Res::Err("Failed to erase futures");
}

Require(EraseBy<ByFuturesDUSDKey>(key), "Failed to erase futures");
return Res::Ok();
}
34 changes: 14 additions & 20 deletions src/masternodes/balances.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,30 @@ struct CBalances {
return Res::Ok();
}
auto current = CTokenAmount{amount.nTokenId, balances[amount.nTokenId]};
auto res = current.Add(amount.nValue);
if (!res.ok) {
return res;
}
Require(current.Add(amount.nValue));
if (current.nValue == 0) {
balances.erase(amount.nTokenId);
} else {
balances[amount.nTokenId] = current.nValue;
}
return Res::Ok();
}

Res Sub(CTokenAmount amount) {
if (amount.nValue == 0) {
return Res::Ok();
}
auto current = CTokenAmount{amount.nTokenId, balances[amount.nTokenId]};
auto res = current.Sub(amount.nValue);
if (!res.ok) {
return res;
}
Require(current.Sub(amount.nValue));

if (current.nValue == 0) {
balances.erase(amount.nTokenId);
} else {
balances[amount.nTokenId] = current.nValue;
}
return Res::Ok();
}

CTokenAmount SubWithRemainder(CTokenAmount amount) {
if (amount.nValue == 0) {
return CTokenAmount{amount.nTokenId, 0};
Expand All @@ -58,15 +55,14 @@ struct CBalances {
}
return CTokenAmount{amount.nTokenId, remainder};
}

Res SubBalances(const TAmounts &other) {
for (const auto &kv : other) {
auto res = Sub(CTokenAmount{kv.first, kv.second});
if (!res.ok) {
return res;
}
}
for (const auto &[tokenId, amount] : other)
Require(Sub(CTokenAmount{tokenId, amount}));

return Res::Ok();
}

CBalances SubBalancesWithRemainder(const TAmounts &other) {
CBalances remainderBalances;
for (const auto &kv : other) {
Expand All @@ -77,13 +73,11 @@ struct CBalances {
}
return remainderBalances;
}

Res AddBalances(const TAmounts &other) {
for (const auto &kv : other) {
auto res = Add(CTokenAmount{kv.first, kv.second});
if (!res.ok) {
return res;
}
}
for (const auto &[tokenId, amount] : other)
Require(Add(CTokenAmount{tokenId, amount}));

return Res::Ok();
}

Expand Down
Loading

0 comments on commit 03d8ed0

Please sign in to comment.