Packages

package conflictdetection

Ordering
  1. Alphabetic
Visibility
  1. Public
  2. Protected

Type Members

  1. final case class ActivenessResult(contracts: ActivenessCheckResult[LfContractId, Status], inactiveTransfers: Set[TransferId], keys: ActivenessCheckResult[LfGlobalKey, Status]) extends PrettyPrinting with Product with Serializable

    The result of the activeness check for an ActivenessSet.

    The result of the activeness check for an ActivenessSet. If all sets are empty, the activeness check was successful.

    contracts

    The contracts whose activeness check has failed

    inactiveTransfers

    The transfers that shall be completed, but that are not active.

  2. final case class ActivenessSet(contracts: ActivenessCheck[LfContractId], transferIds: Set[TransferId], keys: ActivenessCheck[LfGlobalKey]) extends PrettyPrinting with Product with Serializable

    Defines the contracts and transfers for conflict detection.

    Defines the contracts and transfers for conflict detection. Transfers are not locked because the transferred contracts are already being locked.

  3. final case class CommitSet(archivals: Map[LfContractId, WithContractHash[ArchivalCommit]], creations: Map[LfContractId, WithContractHash[CreationCommit]], transferOuts: Map[LfContractId, WithContractHash[TransferOutCommit]], transferIns: Map[LfContractId, WithContractHash[TransferInCommit]], keyUpdates: Map[LfGlobalKey, Status]) extends PrettyPrinting with Product with Serializable

    Describes the effect of a confirmation request on the active contracts, contract keys, and transfers.

    Describes the effect of a confirmation request on the active contracts, contract keys, and transfers. Transient contracts appear the following two sets:

    archivals

    The contracts to be archived, along with their stakeholders. Must not contain contracts in transferOuts.

    creations

    The contracts to be created.

    transferOuts

    The contracts to be transferred out, along with their target domains and stakeholders. Must not contain contracts in archivals.

    transferIns

    The contracts to be transferred in, along with their transfer IDs.

    keyUpdates

    The contract keys with their new state.

    Exceptions thrown

    java.lang.IllegalArgumentException if transferOuts overlap with archivals or creations overlaps with transferIns.

  4. trait RequestTracker extends RequestTrackerLookup with AutoCloseable with NamedLogging

    The request tracker handles all the tasks around conflict detection that are difficult to parallelize.

    The request tracker handles all the tasks around conflict detection that are difficult to parallelize. In detail, it tracks in-flight requests, performs activeness checks, detects conflicts between requests, keeps track of the sequencer time, checks for timeouts, and orchestrates the updates to the com.digitalasset.canton.participant.store.ActiveContractStore. It does not write to the com.digitalasset.canton.participant.protocol.RequestJournal, though. The request tracker lives entirely in memory on a single compute node.

    The request tracker is a deterministic component that depends only on the ACS state and the sequencer messages. The order and timing in which the request tracker receives this information does not matter. (Even more broadly, the participant has no functional notion of “wall-clock” time; all time and timestamps come from sequencer messages.) These properties of determinism and sequencer time are both important parts of Canton and critical to the crash recovery model.

    To keep track of the sequencer time, the request tracker must be notified of every message that is received from the sequencer. These notifications need not happen in order, but they must happen eventually. Every such message has an associated monotonically increasing SequencerCounter. If one of the sequencer counters is skipped, the request tracker may stall indefinitely. Every message has an associated timestamp. Time must increase with every message in the order given by the sequencer counter. This means that for sequencer counters sc1 and sc2 with sc1 < sc2, the associated timestamps ts1 and ts2 must satisfy ts1 < ts2.

    Requests are identified by RequestCounters, which themselves must be a monotonically increasing sequence without gaps.

    The request tracker uses these time signals to determine on which requests a verdict can be issued, which requests have timed out, and which requests and contract states can be safely evicted from the tracker's internal state. We say that the request tracker has observed a timestamp if it has been signalled this timestamp or a later one. The request tracker can progress to a timestamp ts if it has observed all timestamps up to and including ts and all commit sets with commit times up to ts have been added with RequestTracker.addCommitSet.

    If the request tracker can progress to a timestamp ts, then it must eventually complete all futures that RequestTracker.addRequest and RequestTracker.addCommitSet have returned and that are associated with a timestamp equal or prior to ts. The futures are associated to the following timestamps:

    • Activeness result: the activeness time of the request, typically the timestamp on the request
    • Timeout result: the decision time of the request
    • Finalization result: the commit time of the request

    The three methods RequestTracker.addRequest, RequestTracker.addResult, and RequestTracker.addCommitSet must normally be called in the given sequence; the latter two need not be called if the request has timed out. A request is in flight from the corresponding call to RequestTracker.addRequest until the request tracker has progressed to its decision time (if the request times out) or its commit time.

    These three methods are idempotent while the request is in flight. That is, if one of the methods is called twice with the same arguments, provided that the first one succeeded, then the second call has no effect, but its return value is equivalent to what the first call returned. If the method is called twice for the same request counter with different arguments, the subsequent behavior of the request tracker becomes unspecified. The same applies if the same sequencer counter is supplied several times with different timestamps.

    A request tracker is typically initialized with a SequencerCounter and a com.digitalasset.canton.data.CantonTimestamp, causing it to be ready to handle requests starting from the given sequencer counter (inclusive) and timestamp (exclusive).

    Conflict detection

    The request tracker checks whether a request uses only contracts that are active at the activeness timestamp of the request. To that end, it determines the ActivenessResult of the request. A non-conflicting request should be approved in a response by the participant. A conflicting request should be rejected.

    To describe conflict behavior, we introduce a few concepts:

    A conflict detection time is a triple (com.digitalasset.canton.data.CantonTimestamp, Kind, SequencerCounter). There are three kinds, and they are ordered by

    Finalization < Timeout < Activeness

    . Conflict detection times are ordered lexicographically. In other words,

    (ts1, kind1, sc1) < (ts2, kind2, sc2)

    if and only if

    ts1 < ts2

    or

    ts1 == ts2 && kind1 < kind2

    or

    ts1 == ts2 && kind1 == kind2 && sc1 < sc2.

    A request with SequencerCounter sc and com.digitalasset.canton.data.CantonTimestamp ts induces two conflict detection times: The sequencing time at (ts, Activeness, sc) and the timeout time at (decisionTime, Timeout, sc) where decisionTime is the decision time of the request. Without logical reordering, the sequencing time is also the request's activeness time. (Technically, the activeness time must lie between the sequencing time and the decision time; see RequestTracker.addRequest.) A result with SequencerCounter sc and com.digitalasset.canton.data.CantonTimestamp ts also defines two conflict detection times: The verdict time (ts, Result, sc) and the finalization time (commitTime, Finalize, sc) where commitTime is the commit time of the request.

    A request is active at some conflict detection time t if all of the following holds:

    • Its sequencing time is equal or prior to t.
    • If no finalization time is known for the request, then t is equal or prior to the request's timeout time.
    • If a finalization time is known for the request, then t is equal or prior to the finalization time.

    The finalization time of a request is known if the result has been successfully signalled to the request tracker using RequestTracker.addResult.

    A request is finalized at some conflict detection time t if its finalization time is known and equal or prior to t.

    A contract is active at time t if a request with activeness time at most t activates it, and there is no finalized request at time t that has deactivated it. Activation happens through creation and transfer-in. Deactivation happens through archival and transfer-out. An active contract c is locked at time t if one of the following cases holds:

    • There is an active request at time t that activates c. In that case, we say that the contract is in activation.
    • There is an active request at time t that deactivates c and the request does not activate c.

    A contract may be locked because of activation and deactivation at the same time if there are two active requests, one activating the contract and another deactivating it. For example, if one request r1 creates a contract with sequencing time t1 and finalization time t1' and another request r2 with sequencing time t2 between t1 and t1' archives it (despite that r2's activeness check fails), then the contract is created at time t1 and archived at t2.

    Activeness of contracts is checked at the request's activeness time. The ActivenessResult lists all contracts from the ActivenessSet of the request that are either locked or whose precondition fails. The activeness check succeeds if the activeness result is empty.

  5. trait RequestTrackerLookup extends AutoCloseable with NamedLogging

Value Members

  1. object ActivenessSet extends Serializable
  2. object CommitSet extends Serializable
  3. object RequestTracker

Ungrouped