Skip to content

Commit

Permalink
Merge pull request #220 from CounterpartyXCP/utxosupport
Browse files Browse the repository at this point in the history
Update UTXO Support documentation
  • Loading branch information
adamkrellenstein authored Nov 11, 2024
2 parents ebe7b96 + 9e28a22 commit ba167d8
Showing 1 changed file with 35 additions and 41 deletions.
76 changes: 35 additions & 41 deletions docs/advanced/specifications/utxo-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,58 @@

# Motivations

With Ordinals, a user who does not own an Ordinal cannot create a valid Bitcoin transaction to move an Ordinal that is not in their wallet. This is because the user must possess the UTXO that holds the "sat". Unlike Ordinals, Counterparty as a metaprotcol is entirely detached from Layer-1 consensus rules—this allows Counterparty to be much more versatile and extendable. However, Ordinals, given its large community, offers Counterparty asset owners the opportunity to benefit from greater liquidity and a larger ecosystem generally. For this it is necessary to be able to **attach and detach Counterparty assets to/from UTXOs**. This will allow Counterparty assets to be compliant with the Ordinals trading transactional structure, allowing the large players in the Ordinals ecosystem to seamlessly integrate with Counterparty assets.
With UTXO support, it is possible to **attach** / **detach** Counterparty assets directly to / from Bitcoin UTXOs, so that they can be spent just like Colored Coins–based protocols (such as Ordinals and Runes) using any Bitcoin wallets with support for sat tracking. This featuer enables single-transaction, trustless atomic swaps between BTC and Counterparty assets, as well as Counterparty assets and other L2 protocols. Attaching assets to UTXOs uses the [new gas system](gas-system.md) that allows for a dynamic XCP fee for transactions to reduce the barrier to entry into Counterparty for new users.

# Design

The `balances`, `credits` and `debits` tables, as well as the `ledger.credit()` and `ledger.debit()` functions will be modified to be able to support balances attached to UTXOs.
## Attach

A new contract `utxo.py` will allow you to attach and detach assets from a UTXO. This new contract will be similar to a classic `send` except that the source and destination will be integrated into the data embedded in the transaction.
1. It is possible to attach an arbitrary number of assets from an address to a UTXO.

The `get_tx_info()` function will be modified to also return inputs with attached assets as well as the first non-OP_RETRUN output.
1. Assets are attached from transaction source address to the first UTXO non-`OP_RETURN` output or, if provided, to the `destination_vout` output.

The inputs and output returned by `get_tx_info()` will be stored in the `utxos_info` field of the `transactions` table by the `list_tx()` function.
1. If `destination_vout` designates an invalid output (`OP_RETURN` or non-existent) or if the transaction contains only a single OP_RETURN output, the transaction is invalid.

Then the `parse_tx()` function will check that the `utxos_info` field contains entries and if so will pass them to the `utxo.move_assets()` function.
1. Fees in XCP, calculated using the [new gas system](gas-system.md), will be paid by the `source` address for an `attach`.

Here is the signature of the `utxo.compose()` function:
1. For each `attach`, a row will be added to the `send` table, triggering the `ATTACH_TO_UTXO` event.

```python
def compose(db, source, destination, asset, quantity):
"""
Compose a UTXO message.
source: the source address or UTXO
destination: the destination address or UTXO
asset: the asset to transfer
quantity: the quantity to transfer
"""
```
1. When assets are attached to a UTXO, it is impossible to use them for a Counterparty transaction (`order`, `send`, etc.), apart from `detach`.

For convenience, two functions, as well as two distinct routes, will be made available:
1. The embedded data in a `attach` transaction is small enough that an `OP_RETURN` output is always sufficient.

```python
"/v2/addresses/<address>/compose/attach": transaction.compose_attach,
"/v2/utxos/<utxo>/compose/detach": transaction.compose_detach,
```

## Considerations
## Detach

1. It is possible to attach and detach an arbitrary number of assets from an address or UTXO, however when a UTXO is used in a transaction, all assets attached to that UTXO are moved to the first UTXO non- `OP_RETURN` output of the transaction.
2. Fees in XCP, calculated using the [new Gas system](https://gist.github.com/adamkrellenstein/7c7cab257cee162233fc2ba6682eb8da), will be paid by the source address for an `attach`.
3. `utxo.move_assets()` is executed before Counterparty contracts. This means that if a UTXO with attached assets is used for a Counterparty transaction, the assets are first moved and then the Counterparty transaction executed.
4. To avoid problems due to (3), a new parameter `exclude_utxos` will be added to all transaction composition functions.
5. For each `attach` and `detach`, a row will be added to the `send` table, triggering the `ATTACH_TO_UTXO` and `DETACH_FROM_UTXO` events respectively.
6. When a UTXO is spent, a row is added to the `send` table for each asset attached to this UTXO, triggering a `UTXO_MOVE` event.
7. When assets are attached to a UTXO, it is impossible to use them for a Counterparty transaction (`order`, `send`, etc.) apart from `detach`.
1. All inputs of every `detach` transaction are detached.

## API Changes
1. If no `destination` is provided, the assets are sent to the address corresponding to the detached input.

Three new routes will be added:
1. It is impossible to perform a `move` at the same time as a `detach`.

1. For each `detach`, a row will be added to the `send` table, triggering the `DETACH_FROM_UTXO` event.

1. The embedded data in a `detach` transaction is small enough that an `OP_RETURN` output is always sufficient.

```python
"/v2/addresses/<address>/compose/attach": transaction.compose_attach,
"/v2/utxos/<utxo>/compose/detach": transaction.compose_detach,
"/v2/utxos/<utxo>/compose/movetoutxo": transaction.compose_movetoutxo,
```

Balances will now contain an additional `utxo` field.
## Move

## Database Changes
1. `utxo.move_assets()` is executed before all Counterparty contracts, except for `attach` transaction.

1. When a UTXO is spent, a row is added to the `send` table for each asset attached to this UTXO, triggering a `UTXO_MOVE` event.


# API

1. API routes

```python
"/v2/addresses/<address>/compose/attach": compose.compose_attach,
"/v2/utxos/<utxo>/compose/detach": compose.compose_detach,
"/v2/utxos/<utxo>/compose/movetoutxo": compose.compose_movetoutxo,
"/v2/compose/attach/estimatexcpfees": compose.get_attach_estimate_xcp_fee,
```

A `utxo` field will be added to the `credits`, `debits` and `balances` tables. One of the two fields, `address` or `utxo` will be null. The format of the `utxo` field is `<tx_hash>:<n>` .
1. To prevent assets from being moved unintentionally, the transaction composition API excludes UTXOs with assets attached by default.

A `utxos_info` field will be added to the `transactions` table. This field will contain a list of UTXOs separated by spaces. The last in the list is the first non-`OP_RETURN` output of the transaction, and the previous ones, if present, are the transaction inputs with assets attached. If there is more than one, that means we need to move all the assets of the first(s) UTXO(s) to the last one.
1. Balances contain two fields for UTXO support: `utxo` and `utxo_address`.

0 comments on commit ba167d8

Please sign in to comment.