Cadence Resource.uuid change on Flow testnet and mainnet

What is changing?

Resources in Cadence are automatically assigned a unique identifier. The identifier is unique and is accessible through the uuid field, and has the type UInt64, a 64-bit unsigned integer.

Like warned about in the documentation, the details of how the identifiers are generated is an implementation detail, and developers should not assume any particular behavior.

Still, the behavior of the resource ID generation is changing, and this may impact programs that had previously made assumptions about the behavior of the IDs are generated.

Previously, resource IDs were generated in a sequential scheme: Newer resources got higher IDs, older resources have lower IDs.

After the change, resource IDs are no longer generated sequentially.

This means that resource IDs are more likely to be distributed in the full range of the integer space, e.g. higher than the maximum of UInt32 , Int64, etc.

Applications working with resource IDs may have previously used data types which do not support the representation of the full range of 64-bit unsigned integers. Before, this did not cause problems, as the number of generated resource IDs was still small.

For example, databases like PostgreSQL and Firebase do not natively support 64-bit unsigned integers, so developers might have used types with smaller ranges. In PostgreSQL, use NUMERIC(20,0), not a type like bigint (only a signed 64-bit integer).

Also note that some programming languages may not be able to represent 64-bit unsigned integers by default. For example, the JavaScript number type can only safely store integers up to 2^53 − 1 (see ([Number.MIN_SAFE_INTEGER](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_SAFE_INTEGER)). Use BigInt instead.

Why?

This change was made to remove a bottleneck for concurrent execution. Previously, the ID generator was a global state, and all transactions generating IDs would be bottlenecked by the generator and couldn’t be parallelized. Concurrent execution is required to unlock higher TPS on the network, and updates are being rolled out piecemeal since it’s a fairly large change. Concurrent execution will be turned on once its feature complete.

When is this changing?

This change has been deployed on Flow testnet and will be deployed to Flow mainnet after the Flow mainnet upgrade on Nov 8th, 2023.

The change has been rolled back from Testnet as of today, Oct 27th.
The decision on whether or not the change will be rolled out to mainnet as part of the network upgrade (spork) on Nov 8th is still pending.

The change has been on the emulator since July this year.

How this may impact your dApp / client code?

Resource id generation has always been an implementation detail, and dApps or client code should not rely on any particular behaviour (see warning here: Resources | Cadence)

If you are using a signed integer type (see Integers) to store the UUID, those values may overflow causing IDs to no longer be unique.

Resolution

If you are using an signed integer to store the resource.uuid please switch to using an unsigned integer.

More about the change: See pull request: Partition UUID to reduce transaction conflicts by pattyshack · Pull Request #4497 · onflow/flow-go · GitHub

Emulator change: Update to onflow/cadence v0.39.14 by SupunS · Pull Request #447 · onflow/flow-emulator · GitHub

3 Likes

Update - after the discussion with the community today, it was decided that:

  1. This change will NOT be rolled out to mainnet during the upcoming network upgrade scheduled for Nov 8th.
  2. The Flow FVM team will investigate an alternative approach to implement this change, which uses a different byte to shard the IDs.
  3. The Flow foundation will give a six weeks notice before rolling out this change.