From 4fda7ff7f606ab686b08d36a285f4cb97d357cac Mon Sep 17 00:00:00 2001 From: Ouziel Slama Date: Mon, 11 Nov 2024 11:17:32 +0100 Subject: [PATCH 1/2] Update UTXO Support documentation --- docs/advanced/specifications/utxo-support.md | 120 +++++++++++++++---- 1 file changed, 94 insertions(+), 26 deletions(-) diff --git a/docs/advanced/specifications/utxo-support.md b/docs/advanced/specifications/utxo-support.md index e35ef8d4..c3327d74 100644 --- a/docs/advanced/specifications/utxo-support.md +++ b/docs/advanced/specifications/utxo-support.md @@ -8,58 +8,126 @@ With Ordinals, a user who does not own an Ordinal cannot create a valid Bitcoin 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. -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. +Three new contracts allow managing UTXOs: + +- `attach.py` to move assets from an address to a UTXO +- `detach.py` to move assets from a UTXO to an address +- `move.py` to move assets from one UTXO to another 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. 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. -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. +Then the `parse_tx()` function will check that the `utxos_info` field contains entries and if so will pass them to the `move.move_assets()` function. + +Here is the signature of the three new compose functions: -Here is the signature of the `utxo.compose()` function: +**`compose_attach()`** ```python -def compose(db, source, destination, asset, quantity): +def compose_attach( + db, + address: str, + asset: str, + quantity: int, + destination_vout: str = None, + **construct_args, +): """ - 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 + Composes a transaction to attach assets from an address to UTXO. + :param address: The address from which the assets are attached + :param asset: The asset or subasset to attach (e.g. XCP) + :param quantity: The quantity of the asset to attach (in satoshis, hence integer) (e.g. 1000) + :param destination_vout: The vout of the destination output """ ``` -For convenience, two functions, as well as two distinct routes, will be made available: +**`compose_detach()`** ```python -"/v2/addresses/
/compose/attach": transaction.compose_attach, -"/v2/utxos//compose/detach": transaction.compose_detach, +def compose_detach( + db, + utxo: str, + destination: str = None, + **construct_args, +): + """ + Composes a transaction to detach assets from UTXO to an address. + :param utxo: The utxo from which the assets are detached + :param destination: The address to detach the assets to, if not provided the addresse corresponding to the utxo is used + """ +``` + +**`compose_movetoutxo()`** + +```python +def compose_movetoutxo(db, utxo: str, destination: str, **construct_args): + """ + Composes a transaction to move assets from UTXO to another UTXO. + :param utxo: The utxo from which the assets are moved + :param destination: The address to move the assets to + """ ``` ## Considerations -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`. +### Attach + +1. It is possible to attach an arbitrary number of assets from an address to a UTXO. + +1. Assets are attached from transaction source address to the first UTXO non- `OP_RETURN` output or, if provided, to the `destination_vout` output. + +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. + +1. 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`. + +1. For each `attach` a row will be added to the `send` table, triggering the `ATTACH_TO_UTXO` event. + +1. When assets are attached to a UTXO, it is impossible to use them for a Counterparty transaction (`order`, `send`, etc.) apart from `detach`. + +1. The embedded data in a `attach` transaction is small enough that an `OP_RETURN` output is always sufficient. + +### Detach + +1. All inputs of a `detach` transaction are detached. + +1. If no `destination` is provided, the assets are sent to the address corresponding to the detached input. + +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. + + +### Move + +1. `utxo.move_assets()` is executed before 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 Changes -Three new routes will be added: +1. Four new routes will be added: ```python -"/v2/addresses/
/compose/attach": transaction.compose_attach, -"/v2/utxos//compose/detach": transaction.compose_detach, -"/v2/utxos//compose/movetoutxo": transaction.compose_movetoutxo, +"/v2/addresses/
/compose/attach": compose.compose_attach, +"/v2/utxos//compose/detach": compose.compose_detach, +"/v2/utxos//compose/movetoutxo": compose.compose_movetoutxo, +"/v2/compose/attach/estimatexcpfees": compose.get_attach_estimate_xcp_fee, ``` -Balances will now contain an additional `utxo` field. +1. To prevent assets from being moved unintentionally, the transaction composition API excludes UTXOs with assets attached by default. + +1. Balances will now contain two additionals fields: `utxo` and `utxo_address`. ## Database Changes -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 `:` . +`utxo` and `utxo_address` fields 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 `:` . + +A `utxos_info` field will be added to the `transactions` table. This field will contain: -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. \ No newline at end of file +- the list of inputs with assets attached +- the first non-OP_RETURN output +- the number of outputs +- the position of a possible OP_RETURN output \ No newline at end of file From 9e28a2263a2fefe40152accf8bb17c3d035db469 Mon Sep 17 00:00:00 2001 From: Adam Krellenstein Date: Mon, 11 Nov 2024 08:05:31 -0500 Subject: [PATCH 2/2] Edit UTXO Support Docs --- docs/advanced/specifications/utxo-support.md | 106 +++---------------- 1 file changed, 16 insertions(+), 90 deletions(-) diff --git a/docs/advanced/specifications/utxo-support.md b/docs/advanced/specifications/utxo-support.md index c3327d74..5ed2f854 100644 --- a/docs/advanced/specifications/utxo-support.md +++ b/docs/advanced/specifications/utxo-support.md @@ -2,113 +2,50 @@ # 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. - -Three new contracts allow managing UTXOs: - -- `attach.py` to move assets from an address to a UTXO -- `detach.py` to move assets from a UTXO to an address -- `move.py` to move assets from one UTXO to another 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. - -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. - -Then the `parse_tx()` function will check that the `utxos_info` field contains entries and if so will pass them to the `move.move_assets()` function. - -Here is the signature of the three new compose functions: - -**`compose_attach()`** - -```python -def compose_attach( - db, - address: str, - asset: str, - quantity: int, - destination_vout: str = None, - **construct_args, -): - """ - Composes a transaction to attach assets from an address to UTXO. - :param address: The address from which the assets are attached - :param asset: The asset or subasset to attach (e.g. XCP) - :param quantity: The quantity of the asset to attach (in satoshis, hence integer) (e.g. 1000) - :param destination_vout: The vout of the destination output - """ -``` - -**`compose_detach()`** - -```python -def compose_detach( - db, - utxo: str, - destination: str = None, - **construct_args, -): - """ - Composes a transaction to detach assets from UTXO to an address. - :param utxo: The utxo from which the assets are detached - :param destination: The address to detach the assets to, if not provided the addresse corresponding to the utxo is used - """ -``` - -**`compose_movetoutxo()`** - -```python -def compose_movetoutxo(db, utxo: str, destination: str, **construct_args): - """ - Composes a transaction to move assets from UTXO to another UTXO. - :param utxo: The utxo from which the assets are moved - :param destination: The address to move the assets to - """ -``` - -## Considerations - -### Attach +## Attach 1. It is possible to attach an arbitrary number of assets from an address to a UTXO. -1. Assets are attached from transaction source address to the first UTXO non- `OP_RETURN` output or, if provided, to the `destination_vout` 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. 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. -1. 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`. +1. Fees in XCP, calculated using the [new gas system](gas-system.md), will be paid by the `source` address for an `attach`. -1. For each `attach` a row will be added to the `send` table, triggering the `ATTACH_TO_UTXO` event. +1. For each `attach`, a row will be added to the `send` table, triggering the `ATTACH_TO_UTXO` event. -1. When assets are attached to a UTXO, it is impossible to use them for a Counterparty transaction (`order`, `send`, etc.) apart from `detach`. +1. When assets are attached to a UTXO, it is impossible to use them for a Counterparty transaction (`order`, `send`, etc.), apart from `detach`. 1. The embedded data in a `attach` transaction is small enough that an `OP_RETURN` output is always sufficient. -### Detach -1. All inputs of a `detach` transaction are detached. +## Detach + +1. All inputs of every `detach` transaction are detached. 1. If no `destination` is provided, the assets are sent to the address corresponding to the detached input. 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. 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. -### Move +## Move -1. `utxo.move_assets()` is executed before Counterparty contracts except for `attach` transaction. +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 Changes -1. Four new routes will be added: +# API + +1. API routes ```python "/v2/addresses/
/compose/attach": compose.compose_attach, @@ -119,15 +56,4 @@ def compose_movetoutxo(db, utxo: str, destination: str, **construct_args): 1. To prevent assets from being moved unintentionally, the transaction composition API excludes UTXOs with assets attached by default. -1. Balances will now contain two additionals fields: `utxo` and `utxo_address`. - -## Database Changes - -`utxo` and `utxo_address` fields 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 `:` . - -A `utxos_info` field will be added to the `transactions` table. This field will contain: - -- the list of inputs with assets attached -- the first non-OP_RETURN output -- the number of outputs -- the position of a possible OP_RETURN output \ No newline at end of file +1. Balances contain two fields for UTXO support: `utxo` and `utxo_address`.