Benefits of the new (hash based) contract ID scheme

Since Version 1.0.0 of the SDK, there is a new contract ID scheme.

Contract identifiers are hashes instead of longer sequence numbers.

What is the new scheme, in a nutshell?

What are the benefits of the new scheme from a user’s perspective?
E.g.:

  • New things you can do with contract IDs (and why they are valuable)
  • Better security properties

Are there any other concerns (not visible to users) that have motivated this change?

2 Likes

My understanding is the only thing you can do with contract IDs (old or new) is pass them back to the API. Treat them as opaque blobs.

Disclaimer: As @Gary_Verhaegen pointed it out, users should consider contract IDs as opaque blocks.

In earlier SDKs, contract IDs were ledger-specific strings assigned before committing the transaction on the ledger but after DAML evaluation. Concretely, during evaluation of a DAML program, the engine was using special placeholders (called relative contract IDs) to identify contracts created within the transaction being built. Those relative contract IDs were later substituted with their final value by the ledger implementation.

The main drawback of this approach was that the contract IDs could not be ordered in a stable way. Because it was not known at interpretation time to which string a relative contract ID will be assigned, it was not possible to compare in a stable way a relative contract ID with another contract ID.

Staring from SDK 1.0.0, contract IDs are built from a cryptography hash (called a discriminator), computed during evaluation via a deterministic derivation scheme from an initial high-entropy number (called a submission seed) picked at submission time. The scheme leaves the ledger implementation free to suffix the contract ID as its convenience before committing the transaction. Without entering too much into the details, the derivation scheme guarantees that if the submission seed was never used before, (1) the discriminators of contract IDs created by the transaction are globally unique and (2) that no information about the transaction can be inferred from one of the discriminators given alone.

Assuming a participant is honest and chooses a proper high-entropy submission seed for each of its submissions, the uniqueness property we describe above ensures that only the discriminators, not the suffix are needed to order the contract IDs of created contracts w.r.t. other contract IDs. Upcoming SDKs will take advantage of this, and provide new builtins to order contract IDs and a new kind of ordered map where keys can contain arbitrary serializable values, including contract IDs.

Additionally, this new scheme makes it easier for a particular ledger implementation to limit information leakage through contract IDs. For instance, Sandbox, which chooses itself a fresh submission seed for each submission, uses the discriminator without a suffix, hence leaking (almost) no information through the contract IDs it generates. Though, exact security properties rely on a particular ledger implementation and how it uses contract ID suffixes.

More details about contract IDs can be found in the contract ID specification.

1 Like

Given:

contract C0 created at time t0
contract C1 created at t1
contract C2 created at t2
t0 < t1 < t2

With the new contract ID scheme, can we compare the discriminators, does the following stand:

discriminator(C0) < discriminator(C1) < discriminator(C2)
discriminator(C0) < discriminator(C2)

and do we specify how to compare the contract IDs (how to extract a discriminator from a contract ID)?

1 Like

I’m very much interested to know how I could order the new contract ids by created time. It’s often a concern in UIs where I want to display contracts in the order they’ve been created. Adding a field on the contracts just for that seems an overkill. The previous implementation (#1:0, #2:0, …) made this straight forward.

1 Like

@Remy Thanks for this detailed answer!

Concerning the benefits of the new scheme from a users’ perspective I read:

  • Contract IDs can soon be used as part of map keys.
  • DAML-LF now enforces for all ledger implementations that contract IDs do not leak information about the transaction. (Previously, this was only true for some ledger implementations.)

Is that correct? Anything else?

@georg I think we have conflicting requirements here:

  • You want to be able to order contract IDs by creation time.
  • The contract ID scheme must not leak information about the transaction creating the contract.

That does not mean your concern is not valid.

@georg all contracts have two timestamps: Record Time and Ledger Effective Time. We also have an offset, which is the order in which things are output through the Ledger API

  • Both are monotonous with causality on the ledger,
  • Ledger Effective Time is available in DAML via getTime
  • RecordTime is more likely to be comonotonous with ledger offset

Is what you are after is have one of those available through the Ledger API so you can sort by them.

1 Like

@bernhard yes, it’s just about having some way to order them provided through the JSON API, respectively the JS libraries. LET would work just fine for that. I just thought if there’s a way to order contract ids (which @Remy seems to be hinting at) we might not even need that.

1 Like

The ordering Rémy is talking about is not wtr to contract creation time. It’s just some stable ordering that you can use to implement things like ordered maps.

1 Like

@Leonid_Shlyapnikov. Contract IDs are simply compared lexicographically. The discriminator being a cryptographic hash (it looks like random), the resulting ordering does not have any special property. As stated by @MatthiasSchmalz this is important to not leak information.

Sorting contract IDs from a DAML program will be available soon in an upcoming SDK. To sort contract IDs in a client, one can simply compare them lexicographically and it will obtain the same result than in DAML.

As stated before, users should consider contract IDs as opaque blocks and not try to scrutinize them. In other words one should not try to extract discriminator from a contract ID.

1 Like

@MatthiasSchmalz

Concerning your first question, Yes, it will be soon possible to use Contract IDs as map keys.

Concerning your second question, unfortunately no. Contract IDs in a particular ledger implementation may still leak information. This all depends on how contract ID are suffixed. However for ledger implementations that do not have to suffix contract ID (like Sandbox and vDAML) this property is guaranteed.

I did not mention it before, but the new scheme makes it also difficult for an attacker to guess the IDs of contracts that actually exist on the ledger. This adds a level of security in to all DAML ledger implementations.

1 Like

@georg Take in consideration that nothing in the design of DAML enforces that a contract ID actually refers to a contract existing on the ledger. Dishonest participants can use arbitrary contract IDs inside their requests.
Furthermore it will be too costly (and very impractical in client side) to have to fetch contracts every-time one have to compare two contract IDs.

1 Like