| Safe Haskell | Safe-Inferred |
|---|---|
| Language | GHC2021 |
Hydra.API.ClientInput
Synopsis
- data ClientInput tx
- = Init
- | NewTx {
- transaction :: tx
- | Recover {
- recoverTxId :: TxIdType tx
- | Decommit {
- decommitTx :: tx
- | Close
- | SafeClose
- | Contest
- | Fanout
- | PartialFanout {
- utxoToFanout :: UTxOType tx
- | SideLoadSnapshot {
- snapshot :: ConfirmedSnapshot tx
- validateClientInput :: IsTx tx => ClientInput tx -> Either (Int, Int) (ClientInput tx)
Documentation
data ClientInput tx Source #
Constructors
| Init | |
| NewTx | |
Fields
| |
| Recover | |
Fields
| |
| Decommit | |
Fields
| |
| Close | |
| SafeClose | |
| Contest | |
| Fanout | |
| PartialFanout | Fan out a user-selected subset of the closed head's UTxO. Unlike
|
Fields
| |
| SideLoadSnapshot | |
Fields
| |
Instances
validateClientInput :: IsTx tx => ClientInput tx -> Either (Int, Int) (ClientInput tx) Source #
Reject a client input this node must not process, before it is queued.
SECURITY: SideLoadSnapshot is the one client command carrying a whole
Snapshot, and decoding one rebuilds both of its accumulators from the
client-supplied UTxO sets (FromJSON). That decode always
succeeds regardless of size -- the accumulators' commitment and hash are lazy
thunks -- and the over-capacity error inside
computeG1CommitmentBytes then fires from wherever one
of those thunks is first forced. In the node that is not a single place:
- the tracer's 'ToJSON (Input tx)' in
stepHydraNode, whose encoding runs on the log writer thread and would take logging (and then, once the log queue fills, the whole node) down with it; - 'ToJSON (ClientMessage tx)' when a rejection echoes the offending input back to WebSocket clients;
getSignableRepresentationduring multisignature verification, on the node's main loop, which has no handler for it.
None of these can be guarded individually, so the size is bounded here
instead: an oversized snapshot never enters the input queue, and the client
gets a 400 / InvalidInput rather than a dead node. HeadLogic keeps
an independent backstop for the same invariant.
This must not force the accumulators, so it goes through
checkAccumulatorSize (an element-map fold) and never toJSON
or getAccumulatorHash.
Reports the offending size and the maximum rather than a
SideLoadRequirementFailure: that type transitively
depends on this module (Input carries a ClientInput), so the callers
build SideLoadUTxOSetTooLarge from these two numbers instead.