ZooBC wiki
Transactions

Expiry and timestamps

Every ZooBC transaction carries the moment it was made, in Unix seconds, inside its signed bytes. That timestamp opens a validity window: a block may include the transaction only within the window, and after it the transaction is dead and must be signed again. The window protects the signer. A payment that could not get into a block at a busy moment does not linger for days and then surprise them; it simply expires, and they can decide again.

The default window: one hour

By default a block may include a transaction until 3,600 seconds after its timestamp: one hour, or 240 blocks at one block every 15 seconds. After that, nodes refuse it with a message that ends "...sign it again".

The window also has a front edge. A transaction dated more than 3,600 seconds in the future is refused too, with a hint to check the signer's clock. This catches a device whose clock is wrong.

A time axis from the transaction's timestamp: a green band up to one hour where a block may include it, a red zone after it, and a dashed band reaching 24 hours for version 3
A time axis from the transaction's timestamp: a green band up to one hour where a block may include it, a red zone after it, and a dashed band reaching 24 hours for version 3

Choosing the window: version 3

A version-3 transaction carries a 4-byte expiry field, right after the fee and the survival field, and states its own window in seconds:

  • 0 means the default hour;
  • a smaller value shortens the window, for a payment that must happen soon or not at all;
  • the largest allowed value is 86,400 seconds, one day; a larger value is refused.

A version 1 or 2 transaction has no expiry field, and one that states an expiry anyway is refused. Whatever the version, the limit of one hour into the future still applies.

A longer window helps when a signature takes time to collect: on a hardware wallet, or among the participants of a multisignature account.

How pools and chains keep up

Two companion rules make the day-long window safe:

  • a node's transaction pool keeps each transaction for its own stated window;
  • every chain keeps transaction ids for at least 25 hours: the longest window plus the one-hour tolerance into the future.

Since a node refuses an id it has already confirmed (see signing a transaction), a transaction can never be replayed while it is still valid.

A ruler from the timestamp with marks at 1 hour (the default), 24 hours (the cap) and 25 hours (how long ids are kept), and a red zone beyond 24 hours
A ruler from the timestamp with marks at 1 hour (the default), 24 hours (the cap) and 25 hours (how long ids are kept), and a red zone beyond 24 hours

Time in blocks

Blocks are checked against the same windows, so every node reaches the same verdict:

  • a block whose timestamp is past a transaction's timestamp plus its window is invalid;
  • so is a block that carries a transaction dated more than 3,600 seconds after the block.

Some settlements happen by themselves, block by block: Escrow deadlines, the completion of liquid payments (streams), scheduled transfers falling due, the expiry of orders resting on a market and the phases of the fee vote. These read the previous block's timestamp, not the block's own. A producer therefore cannot stamp its block a little ahead of time to pull a payout into it.

How blocks are spaced in time is explained in blocks and time.

See also