> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lasso.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Block regression protection

> Protect block choices and share progress across connected RPC Core peers.

Keep each query at one block, and keep later block choices from going backwards.

Set `head_policy: local` for a chain in your file profile to protect sequential
block choices on each running instance, with best-effort recovery from connected
peers. This is the behavior labeled **Block regression protection: On** in Lasso
Cloud. Peer sharing is automatic when the runtimes are connected; there is no
separate protection switch for it. Local mode needs no publication database. Use `global` only when you need
the stronger fleet-wide contract and have
[configured its journal and serving fleet](/deployment/block-continuity).

Choose a block once with `eth_getBlockByNumber("latest", false)` and pass its
hash to every state read in your query. Your existing RPC endpoint and standard
Ethereum methods stay the same.

This works for queries that combine proxy resolution, storage and code reads,
Multicall, and dependent `eth_call` rounds. Follow the
[read at one block guide](/advanced/read-at-one-block) to integrate it.

## What the setting guarantees

After a successful block choice returns height **N**, a later block choice
returns **N or higher**, or an error. Returning the same height is allowed.

The scope depends on the selected mode. All API keys using the same profile and
chain share its floor within that scope. Different profiles and chains remain
independent. The guarantee applies when a later request starts after the earlier
response completes; overlapping requests can finish out of height order.

| Mode   | Protected scope                  | Restart and node-switch behavior                                                                                            |
| ------ | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| Off    | Ordinary provider routing        | No monotonic floor.                                                                                                         |
| Local  | One running application instance | Peer hints help choose a suitable provider, but recovery is best effort. A restart or node switch can return a lower block. |
| Global | All admitted serving instances   | A durable publication preserves the floor; unavailable members or coordination can prevent advancement.                     |

Local choices use providers and retain an in-memory floor. Peer hints influence
provider preference without requiring a database lookup or peer acknowledgment.
They do not raise the receiving node's mandatory floor. A valid response may
therefore be below a peer hint. Recovery has no guaranteed maximum time or block
gap; disconnected peers, lost processes and the fleet's total profile/chain
inventory affect it. Losing every copy of local state loses that history.

| Request                                           | Behavior in Local or Global mode                                                          |
| ------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| `eth_blockNumber []`                              | Returns an eligible block number or an error.                                             |
| `eth_getBlockByNumber ["latest", false]`          | Returns an eligible block including its number and hash. Use this to start a query.       |
| `eth_getBlockByNumber ["latest", true]`           | Returns an eligible block with full transactions, or an error.                            |
| State reads with an explicit number or hash       | Keep the requested target through routing and retries, including targets below the floor. |
| State reads using `latest` or an omitted selector | Use ordinary provider routing. Separate reads can observe different blocks.               |

The setting does not group requests into a query. Your application carries the
chosen hash through discovery, independent calls, and dependent rounds. A
JSON-RPC batch alone does not select a shared block. `safe`, `finalized`,
`pending`, log ranges, and subscriptions retain their usual semantics.

## One query, one block identity

For state reads, use the standard
[EIP-1898 selector](https://eips.ethereum.org/EIPS/eip-1898):

```js theme={null}
{ blockHash: block.hash, requireCanonical: true }
```

A number identifies a height; a hash identifies the particular block at that
height. During a reorg, the same number can refer to a different block. If you
start with a number, resolve it to a hash **once**, before the first state read.

Use providers that support the method, hash selector and required state history.
Lasso keeps the hash during failover and returns an error if the read cannot be
completed. Provider capability evidence guides routing; it does not certify that
every backend behind an endpoint can execute the request.
Your query can therefore finish at block 100 while a newer query reads block 101.

## Freshness and provider lag

A local choice validates a provider response against the floor captured when
that request began. A lower response is rejected; Lasso can try another eligible
provider within the request's deadline and retry budget. Local mode does not
cache block responses to hide provider failures. If a provider regresses and all
fallbacks are unavailable or quota-limited, the choice fails explicitly.

Global mode retains a published block. It can return 101 again after publishing
101 even when a provider later reports 100. During a publication change, a choice
can wait up to one second within its request deadline before failing.

Both modes reject protected block choices older than the greater of **60 seconds or four configured
block intervals**, measured from the block timestamp. Repeating a block does not
renew its age. This bounds staleness; it does not promise the newest block on the
network. Executing state reads still requires a provider with the selected state.
Hash-pinned reads continue without waiting for block publication.

A provider URL can sit in front of several nodes with different heads. Lasso
keeps the hash on every attempt; a lagging node must serve that state or return
an error. A successful head probe alone does not establish state availability.

One provider is enough to enable the policy. It provides no provider failover or
independent verification; reads fail if that provider cannot serve the chosen state.

## Reorgs and failures

With `requireCanonical: true`, a provider must reject a block it knows is no
longer canonical. Lasso surfaces that conflict; it does not silently replace
the query's hash. Discard the incomplete query and retry the whole operation
within your deadline if a fresh result is still useful.

Global publication can report attributed replacements at the previous selected
height as `anchor_hash_changed`. Local mode rejects a different hash at its
captured floor height. Neither mechanism detects every reorg, and missing state
alone is not evidence of one. The floor does not reset downward within its
protected scope, so a reorg can temporarily prevent new block choices.

Canonicality reflects provider observations at the time of a read. A block can
be reorganized later. Lasso does not cryptographically verify arbitrary
`eth_call` results: a provider that silently ignores the selector can return
incorrect data without revealing that in its response. Provider head checks
and routing evidence do not prove execution correctness or finality.

## Return the block and routing evidence

Add `?include_meta=headers` to collect Lasso's request ID and routing metadata
without changing the JSON-RPC result. Return the chosen number, hash, and
collected evidence alongside your application's query result. The
[guide](/advanced/read-at-one-block#3-return-results-with-evidence) shows what to retain.

Local routing evidence includes the application `generation`, captured
`minimum_height`, best-effort `recovery_height`, and `recovery_gap_blocks`.
A missing recovered height is represented by `null`; a nonzero gap is allowed.
Compare sequential choices within the same generation to assess the local
invariant. Node changes and new generations have the softer recovery contract.

The local floor survives a recovery-worker restart, but not loss of its owning
application. Disabling protection does not cover calls made while it is off.
Global floors survive service restarts through the journal; changing away from
Global first completes coordinated shutdown. Choices can keep failing until that
transition finishes, including when a failed member still needs to be fenced.
