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 time_buckets to EarningsTracker data #228

Closed
331 changes: 310 additions & 21 deletions Boss/Mod/EarningsTracker.cpp

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion Boss/Mod/EarningsTracker.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef BOSS_MOD_EARNINGSTRACKER_HPP
#define BOSS_MOD_EARNINGSTRACKER_HPP

#include"Ev/now.hpp"
#include<functional>
#include<memory>

namespace S { class Bus; }
Expand Down Expand Up @@ -28,7 +30,10 @@ class EarningsTracker {
~EarningsTracker();

explicit
EarningsTracker(S::Bus& bus);
EarningsTracker(S::Bus& bus, std::function<double()> get_now_ = &Ev::now);

// exposed for unit testing, otherwise internal
static double bucket_time(double input_time);
};

}}
Expand Down
53 changes: 53 additions & 0 deletions Jsmn/Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,59 @@ Detail::Iterator Object::end() const {
return pimpl->end();
}

Object Object::parse_json(char const* txt) {
auto is = std::istringstream(std::string(txt));
auto js = Jsmn::Object();
is >> js;
return js;
}

bool Object::operator==(Object const& other) const {
if (this == &other) {
return true;
}

// Compare types first
if (is_null() != other.is_null() || is_boolean() != other.is_boolean() ||
is_string() != other.is_string() || is_object() != other.is_object() ||
is_array() != other.is_array() || is_number() != other.is_number()) {
return false;
}

// Compare values based on type
if (is_null()) {
return true; // Both are null
} else if (is_boolean()) {
return static_cast<bool>(*this) == static_cast<bool>(other);
} else if (is_string()) {
return static_cast<std::string>(*this) == static_cast<std::string>(other);
} else if (is_number()) {
return static_cast<double>(*this) == static_cast<double>(other);
} else if (is_object()) {
if (size() != other.size()) {
return false;
}
for (const auto& key : keys()) {
if (!other.has(key) || (*this)[key] != other[key]) {
return false;
}
}
return true;
} else if (is_array()) {
if (size() != other.size()) {
return false;
}
for (std::size_t i = 0; i < size(); ++i) {
if ((*this)[i] != other[i]) {
return false;
}
}
return true;
}

return false; // Fallback, should not reach here
}

/* Implements indented printing. */
namespace {

Expand Down
7 changes: 7 additions & 0 deletions Jsmn/Object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class Object {
Object& operator=(Object const&) =default;
Object& operator=(Object&&) =default;

static Object parse_json(char const* txt);

/* Type queries on the object. */
bool is_null() const;
bool is_boolean() const;
Expand Down Expand Up @@ -69,6 +71,11 @@ class Object {
Object operator[](std::size_t) const; /* Return null if out-of-range. */
/* TODO: Iterator. */

bool operator==(Object const& other) const;
bool operator!=(Object const& other) const {
return !(*this == other);
}

/* Formal factory. */
friend class ParserExposedBuffer;
/* Iterator type. */
Expand Down
4 changes: 4 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,7 @@ TESTS = \
tests/boss/test_channelcreator_rearrangerbysize \
tests/boss/test_channelcreator_reprioritizer \
tests/boss/test_earningsrebalancer \
tests/boss/test_earningstracker \
tests/boss/test_feemodderbypricetheory \
tests/boss/test_forwardfeemonitor \
tests/boss/test_getmanifest \
Expand All @@ -598,6 +599,8 @@ TESTS = \
tests/boss/test_needsconnectsolicitor \
tests/boss/test_onchainfeemonitor_samples_init \
tests/boss/test_peerjudge_agetracker \
tests/boss/test_recentearnings \
tests/boss/test_earningshistory \
tests/boss/test_peerjudge_algo \
tests/boss/test_peerjudge_datagatherer \
tests/boss/test_peerstatistician \
Expand All @@ -621,6 +624,7 @@ TESTS = \
tests/ev/test_semaphore \
tests/ev/test_throw_in_then \
tests/graph/test_dijkstra \
tests/jsmn/test_equality \
tests/jsmn/test_iterator \
tests/jsmn/test_parser \
tests/jsmn/test_performance \
Expand Down
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,36 @@ Earlier versions do not record, so if you have been using CLBOSS
before 0.11D, then historical offchain-to-onchain swaps are not
reported.

### `clboss-recent-earnings`, `clboss-earnings-history`

As of CLBOSS version [TBD], earnings and expenditures are tracked on a daily basis.
The following commands have been added to observe the new data:

- **`clboss-recent-earnings`**:
- **Purpose**: Returns a data structure equivalent to the
`offchain_earnings_tracker` collection in `clboss-status`, but
only includes recent earnings and expenditures.
- **Arguments**:
- `days` (optional): Specifies the number of days to include in
the report. Defaults to a fortnight (14 days) if not provided.

- **`clboss-earnings-history`**:
- **Purpose**: Provides a daily breakdown of earnings and expenditures.
- **Arguments**:
- `nodeid` (optional): Limits the history to a particular node if
provided. Without this argument, the values are accumulated
across all peers.
- **Output**:
- The history consists of an array of records showing the earnings
and expenditures for each day.
- The history includes an initial record with a time value of 0,
which contains any legacy earnings and expenditures collected by
CLBOSS before daily tracking was implemented.

These commands enhance the tracking of financial metrics, allowing for
detailed and recent analysis of earnings and expenditures on a daily
basis.

### `--clboss-min-onchain=<satoshis>`

Pass this option to `lightningd` in order to specify a target
Expand Down
14 changes: 14 additions & 0 deletions Util/Either.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define UTIL_EITHER_HPP

#include<cstdint>
#include<iostream>
#include<utility>

namespace Util {
Expand Down Expand Up @@ -225,6 +226,19 @@ bool operator<=(Util::Either<L,R> const& a, Util::Either<L,R> const& b) {
return !(b < a);
}

template<typename L, typename R>
std::ostream& operator<<(std::ostream& os, const Either<L, R>& either) {
either.cmatch(
[&](const L& l) {
os << "Left(" << l << ")";
},
[&](const R& r) {
os << "Right(" << r << ")";
}
);
return os;
}

} // namespace Util

#endif /* !defined(UTIL_EITHER_HPP) */
10 changes: 10 additions & 0 deletions tests/boss/test_availablerpccommandsannouncer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ auto const help = std::string(R"JSON(
, { "command": "clboss-unmanage nodeid tags"
, "category": "plugin"
}
, { "command": "clboss-recent-earnings [days]"
, "category": "plugin"
}
, { "command": "clboss-earnings-history [nodeid]"
, "category": "plugin"
}
]
}
)JSON");
Expand Down Expand Up @@ -73,6 +79,10 @@ int main() {
assert(commands["clboss-status"].usage == "");
assert(commands["clboss-ignore-onchain"].usage == "[hours]");
assert(commands["clboss-unmanage"].usage == "nodeid tags");
assert(commands.count("clboss-recent-earnings") != 0);
assert(commands["clboss-recent-earnings"].usage == "[days]");
assert(commands.count("clboss-earnings-history") != 0);
assert(commands["clboss-earnings-history"].usage == "[nodeid]");

return Ev::lift();
});
Expand Down
Loading
Loading