You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hydra Heads should not need to be closed and re-opened just to add more funds. This will make Hydra Heads more flexible in enables use cases where long-living Heads are beneficial.
Furthermore, it could pave the way for getting rid of the initialization phase altogether, which would result in a much simpler protocol.
What
Implement the protocol extension for more committing additional UTXOs into a Head as already briefly described in the original Hydra Head paper.
"As user, I want to add more funds to the head, such that I can spend them later in the head"
When the head is open, a hydra client can request an incremental commit:
Requesting can be done via HTTP using the POST /commit. Just like with the "normal" commit, the user needs to send either a UTxO or a "blueprint transaction".
The api call is synchronous and returns a depositTx corresponding to the requested commit. (This works just the same way as the commit endpoint works so far during initialization phase)
Alternatively, or in addition, we provide a library to build such depositTx
Submitting the depositTx transaction should have the requested UTxO eventually added to the head
A CommitRequested (TBD: or DepositDetected?) server output is sent to signal observation of the deposit
The hydra-node will request inclusion of the deposited UTxO and wait for a SnapshotConfirmed with inclusion approval.
Using the snapshot, the creates an incrementTx, signs and submits that.
A CommitFinalized server output is sent to the clients when the incrementTx is observed.
The node provides a list of pending commits via the API using GET /commits
Each pending commit (deposit) has an id (i.e. the deposit outputs' TxIn) and a deadline attached, after which a user can request refund of the commit
Requesting can be done via HTTP using DELETE /commits/<id>, which has the node construct and submit a recoverTx for the user. TBD: okay that node pay fees here?
Alternatively, or in addition, we provide a library to build such a recoverTx
Any UTxO which can be committed, can also be incrementally committed
Scenarios
All of the positive scenarios also ensure correct balance after fanout:
Can commit to an open Head
not matter what is currently available on L2 (also empty head)
Can commit and immediately close with the same snapshot
Can do multiple increments one after another
Can do multiple commits and decommits in sequence as long as decommitted UTxO are consistent
Can commit and decommit the same UTxO should result in the same open Head UTxO
Cannot commit while another decommit is pending
Cannot decommit funds you don't own
Cannot commit funds you don't own
Can decommit everything from the Head
Can process L2 transactions of independent UTxO while commit is happening.
Cannot commit same UTxO in two Heads
specially in presence of rollbacks (due to network partition)
Can close and fanout while commit is pending
i.e. when someone did not submit incrementTx
either funds did not get committed at all or reimbursed by fanout
Security
The specification is updated and checked with researchers whether it is consistent with the properties above (walk-through)
All validator changes are tested using the mutation testing framework, covering all constraints from the specification and we saw each test "fail for the right reason", i.e. no specification change without a corresponding mutation and (at least) one mutation per constraint
Idea: Deposit anything to commit into a deposit output. Head participants then re-use the ReqSn off-chain consensus to request inclusion of UTxO (like incremental decommit). Deposits have an asymmetric deadline, such that users need to wait longer before they can reclaim than the head participants have time to ensure the deposit is not rolled back (double spent). Deposits are recording outputs like in the commitTx and claiming a deposit into the head via an incrementTx ensures the recorded UTxO matches (completely) with what was agreed off-chain. Participants only agree off-chain if they saw a matching deposit.
Outline of one deposit being claimed in an increment and one deposit being recovered:
Situation: Head is open, $U_0$ locked, off-chain busy transacting
Deposit:
Anyone can create a deposit by posting a depositTx
we can enable this through hydra-node or through a library/tool.
The depositTx ensures through minting of a deposit token (DT) that anything to be committed $\phi$ is recorded correctly into the datum (isomorphic to $U_\alpha$)
this also ensures contract continuity for next steps
TBD: Needed? pub key outputs need signature anyways and script outputs could inspect depositTx to ensure the transition to L2 is "correct"? Could mean more coupling, but simpler protocol here.
All deposit outputs have the same address and the datum also contains target headid $\mathsf{cid}$ and a deadline $T_{DL}$
TBD: on commits users asked to identify heads not only by id but by participant keys, we could put them into the datum here and ensure only heads with those PTs can claim a deposit?
Recover:
In case deposit was not picked up by a head, anyone can "undo" a commit using a recoverTxafter the deadline has passed
most of the time, this is going to be the original user who wanted to deposit
Deadline should be long enough such that the head has enough time to wait for the deposit "to settle" and still absorb it into the head (synchrony assumption on Cardano).
Increment:
One or more Head participants (i.e. their hydra-node) observe pending deposits using the common deposit address
this should only happen after gaining enough confidence that the accompanying depositTx is not rolled back
need to check head id and deadline (should be configurable)
A node requests inclusion of a pending decommit by sending a ReqSn message with $U_\alpha$
Not needed as every participant would observe it on-chain and its up to the snapshot leader to include it anyways
The snapshot leader will request inclusion: $ReqSn(v, sn, txids, U_\alpha)$
Note that this submits a utxo set, not a transaction
All participants acknowledge by signing this snapshot $\eta = \mathsf{combine}(\bar{U})$ and $\eta_\alpha = \mathsf{combine}(U_\alpha))$
This yields a multi-signed certificate $\xi$ which can be used to post the incrementTx, which:
spends a deposit output, where the deposit validator ensures
recorded commits match $\eta_\alpha$
head id from datum matches (using the head state thread token)
deadline has not passed
evolves on-chain head state $(open, v, \eta)$ into updated head state $(open, v+1, \eta')$,
given a multi-signed certificate $\xi$ and snapshot number,
by verifying the signature using snapshot number, version and $\eta'$ from the head output, as well as $\eta_\alpha$ from the deposit output
Head participants observe incrementTx on L1 with added $U_\alpha$ and make it available in their L2 state
no delay because rollbacks are impossible here -> deposit can only be spent into the head before the deadline
To be discussed
What happens if incrementTx is not posted after being signed on L2?
Any node can submit this transaction; similar situation as fanout for example
Do we really need to change η to be a merkle-tree-like structure with inclusion proofs?
Checking the value on L1 + signature on L2 would be enough, but this requires interaction with L1 when signing on L2
By using deposit, we can observe correct locking before requesting inclusion and our basic digest is good enough to check all-or-nothing on any individual deposit UTxO.
Shall we drop the initialization phase?
Maybe as a follow-up; Not in scope
How to deal with rollbacks/forward which result in a different $\eta$? When is it safe to integrate $U_\alpha$ into confirmed $U$?
Deadline after which a user can submit recoverTx should be >> than a safe margin on observing depositTx (e.g. deadline = 7 days, delay on deposit observe ~ 1 day); As deposits can only be spent into the head before the deadline passed, we don't need to wait when observing incrementTx
IMPORTANT should require a safe margin before the deadline in incrementTx (re-use contestation period?)
Why
Hydra Heads should not need to be closed and re-opened just to add more funds. This will make Hydra Heads more flexible in enables use cases where long-living Heads are beneficial.
Furthermore, it could pave the way for getting rid of the initialization phase altogether, which would result in a much simpler protocol.
What
Implement the protocol extension for more committing additional UTXOs into a Head as already briefly described in the original Hydra Head paper.
"As user, I want to add more funds to the head, such that I can spend them later in the head"
When the head is open, a hydra client can request an incremental commit:
POST /commit. Just like with the "normal" commit, the user needs to send either a UTxO or a "blueprint transaction".depositTxcorresponding to the requested commit. (This works just the same way as the commit endpoint works so far during initialization phase)depositTxSubmitting the
depositTxtransaction should have the requestedUTxOeventually added to the headCommitRequested(TBD: orDepositDetected?) server output is sent to signal observation of the depositUTxOand wait for aSnapshotConfirmedwith inclusion approval.incrementTx, signs and submits that.CommitFinalizedserver output is sent to the clients when theincrementTxis observed.The node provides a list of pending commits via the API using
GET /commitsEach pending commit (deposit) has an id (i.e. the deposit outputs'
TxIn) and a deadline attached, after which a user can request refund of the commitDELETE /commits/<id>, which has the node construct and submit arecoverTxfor the user. TBD: okay that node pay fees here?recoverTxAny UTxO which can be committed, can also be incrementally committed
Scenarios
All of the positive scenarios also ensure correct balance after fanout:
incrementTxSecurity
Out of scope
How
Protocol design
Important
Idea: Deposit anything to commit into a
depositoutput. Head participants then re-use theReqSnoff-chain consensus to request inclusion of UTxO (like incremental decommit). Deposits have an asymmetric deadline, such that users need to wait longer before they can reclaim than the head participants have time to ensure the deposit is not rolled back (double spent). Deposits are recording outputs like in thecommitTxand claiming adepositinto the head via anincrementTxensures the recorded UTxO matches (completely) with what was agreed off-chain. Participants only agree off-chain if they saw a matchingdeposit.Outline of one deposit being claimed in an increment and one deposit being recovered:
Protocol transitions:
Situation: Head is open,$U_0$ locked, off-chain busy transacting
Deposit:
depositTxhydra-nodeor through a library/tool.depositTxensures through minting of a deposit token (DT) that anything to be committeddepositTxto ensure the transition to L2 is "correct"? Could mean more coupling, but simpler protocol here.Recover:
recoverTxafter the deadline has passedIncrement:
hydra-node) observe pending deposits using the common deposit addressdepositTxis not rolled backA node requests inclusion of a pending decommit by sending a$U_\alpha$ ReqSnmessage withincrementTx, which:incrementTxon L1 with addedTo be discussed
What happens if
incrementTxis not posted after being signed on L2?fanoutfor exampleDo we really need to change
ηto be a merkle-tree-like structure with inclusion proofs?Shall we drop the initialization phase?
How to deal with rollbacks/forward which result in a different$\eta$ ? When is it safe to integrate $U_\alpha$ into confirmed $U$ ?
recoverTxshould be>>than a safe margin on observingdepositTx(e.g. deadline = 7 days, delay on deposit observe ~ 1 day); As deposits can only be spent into the head before the deadline passed, we don't need to wait when observingincrementTxincrementTx(re-use contestation period?)