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

Proper types for UNIX timestamps #1990

Merged
merged 15 commits into from
Oct 18, 2021
Merged

Proper types for UNIX timestamps #1990

merged 15 commits into from
Oct 18, 2021

Conversation

pm47
Copy link
Member

@pm47 pm47 commented Oct 5, 2021

We define TimestampSecond and TimestampMilli for second and millisecond precision UNIX-style timestamps.

Let me know what you think of the syntaxic sugar, I went for 123456 unix and 123456789 unixms.

Json serialization is as follows for resp. second and millisecond precision. Note that in both case we display the unix format in second precision, but the iso format is more precise:

{
  "iso": "2021-10-04T14:32:41Z",
  "unix": 1633357961
}
{
  "iso": "2021-10-04T14:32:41.456Z",
  "unix": 1633357961
}

@codecov-commenter
Copy link

codecov-commenter commented Oct 5, 2021

Codecov Report

Merging #1990 (e44d0d3) into master (c803da6) will increase coverage by 0.15%.
The diff coverage is 92.85%.

@@            Coverage Diff             @@
##           master    #1990      +/-   ##
==========================================
+ Coverage   87.59%   87.74%   +0.15%     
==========================================
  Files         159      160       +1     
  Lines       12444    12477      +33     
  Branches      525      549      +24     
==========================================
+ Hits        10900    10948      +48     
+ Misses       1544     1529      -15     
Impacted Files Coverage Δ
...r-core/src/main/scala/fr/acinq/eclair/Eclair.scala 42.46% <0.00%> (-6.57%) ⬇️
.../acinq/eclair/blockchain/bitcoind/ZmqWatcher.scala 88.13% <ø> (-1.87%) ⬇️
...ir/blockchain/bitcoind/rpc/BitcoinCoreClient.scala 94.23% <ø> (ø)
.../main/scala/fr/acinq/eclair/db/DualDatabases.scala 0.00% <ø> (ø)
...src/main/scala/fr/acinq/eclair/db/PaymentsDb.scala 92.85% <ø> (ø)
...in/scala/fr/acinq/eclair/io/ReconnectionTask.scala 97.82% <ø> (ø)
...n/scala/fr/acinq/eclair/json/JsonSerializers.scala 87.09% <ø> (ø)
.../eclair/payment/relay/PostRestartHtlcCleaner.scala 89.63% <ø> (-1.11%) ⬇️
...scala/fr/acinq/eclair/payment/send/Autoprobe.scala 0.00% <0.00%> (ø)
...ire/internal/channel/version0/ChannelCodecs0.scala 96.77% <ø> (ø)
... and 48 more

Copy link
Member Author

@pm47 pm47 left a comment

Choose a reason for hiding this comment

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

A few highlights to facilitate review.

}

object TimestampSecond {
def now: TimestampSecond = TimestampSecond(System.currentTimeMillis() / 1000)
Copy link
Member Author

Choose a reason for hiding this comment

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

This is mostly the only file now where we call System.currentTimeMillis(), apart from very few cases where it made sense to be as close to the JVM as possible (e.g. for the RNG) .

Copy link
Member

Choose a reason for hiding this comment

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

I think it should be:

Suggested change
def now: TimestampSecond = TimestampSecond(System.currentTimeMillis() / 1000)
def now(): TimestampSecond = TimestampSecond(System.currentTimeMillis() / 1000)

preimage_opt match {
// If we have a pre-image, the payment succeeded.
case Some(preimage) => OutgoingPaymentStatus.Succeeded(
preimage, fees_opt.getOrElse(MilliSatoshi(0)), paymentRoute_opt.map(b => paymentRouteCodec.decode(b) match {
case Attempt.Successful(route) => route.value
case Attempt.Failure(_) => Nil
}).getOrElse(Nil),
completedAt_opt.getOrElse(0)
completedAt_opt.getOrElse(0 unixms)
Copy link
Member Author

Choose a reason for hiding this comment

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

Example of unixms usage:

Suggested change
completedAt_opt.getOrElse(0 unixms)
completedAt_opt.getOrElse(0 unixms)

// BOLT 7: "nodes MAY prune channels should the timestamp of the latest channel_update be older than 2 weeks"
// but we don't want to prune brand new channels for which we didn't yet receive a channel update
val staleThresholdSeconds = (System.currentTimeMillis.milliseconds - 14.days).toSeconds
val staleThresholdSeconds = TimestampSecond.now - 14.days
Copy link
Member Author

Choose a reason for hiding this comment

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

😎

Comment on lines 71 to 72
val staleThreshold = TimestampSecond.now - 14.days
timestamp < staleThreshold
Copy link
Member Author

Choose a reason for hiding this comment

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

😎

Comment on lines 374 to 375
val timestamp1 = c.update_1_opt.map(_.timestamp).getOrElse(0L unix)
val timestamp2 = c.update_2_opt.map(_.timestamp).getOrElse(0L unix)
Copy link
Member Author

Choose a reason for hiding this comment

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

Example of unix usage.

@@ -352,7 +353,7 @@ private[channel] object ChannelCodecs0 {
val DATA_WAIT_FOR_FUNDING_CONFIRMED_COMPAT_01_Codec: Codec[DATA_WAIT_FOR_FUNDING_CONFIRMED] = (
("commitments" | commitmentsCodec) ::
("fundingTx" | provide[Option[Transaction]](None)) ::
("waitingSince" | provide(System.currentTimeMillis.milliseconds.toSeconds)) ::
("waitingSince" | provide(TimestampSecond.now.toLong)) ::
Copy link
Member Author

Choose a reason for hiding this comment

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

Please review carrefully.

@@ -69,6 +69,8 @@ object CommonCodecs {
// this codec will fail if the amount does not fit on 32 bits
val millisatoshi32: Codec[MilliSatoshi] = uint32.xmapc(l => MilliSatoshi(l))(_.toLong)

val timestampSecond: Codec[TimestampSecond] = uint32.xmapc(TimestampSecond(_))(_.toLong)
Copy link
Member Author

Choose a reason for hiding this comment

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

Codecs are now typed.

Copy link
Member Author

@pm47 pm47 left a comment

Choose a reason for hiding this comment

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

(continued)

Comment on lines 45 to 46
val fromFormParam: NameDefaultUnmarshallerReceptacle[TimestampSecond] = "from".as[TimestampSecond](timestampSecondUnmarshaller).?(0 unix)
val toFormParam: NameDefaultUnmarshallerReceptacle[TimestampSecond] = "to".as[TimestampSecond](timestampSecondUnmarshaller).?(Long.MaxValue unix)
Copy link
Member Author

Choose a reason for hiding this comment

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

Note how we provide a default value here now.

@@ -101,8 +101,8 @@ trait Channel {
}

val channelStats: Route = postRequest("channelstats") { implicit t =>
formFields(fromFormParam.?, toFormParam.?) { (from_opt, to_opt) =>
complete(eclairApi.channelStats(from_opt, to_opt))
formFields(fromFormParam, toFormParam) { (from, to) =>
Copy link
Member Author

Choose a reason for hiding this comment

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

Note how the param extractors return a non-optional value.

Copy link
Member

@t-bast t-bast left a comment

Choose a reason for hiding this comment

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

That must have been quite painful, thanks!
Worth integrating quickly to avoid lengthy merge/rebase IMO.

}

object TimestampSecond {
def now: TimestampSecond = TimestampSecond(System.currentTimeMillis() / 1000)
Copy link
Member

Choose a reason for hiding this comment

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

I think it should be:

Suggested change
def now: TimestampSecond = TimestampSecond(System.currentTimeMillis() / 1000)
def now(): TimestampSecond = TimestampSecond(System.currentTimeMillis() / 1000)

eclair-core/src/main/scala/fr/acinq/eclair/Timestamp.scala Outdated Show resolved Hide resolved
eclair-core/src/main/scala/fr/acinq/eclair/package.scala Outdated Show resolved Hide resolved
eclair-core/src/main/scala/fr/acinq/eclair/Eclair.scala Outdated Show resolved Hide resolved
t-bast
t-bast previously approved these changes Oct 18, 2021
Copy link
Member

@t-bast t-bast left a comment

Choose a reason for hiding this comment

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

🚀

@pm47 pm47 merged commit b4d285f into master Oct 18, 2021
@pm47 pm47 deleted the timestamp-types branch October 18, 2021 14:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants