Skip to content

Commit

Permalink
Use Timestamp instead of Instant (#11356)
Browse files Browse the repository at this point in the history
changelog_begin
changelog_end
  • Loading branch information
rautenrieth-da authored Oct 26, 2021
1 parent ea5f09e commit 3587eb8
Show file tree
Hide file tree
Showing 40 changed files with 215 additions and 229 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ object Time {
addMicros(secondsInMicros + nanosecondsInMicros)
}

@throws[IllegalArgumentException]
def subtract(duration: Duration): Timestamp =
add(duration.negated())

@throws[IllegalArgumentException]
def addMicros(x: Long): Timestamp =
Timestamp.assertFromLong(micros + x)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

package com.daml.ledger.configuration

import java.time.{Duration, Instant}
import java.time.Duration

import com.daml.ledger.configuration.LedgerTimeModel._
import com.daml.lf.data.Time.Timestamp
Expand Down Expand Up @@ -32,36 +32,29 @@ case class LedgerTimeModel private (
* In particular, checks the skew condition: rt_TX - s_min <= lt_TX <= rt_TX + s_max.
*/
def checkTime(
ledgerTime: Instant,
recordTime: Instant,
ledgerTime: Timestamp,
recordTime: Timestamp,
): Either[OutOfRange, Unit] = {
val lowerBound = minLedgerTime(recordTime)
val upperBound = maxLedgerTime(recordTime)
if (ledgerTime.isBefore(lowerBound) || ledgerTime.isAfter(upperBound)) {
if (ledgerTime < lowerBound || ledgerTime > upperBound) {
Left(OutOfRange(ledgerTime, lowerBound, upperBound))
} else {
Right(())
}
}

def checkTime(
ledgerTime: Timestamp,
recordTime: Timestamp,
): Either[OutOfRange, Unit] = {
checkTime(ledgerTime.toInstant, recordTime.toInstant)
}

private[ledger] def minLedgerTime(recordTime: Instant): Instant =
recordTime.minus(minSkew)
private[ledger] def minLedgerTime(recordTime: Timestamp): Timestamp =
recordTime.subtract(minSkew)

private[ledger] def maxLedgerTime(recordTime: Instant): Instant =
recordTime.plus(maxSkew)
private[ledger] def maxLedgerTime(recordTime: Timestamp): Timestamp =
recordTime.add(maxSkew)

private[ledger] def minRecordTime(ledgerTime: Instant): Instant =
ledgerTime.minus(maxSkew)
private[ledger] def minRecordTime(ledgerTime: Timestamp): Timestamp =
ledgerTime.subtract(maxSkew)

private[ledger] def maxRecordTime(ledgerTime: Instant): Instant =
ledgerTime.plus(minSkew)
private[ledger] def maxRecordTime(ledgerTime: Timestamp): Timestamp =
ledgerTime.add(minSkew)
}

object LedgerTimeModel {
Expand All @@ -88,7 +81,7 @@ object LedgerTimeModel {
new LedgerTimeModel(avgTransactionLatency, minSkew, maxSkew)
}

final case class OutOfRange(ledgerTime: Instant, lowerBound: Instant, upperBound: Instant) {
final case class OutOfRange(ledgerTime: Timestamp, lowerBound: Timestamp, upperBound: Timestamp) {
lazy val message: String =
s"Ledger time $ledgerTime outside of range [$lowerBound, $upperBound]"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
package com.daml.ledger.configuration

import java.time._

import com.daml.ledger.configuration.LedgerTimeModel.OutOfRange
import com.daml.lf.data.Time.Timestamp
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec

class LedgerTimeModelSpec extends AnyWordSpec with Matchers {

private val referenceTime = Instant.EPOCH
private val referenceTime = Timestamp.Epoch
private val epsilon = Duration.ofMillis(10L)
private val defaultSkew = Duration.ofSeconds(30L)
private val timeModel =
Expand All @@ -32,43 +32,43 @@ class LedgerTimeModelSpec extends AnyWordSpec with Matchers {
}

"succeed if the ledger time is higher than the record time and is within tolerance limit" in {
val result = timeModel.checkTime(referenceTime.plus(epsilon), referenceTime)
val result = timeModel.checkTime(referenceTime.add(epsilon), referenceTime)

result should be(Right(()))
}

"succeed if the ledger time is equal to the high boundary" in {
val result = timeModel.checkTime(referenceTime.plus(timeModel.maxSkew), referenceTime)
val result = timeModel.checkTime(referenceTime.add(timeModel.maxSkew), referenceTime)

result should be(Right(()))
}

"fail if the ledger time is higher than the high boundary" in {
val ledgerTime = referenceTime.plus(timeModel.maxSkew).plus(epsilon)
val minRecordTime = referenceTime.minus(defaultSkew)
val maxRecordTime = referenceTime.plus(defaultSkew)
val ledgerTime = referenceTime.add(timeModel.maxSkew).add(epsilon)
val minRecordTime = referenceTime.subtract(defaultSkew)
val maxRecordTime = referenceTime.add(defaultSkew)

val result = timeModel.checkTime(ledgerTime, referenceTime)

result should be(Left(OutOfRange(ledgerTime, minRecordTime, maxRecordTime)))
}

"succeed if the ledger time is lower than the record time and is within tolerance limit" in {
val result = timeModel.checkTime(referenceTime.minus(epsilon), referenceTime)
val result = timeModel.checkTime(referenceTime.subtract(epsilon), referenceTime)

result should be(Right(()))
}

"succeed if the ledger time is equal to the low boundary" in {
val result = timeModel.checkTime(referenceTime.minus(timeModel.minSkew), referenceTime)
val result = timeModel.checkTime(referenceTime.subtract(timeModel.minSkew), referenceTime)

result should be(Right(()))
}

"fail if the ledger time is lower than the low boundary" in {
val ledgerTime = referenceTime.minus(timeModel.minSkew).minus(epsilon)
val minRecordTime = referenceTime.minus(defaultSkew)
val maxRecordTime = referenceTime.plus(defaultSkew)
val ledgerTime = referenceTime.subtract(timeModel.minSkew).subtract(epsilon)
val minRecordTime = referenceTime.subtract(defaultSkew)
val maxRecordTime = referenceTime.add(defaultSkew)

val result = timeModel.checkTime(ledgerTime, referenceTime)

Expand All @@ -78,25 +78,25 @@ class LedgerTimeModelSpec extends AnyWordSpec with Matchers {
"succeed if the ledger time is equal to the high boundary (asymmetric case)" in {
val instance = createAsymmetricTimeModel(minSkew = largeSkew, maxSkew = smallSkew)

val result = instance.checkTime(referenceTime.plus(instance.maxSkew), referenceTime)
val result = instance.checkTime(referenceTime.add(instance.maxSkew), referenceTime)

result should be(Right(()))
}

"succeed if the ledger time is equal to the low boundary (asymmetric case)" in {
val instance = createAsymmetricTimeModel(minSkew = smallSkew, maxSkew = largeSkew)

val result = instance.checkTime(referenceTime.minus(instance.minSkew), referenceTime)
val result = instance.checkTime(referenceTime.subtract(instance.minSkew), referenceTime)

result should be(Right(()))
}

"fail if the ledger time is higher than the high boundary (asymmetric case)" in {
val instance = createAsymmetricTimeModel(minSkew = largeSkew, maxSkew = smallSkew)

val ledgerTime = referenceTime.plus(instance.maxSkew).plus(epsilon)
val minRecordTime = referenceTime.minus(largeSkew)
val maxRecordTime = referenceTime.plus(smallSkew)
val ledgerTime = referenceTime.add(instance.maxSkew).add(epsilon)
val minRecordTime = referenceTime.subtract(largeSkew)
val maxRecordTime = referenceTime.add(smallSkew)

val result = instance.checkTime(ledgerTime, referenceTime)

Expand All @@ -106,9 +106,9 @@ class LedgerTimeModelSpec extends AnyWordSpec with Matchers {
"fail if the ledger time is lower than the low boundary (asymmetric case)" in {
val instance = createAsymmetricTimeModel(minSkew = smallSkew, maxSkew = largeSkew)

val ledgerTime = referenceTime.minus(instance.minSkew).minus(epsilon)
val minRecordTime = referenceTime.minus(smallSkew)
val maxRecordTime = referenceTime.plus(largeSkew)
val ledgerTime = referenceTime.subtract(instance.minSkew).subtract(epsilon)
val minRecordTime = referenceTime.subtract(smallSkew)
val maxRecordTime = referenceTime.add(largeSkew)

val result = instance.checkTime(ledgerTime, referenceTime)

Expand All @@ -122,10 +122,10 @@ class LedgerTimeModelSpec extends AnyWordSpec with Matchers {
maxSkew = Duration.ofSeconds(20L),
).get

val ledgerTime = Instant.parse("2000-01-01T12:00:00Z")
val recordTime = Instant.parse("2000-01-01T12:30:00Z")
val minRecordTime = Instant.parse("2000-01-01T12:29:50Z")
val maxRecordTime = Instant.parse("2000-01-01T12:30:20Z")
val ledgerTime = Timestamp.assertFromString("2000-01-01T12:00:00Z")
val recordTime = Timestamp.assertFromString("2000-01-01T12:30:00Z")
val minRecordTime = Timestamp.assertFromString("2000-01-01T12:29:50Z")
val maxRecordTime = Timestamp.assertFromString("2000-01-01T12:30:20Z")

val result = timeModel.checkTime(ledgerTime, recordTime)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

package com.daml.ledger.on.memory

import java.time.Instant

import com.daml.api.util.TimeProvider
import com.daml.caching.Cache
import com.daml.ledger.api.health.{HealthStatus, Healthy}
Expand All @@ -28,6 +26,7 @@ import com.daml.ledger.validator.preexecution.{
import com.daml.ledger.validator.reading.{DamlLedgerStateReader, LedgerStateReader}
import com.daml.ledger.validator.{SerializingStateReader, StateKeySerializationStrategy}
import com.daml.lf.data.Ref
import com.daml.lf.data.Time.Timestamp
import com.daml.lf.engine.Engine
import com.daml.metrics.Metrics
import com.daml.platform.akkastreams.dispatcher.Dispatcher
Expand All @@ -40,7 +39,7 @@ final class InMemoryLedgerWriter private[memory] (
override val participantId: Ref.ParticipantId,
dispatcher: Dispatcher[Index],
offsetBuilder: KVOffsetBuilder,
now: () => Instant,
now: () => Timestamp,
state: InMemoryState,
committer: Committer,
committerExecutionContext: ExecutionContext,
Expand Down Expand Up @@ -91,7 +90,7 @@ object InMemoryLedgerWriter {
engine: Engine,
committerExecutionContext: ExecutionContext,
) extends ResourceOwner[LedgerWriter] {
private val now = () => timeProvider.getCurrentTime
private val now = () => timeProvider.getCurrentTimestamp

override def acquire()(implicit context: ResourceContext): Resource[LedgerWriter] =
for {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@

package com.daml.ledger.on.memory

import java.time.Instant

import com.codahale.metrics.MetricRegistry
import com.daml.ledger.api.testing.utils.AkkaBeforeAndAfterAll
import com.daml.ledger.participant.state.kvutils.api.CommitMetadata
import com.daml.ledger.participant.state.kvutils.{KVOffsetBuilder, Raw}
import com.daml.ledger.participant.state.v2.SubmissionResult
import com.daml.ledger.validator.LedgerStateAccess
import com.daml.lf.data.Ref
import com.daml.lf.data.Time.Timestamp
import com.daml.metrics.Metrics
import com.daml.platform.akkastreams.dispatcher.Dispatcher
import com.daml.telemetry.{NoOpTelemetryContext, TelemetryContext}
Expand Down Expand Up @@ -42,7 +41,7 @@ class InMemoryLedgerWriterSpec
any[Ref.ParticipantId],
any[String],
any[Raw.Envelope],
any[Instant],
any[Timestamp],
any[LedgerStateAccess[Any]],
)(any[ExecutionContext])
)
Expand All @@ -53,7 +52,7 @@ class InMemoryLedgerWriterSpec
participantId = Ref.ParticipantId.assertFromString("participant ID"),
dispatcher = mockDispatcher,
offsetBuilder = new KVOffsetBuilder(0),
now = () => Instant.EPOCH,
now = () => Timestamp.Epoch,
state = InMemoryState.empty,
committer = mockCommitter,
committerExecutionContext = executionContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import com.daml.ledger.participant.state.kvutils.updates.TransactionRejections._
import com.daml.ledger.participant.state.v2.Update.CommandRejected.FinalReason
import com.daml.ledger.participant.state.v2.{CompletionInfo, SubmitterInfo}
import com.daml.lf.data.Relation.Relation
import com.daml.lf.data.Time.Timestamp
import com.daml.lf.data.{Ref, Time}
import com.daml.lf.transaction._
import com.daml.lf.value.Value.{ContractId, VersionedValue}
Expand Down Expand Up @@ -177,7 +178,7 @@ private[state] object Conversions {

@nowarn("msg=deprecated")
def parseCompletionInfo(
recordTime: Instant,
recordTime: Timestamp,
subInfo: DamlSubmitterInfo,
): CompletionInfo = {
val deduplicationPeriod = subInfo.getDeduplicationPeriodCase match {
Expand All @@ -196,7 +197,7 @@ private[state] object Conversions {
// As the deduplicate until timestamp is always relative to record time, we take the duration
// between record time and the previous timestamp as the deduplication period (duration).
val until = parseInstant(subInfo.getDeduplicateUntil)
val duration = Duration.between(recordTime, until).abs()
val duration = Duration.between(recordTime.toInstant, until).abs()
Some(
DeduplicationPeriod.DeduplicationDuration(duration)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ object KeyValueConsumption {
val reason = Conversions.decodeTransactionRejectionEntry(rejEntry, errorVersionSwitch)
Update.CommandRejected(
recordTime = recordTime,
completionInfo = parseCompletionInfo(parseInstant(recordTime), rejEntry.getSubmitterInfo),
completionInfo = parseCompletionInfo(recordTime, rejEntry.getSubmitterInfo),
reasonTemplate = reason,
)
}
Expand Down Expand Up @@ -281,7 +281,7 @@ object KeyValueConsumption {
Update.TransactionAccepted(
optCompletionInfo =
if (txEntry.hasSubmitterInfo)
Some(parseCompletionInfo(parseInstant(recordTime), txEntry.getSubmitterInfo))
Some(parseCompletionInfo(recordTime, txEntry.getSubmitterInfo))
else None,
transactionMeta = TransactionMeta(
ledgerEffectiveTime = parseTimestamp(txEntry.getLedgerEffectiveTime),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

package com.daml.ledger.participant.state.kvutils.committer

import java.time.Instant

import com.daml.ledger.participant.state.kvutils.store.{DamlLogEntry, DamlStateKey, DamlStateValue}
import com.daml.ledger.participant.state.kvutils.{DamlStateMap, Err}
import com.daml.lf.data.Ref
Expand Down Expand Up @@ -32,9 +30,9 @@ private[kvutils] case class CommitContext(
mutable.HashMap.empty[DamlStateKey, DamlStateValue]
private val accessedInputKeys: mutable.Set[DamlStateKey] = mutable.Set.empty[DamlStateKey]

var minimumRecordTime: Option[Instant] = None
var maximumRecordTime: Option[Instant] = None
var deduplicateUntil: Option[Instant] = None
var minimumRecordTime: Option[Timestamp] = None
var maximumRecordTime: Option[Timestamp] = None
var deduplicateUntil: Option[Timestamp] = None

// Rejection log entry used for generating an out-of-time-bounds log entry in case of
// pre-execution.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,8 @@ private[committer] trait Committer[PartialResult] extends SubmissionExecutor {
successfulLogEntry = successfulLogEntry,
stateUpdates = commitContext.getOutputs.toMap,
outOfTimeBoundsLogEntry = constructOutOfTimeBoundsLogEntry(commitContext),
minimumRecordTime = commitContext.minimumRecordTime
.map(Timestamp.assertFromInstant),
maximumRecordTime = commitContext.maximumRecordTime
.map(Timestamp.assertFromInstant),
minimumRecordTime = commitContext.minimumRecordTime,
maximumRecordTime = commitContext.maximumRecordTime,
)
}

Expand All @@ -124,14 +122,14 @@ private[committer] trait Committer[PartialResult] extends SubmissionExecutor {
.map { rejectionLogEntry =>
val builder = DamlOutOfTimeBoundsEntry.newBuilder
.setEntry(rejectionLogEntry)
commitContext.minimumRecordTime.foreach { instant =>
builder.setTooEarlyUntil(buildTimestamp(instant))
commitContext.minimumRecordTime.foreach { timestamp =>
builder.setTooEarlyUntil(buildTimestamp(timestamp))
}
commitContext.maximumRecordTime.foreach { instant =>
builder.setTooLateFrom(buildTimestamp(instant))
commitContext.maximumRecordTime.foreach { timestamp =>
builder.setTooLateFrom(buildTimestamp(timestamp))
}
commitContext.deduplicateUntil.foreach { instant =>
builder.setDuplicateUntil(buildTimestamp(instant))
commitContext.deduplicateUntil.foreach { timestamp =>
builder.setDuplicateUntil(buildTimestamp(timestamp))
}
DamlLogEntry.newBuilder
.setOutOfTimeBoundsEntry(builder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ private[kvutils] class ConfigCommitter(
} else {
if (ctx.preExecute) {
// Propagate the time bounds and defer the checks to post-execution.
ctx.maximumRecordTime = Some(maximumRecordTime.toInstant)
ctx.maximumRecordTime = Some(maximumRecordTime)
setOutOfTimeBoundsLogEntry(result.submission, ctx)
}
StepContinue(result)
Expand Down
Loading

0 comments on commit 3587eb8

Please sign in to comment.