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 the time we received and resolved a forwarding to listforwards #2528

Merged
merged 5 commits into from
Apr 10, 2019

Conversation

cdecker
Copy link
Member

@cdecker cdecker commented Apr 3, 2019

This adds a received_time timestamp to incoming HTLCs and adds both a received_time and resolved_timetimestamp to the channelforwarded_payments`. This allows us to see how long an HTLC was pending before it was resolved (with a granularity of seconds).

If desired we could probably change the granularity to milliseconds, but I wanted to try this first since #2491 only talks about an absolute time.

Fixes #2491

wallet/wallet.c Outdated
@@ -2594,6 +2611,8 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w,

cur->channel_in.u64 = sqlite3_column_int64(stmt, 4);
cur->channel_out.u64 = sqlite3_column_int64(stmt, 5);
cur->received_time = sqlite3_column_int64(stmt, 6);
cur->resolved_time = sqlite3_column_int64(stmt, 7);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! In the FORWARD_OFFERED case, we store resolved_time with NULL. There should handle this case.
BTW, may I ask you a question: what does FORWARD_OFFERED mean?

I'm trying to add local failcode #2524 , maybe I should add a new forward status: FORWARD_FAILED_LOCAL and also set resolved_time with NULL.

Copy link
Member Author

@cdecker cdecker Apr 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FORWARD_OFFERED means that the forward was received, and potentially forwarded, but wasn't resolved yet. The state machine looks like this:

FORWARD_OFFERED --------> FORWARD_SETTLED
                   \----> FORWARD_FAILED

FORWARD_OFFERED therefore is the initial state for all forwards, while FORWARD_SETTLED and FORWARD_FAILED are the terminal states for those. Hence we only set the resolved_time once we reach a terminal state.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your explain :)

Copy link
Collaborator

@m-schmoock m-schmoock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

concept ACK

There could be a simple testcase that does a chained routing of i.e. 10 hops (so the processing takes a bit longer than a second):

  1. After a payment the test could iterate through the chain and check that result of lxyz.rpc.listforwards() received_time and resolved_time is actually increasing or equal along the chain.
  2. On an intentionally failed payment somewhere along the route received_time is increasing but 'resolved_time' is epxceted to be (question:) not a number ? (see @trueptolemy 's comment)
  3. resolved_time should always >= received_time when status is settled
    ...

@@ -47,7 +47,7 @@ endif

ifeq ($(COMPAT),1)
# We support compatibility with pre-0.6.
COMPAT_CFLAGS=-DCOMPAT_V052=1 -DCOMPAT_V060=1 -DCOMPAT_V061=1 -DCOMPAT_V062=1
COMPAT_CFLAGS=-DCOMPAT_V052=1 -DCOMPAT_V060=1 -DCOMPAT_V061=1 -DCOMPAT_V062=1 -DCOMPAT_V070=1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I'm captain obvious, but the Makefile only sets these preprocessor variables if COMPAT is also 1. Currently, this causes a problem with Travis runner 3, where DCOMPAT_V070 is not defined at all: https://travis-ci.org/ElementsProject/lightning/jobs/515380339
Proposed solution (without being in the know of Travis internals and why it didnt fail for other COMPAT vairables):

ifeq ($(COMPAT),1)                                                                 
# We support compatibility with pre-0.6.                                           
COMPAT_CFLAGS=-DCOMPAT_V052=1 -DCOMPAT_V060=1 -DCOMPAT_V061=1 -DCOMPAT_V062=1 -DCOMPAT_V070=1
else
COMPAT_CFLAGS=-DCOMPAT_V052=0 -DCOMPAT_V060=0 -DCOMPAT_V061=0 -DCOMPAT_V062=0 -DCOMPAT_V070=0
endif

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, I added a fixup using #ifdef :-)

@@ -1902,6 +1902,17 @@ static void listforwardings_add_forwardings(struct json_stream *response, struct
cur->fee,
"fee", "fee_msat");
json_add_string(response, "status", forward_status_name(cur->status));
#if COMPAT_V070
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or change to, and do not set to 0 :D

#ifdef COMPAT_V070

@cdecker
Copy link
Member Author

cdecker commented Apr 4, 2019

On an intentionally failed payment somewhere along the route received_time is increasing but 'resolved_time' is epxceted to be (question:) not a number ? (see @trueptolemy 's comment)

I added an if-statement that only adds resolved_time once it was actually resolved, not 0 :-)

@m-schmoock
Copy link
Collaborator

ACK 10d749a (but squash the fixups)

@rustyrussell
Copy link
Contributor

nsec granularity please!

@m-schmoock
Copy link
Collaborator

nsec granularity please!

Yes, higher resolution would be better if we want to trace stuff in local test cases etc.
@rustyrussell Typo? milliseconds or nanoseconds?

@rustyrussell
Copy link
Contributor

It's fairly easy to have sub-microsecond network latency between peers, so I'd think that micro or nanoseconds are necessary. If we store in a 64 bit value as nanoseconds since 1970, we don't get in any trouble for another 200+ years anyway (500+ if we allow unsigned). But it's up to the implementer.

Copy link
Contributor

@rustyrussell rustyrussell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Time is hard". We should probably display the JSON as two fields: start in seconds (ie. 6 or 9 decimal places), and duration in seconds. But time isn't stable, and can go backwards, especially across reboots. So using received and resolved times is probably clearest.

@cdecker
Copy link
Member Author

cdecker commented Apr 8, 2019

Nanoseconds sounds excessive, but can do :-)

@cdecker
Copy link
Member Author

cdecker commented Apr 10, 2019

If we store in a 64 bit value as nanoseconds since 1970, we don't get in any trouble for another 200+ years anyway (500+ if we allow unsigned). But it's up to the implementer.

We are storing as u64 anyway, so that's not an issue. Just felt trivial to use ts.tv_sec directly. I'll change this to use nsec then ^^

The timestamps are UNIX-Timestamps with 3 decimal places, even though we have
the timestamp with nanosecond granularity. This is deliberate choice not to
over overload the users :-)

Signed-off-by: Christian Decker <[email protected]>
We'd like to display the receive and resolution times in the forwardings
table. In order to remember the receive time we need to store it in the DB
along with the other information.

Signed-off-by: Christian Decker <[email protected]>
@cdecker
Copy link
Member Author

cdecker commented Apr 10, 2019

Ok, rebased and squashed.

I also switched to storing the nsec timestamps in the DB (with some helpers) and display the timestamp with 3 significant digits in the JSON output.

Ping @rustyrussell and @m-schmoock 😉

@kristapsk
Copy link
Contributor

This allows also calculate fees earned in a specific time period, like lncli feereport which has day_fee_sum, week_fee_sum, month_fee_sum, if I understand it correctly (didn't test myself).

@cdecker
Copy link
Member Author

cdecker commented Apr 10, 2019

This allows also calculate fees earned in a specific time period, like lncli feereport which has day_fee_sum, week_fee_sum, month_fee_sum, if I understand it correctly (didn't test myself).

It should indeed, yes. Would you like to implement something like this? A neat little table channel x date_bucket seems like it could be nice.

@kristapsk
Copy link
Contributor

Yes, I could. You mean like a built-in feature or as a plug-in?

A neat little table channel x date_bucket seems like it could be nice.

You mean like not only total fees collected but also fees collected per channel?

Btw I already have a shell script, that calculates summaries for fees collected per channel. But so far I only could get total fees, not the fees in a specific time period.

@rustyrussell
Copy link
Contributor

BTW, our general philosophy should be to expose all the data, and let plugins sort it out. We have a few cases where we public summary data, and it's never quite the right thing, but we're committed to it for backwards compat reasons.

Copy link
Contributor

@rustyrussell rustyrussell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack 6013e53

@rustyrussell rustyrussell merged commit 27afc80 into ElementsProject:master Apr 10, 2019
@kristapsk
Copy link
Contributor

Doing it as a plugin was my first idea too and I will go that way unless somebody here tells me to do otherwise and integrate that functionality directly into C-lightning code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature Request: Include timestamp in channel_htlcs or forwarded_payments table
5 participants