Skip to content

Commit

Permalink
Update protocol.md
Browse files Browse the repository at this point in the history
  • Loading branch information
tomt1664 authored Apr 17, 2024
1 parent 818831a commit c9693b2
Showing 1 changed file with 28 additions and 32 deletions.
60 changes: 28 additions & 32 deletions docs/protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,48 @@ In addition, a public key encryption scheme is required for blinded private key

All transactions are pay to taproot addresses using segregated witness, which enables input transaction IDs to be determined before signing and prevents their malleability.

## Deposit
The service is operated by the 'statechain entity' (SE) server.

A user wants to deposit an amount of BTC into the platform, and they request that the SE initialize the process. To begin, the user must provide a valid `token_id` (UUID), which will be listed in the the server token database. This `token_id` is generated by the SE on payment of a deposit fee (via a separate lighning, bitcoin or other out of band payment) and is used to provide access to the service.
## Initialisation

A user wants to create a shared key, and they request that the SE initialize the process. To begin, the user must provide a valid `token_id` (UUID) in order to initialise the key, which will be listed in the the server token database. This `token_id` is generated by the SE on payment of a deposit fee (via a separate lighning, bitcoin or other out of band payment) and is used to provide access to the service.

1. The depositor (Owner 1) generates a private key: `o1` and then calculates the corresponding public key `O1 = o1.G`. They also generate an authentication key `a1` and corresponding public key `A1 = a1.G`. These two private keys can be derived from a single BIP32 seed via different paths.
2. Owner 1 requests a key share from the SE with a valid `token_id`, amount value `v` and authentication key `A1`.
3. The SE then generates a private key: `s1` (the SE private key share), calculates the corresponding public key and sends it to Owner 1: `S1 = s1.G` along with a `statechain_id` (UUID - used for the server to reference this shared key). The SE then stores `s1`, `S1`, `v` and `A1` indexed with `statechain_id`.
2. Owner 1 requests a key share from the SE with a valid `token_id` (for access) and authentication key `A1`, and signature for `A1`.
3. The SE then generates a private key: `s1` (the SE private key share), calculates the corresponding public key and sends it to Owner 1: `S1 = s1.G` along with a new random `statechain_id` (UUID - used for the server to reference this shared key). The SE then stores `s1`, `S1` and `A1` indexed with `statechain_id`.
4. Owner 1 then adds the public key they receive by their own public key to obtain the shared (aggregated) public key `P` (which corresponds to a shared private key of `p = o1 + s1`): `P = O1 + S1`
5. Owner 1 creates and broadcasts a funding transaction (`Tx0`) to pay an amount `v` to the address corresponding to `P`. This defines the UTXO `TxID:vout` (the outpoint).
5. Owner 1 creates and broadcasts a funding transaction (`Tx0`) to pay an amount `v` to the bitcoin address derived from `P`. This defines the UTXO `TxID:vout` (the coin outpoint).
6. Owner 1 creates an unsigned *backup transaction* (`Tx1`) that pays the `P` output of `Tx0` to an address `O1`, and sets the `nLocktime` to the initial future block height `h0` (where `h0 = cheight + hinit`, `cheight` is the current Bitcoin block height and `hinit` is the initial locktime specified by the server).
7. Owner 1 cooperates with SE to generate a valid signature on `Tx1` as follows:
7. Owner 1 cooperates with SE to generate a valid signature on `Tx1` as follows (MuSig2):

> To generate a signature on `Tx1`, the owner first computes the sighash `m1`.
> Owner 1 then generates a random ephemeral nonce `r2_1` and blinding nonce `b1` and computes `R2_1 = r2_1.G`
> Owner 1 then requests a co-signing from the SE sending commitments: `SHA256(R2_1)` and `SHA256(b1)`, authenticated with a signature on `A1`.
> SE verifies the signature against `A1` and stores the commitments for `statechain_id` and generates a random `r1_1` and computes `R1_1 = r1_1.G`. `R1_1` is returned to Owner 1.
> Owner 1 then requests a co-signing from the SE authenticated with a signature on `A1`.
> SE verifies the signature against the `A1` stored in the database for `statechain_id` and generates a random `r1_1` and computes `R1_1 = r1_1.G`. `R1_1` is returned to Owner 1.
> Owner 1 then computes `R_1 = R1_1 + r2_1.G + b1.P`, `e1 = SHA256(P||R_1||m1)` and `c1 = e1 + b1` and sends `c1` to the SE.
> The SE then computes `sig1_1 = r1_1 + c1.s1` and sends to Owner 1 (and stores `c1` with `statechain_id`).
> The SE then computes `sig1_1 = r1_1 + c1.s1` and sends to Owner 1.
> Owner 1 computes `sig2_1 = r2_1 + c1.o1` and `sig_1 = sig1_1 + sig2_1`. The full signature `(sig_1,R_1)` is then added to `Tx1`.
8. `Tx1` is verified and stored by Owner 1, along with the values `b1`, `R1_1` and `e1`.
8. `Tx1` signature is verified and stored by Owner 1, along with the values `b1`, `R1_1` and `e1`.
9. The SE then adds the public key `S1` to the list of current statechain SE keys and publishes.

## Transfer

Owner 1 wishes to transfer the value of the deposit `v` to a new owner (Owner 2) (as a payment or as part of a swap). The protocol then proceeds as follows:
Owner 1 wishes to transfer the value of the UTXO `TxID:vout` `v` to a new owner (Owner 2) (as a payment or as part of a swap). The protocol then proceeds as follows:

### Sender

1. The receiver (Owner 2) generates a private key `o2`. They then compute the corresponding public key `O2 = o2.G`. They also generate an authentication key `a2` and corresponding public key `A2 = a2.G`.
2. `O2 || A2` is the Owner 2 'address' and is communicated to Owner 1 (or published) in order for them to send the statecoin to it.
2. `O2 || A2` is the Owner 2 'mercury address' and is communicated to Owner 1 (or published) in order for them to send the statecoin to it.
3. Owner 1 then creates a new unsigned backup transaction `Tx2` paying the output of `Tx0` to the bitcoin address defined from `O2`, and sets the `nLocktime` to `h0 - (n-1)*c` where `c` is the confirmation interval and `n` is the owner number (i.e. 2).
4. Owner 1 cooperates with SE to generate a valid signature on `Tx2` as follows:

> To generate a signature on `Tx2`, the owner first computes the sighash `m2`.
> Owner 1 then generates a random ephemeral nonce `r2_2` and blinding nonce `b2` and computes `R2_2 = r2_2.G`
> Owner 1 then requests a co-signing from the SE sending commitments: `SHA256(R2_2)` and `SHA256(b2)`, authenticated with a signature on `A1`.
> SE stores the commitments for `statechain_id` and generates a random `r1_2` and computes `R1_2 = r1_2.G`. `R1_2` is returned to Owner 1.
> Owner 1 then requests a co-signing from the SE, authenticated with a signature on `A1`.
> SE verifies the signature against the `A1` stored in the database and generates a random `r1_2` and computes `R1_2 = r1_2.G`. `R1_2` is returned to Owner 1.
> Owner 1 then computes `R_2 = R1_2 + r2_2.G + b2.P`, `e2 = SHA256(P||R_1||m1)` and `c2 = e2 + b2` and sends `c2` to the SE.
> The SE then computes `sig1_2 = r1_2 + c2.s1` and sends to Owner 1 (and stores `c2` with `statechain_id`).
> The SE then computes `sig1_2 = r1_2 + c2.s1` and sends to Owner 1.
> Owner 1 computes `sig2_2 = r2_2 + c2.o1` and `sig_2 = sig1_2 + sig2_2`. The full signature `(sig_2,R_2)` is then added to `Tx2`.
5. SE generates a random key `x1` and sends it to Owner 1.
Expand All @@ -57,17 +59,15 @@ Owner 1 wishes to transfer the value of the deposit `v` to a new owner (Owner 2)

a. All `K` (here `K = 2`) signed backup transactions (`Txi i=1,...,K`): `Tx1` and `Tx2`

b. For each backup transaction signature (`bi`,`R2_i i=1,...,K`): `b1`,`b2`,`R2_1` and `R2_2`.

c. `SC_sig_1`
b. `SC_sig_1`

d. `t1`
c. `t1`

e. `statechain_id`
d. `statechain_id`

9. `TransferMsg` is encrypted with `A2`: `EncTransferMsg = Enc(TransferMsg,A2)`. `EncTransferMsg` is then sent to Owner 2. As it is encrypted, this can be via the server - i.e. the message is uploaded to the server and stored indexed with `A2`.
9. `TransferMsg` is encrypted with the receiver key `A2`: `EncTransferMsg = Enc(TransferMsg,A2)`. `EncTransferMsg` is then sent to Owner 2. As it is encrypted, this can be relayed via the server - i.e. the message is uploaded to the server and stored indexed with `A2`.

> At this point the Owner 1 has sent all the information required to complete the transfer to Owner 2 and is no longer involved in the protocol. Owner 2 then verifies the correctness and validity of the objects as follows.
> At this point the Owner 1 has sent all the information required to complete the transfer to Owner 2 and is no longer involved in the protocol. Owner 2 then verifies the correctness and validity of the objects as follows:
### Receiver

Expand All @@ -80,34 +80,30 @@ Owner 1 wishes to transfer the value of the deposit `v` to a new owner (Owner 2)

b. The `nLocktimes` are decremented correctly (i.e. the latest `TxK` has the lowest).

c. Retreives `ci`, and commitments `SHA256(R2_i)` and `SHA256(bi)` from the SE.

d. Verifies the commitments to `R2_i` and `bi` and verfies that `ci = bi + SHA256(P||R_i||mi)` (where `mi` is the sighash of `Txi`).

5. Owner 2 queries SE for 1) The total number of signatures generated for `statechain_id`: `N` and 2) Current SE public key share. 3) The public point `X1 = x1.G`
6. Owner 2 then verifies that `K = N` and that `t1.G = O1 + X1`
7. Verify the signature `SC_sig_1` verifies against `O1` and that `P = S1 + O1`. This check mitigates the key cancellation vulnerability.
6. Owner 2 then verifies that `K = N` and that `t1.G = O1 + X1`. This check verifies that the value `t1` has been computed correctly from the sender private key.
7. Owner 2 verifies the signature `SC_sig_1` verifies against `O1` and that `P = S1 + O1`. This check mitigates the key cancellation vulnerability.

The SE key share update then proceeds as follows:

5. Owner 2 computes `t2 = t1 - o2`.
6. Owner 2 then sends `t2` to the SE, authenticated with a signature on `A2`.
7. SE the updates the private key share `s2 = s1 + t2 - x1 = s1 + x1 + o1 - o2 - x1 = s1 + o1 - o2`

> `s2` and `o2` are now key the private key shares of `P = (s2 + o2).G` which remains unchanged (i.e. `s2 + o2 = s1 + o1`), without anyone having learnt the full private key. Provided the SE deletes `s1`, then there is no way anyone but the current owner (with `o2`) can spend the output.
> `s2` and `o2` are now key the private key shares of `P = (s2 + o2).G` which remains unchanged (i.e. `s2 + o2 = s1 + o1`), without anyone having learnt the full private key. Provided the SE deletes `s1`, then there is no way anyone but the current owner (with `o2`) can spend the output.
8. The SE then adds the current server public key share `S2` and signature count `K` to the list of active key shares and publishes. This enables the current owner to verify that their share (`O2`) uniquely combines with the published share.

## Orderly Withdrawal
## Orderly Closure

The current owner of a coin can at any time withdraw from the platform by simply co-signing a withdrawal transaction. The server cannot identify a withdrawal, but the coin can no longer be transferred to a new owner because the server will have produced an additional signature that cannot be verified as a valid backup by a receiver.
The current owner of a coin can at any time close the shared key session from the platform by simply co-signing a withdrawal transaction. The server cannot identify a closure transaction, but the coin can no longer be transferred to a new owner because the server will have produced an additional signature that cannot be verified as a valid backup by a receiver.

Withdrawal proceeds as follows:

1. The current owner (e.g. Owner 2) creates an unsigned transaction `TxW` that spends `Tx0` to a withdrawal address `W`.
2. The owner then co-signs this transaction with the SE (as above). `TxW` is broadcast.
3. The owner then sends the SE a withdrawal notification (with their current `user_id`) that the coin is withdrawn so the SE can remove the coin public key from the published key share list.

## Backup withdrawal
## Backup Closure

In the case that the SE disappears or does not cooperate with the current owner, the current owner can reclaim their funds to an address they control by submitting their backup transaction when the `nLocktime` is reached.

0 comments on commit c9693b2

Please sign in to comment.