Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specify deposit workflow in ticket and technical specification #1571

Closed
Tracked by #199
ch1bo opened this issue Aug 16, 2024 · 7 comments · Fixed by cardano-scaling/hydra-formal-specification#10
Closed
Tracked by #199
Assignees
Labels
task Subtask of a bigger feature.

Comments

@ch1bo
Copy link
Collaborator

ch1bo commented Aug 16, 2024

Why

While working on #199 we realized that if we want to properly secure Hydra Heads against rollbacks of incrementally committed funds, having full sequencing requirements + potentially long lockup times is going to be really bad. In presence of rollbacks/pessimistic settings, this is creating a Head that is not "very live" as it would need to be forced to close in case a requested to commit UTxO is spent otherwise before the incrementTx hits the chain.

More details here: #199 (comment)

What

We want to revisit the deposit workflow again which should not have these issues.

This issue will be about collecting the necessary design pieces before we head into implementation.

@ch1bo ch1bo mentioned this issue Aug 16, 2024
12 tasks
@ch1bo
Copy link
Collaborator Author

ch1bo commented Aug 16, 2024

Created a slightly more detailed transaction trace including deposits and cancellations (naming is still not 100%):

Transaction traces - Increment_ Deposit + versioned sequential commits 2024-08-01(1)

@ch1bo
Copy link
Collaborator Author

ch1bo commented Aug 16, 2024

Also explored how we could use PlutusV3 (CIP-69) multi-purpose scripts:

An analogous design to the initialization phase (PlutusV2) would be that the deposit is controlled by two validators:

  • μ_deposit: minting validator for a deposit token (DT)
  • ν_deposit: spending validator

Besides other things, μ_deposit needs to ensure that the minted token is paid to the ν_deposit script. Hence, it's parameterized by the script hash H(ν_deposit). With PlutusV3, we could re-use the same script without losing anything here. All transactions that involve spending from the deposit output would need to burn the DT anyways and need the script included.

However, if we want to re-use the script, the output address of the deposit (purple in the image), would be parameterized too. So it's not a fixed address to "discover" and observe deposits:

Transaction traces - Combined PlutusV3 scripts

But, do we need uniqueness of deposit tokens? Maybe it's enough to have it as evidence that the minting policy ran. Which would lead to this design:

Transaction traces - Non-unique deposit tokens with PlutusV3 scripts

@ch1bo
Copy link
Collaborator Author

ch1bo commented Aug 16, 2024

Updated the #199 feature How section with this protocol design:

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 cancelled:

flowchart LR
  seed([seed])--> initTx
  initTx --> open0([open v0 η0])

  u1([u1]) --> depositTx1 --> deposit1(["deposit DL [u1]"])
  u2([u2]) --> depositTx2 --> deposit2(["deposit DL [u2]"])

  open0 -- Increment ξ3 --> incrementTx
  deposit1 -- Claim --> incrementTx
  incrementTx --> open1([open v1 η3])

  open1 -- Close ξ1 --> closeTx

  deposit2 -- Cancel --> cancelTx --> u3([u2])
Loading

Protocol transitions:

  • Situation: Head is open, $U_0$ locked, off-chain busy transacting

  • Deposit:

    1. Anyone can create a deposit by posting a depositTx
      • we can enable this through hydra-node or through a library/tool.
    2. 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.
    3. All deposit outputs have the same address and the datum also contains target headid $\mathsf{cid}$ and a deadline $T_{DL}$
  • Cancel:

    1. In case deposit was not picked up by a head, anyone can "undo" a commit using a cancelTx after the deadline has passed
      • most of the time, this is going to be the original user who wanted to deposit
    2. 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:

    1. 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)
    2. 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
    3. The snapshot leader will request inclusion: $ReqSn(v, sn, txids, U_\alpha)$
      • Note that this submits a utxo set, not a transaction
    4. All participants acknowledge by signing this snapshot $\eta = \mathsf{combine}(\bar{U})$ and $\eta_\alpha = \mathsf{combine}(U_\alpha))$
    5. 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
    6. 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

@ch1bo
Copy link
Collaborator Author

ch1bo commented Aug 16, 2024

Also updated #199 What with these requirements to represent better the new workflow (no L2 protocol interaction on deposit/cancel and the node just picking up pending commits):

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 (TBD: or call it deposits?) 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 cancelTx for the user. TBD: okay to pay fees here?
    • Alternatively, or in addition, we provide a library to build such a cancelTx
  • Any UTxO which can be committed, can also be incrementally committed

@ch1bo ch1bo self-assigned this Aug 16, 2024
@ch1bo ch1bo added the task Subtask of a bigger feature. label Aug 16, 2024
@ch1bo
Copy link
Collaborator Author

ch1bo commented Aug 19, 2024

Changed the naming of a commit to consist of two steps: deposit and claim (through an increment or deposit and recover (if not claimed).

Also, we realized that we do not need unique deposit tokens (if we need them at all), so we can simplify the minting policy to be non-parameterized.

Updated transaction trace with both changes:

Transaction traces - Increment_ Deposit + versioned sequential commits 2024-08-19

@ch1bo
Copy link
Collaborator Author

ch1bo commented Aug 26, 2024

Further simplification of the protocol by asking more from the scripts which are committed into a head: #199 (comment)

Resulting in the transaction trace:

Transaction traces - Increment_ Deposit + versioned sequential commits 2024-08-01(3)

Why?

  • Simpler deposit protocol
  • Off-chain checks need to be done anyways (discover eligible deposits)
  • More complicated check for scripts that allow being committed to a head (they would need to check the head id anyways though)

@ch1bo
Copy link
Collaborator Author

ch1bo commented Aug 26, 2024

Drafted a quick example diagram of a script (a lottery) that is spent into a deposit:

Transaction traces - Deposit from script example(1)

It would need to check that its own (TxIn, TxOut) is exactly contained in the list of deposited UTxO ([Commit] in the diagram). For this, it must

  • know the cid of which head to deposit to (could be generalized to list of participant keys)
  • know the deposit validator hash hash(ν_deposit) to check the right output
  • serialize its own TxOut and search the list (a proper map would be great, but redeemer could contain an index)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
task Subtask of a bigger feature.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant