-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
cmd
committed
Oct 13, 2023
1 parent
6402b75
commit fba7619
Showing
39 changed files
with
1,984 additions
and
530 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# Contract | ||
|
||
A contract is the result of a proposal that has been verified and published. It is hosted by our platform and accessible via the `contract_id`. Each contract is assigned an automated `agent`. This agent will service the contract, collect signatures from depositors, and produce the final spending transaction once a settlement is reached. | ||
|
||
```ts | ||
{ | ||
active_at : null, | ||
agent : {} as AgentSession, | ||
balance : 0, | ||
cid : 'f86bea011ea7415e44c3fa3097141553f00b713e1f2a489535eec31687717eca', | ||
covenants : [] as Covenant[], | ||
created_at : 1696960555, | ||
deadline : 7200, | ||
expires : null, | ||
fees : [[ 1500, 'bcrt1q0rt35v4scsmw3udps84rdctduvzz0tlvst0lpq' ]], | ||
templates : [] as SpendTemplate[], | ||
terms : {} as ProposalData, | ||
state : null, | ||
status : 'published', | ||
target : 101500, | ||
tx : null, | ||
witness : [] as WitnessEntry[] | ||
} | ||
``` | ||
|
||
## Glossary | ||
|
||
The following table defines a complete list of terms that are included in a contract. | ||
|
||
| Term | Description | | ||
|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||
| active_at | The UTC timestamp (in seconds) of when the contract was activated. If the contract is inactive, this value is null. | | ||
| agent | The details of the signing agent. Used for collecting pre-signed covenants from depositors. | | ||
| balance | The current balance of the contract, which is the sum of all deposits that have been confirmed and signed. | | ||
| cid | A hash commitment of the complete terms of the contract. | | ||
| covenants | A collection of covenant packages that have been pleged to the contract. | | ||
| created_at | The UTC timestamp (in seconds) of when the contract was published. | ||
| deadline | The amount of time (in seconds) available for collecting funds, starting from the published date. | | ||
| expires | The UTC timestamp (in seconds) of when the contract expires. If the contract is inactive, this value is null. | | ||
| fees | A collection of spending outputs that should be included in all spending paths. This field is defined by the platform. | | ||
| templates | A collection of spending templates, labeled by path name. These templates are computed from the proposal and contract fees. | | ||
| terms | The full terms of the contract. This field should be identical to the original proposal. | | ||
| state | The current serialized state of the virtual machine (CVM). If the contract is inactive, this value is null. | | ||
| status | The current status of the contract. | | ||
| target | The target value that must be covered by deposits. The contract `balance` must exceed this value by the specified `deadline`. | | ||
| tx | Information regarding the settlement transaction. If the contract has not yet been settled, this value is null. | | ||
| witness | A collection of signed statements from the contract members. Each statement is evaluated inside the CVM. | | ||
|
||
## Components | ||
|
||
### Agent Session | ||
|
||
### Fees | ||
|
||
### Templates | ||
|
||
### Terms | ||
|
||
## Covenants | ||
|
||
## Virtual Machine (CVM) | ||
|
||
### Programs | ||
|
||
### State | ||
|
||
### Witness | ||
|
||
### Verification | ||
|
||
## Settlement |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
## Covenants | ||
|
||
Once a deposit is secured, the depositor can then negotiate with the agent in order to pledge funding towards a contract. | ||
|
||
However, there are several issues when negotiating a pledge of funds: | ||
|
||
* It is not immediately clear which set of outputs should be chosen for settlement. | ||
* A contract may not close right away, so the movement of funds is deferred. | ||
* A depositor may refuse to participate in the fair settlement of a contract. | ||
|
||
To address the issues above, the depositor constructs a "covenant", or a package of pre-signed transactions, then provides these signatures to the agent. The covenant provides the agent with a limited authorization on how the deposit may be spent. | ||
|
||
Each signature produced by the depositor is a partial one, thus it cannot be used by the depositor to move funds prematurely. This limited authorization is transferred exclusively to the agent, as only the agent is capable of completing a given partial signature. | ||
|
||
Each signature is signed using the sighash flag ANYONECANPAY, thus the deposit may be included with any combination of other inputs used to fund the contract. | ||
|
||
The covenant itself is constructed using a custom protocol based on the musig2 specification, with a number of optimizations. The largest optimization is the establishment of a "root" nonce value, which is further tweaked by each depositor using a non-interactive protocol. | ||
|
||
This optimization allows for an unbounded number of depositors to cooperate with the agent, and for each depositor to pre-sign an unlimited number of transactions - all within a single round of communication. | ||
|
||
The protocol is relatively simple: | ||
|
||
```md | ||
All parties compute a hash that commits to the full terms of the contract. | ||
|
||
Ex: hash340('contract/id', serialize(contract_terms)) | ||
|
||
Each member uses this hash to produce a "root" secret nonce value (using BIP340). | ||
|
||
The agent shares their root public nonce value and public key with all depositors. | ||
|
||
For each transaction, the depositor performs the following protocol: | ||
|
||
The depositor produces a second commitment that includes both root pnonces, plus the transaction. | ||
|
||
Ex: hash340('contract/root_tweak', depositor_root_pnonce, agent_root_pnonce, sighash(tx)) | ||
|
||
This second hash is used to tweak the root pnonce for both the depositor and the agent. | ||
|
||
The agent pubkey and new pnonce values are used to perform a musig2 signing operation and produce a partial signature for the transaction. | ||
|
||
Each depositor delivers their pubkey, root pnonce value and package of signatures to the agent. | ||
``` | ||
|
||
The purpose of the root pnonce value is to guarantee that each derived pnonce value is computed fairly, regardless of which participant performs the computation. Each new tweak commits to the root pnonce values and specific transaction being signed. | ||
|
||
Each partial signature is constructed using the standard musig2 protocol, so the security model of the original musig2 paper still holds. | ||
|
||
The agent does not generate any signature material, nor pnonce values outside of the root, so random oracle attacks do not apply. | ||
|
||
Once all deposits and covenant packages have been collected for a given contract (and verified by the agent), the contract is considered live and executable. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Deposits | ||
|
||
In order for an agent to negotiate funding on behalf of a contract, there needs to be some guarantee that a funding source cannot be spent pre-maturely. If a single source of funds is spent before the contract matures, then the contract as a whole will become under-funded, and thus unable to settle. | ||
|
||
To produce this guarantee, we are we are using a 2-of-2 musig output, with a time-locked recovery script as the basis for a deposit utxo. | ||
|
||
* The two-party musig protects the depositor and agent from any custodial concerns. | ||
* The time-lock ensures exclusivity on the spending of funds for a limited time. | ||
* The script reserves the depositor's right to refund after the timelock expires. | ||
|
||
The depositor collects a public key from the agent, then combines it with their own public key to produce a group key (using musig2). This group key is further tweaked (using taproot) to add the time-locked recovery script. | ||
|
||
The depositor may decide how long the time-lock should be. For a deposit to be considered safe to include in a contract, the time remaining on the lock must be greater than the expiration date of the contract. | ||
|
||
If a depositor is only interested in a specific contract, then their time-lock should not exceed the expiration date of the contract. However, if a depositor would like to re-use their deposit in the event a contract fails to execute, then a longer time-lock may be desirable. |
Oops, something went wrong.