├── imgs
├── atlas.png
├── Sign-Order.png
├── CreateChannel.png
├── Global-Pool.png
├── HTLC-diagram.png
├── RSMC-C1a-RD1a.png
├── RSMC-diagram.png
├── orderbookAMM.png
├── orderbookAMM2.png
├── Channel-States.png
├── Matching-Engine.png
├── Matching-Orders.png
├── impermanentLoss.png
├── intervalsUnion.png
├── localExpansion.png
├── Channel-States-new.png
├── Swap-Architecture.png
├── WebSocketTestSite.png
├── expansionExample.png
├── topologicalSpace.png
├── C3a-Terminate-a-HTLC.png
├── OmniBOLT-Protocol-Suite.png
├── constantFuncDerivative.png
├── differentMarketStates.png
├── C3a-Terminate-a-HTLC-both-sides.png
├── HTLC-diagram-with-Breach-Remedy.png
└── HTLC-diagram-with-Breach-Remedy-BTC-channel.png
├── docs
└── OmniBOLT-Technology-guide-part-I-2020-05-01_en.pdf
├── LICENSE
├── OmniBOLT-01-basic-protocol-and-Terminology.md
├── OmniBOLT-06-Mortgage-Loan-Contracts-for-Crypto-Assets.md
├── README.md
├── OmniBOLT-07-Hierarchical-Deterministic-(HD)-wallet.md
├── OmniBOLT-05-Atomic-Swap-among-Channels.md
├── OmniBOLT-02-peer-protocol.md
├── OmniBOLT-04-HTLC-and-Payment-Routing.md
├── OmniBOLT-06-Automatic-Market-Maker-and-DEX.md
└── OmniBOLT-03-RSMC-and-OmniLayer-Transactions.md
/imgs/atlas.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/atlas.png
--------------------------------------------------------------------------------
/imgs/Sign-Order.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/Sign-Order.png
--------------------------------------------------------------------------------
/imgs/CreateChannel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/CreateChannel.png
--------------------------------------------------------------------------------
/imgs/Global-Pool.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/Global-Pool.png
--------------------------------------------------------------------------------
/imgs/HTLC-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/HTLC-diagram.png
--------------------------------------------------------------------------------
/imgs/RSMC-C1a-RD1a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/RSMC-C1a-RD1a.png
--------------------------------------------------------------------------------
/imgs/RSMC-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/RSMC-diagram.png
--------------------------------------------------------------------------------
/imgs/orderbookAMM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/orderbookAMM.png
--------------------------------------------------------------------------------
/imgs/orderbookAMM2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/orderbookAMM2.png
--------------------------------------------------------------------------------
/imgs/Channel-States.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/Channel-States.png
--------------------------------------------------------------------------------
/imgs/Matching-Engine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/Matching-Engine.png
--------------------------------------------------------------------------------
/imgs/Matching-Orders.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/Matching-Orders.png
--------------------------------------------------------------------------------
/imgs/impermanentLoss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/impermanentLoss.png
--------------------------------------------------------------------------------
/imgs/intervalsUnion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/intervalsUnion.png
--------------------------------------------------------------------------------
/imgs/localExpansion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/localExpansion.png
--------------------------------------------------------------------------------
/imgs/Channel-States-new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/Channel-States-new.png
--------------------------------------------------------------------------------
/imgs/Swap-Architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/Swap-Architecture.png
--------------------------------------------------------------------------------
/imgs/WebSocketTestSite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/WebSocketTestSite.png
--------------------------------------------------------------------------------
/imgs/expansionExample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/expansionExample.png
--------------------------------------------------------------------------------
/imgs/topologicalSpace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/topologicalSpace.png
--------------------------------------------------------------------------------
/imgs/C3a-Terminate-a-HTLC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/C3a-Terminate-a-HTLC.png
--------------------------------------------------------------------------------
/imgs/OmniBOLT-Protocol-Suite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/OmniBOLT-Protocol-Suite.png
--------------------------------------------------------------------------------
/imgs/constantFuncDerivative.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/constantFuncDerivative.png
--------------------------------------------------------------------------------
/imgs/differentMarketStates.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/differentMarketStates.png
--------------------------------------------------------------------------------
/imgs/C3a-Terminate-a-HTLC-both-sides.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/C3a-Terminate-a-HTLC-both-sides.png
--------------------------------------------------------------------------------
/imgs/HTLC-diagram-with-Breach-Remedy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/HTLC-diagram-with-Breach-Remedy.png
--------------------------------------------------------------------------------
/imgs/HTLC-diagram-with-Breach-Remedy-BTC-channel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/imgs/HTLC-diagram-with-Breach-Remedy-BTC-channel.png
--------------------------------------------------------------------------------
/docs/OmniBOLT-Technology-guide-part-I-2020-05-01_en.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/omnilaboratory/OmniBOLT-spec/HEAD/docs/OmniBOLT-Technology-guide-part-I-2020-05-01_en.pdf
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2009-2019 The Bitcoin Core developers
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/OmniBOLT-01-basic-protocol-and-Terminology.md:
--------------------------------------------------------------------------------
1 | # OmniBOLT #1: Basic Protocol and Terminology
2 |
3 | ## Terminology
4 |
5 | * `OBD`: OmniBOLT Daemon.
6 | * `channel`: A channel refers to Poon-Dryja channel in the lightning network. Channel is denoted by `[Alice, USDT, Bob]`, which means Alice and Bob build a channel and fund it by USDT.
7 | * `asset id`: Each asset has an id(unsigned 32-bit integer) that is published by Omnilayer on the mainnet. In most protocol messages, if `asset_id = 0`, then OmniBOLT processes bitcoin transactions, and is compatible with the current bitcoin-only lightning network. Other assets, for example, `OMNI` has asset id `1`, USDT has asset id `31` on the mainnet.
8 | * `[A, token symbol, B]`: stands for the channel built by A and B, funded by token `token symbol`, for example, `omni`,`usdt`.
9 | * `[A --(10 USDT)--> B]`: A pays 10 usdt to B in channel `[A, USDT, B]`.
10 | * `property`: refers to tokens issued on Omnilayer, the same as "asset".
11 | * `RSMC`: Revocable Sequence Maturity Contract is composed to punish malicious peers, who broadcast elder commitment transactions to get more refund than what's exactly in his balance.
12 | * `HTLC`: Hashed Time-Lock Contract chains multiple channels for transferring tokens from one peer to another, between whom there is no direct channel established.
13 | * `Commitment Transaction`: is created but not broadcast, and will be invalidated by the next commitment transaction.
14 | * `BR`: Breach Remedy transaction is used in RSMC, that if Alice cheats by broadcasting an elder commitment transaction, BR will send all her money to Bob.
15 | * `RD`: Revocable Delivery transaction pays out from the 2-2 P2SH transaction output, when Alice broadcast the latest legitimate commitment transaction. It sends money to Bob immediately and will send money to Alice after relatively, say 100 blocks, from the current block height.
16 | * `HED`: HTLC Execution Delivery
17 | * `HT`: HTLC Timeout
18 | * `HBR`: HTLC Breach Remedy, the breach remedy transaction in HTLC
19 | * `HTRD`: HTLC Timeout Revocable Delivery, the revocable delivery transaction in HTLC
20 | * `HTBR`: HTLC Timeout Breach Remedy, punishes Alice who broadcasts the elder hash time-locked transaction during the time lock period.
21 | * `Atomic Swap`: Atomic swap technology enables the exchange of one cryptocurrency for another without using centralized intermediaries, such as exchanges.
22 | * `HTLSC`: Hashed TimeLock Swap Contract, which consists of two separate HTLCs with an extra specified exchange rate of tokens and time lockers.
23 |
24 | ## Data types
25 |
26 | `byte_array`: an array of bytes, the first 2 bytes indicate the length of the array. the maximum length is 65535
27 | `32*byte`: a fixed-length version of `byte_array`, where the decimal value of the first 2 bytes is 32.
28 | `64*byte`: a fixed-length version of `byte_array`, where the decimal value of the first 2 bytes is 64.
29 | `float64`: 8 bytes represent a float number, [8 decimal is allowed and can be recognized](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-03-RSMC-and-OmniLayer-Transactions.md#string-to-int64)
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/OmniBOLT-06-Mortgage-Loan-Contracts-for-Crypto-Assets.md:
--------------------------------------------------------------------------------
1 | # OmniBOLT #6: Collateral Lending Contract, online store and more Applications
2 |
3 | **The content of this section will be moved to the community discussion forum and will no longer be part of the specification until proven feasible**
4 |
5 |
6 | Following examples use multi-stage atomic swaps for specific scenarios. Each procedure shall be implemented as a piece of program written in a turing complete language, like Javascript or Solidity, calling obd API to execute the foundamental tasks. All participants shall run the program to check if all the transactions are valid and if the counterparties are honest.
7 |
8 |
9 |
10 | ## Collateral Lending Contract (CLC)
11 | Collateral Lending Contract serves this certain purpose:
12 |
13 | >“
14 | You deposit something valuable as mortgage in an escrow account, and I lend money to you according to a proper LTV(Loan to Value). If you repay the loan within agreed deadline, i will return your mortgage. If you don’t, your mortgage will be mine.
15 | ”
16 |
17 |
18 | Actually an HTLSC creates an escrow accounts for participants in a loan. We assume a normal scenario:
19 |
20 | >Bob wants to borrow 900 USDT from Alice, he use his 1 BTC as collateral.
21 |
22 | So Bob initiates a swap (HTLSC 1):
23 |
24 | 1) Bob --> Alice: swap(amount = 1 BTC, property = USDT, exchange_rate = 900, time_locker = 30 days, Hash(R1), ...).
25 | This creates HTLSC in channel `[Alice, BTC, Bob]`.
26 |
27 | 2) Alice --> Bob: swap_accepted(amount = 900 USDT, exchange_rate = 900, time_locker = 20 days, Hash(R1), ...).
28 | This creates HTLSC in channel `[Alice, USDT, Bob]`.
29 |
30 |
31 | Meanwhile, Bob needs to create the redeem swap (HTLSC 2) to get his 1 BTC back:
32 |
33 | 1) Bob --> Alice: swap(amount = 900 USDT, property = BTC, exchange_rate = 1/900, time_locker = 60 days, Hash(R2), ...).
34 | This creates HTLSC in channel `[Alice, USDT, Bob]`.
35 |
36 | 1) Alice --> Bob: swap_accepted(amount = 1 BTC, exchange_rate = 1/900, time_locker = 50 days, Hash(R2), ...).
37 | This creates HTLSC in channel `[Alice, BTC, Bob]`.
38 |
39 | Only when the participants accepted the two swaps, and their OBDs helps to create all the corresponding transaction required by HTLSC, Bob is able to use R1 to get his 900 USDT by HTLSC 1 in channel `[Alice, USDT, Bob]`, hence Alice gets 1 BTC as collateral from Bob.
40 |
41 | And after a timeframe, Bob wants to redeem his 1 BTC. He use R2 in HTLSC 2 to get his 1 BTC back by HTLSC 2 in channel `[Alice, BTC, Bob]`, hence Alice get her 900 USDT back in channel `[Alice, USDT, Bob]`.
42 |
43 | Ofcourse, Alice can require a loan rate according to her knowledge of the price of BTC. For example she require Bob to create a swap with exchange rate 1/905. Then she will get 905 USDT when Bob redeems his BTC.
44 |
45 | ```
46 |
47 | [Alice,USDT,Bob] [Alice,BTC,Bob]
48 | +----------------+ +------------------+
49 | | | | |
50 | | | | |
51 | | |<---(1)--- swap 1 -----> | HTLSC 1 |
52 | | | | Bob + 900 USDT |
53 | | | | Alice - 900 USDT |
54 | | Alice + 1 BTC | | |
55 | | Bob - 1 BTC | | |
56 | | | | |
57 | | | | |
58 | | |<---(2)-- swap 2 -----> | HTLSC 2 |
59 | | Bob + 1 BTC | | |
60 | | Alice - 1 BTC | | |
61 | | | | Bob - 900 USDT |
62 | | | | Alice + 900 USDT |
63 | | | | |
64 | | | | |
65 | | | | |
66 | | |<---(3)----or time out, | |
67 | | | refund to both sides --> | |
68 | | | | |
69 | +----------------+ +------------------+
70 |
71 | ```
72 |
73 |
74 |
75 | ## Online Pet Store
76 |
77 | This example is one stage swap, which is quite straight farward:
78 |
79 | 1) Alice issues smart asset "PET" on Omnilayer, for each token represents a crypto cat.
80 | 2) Bob establishes an USDT channel and a PET channel with Alice, and funds the USDT channel.
81 | 3) Bob creates a HTLSC to pay Alice 100 USDT for one cat.
82 |
83 | That's it :-)
84 |
85 |
86 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OmniBOLT: Facilitates smart assets lightning transactions
2 |
3 | [](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/LICENSE) []() [](https://github.com/omnilaboratory/obd)
4 |
5 | * `Contact`: Neo Carmack(neocarmack@omnilab.online), Ben Fei(benfei@omnilab.online)
6 |
7 | Based on the fundamental theory of the Lightning network, the OmniBOLT specification describes how to enable OmniLayer assets to be circulated via lightning channels, and how can smart assets benefit from this novel quick payment theory.
8 |
9 | In addition, OmniBOLT provides more flexible contracts for upper-layer decentralized applications. [OmniBOLT daemon](https://github.com/omnilaboratory/obd) is a golang implementation of this specification, an open source, off-chain decentralized platform, built upon BTC/OmniLayer network, implements basic HTLC payment, atomic swap of multi-currencies, and more off-chain contracts on the network of [smart assets enabled lightning channels](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-02-peer-protocol.md#omnilayer-assets).
10 |
11 |
12 | ## Features
13 |
14 | * Instant payment of smart assets issued on OmniLayer and Etherium(soon future).
15 | * Cross channel atomic swap for various crypto assets.
16 | * Decentralized exchange on top of stable coin enabled lightning channels.
17 |
21 | * Automatic market maker and liquidity pool for DEX.
22 |
23 | ## Why OmniBOLT
24 |
25 | The decentralized finance industry requires a much more flexible, extensible, and cheaper smart assets circulation solution to solve the main chain scalability problem. The Lightning Network is a solid technology for this problem. Besides the layer-2 protocol [BOLT (Basis of Lightning Technology)](https://github.com/lightningnetwork/lightning-rfc/blob/master/00-introduction.md) specification for off-chain bitcoin transfer, we need a protocol to support a wider range of assets for upper-layer applications: payment, game, finance, or scenarios that need stablecoins.
26 |
27 | Meanwhile, Omnilayer is an on-chain smart assets issuance technology, which is proven secure and stable. Constructing lightning channels on top of it automatically acquires the ability to issue assets, tamper resistance, and on-chain settlement. This is where OmniBOLT is built upon.
28 |
29 | ## How it works:
30 |
31 |
32 |
33 |
34 |
35 | 1. On-chain protocol is [Omnilayer](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc), which is the token issuance and settlement layer;
36 | 2. OmniBOLT 2, 3, and 4 form the main network protocols;
37 | 3. Applications level consists of contracts for various applications;
38 |
39 | OmniBOLT does not issue tokens. All tokens are issued on [Omnilayer](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc), and enter the OmniBOLT lightning network through P2(W)SH backed channels, being locked on the main chain, and can be redeemed on the Omnilayer main chain at any time.
40 |
41 | Currently supported assets are of:
42 | 1. [Fixed number tokens](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc#731-new-property-creation-with-fixed-number-of-tokens): [divisible or indivisible](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc#field-property-type)
43 | 2. [Variable number tokens](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc#732-new-property-creation-via-crowdsale-with-variable-number-of-tokens): [divisible or indivisible](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc#field-property-type)
44 |
45 | All assets are fungible assets.
46 |
47 |
48 | ## Chapters and Protocol Suite
49 |
50 | We not only just list messages and arguments that are used in our implementation, but also complete content that explains why we do so. Most of this spec strictly follows the rules/logic defined in the lightning white paper. The original paper may be hard to read for our programmers, so we draw some diagrams for better understanding. Hope it helps :-)
51 |
52 | [OmniBOLT #01](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-01-basic-protocol-and-Terminology.md): Base Protocol and Terminology
53 |
54 | [OmniBOLT #02:](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-02-peer-protocol.md) peer-protocol, Poon-Dryja channel open
55 |
56 | [OmniBOLT #03:](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-03-RSMC-and-OmniLayer-Transactions.md) RSMC and OmniLayer Transactions
57 |
58 | [OmniBOLT #04:](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-04-HTLC-and-Payment-Routing.md) HTLC and payment Routing
59 |
60 | [OmniBOLT #05:](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-05-Atomic-Swap-among-Channels.md) Atomic Swap Protocol among Channels
61 |
62 |
65 | [OmniBOLT #06:](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-06-Automatic-Market-Maker-and-DEX.md) Automatic Market Maker, Liquidity Pool and DEX
66 |
67 | [OmniBOLT #07:](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-07-Hierarchical-Deterministic-(HD)-wallet.md) Hierarchical Deterministic (HD) wallet, Invoice Encoding
68 |
69 |
70 |
71 | ## Technology Guide
72 | [OmniBOLT Technology Guide Part I](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/docs/OmniBOLT-Technology-guide-part-I-2020-05-01_en.pdf) offers quick understanding of the rationale, concepts, architecture of OmniBOLT.
73 |
74 | ## Implementation and API for client applications
75 |
76 | Implementation of OmniBOLT specification can be found in this repository [OmniBOLT Daemon](https://github.com/omnilaboratory/obd).
77 |
78 | ## Quick Start
79 |
80 | It is recommended to start with a graphic tool to play with OmniBOLT: [https://github.com/omnilaboratory/obd#quick-start-on-regtest](https://github.com/omnilaboratory/obd#quick-start-on-regtest)
81 |
82 |
83 | ## Contribution
84 |
85 | OmniBolt specification is incubated by [Omnilayer.foundation](https://github.com/OmniLayer).
86 | Any proposal, please submit issues in this repo.
87 |
--------------------------------------------------------------------------------
/OmniBOLT-07-Hierarchical-Deterministic-(HD)-wallet.md:
--------------------------------------------------------------------------------
1 | # OmniBOLT #7: Hierarchical Deterministic(HD) wallet, Non Custodial Daemon, Invoice Encoding.
2 |
3 | * `correct me`: neo.carmack@gmail.com or join our slack channel to discuss: https://omnibolt.slack.com/archives/CNJ0PMUMV
4 |
5 | # Table of Contents
6 | * [Hierarchical Deterministic(HD) wallet](#hierarchical-deterministichd-wallet)
7 | * [Motivation](#motivation)
8 | * [Mneminic word and hardened HD chain](#mneminic-word-and-hardened-hd-chain)
9 | * [Client SDK Implementation](#client-sdk-implementation)
10 | * [Non Custodial OmniBOLT Daemon](#non-custodial-omnibolt-daemon)
11 |
12 |
13 | * [Invoice encoding](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-07-Hierarchical-Deterministic-(HD)-wallet.md#invoice-encoding)
14 | * [Human readable part](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-07-Hierarchical-Deterministic-(HD)-wallet.md#human-readable-part)
15 | * [Reference](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-07-Hierarchical-Deterministic-(HD)-wallet.md#reference)
16 |
17 |
18 | ## Hierarchical Deterministic(HD) wallet
19 |
20 | ### Motivation
21 |
22 | The life cycle of an HTLC includes 20+ transactions and generates many temporary addresses to receive, store, and send assets. Each of these transactions constructed to transfer assets from these addresses requires the signature by private keys of the transaction owner. And more importantly, by the design of the lightning network, constructing a new transaction requires handing over the private key of the previous commitment transaction, it is necessary to specify a proper key generation process, to simplify interoperability between light clients and obd nodes.
23 |
24 |
25 |
26 | ### Mneminic word and hardened HD chain
27 |
28 | The only thing for a user needed to be recorded in some safe places is the mnemonic words(12 words), which are used to generate all the pub/priv key pairs during the life cycle of channels owned by the user. Mnemonic words are generated for the first time when the user creates his wallet on an OBD.
29 |
30 | The 12 words code is generated on the client-side, and so are all the child, grandchild key pairs, and so on. OBD in non-custodial mode has no access to these keys.
31 |
32 |
33 | ```
34 | +-------------------------------+
35 | | mnemonic code word: |
36 | | brave van defence carry |
37 | | true garbage echo media |
38 | | make branch morning dance |
39 | +-------------------------------+
40 | |
41 | | (1) key streching function
42 | | PBKDF2 using SHA-512
43 | |
44 | |
45 | | (2) 2048 rounds
46 | |
47 | +-------------------------+ +-------------------+
48 | | 512 bit Seed |---(3)--> | master key K_m |
49 | | 5b5a7e5......4988c0570 | +-------------------+
50 | +-------------------------+ |
51 | child keys |
52 | |
53 | +--------+ +--------+ +--------+
54 | | K_m1 | | K_m2 | | K_m3 |
55 | +--------+ +--------+ +--------+
56 | | | |
57 | grand child keys | | |
58 | +----------+ +---------+ +---------+
59 | | k,k,k,k | | k,k,k,k | | k,k,k,k |
60 | +----------+ +---------+ +---------+
61 | .....................
62 | ```
63 |
64 | According to BIP44, which uses hardening/private derivation on most levels:
65 |
66 | `m / purpose' / coin_type' / account' / change / address_index`
67 |
68 | but not on the change and address index level.
69 |
70 | Non-hardened child keys will [compromise the parent keys](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#security). Since The private key of a commitment transaction shall be handed over to the counterparty when a new commitment transaction is created, we apply a hardened key, generated up to the account level, for every temporary multi-sig address.
71 |
72 |
73 | ### Client SDK Implementation
74 |
75 | [Javascript SDK:](https://github.com/omnilaboratory/DebuggingTool/tree/master/sdk). This JS SDK exposes an API set that manages mnemonic codes and pub/priv key generation. Plus it helps developers to construct and sign transactions required by the lightning channels.
76 |
77 |
78 | ## Non Custodial OmniBOLT Daemon
79 |
80 |
81 | ```
82 | ______
83 | ___/- \____
84 | / - / \___-------- | tracker |:records the quality of nodes' service.
85 | __| / \-------------------| tracker |
86 | | obd network \
87 | -------|___________________________|-------
88 | / \
89 | / \
90 | | reomote obd | |
91 | | |
92 | | |
93 | ----------------------------- ------------------------------------------
94 | | | | | | |
95 | | | | | | |
96 | +---------+ +--------+ +--------+ +--------+ +--------+ +--------+
97 | | desktop | | mobile | | mobile | | mobile | | desktop| | mobile |
98 | | wallet | | wallet | | wallet | | wallet | | wallet | | wallet |
99 | +---------+ +--------+ +--------+ +--------+ +--------+ +--------+
100 | | obd SDK | | mobile obd | | desktop obd | | mobile obd |
101 | | seeds | ...................................... | seeds |
102 | | keys | | keys |
103 |
104 | ```
105 |
106 | If OBD(OmniBOLT daemon) runs in non-custodial mode, then the clients' seeds and keys are not generated by or stored in OBD, but in their own local storage managed by the client SDK. When a client(wallet) needs to sign a transaction, it receives the transaction's hex from the obd it connects, uses corresponding private keys to sign, and sends the signature back to the OBD node to verify. Even if the OBD server has been compromised, users' transaction data are still secure: hackers can not make any transaction to steal without users' keys.
107 |
108 |
109 | Users don't need to trust any obd node, even those nodes they deploy by themselves.
110 |
111 |
112 |
113 | ## Exclusive mode
114 | The exclusive mode works in the same way as lnd. Every user MUST run his private obd node, which manages and stores all his keys. For application integrators, obd exposes GRPC API to interact with and the tech stack is the same as lnd.
115 |
116 | ## Invoice encoding
117 |
118 | The difference between an OBD invoice and LND invoice is that obd invoice has specified asset id in human readable part. Remaining parts are the same to [specified in BOLT 11](https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md#bolt-11-invoice-protocol-for-lightning-payments).
119 |
120 |
121 | ### Human readable part
122 |
123 | The human-readable part of an obd invoice consists of three sections:
124 |
125 | prefix: ob + [SLIP-0173 registered Human Readable Part (prefix)](https://github.com/satoshilabs/slips/blob/master/slip-0173.md#registered-human-readable-parts):
126 |
127 |
128 | | | Omni/BTC Mainnet | Omni/BTC Testnet | Omni/BTC Regtest |
129 | |----------| ---------------- | ---------------- | ---------------- |
130 | | prefix | obo | obto | obort |
131 |
132 |
133 | asset ID: the omni asset id. `id=0` is the Bitcoin.
134 |
135 | amount: optional, number in that currency, followed by an optional multiplier letter. The unit encoded here is one token, for example: 1 usdt or 0.1 usdt.
136 |
137 | ## Reference
138 |
139 | * [BIP-0044: Multi-Account Hierarchy for Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)
140 | * [slip-0173: registered-human-readable-parts](https://github.com/satoshilabs/slips/blob/master/slip-0173.md#registered-human-readable-parts)
141 | * [OLE-300: human-readable-part](https://github.com/OmniLayer/Documentation/blob/master/OLEs/ole-300.adoc#human-readable-part)
142 | * [BOLT-11: payment encoding](https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md#bolt-11-invoice-protocol-for-lightning-payments)
143 | * [BIP-0032: security](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#security)
144 |
145 |
--------------------------------------------------------------------------------
/OmniBOLT-05-Atomic-Swap-among-Channels.md:
--------------------------------------------------------------------------------
1 | # OmniBOLT #5: Atomic Swap Protocol among Channels
2 |
3 | >*An atomic swap is a smart contract technology that enables the exchange of one cryptocurrency for another without using centralized intermediaries, such as exchanges.*
4 |
5 | > -- https://www.investopedia.com/terms/a/atomic-swaps.asp
6 |
7 | In general, atomic swaps take place between different blockchains, for exchanging tokens with no trust in each other. Channels defined in OmniBOLT can be funded by any token issued on OmniLayer. If one needs to trade his tokens, say USDT, for someone else's Bitcoins, both parties are required to acknowledge receipt of funds of USDT and BTC, within a specified timeframe using a cryptographic hash function. If one of the involved parties fails to confirm the transaction within the timeframe, then the entire transaction is voided, and funds are not exchanged, but refunded to the original account. The latter action ensures to the removal of counterparty risk.
8 |
9 | The standard swap procedure between channels is:
10 |
11 | ```
12 | Alice creats HTLC 1 Bob creats HTLC 2
13 | [Alice --- X USDT---> Bob] [Alice <--- Y BTC--- Bob]
14 | +----------------+ +----------------+
15 | | | | |
16 | | create | | |
17 | | HTLC 1 |----(1)--- tell Bob Tx 1 created -----> | create |
18 | | | | HTLC 2 |
19 | | | | |
20 | | Locked |<---(2)-- Acknowledge and create Tx 2 --- | Locked |
21 | | by | | by |
22 | | Hash(R), | | Hash(R) |
23 | | Time-Locker t1 | | Time-Locker t2 |
24 | | and | | and |
25 | | Bob's Sig | | Alice's Sig |
26 | | | | t2 < t1 |
27 | | | | |
28 | | | | |
29 | | | | |
30 | | |----(3)---- Send R to get BTC -----> | Alice + Y BTC |
31 | | Bob + X USDT |<---(4)---- Use R to get USDT ------ | |
32 | | | | |
33 | | | | |
34 | | |----(5)---- or time out, | |
35 | | | refund to both sides -----> | |
36 | | | | |
37 | +----------------+ +----------------+
38 |
39 | - where `HTLC 1` transfers X USDT to Bob in channel `[Alice, USDT, Bob]`, locked by `Hash(R)`, `t1` and Bob's signature.
40 | - `HTLC 2` transfers Y BTC to Alice in channel `[Alice, BTC, Bob]`, locked by `Hash(R)`, `t2`(`t2 < t1`) and Alice's signature .
41 |
42 |
43 | ```
44 |
45 | Apparently it is not necessary that Alice and Bob have a direct channel between them:
46 |
47 |
48 | ```
49 | Alice creats HTLC 1 Bob creats HTLC 2
50 | [Alice --- X USDT---> David_1] [Bob --- Y BTC---> Carol_1]
51 | +----------------+ +----------------+
52 | | HTLC 1 |----(1)--- tell Bob Tx 1 created -----> | |
53 | | |<---(2)-- Acknowledge and create Tx 2 --- | HTLC 2 |
54 | +----------------+ +----------------+
55 | . .
56 | . .
57 | . .
58 | . .
59 | . .
60 |
61 | [David_n --- X USDT---> Bob] [Carol_m ---Y BTC---> Alice]
62 | +----------------+ +----------------+
63 | | HTLC 1 | | HTLC 2 |
64 | +----------------+ +----------------+
65 |
66 | +----------------+
67 | Alice ----(3)----Send R to Bob to get BTC -----> | Alice + Y BTC |
68 | +----------------+
69 | +----------------+
70 | | Bob + X USDT |<---(4)---- Use R to get USDT ------- Bob
71 | +----------------+
72 |
73 | +----------------+ +----------------+
74 | | |----(5)---- or time out, | |
75 | | | refund to both sides -----> | |
76 | +----------------+ +----------------+
77 |
78 |
79 | ```
80 |
81 | ## Hashed TimeLock Swap Contract
82 |
83 | Hashed TimeLock Swap Contract (HTLSC), which defines a swap, consists of two separate HTLCs with an extra specified exchange rate of tokens and time lockers.
84 |
85 | Simply there are 5 steps in a swap.
86 |
87 | **Step 0**: Alice creats `HTLC 1` to pay Bob X USDT. `HTLC 1` is locked by `Hash(R)` and time locker `t1`.
88 | **Step 1**: Alice notifies Bob of the details of `HTLC 1`.
89 | **Step 2**: Bob either acknowledges and creates `HTLC 2` to pay Alice Y BTC or ignores the message, in which case `HTLC 1` will be automatically canceled after timeframe `t1`. `HTLC 2` is also locked by `Hash(R)`.
90 | **Step 3**: In this step, Alice applies `R` in her BTC channel to get her BTC fund. She has to check the redeem script `HTLC 2`, to see whether or not the `HTLC 2` is locked by `Hash(R)`. If Bob is cheating, he could use a faked `Hash(R')` in redeem script. Therefore when Alice applies `R` to unlock her fund in the BTC channel, she will get nothing but expose the secrete `R` to Bob.
91 | **Step 4**: After Alice exposes `R` to Bob, Bob then can use `R` to get his fund in his USDT channel.
92 | **Step 5**: If Alice changes her mind, and refuses to apply `R` to get her fund in BTC, then after a timeframe, funds in BTC channels and USDT channels are all refunded to the original accounts. No one in this swap will take a loss.
93 |
94 |
95 | No participant can cheat. After inputting `R` in each channel, the `HTLC 1` and `2` transform into general commitment transactions, which is the same procedure that how an [HTLC transforms to a commitment transaction](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-05-Atomic-Swap-among-Channels.md#terminate-htlc-off-chain).
96 |
97 | In chain `[Alice, USDT, David_1] --> ... --> [David_n, USDT, Bob]`, Alice creates `HTLC 1` and its mirror transactions on Bob side, with time locker `t1`, which in the diagram is 3 days as an example.
98 |
99 |
100 |
101 |
102 |
103 | At the same time, Bob creates `HTLC 2` in the chain `[Bob, BTC, Carol_1] --> ... --> [Carol_n, BTC, Alice]` and its mirror transactions on Alice's side, sending the agreed number of BTCs to Alice. Time locker `t2` is set to be 2 days, less than `t1=3` days.
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 | ## `swap`
112 |
113 | `swap` specifies the asset that one peer needs to transfer.
114 |
115 | 1. type: -80 (swap)
116 | 2. data:
117 | * [`channel_id`:`channel_id_from`]: Alice initiate the swap procedure by creating an HTLSC.
118 | * [`channel_id`:`channel_id_to`]: Bob who Alice want to trade token with.
119 | * [`u64`:`property_sent`]: Omni asset (id), which is sent out to Bob.
120 | * [`u64`:`property_receieved`]: the Omni asset (id), which is required to the counter party (Bob)
121 | * [`u64`:`amount`]: ammout of the property that is sent.
122 | * [`float64`:`exchange_rate`]: `= property_sent/property_receieved`. For example, sending out X USDT in exchange of Y BTC, the exchange rate is X/Y.
123 | * [`string`:`transaction_id`]: HTLSC transaction ID, which is the one sending asset in `channel_id_from`.
124 | * [`u64`:`hashed_R`]: Hash(R).
125 | * [`u64`:`time_locker`]: For example, 3 days.
126 |
127 |
128 | ## `swap_accepted`
129 |
130 | `swap_accepted` specifies the asset that one peer needs to transfer.
131 |
132 | 1. type: -81 (swap_accepted)
133 | 2. data:
134 | * [`channel_id`:`channel_id_from`]: Alice initiate the swap procedure by creating an HTLSC.
135 | * [`channel_id`:`channel_id_to`]: Bob who Alice want to trade token with.
136 | * [`u64`:`property_sent`]: Omni asset (id), which is sent out to Bob.
137 | * [`u64`:`property_receieved`]: the Omni asset (id), which is required to the counter party (Bob)
138 | * [`u64`:`amount`]: ammout of the `property_receieved` that is sent in `channel_id_to`.
139 | * [`float64`:`exchange_rate`]: `= property_sent/property_receieved`. For example, sending out X USDT in exchange of 1 BTC, the exchange rate is X/1.
140 | * [`string`:`transaction_id`]: HTLSC transaction ID, which is the one sending asset in `channel_id_to`.
141 | * [`u64`:`hashed_R`]: Hash(R).
142 | * [`u64`:`time_locker`]: For example, 2 days, which must be less than the `time_locker` in message `swap`.
143 |
144 | Bob in `channel_id_to` has to monitor the `transaction_id` in channel `channel_id_from`, to see whether or not the corresponding transactions, like RD, HED, HTRD, etc, have been correctly created. After he validates the transactions, he will create HTLSC according to the arguments `amount` in channel `channel_id_to` and then reply to Alice with the message `swap_accepted`.
145 |
146 |
147 | Alice receives the message `swap_accepted`. If anything is not exactly correct, Alice will not send R to get her assets in `channel_id_to`, hence Bob is not able to get this asset in `channel_id_from`. After a timeframe, the two channels revock to their previous state.
148 |
149 | ## Remark
150 | Atomic swap is the foundation of lots of blockchain applications. [Next chapter](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-06-Mortgage-Loan-Contracts-for-Crypto-Assets.md) will see some examples, which are intuitive and will help our readers to build much more complex applications for real-world businesses.
151 |
152 |
153 |
154 |
155 |
--------------------------------------------------------------------------------
/OmniBOLT-02-peer-protocol.md:
--------------------------------------------------------------------------------
1 | # OmniBOLT #2: Peer Protocol for Channel Management
2 |
3 | # Omnilayer Assets
4 |
5 | OmniBOLT itself does not issue tokens. All tokens are issued on [Omnilayer](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc), and enter the OmniBOLT network through P2(W)SH backed channels, being locked on the main chain, and can be redeemed on the Omnilayer main chain at any time.
6 |
7 | Please go to the [token creation](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc#smart-property) section in the Omnilayer spec to check all the types of tokens the spec can create.
8 |
9 |
10 | # Omni Addresses
11 | One most important point is that addresses in OmniBOLT and its implementation must be Omnilayer addresses created by omnicore. Bitcoin-only addresses can not know any asset information. When users fund Omni assets to a channel with bitcoin addresses that do not support Omni Layer transactions, it can be difficult or impossible to recover the transferred Omni assets.
12 |
13 | So this is the main reason that current lnd channels can not be OmniBOLT channels.
14 |
15 | Addresses that are currently supported by OmniBOLT are of types:
16 |
17 | | Network | Coin | Script(address type) | Leading symbol(s) | |
18 | | --------------------------- | ----------------------- | ------------------- | ------------------- | ------------------- |
19 | | Mainnet | Omni, Bitcoin | p2pkh | 1 | funding address |
20 | | Testnet, Regtest | Omni, Bitcoin | p2pkh | `m` or `n` | funding address |
21 | | Mainnet | Omni, Bitcoin | p2sh | 3 | multisig channel address, pay to HTLC, RSMC, internal multisig addresses |
22 | | Testnet, Regtest | Omni, Bitcoin | p2sh | 2 | multisig channel address, pay to HTLC, RSMC, internal multisig addresses |
23 | | Mainnet | Omni, Bitcoin | p2pkh | 1 | settlement address |
24 | | Testnet, Regtest | Omni, Bitcoin | p2pkh | `m` or `n` | settlement address |
25 |
26 |
27 | BECH32 addresses(pubkey hash or script hash starting with `bc1` on mainnet, `tb1` on testnet) are not supported by Omnilayer, hence is not by OmniBOLT.
28 |
29 | In the soon future, OmniBOLT will update to ["Omni Layer Safe Segregated Witness Address Format"](https://github.com/OmniLayer/Documentation/blob/master/OLEs/ole-300.adoc#motivation).
30 |
31 | # Channel
32 | The peer Poon-Dryja channel protocol has three phases: establishment, normal operation (commitment transactions, funding transactions, HTLCs, Collateral lending, etc), and closing.
33 |
34 | The basic logic is the same as [BOLT 02](https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md), but with some updates in messages to be compatible with OmniLayer protocol. The fields are similar to what are defined in BOLT 02, but the [key generation mechanism](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-07-Hierarchical-Deterministic-(HD)-wallet.md) is different, so that the various `_basepoint` fields are not used when creates channels. During our implementation, these fields may be changed.
35 |
36 |
37 | ## `Channel ID`
38 | The concept of channel ID is the same as the definition in [BOLT](https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#definition-of-channel_id). It is a globally unique identifier for a channel, used by wallets to locate and connect to users' account. Before a final channel id is created, a temporary id is normally used before funding real BTC and tokens into the channel to be established.
39 |
40 | The temporary ids may be duplicated. In the current implementation, one instance of OBD will not generate duplicated temp id, and one OBD may manage thousands of light clients(users). Only a channel id has been finalized, it can be broadcast, and can be used in operations from other OBD instances.
41 |
42 | ## [Channel Establishment]()
43 |
44 | Since OmniBOLT uses channels to transfer and exchange tokens, and on bitcoin network, only BTC can be the transaction fee, here comes the difference between OmniBOLT and other lightning specifications: We need extra messages to deposit miner fees into a channel to be established.
45 |
46 | Opening a channel seeks remote an OmniBOLT node, to create a channel according to the requests from the local node.
47 |
48 | The process consists of:
49 |
50 | * funding node (funder) sends an `open_channel` message, followed by the responding node (fundee) sending `accept_channel`.
51 | * The funder creates the funding satoshis transaction and gets approval from the fundee. The satoshis in a channel are only for the gas fee when broadcasts, we don't use satoshis as channel fee. As an HTLC transaction includes a maximum of 7 sub-transactions, each at least has 546 satoshis(dust) in its output, so that the funder has to fund `7*546` satoshis in creating a channel.
52 | * The funder creates the funding token transaction and the corresponding commitment transaction, as described in [OmniBOLT #3](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-03-RSMC-and-OmniLayer-Transactions.md).
53 | * The funder then sends the hex of the funding transaction with the `asset_funding_created` message, along with the hex of the first commitment transaction in the channel, to the fundee.
54 | * Once the fundee learns the funding transaction has been created and validates the hex, it's able to generate the signature for the funder's version of the commitment transaction, create his mirror commitment transaction, and send it back using the `asset_funding_signed` message.
55 | * Once the funder received the signed feedback message, he has to broadcast his asset funding transaction, so that the channel will hold the assets.
56 |
57 |
58 | During funding creation, OmniBOLT adds extra arguments (e.g. `[32*byte:property_id]`) to specify which omni asset is funded in creating this channel.
59 |
60 |
61 | ```
62 | +-------+ +-------+
63 | | |---(1)---- open_channel ----->| |
64 | | |<--(2)--- accept_channel ------| |
65 | | | | |
66 | | A |---(3)-- funding BTC created ---->| B |
67 | | |<--(4)-- funding BTC signed ----| |
68 | | | | |
69 | | |---(5)- funding Tokens created -->| |
70 | | |<--(6)-- funding Tokens signed ---| |
71 | | | | |
72 | | |---(7)---- funding_locked ----->| |
73 | | |<--(8)---- funding_locked ------| |
74 | | | | |
75 | | |<------- wait for close ----->| |
76 | +-------+ +-------+
77 |
78 | - where node A is 'funder' and node B is 'fundee'.
79 | - extra BTC funding is needed as transaction fee, from where OmniBOLT differs BOLT
80 |
81 | ```
82 |
83 | If this fails at any stage, or if one node decides the channel terms offered by the other node are not suitable, the channel establishment fails.
84 |
85 | Note that multiple channels can operate in parallel, as all channel messages are identified by either a `temporary_channel_id` (before the asset funding transaction is created) or a `channel_id` (derived from the funding transaction).
86 |
87 | ### The `open_channel` Message
88 |
89 | This message contains information about a node and indicates its desire to set up a new Omni-aware channel. This is the first step toward creating the funding transaction and both versions of the commitment transaction. In order to recognize an OmniBOLT channel, we use specified `chain_hash:chain_hash` to mark the OmniBOLT-specific messages.
90 |
91 |
92 | We don't specify which asset will be in this channel during creation, so there is no need to modify the existing design. Comments of this message come from the original [BOLT #2](https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#the-open_channel-message) spec, readers may check if the two are consistent:
93 |
94 |
95 | 1. type: -32 (open_channel)
96 | 2. data:
97 | * [`chain_hash`:`chain_hash`]: The `chain_hash` value denotes the exact blockchain that the opened channel will reside within. This is usually the genesis hash of the respective blockchain. We use in this case the hash of the ["Exodus Address"](https://github.com/OmniLayer/spec#initial-token-distribution-via-the-exodus-address) for Omnilayer, which is `1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P`, from which the first Mastercoins were generated during the month of August 2013. PS: `chain_hash` allows nodes to open channels across many distinct blockchains as well as have channels within multiple blockchains opened to the same peer (if it supports the target chains).
98 | * [`32*byte`:`temporary_channel_id`]: used to identify this channel on a per-peer basis until the funding transaction is established, at which point it is replaced by the `channel_id`, which is derived from the funding transaction.
99 | * [`u64`:`funding_satoshis`]: the amount the sender is putting into the channel.
100 | * [`u64`:`push_msat`]: an amount of initial funds that the sender is **unconditionally** giving to the receiver.
101 | * [`u64`:`dust_limit_satoshis`]: the threshold below which outputs should not be generated for this node's commitment or HTLC transactions (i.e. HTLCs below this amount plus HTLC transaction fees are not enforceable on-chain). This reflects the reality that tiny outputs are not considered standard transactions and will not propagate through the Bitcoin/OmniLayer network.
102 | * [`u64`:`max_htlc_value_in_flight_msat`]: is a cap on total value of outstanding HTLCs, which allows a node to limit its exposure to HTLCs.
103 | * [`u64`:`channel_reserve_satoshis`]: the minimum amount that the other node is to keep as a direct payment.
104 | * [`u64`:`htlc_minimum_msat`]: indicates the smallest value HTLC this node will accept.
105 | * [`u32`:`feerate_per_kw`]: indicates the initial fee rate in satoshi per 1000-weight (i.e. 1/4 the more normally-used 'satoshi per 1000 vbytes') that this side will pay for commitment and HTLC transactions, as described in [BOLT #3: fee-calculation](https://github.com/lightningnetwork/lightning-rfc/blob/master/03-transactions.md#fee-calculation) (this can be adjusted later with an `update_fee` message).
106 | * [`u16`:`to_self_delay`]: the number of blocks that the other node's to-self outputs must be delayed, using OP_CHECKSEQUENCEVERIFY delays; this is how long it will have to wait in case of breakdown before redeeming its own funds.
107 | * [`u16`:`max_accepted_htlcs`]: similar to `max_htlc_value_in_flight_msat`, this value limits the number of outstanding HTLCs the other node can offer, **NOT** the total value of HTLCs.
108 | * [`point`:`funding_pubkey`]: the public key in the two-of-two multisig script of the funding transaction output.
109 |
110 |
111 | **basepoint is currently ignored in non-custodial mode**: The [BOLT #3: key-derivation](https://github.com/lightningnetwork/lightning-rfc/blob/master/03-transactions.md#key-derivation) uses the various `_basepoint` fields to derive unique keys for each commitment transaction. This property is used for preserving privacy when outsourcing penalty transactions to third parties. The security mechanism used by Omnibolt is a bit different, and we will improve it based on the community proposal. Readers shall go to [chapter #7 Hierarchical Deterministic wallet](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-07-Hierarchical-Deterministic-(HD)-wallet.md) for the current mechanism. In exclusive mode, the following `_basepoints` are the same to BOLT.
112 |
113 | * [`point`:`revocation_basepoint`]: not used.
114 | * [`point`:`payment_basepoint`]:
115 | * [`point`:`delayed_payment_basepoint`]:
116 | * [`point`:`htlc_basepoint`]:
117 | * [`point`:`first_per_commitment_point`]:
118 |
119 | * [`byte`:`channel_flags`]: Only the least-significant bit of `channel_flags` is currently defined: `announce_channel`. This indicates whether the initiator of the funding flow wishes to advertise this channel publicly to the network, as detailed within [BOLT #7: p2p-node-and-channel-discovery](https://github.com/lightningnetwork/lightning-rfc/blob/master/07-routing-gossip.md#bolt-7-p2p-node-and-channel-discovery).
120 | * [`u16`:`shutdown_len`] (option_upfront_shutdown_script):
121 | * [`shutdown_len*byte`:`shutdown_scriptpubkey`] (option_upfront_shutdown_script): allows the sending node to commit to where funds will go on mutual close, which the remote node should enforce even if a node is compromised later.
122 |
123 | ** Requirement
124 |
125 | Requirement is the same to [BOLT-02-requiremnets](https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#requirements).
126 |
127 | ** Rationale
128 |
129 | Rationale is the same to [BOLT-02-rationale](https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#rationale).
130 |
131 | ** Future
132 |
133 | Future is the same to [BOLT-02-future](https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#future).
134 |
135 |
136 |
137 |
138 |
139 | ### The `accept_channel` Message
140 |
141 | This message contains information about a node and indicates its acceptance of the new channel. This is the second step toward creating the funding transaction and both versions of the commitment transaction.
142 |
143 | 1. type: -33 (accept_channel)
144 | 2. data:
145 | * [`32*byte`:`temporary_channel_id`]
146 | * [`u64`:`dust_limit_satoshis`]
147 | * [`u64`:`max_htlc_value_in_flight_msat`]
148 | * [`u64`:`channel_reserve_satoshis`]
149 | * [`u64`:`htlc_minimum_msat`]
150 | * [`u32`:`minimum_depth`]
151 | * [`u16`:`to_self_delay`]
152 | * [`u16`:`max_accepted_htlcs`]
153 | * [`point`:`funding_pubkey`]
154 | * [`point`:`revocation_basepoint`]
155 | * [`point`:`payment_basepoint`]
156 | * [`point`:`delayed_payment_basepoint`]
157 | * [`point`:`htlc_basepoint`]
158 | * [`point`:`first_per_commitment_point`]
159 | * [`u16`:`shutdown_len`] (option_upfront_shutdown_script)
160 | * [`shutdown_len*byte`:`shutdown_scriptpubkey`] (option_upfront_shutdown_script)
161 |
162 |
163 | #[Requirements](https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#requirements-1)
164 |
165 |
166 |
167 |
--------------------------------------------------------------------------------
/OmniBOLT-04-HTLC-and-Payment-Routing.md:
--------------------------------------------------------------------------------
1 | # OmniBOLT #4: HTLC and Payment Routing
2 |
3 | >*"A bidirectional payment channel only permits secure transfer of funds inside a channel. To be able to construct secure transfers using a network of channels across multiple hops to the final destination requires an additional construction, a Hashed Timelock Contract (HTLC)."*
4 |
5 | > -- Poon & Dryja, The Bitcoin Lightning Network: Scalable Off-chain Instant Payments
6 |
7 |
8 | The building block lightning defines is channel, chained by HTLCs:
9 |
10 | ```
11 | [Alice --(10 USDT)--> Bob] ==(Bob has two channels)== [Bob --(10 USDT)--> Carol] ==(Carol has two channels)== [Carol --(10 USDT)--> David].
12 |
13 | where:
14 |
15 | [A, USDT, B] stands for the channel built by A and B, funded by USDT.
16 | ```
17 |
18 | Alice transfers 10 USDT to Bob inside the `[Alice, USDT, Bob]` channel, then Bob transfers 10 USDT to Carol inside the `[Bob, USDT, Carol]` channel, and finally, Carol sends 10 USDT to David in `[Carol, USDT, David]`.
19 |
20 | # Table of Contents
21 | * [Hashed TimeLock Contract](#Hashed-TimeLock-Contract)
22 | * [OMNI HTLC transaction construction](#OMNI-HTLC-transaction-construction)
23 | * [Commitment Transaction and Concurrency](#Commitment-Transaction-and-Concurrency)
24 | * [HTLC success HED1a](#HTLC-Success-HED1a )
25 | * [HTLC timeout HT1a](#HTLC-Timeout-HT1a)
26 | * [HTLC breach remedy](#HTLC-Breach-Remedy)
27 | * [Fee rate](#Fee-rate)
28 | * [Messages](#messages)
29 | * [Update_add_htlc](#update_add_htlc)
30 | * [Commitment signed](#update_add_htlc)
31 | * [Revock and acknowledge](#update_add_htlc)
32 | * [Terminate HTLC off-chain](#Terminate-HTLC-off-chain)
33 | * [Unit test vectors](#unit-tests)
34 | * [References](#references)
35 |
36 |
37 |
38 | ## Hashed TimeLock Contract
39 |
40 | An HTLC implements this procedure:
41 |
42 | If Bob can tell Alice `R`, which is the pre-image of `Hash(R)` that someone else (Carol) in the chain shared with Bob 3 days ago in an exchange of 15 USDT in the channel `[Bob, USDT, Carol]`, then Bob will get the 15 USDT funds inside the channel `[Alice, USDT, Bob]`, otherwise Alice gets her 15 USDT back.
43 |
44 |
45 |
48 |
49 |
50 |
51 |
52 |
53 | Internal transactions in the above diagram are explained in [chapter 1](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-01-basic-protocol-and-Terminology.md#terminology).
54 |
55 | There are three outputs of a commitment transaction:
56 | `to_rsmc(to local)`: 0. Alice3 & Bob 45,
57 | `to remote`: 1. Bob 40,
58 | `to_htlc`: 2. Alice4 & Bob 15
59 |
60 | `to_htlc` has three branches to handle the situations of time out, breach remedy, and htlc success. We put the payload and outputs together to construct the HTLC transaction:
61 |
62 | ## OMNI HTLC transaction construction
63 |
64 | ### Commitment Transaction and Concurrency
65 |
66 | On sender side:
67 | ```
68 | version: 2
69 | locktime: 0
70 | tx input:
71 | * outpoint: the vout of funding transaction.
72 | * : to spend the funding transaction.
73 |
74 | tx output:
75 | * op_return:{value:0, pkScript:opReturn_encode},
76 | * to_rsmc/reference1:{value:dust, pkScript: RSMC redeem script},
77 | * to_remote/reference2:{value:dust, pkScript: pubkey script},
78 | * to_htlc_1/reference3:{value:dust, pkScript: offered htlc script},
79 | * to_htlc_2/reference4:{value:dust, pkScript: offered htlc script},
80 | * ...
81 | * to_htlc_n/reference_n:{value:dust, pkScript: offered htlc script},
82 | * change:{value:change satoshis, pkScript: the channel pubkey script }
83 | ```
84 | Where:
85 | `opReturn_encode`: the [encoded tx version( = 0 ), tx type( = 7 ), token id and array of receivers](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-03-RSMC-and-OmniLayer-Transactions.md#payload), prefixed by "omni".
86 |
87 | payload in output 0:
88 |
89 | | size | Field | Sender Value |
90 | | -------- | ----------------------- | ------------------- |
91 | | 2 bytes | Transaction version | 0 |
92 | | 2 bytes | Transaction type | 7 (= Send-to-Many) |
93 | | 4 bytes | Token identifier to send | 31 (e.g. USDT ) |
94 | | 1 byte | Number of outputs | 3 |
95 | | 1 byte | Receiver output # | 1 (= vout 1) |
96 | | 8 bytes | Amount to send | to_rsmc (e.g. 45) |
97 | | 1 byte | Receiver output # | 2 (= vout 2) |
98 | | 8 bytes | Amount to send | to_remote (e.g. 40) |
99 | | 1 byte | Receiver output # | 3 (= vout 3) |
100 | | 8 bytes | Amount to send | offered_htlc_1 (e.g. 10)|
101 | | 1 byte | Receiver output # | 4 (= vout 4) |
102 | | 8 bytes | Amount to send | offered_htlc_2 (e.g. 5)|
103 | | ... | ... | ... |
104 | | 1 byte | Receiver output # | 8 (= vout 8) |
105 | | 8 bytes | Amount to send | offered_htlc_6 (e.g. 5) |
106 |
107 |
108 | `op_return` has maximum 83 bytes space, so that concurrently the maximum outputs is 8, including `to_rsmc`, `to_remote`, and 6 `offered_htlc_i` outputs.
109 |
110 | Concurrency means a channel can accept or send HTLCs at the same time. Because of the `op-return` space limitation, if a node needs a bigger throughput, it has to build more channels with more counterparties. Channels are vertical scaling: they work in parallel and will not affect each other, and adding more channels improves the TPS linearly. This is a useful feature for liquidity providers who build thousands of channels to gain a high TPS and earn channel fees by providing liquidity to the network.
111 |
112 | On receiver side:
113 | ```
114 | version: 2
115 | locktime: 0
116 | tx input:
117 | * outpoint: the vout of funding transaction.
118 | * : to spend the funding transaction.
119 |
120 | tx output:
121 | * op_return:{value:0, pkScript:opReturn_encode},
122 | * to_remote/reference1:{value:dust, pkScript: pubkey script},
123 | * to_local/reference2:{value:dust, pkScript: RSMC redeem script},
124 | * to_htlc_1/reference3:{value:dust, pkScript: received htlc script},
125 | * to_htlc_2/reference4:{value:dust, pkScript: received htlc script},
126 | * ...
127 | * to_htlc_n/reference_n:{value:dust, pkScript: received htlc script},
128 | * change:{value:change satoshis, pkScript: the channel pubkey script }
129 | ```
130 |
131 | payload in output 0:
132 |
133 | | size | Field | Receiver Value |
134 | | -------- | ----------------------- | ------------------- |
135 | | 2 bytes | Transaction version | 0 |
136 | | 2 bytes | Transaction type | 7 (= Send-to-Many) |
137 | | 4 bytes | Token identifier to send | 31 (e.g. USDT ) |
138 | | 1 byte | Number of outputs | 3 |
139 | | 1 byte | Receiver output # | 1 (= vout 1) |
140 | | 8 bytes | Amount to send | to_remote (e.g. 45) |
141 | | 1 byte | Receiver output # | 2 (= vout 2) |
142 | | 8 bytes | Amount to send | to_rsmc (e.g. 40) |
143 | | 1 byte | Receiver output # | 3 (= vout 3) |
144 | | 8 bytes | Amount to send | received_htlc_1 (e.g. 10)|
145 | | 1 byte | Receiver output # | 4 (= vout 4) |
146 | | 8 bytes | Amount to send | received_htlc_2 (e.g. 5)|
147 | | ... | ... | ... |
148 | | 1 byte | Receiver output # | 8 (= vout 8) |
149 | | 8 bytes | Amount to send | received_htlc_6 (e.g. 5) |
150 |
151 | `change`: change = satoshis in channel - dust - miner fee. By default, we set dust 546 satoshis.
152 |
153 | The outputs are sorted into the order by omnicore spec: `op_return` payload is in output 0 and the receivers are ordered as in the payload definition.
154 |
155 | On both sides, `to_rsmc` and `to_remote` are locked by redeem script and pubkey script as in chapter 3 RSMC transaction sector. `to_htlc` on the sender side is locked by the `offered HTLC` and on the receiver side is locked by `received HTLC` as in [BOLT 3](https://github.com/lightning/bolts/blob/master/03-transactions.md#offered-htlc-outputs):
156 |
157 | ```bat
158 | # To remote node with revocation key
159 | OP_DUP OP_HASH160 OP_EQUAL
160 | OP_IF
161 | OP_CHECKSIG
162 | OP_ELSE
163 | OP_SWAP OP_SIZE 32 OP_EQUAL
164 | OP_NOTIF
165 | # To local node via HTLC-timeout transaction (timelocked).
166 | OP_DROP 2 OP_SWAP 2 OP_CHECKMULTISIG
167 | OP_ELSE
168 | # To remote node with preimage.
169 | OP_HASH160 OP_EQUALVERIFY
170 | OP_CHECKSIG
171 | OP_ENDIF
172 | OP_ENDIF
173 | ```
174 |
175 |
176 | The remote node can redeem the HTLC with the witness:
177 | ```
178 |
179 | ```
180 |
181 |
182 |
183 | On receiver side, the received HTLC is the same to `received HTLC` in BOLT 3:
184 | ```
185 | # To remote node with revocation key
186 | OP_DUP OP_HASH160 OP_EQUAL
187 | OP_IF
188 | OP_CHECKSIG
189 | OP_ELSE
190 | OP_SWAP OP_SIZE 32 OP_EQUAL
191 | OP_IF
192 | # To local node via HTLC-success transaction.
193 | OP_HASH160 OP_EQUALVERIFY
194 | 2 OP_SWAP 2 OP_CHECKMULTISIG
195 | OP_ELSE
196 | # To remote node after timeout.
197 | OP_DROP OP_CHECKLOCKTIMEVERIFY OP_DROP
198 | OP_CHECKSIG
199 | OP_ENDIF
200 | OP_ENDIF
201 | ```
202 |
203 | ### HTLC Success HED1a
204 |
205 | HED(n)(a/b) spends the `to_htlc` output by receiver's signature and preimage R:
206 |
207 | ```
208 | version: 2
209 | locktime: 0
210 | tx input:
211 | * outpoint: tx id of parent commitment transaction and the `to_htlc` output is 3.
212 | * witness stack: 0 .
213 |
214 | tx output:
215 | * op_return:{value:0, pkScript:opReturn_encode},
216 | * receiver/reference1:{value:dust, pkScript: receiver's pubkey script},
217 | * change:{value:change satoshis, pkScript: the channel pubkey script }
218 | ```
219 |
220 | ### HTLC Timeout HT1a
221 |
222 | If timed out, payer should construct HT1a to get this HTLC payment back.
223 |
224 | ```
225 | version: 2
226 | locktime: 0
227 | tx input:
228 | * outpoint: tx id of parent commitment transaction and the `to_htlc` output is 3.
229 | * witness stack: 0 .
230 |
231 | tx output:
232 | * op_return:{value:0, pkScript:opReturn_encode},
233 | * receiver/reference1:{value:dust, pkScript: RSMC redeem script},
234 | * change:{value:change satoshis, pkScript: the channel pubkey script }
235 | ```
236 |
237 | Where in both HTLC success and timeout:
238 | `opReturn_encode`: the [encoded tx version( = 0 ), tx type( = 0 ), token id and amount](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-03-RSMC-and-OmniLayer-Transactions.md#payload), prefixed by "omni".
239 |
240 | The amount is the amount of vout3 in the `op_return` payload of commitment transaction.
241 |
242 | change satoshis = channel satoshis - dust.
243 |
244 | RSMC redeem script is the same as in [RSMC commitment transaction](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-03-RSMC-and-OmniLayer-Transactions.md#commitment-transaction)
245 |
246 |
247 |
248 | ### HTLC Breach Remedy
249 |
250 | The HTLC BR transaction can be constructed and broadcast without delay when the counter party broadcasts a revocked commitment.
251 |
252 | ```
253 | version: 2
254 | locktime: 0
255 | tx input:
256 | * outpoint: the `to_htlc` output is 3.
257 | * witness stack: to spend the to_htlc output.
258 |
259 | tx output:
260 | * op_return:{value:0, pkScript:opReturn_encode},
261 | * receiver/reference:{value:dust, pkScript: pubkey script},
262 | * change:{value:change in satoshis, pkScript: the channel pubkey script }
263 | ```
264 |
265 | Where:
266 | `opReturn_encode`: the [encoded tx version( = 0 ), tx type( = 0 ), token id and amount](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-03-RSMC-and-OmniLayer-Transactions.md#payload), prefixed by "omni".
267 |
268 |
269 | The receiver is Bob if Alice cheats.
270 |
271 | The amount is the number in `vout=3`( receiver `to_htlc`) of the commitment transaction `op_return` payload.
272 |
273 | ### Fee rate
274 |
275 | For liquidity providers, when relaying an HTLC, a channel fee could be charged in the token(not in satoshis). Generally, the fee rate is known to the network when a node announces itself and a lower fee rate will attract more HTLC traffic.
276 |
277 | For a fee rate example of 50 basis points, an incoming HTLC is 15 USDT, then the outgoing HTLC is `15-15*0.5% = 14.925` USDT.
278 |
279 |
280 | ## Messages
281 |
282 | ```
283 | +-------+ +-------+
284 | | |--(1)------------- update_add_htlc (40) ---------------->| |
285 | | | for asset 1 | |
286 | | | | |
287 | | |--(1)------------- update_add_htlc (40) ---------------->| |
288 | | | for asset 2 | |
289 | | | | |
290 | | |<-(1)------------- update_add_htlc (40) -----------------| |
291 | | A | for asset 3 | B |
292 | | | | |
293 | | |--(2)------------- commitment signed (41) --------------->| |
294 | | | for asset 1 | |
295 | | | | |
296 | | |<-(3)----------- revock and acknowledge (42) --------------| |
297 | | | for asset 1 | |
298 | | | | |
299 | | |<-(2)-------------- commitment signed (41) ----------------| |
300 | | | for asset 3 | |
301 | | | | |
302 | | |--(2)------------- commitment signed (41) --------------->| |
303 | | | for asset 2 | |
304 | | | | |
305 | | |<-(3)----------- revock and acknowledge (42) --------------| |
306 | | | for asset 2 | |
307 | | | | |
308 | | |--(3)----------- revock and acknowledge (42) ------------->| |
309 | | | for asset 3 | |
310 | +-------+ +-------+
311 |
312 | ```
313 |
314 | A node has multiple asset channels, it can simultaneously send out transactions, and wait for the counterparty to respond.
315 |
316 | ## update_add_htlc
317 |
318 | `update_add_htlc` consists of two rounds of signing sub-transactions to forward an HTLC to the remote peer. Users should compare it to [`update_add_htlc`](https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#adding-an-htlc-update_add_htlc) in `lightning-rfc`.
319 |
320 | Please note that the payment information is all encoded in transaction hex.
321 |
322 |
323 | 1. type: -40 (AddHTLC)
324 | 2. data:
325 | * [`channel_id`:`channel_id`]:
326 | * [`4 bytes`:`asset id`]:
327 | * [`byte`:`IsPayInvoice`]: bool type
328 | * [`float64`:`amount`]:
329 | * [`sha256`:`payment_hash`]: the hash(R) used to lock the payment.
330 | * [`byte_array`:`memo`]: memo to the payee.
331 | * [`int32`:`cltv_expiry`]: expiry blocks.
332 | * [`1366*byte`:onion_routing_packet]
333 |
334 |
335 |
336 | 1. type: -41 (commitment signed)
337 | 2. data:
338 | * [`channel_id`:`channel_id`]:
339 | * [`4 bytes`:`asset id`]:
340 | * [`signature`:`signature`]: sender's signature.
341 | * [`u16`:num_htlcs]: number of HTLCs for this `asset id`.
342 | * [`num_htlcs*signature`:htlc_signature]: htlc signatures.
343 |
344 |
345 |
346 |
347 | 1. type: -42 (revock and acknowledge)
348 | 2. data:
349 | * [`channel_id`:`channel_id`]:
350 | * [`4 bytes`:`asset id`]:
351 | * [`32*byte`:per_commitment_secret]
352 | * [`point`:next_per_commitment_point]
353 |
354 | if `asset_id = 0`, then OmniBOLT processes bitcoin lightning network, and is compatible to current bitcoin only lightning network.
355 |
356 | ### Requirements
357 |
358 | TO DO(Neo Carmack, Ben Fei): Complete the asset related "MUST to-do" list.
359 |
360 | A node MUST:
361 |
362 | 1. If a node receives a commitment transaction for a certain asset, which is not the asset(ID) that the channel(ID) is built for, then the node has to close the asset(ID) channel with the remote party.
363 | 2. Check if the asset id in the incoming HTLC is the same in the transaction `op_return` payload for every HTLC. If not, the node has to close the asset(ID) channel.
364 | 3. Validate the signature. If incorrect, then the node has to close the asset(ID) channel with the remote party.
365 |
366 |
367 | ## Terminate HTLC off-chain
368 | After Bob tells Alice the `R`, the balance of this channel shall be updated, and the current HTLC shall be terminated. OBD then creates a new commitment transactions `C3a/C3b` for this purpose.
369 |
370 |
371 |
372 |
373 |
374 | Terminating an HTLC: `update_fulfill_htlc`, `update_fail_htlc`
375 |
376 | To supply the preimage:
377 |
378 | 1. type: -130 (update_fulfill_htlc)
379 | 2. data:
380 | * [`channel_id`:`channel_id`]
381 | * [`u64`:`hop_id`]
382 | * [`4 bytes`:`asset id`]:
383 | * [`u64`:`private_key_Alice_4`]: the private key of Alice 4, encrypted by Bob's public key when sending this message to Bob.
384 | * [`u64`:`private_key_Alice_5`]: the private key of Alice 5, encrypted by Bob's public key when sending this message to Bob.
385 | * [`32*byte`:`payment_preimage`]: the R
386 |
387 | `private_key_Alice_4` and `private_key_Alice_5` are used in breach remedy transactions created in C2. If Bob finds out Alice is cheating, Bob can broadcast these BR transactions to get the money in temporary multi-sig addresses as punishments to Alice. The procedure is the same as RSMC in chapter 2.
388 |
389 | For a timed-out or route-failed HTLC:
390 |
391 | 1. type: -131 (update_fail_htlc)
392 | 2. data:
393 | * [`channel_id`:`channel_id`]
394 | * [`u64`:`id`]
395 | * [`u16`:`len`]
396 | * [`len*byte`:`reason`]
397 |
398 | ### Requirements
399 | the same to [requirement of Removing an HTLC](https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#requirements-10).
400 |
401 | ## Unit tests
402 | Omni HTLC transaction testing vectors will be added soon.
403 |
404 | ## References
405 | 1. BOLT 3 transactions, [https://github.com/lightning/bolts/blob/master/03-transactions.md](https://github.com/lightning/bolts/blob/master/03-transactions.md)
406 | 2. BOLT 2 peer protocol, [https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md](https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md)
407 | 3. Omni specification for sendtomany, [https://gist.github.com/dexX7/1138fd1ea084a9db56798e9bce50d0ef](https://gist.github.com/dexX7/1138fd1ea084a9db56798e9bce50d0ef)
408 |
--------------------------------------------------------------------------------
/OmniBOLT-06-Automatic-Market-Maker-and-DEX.md:
--------------------------------------------------------------------------------
1 | # OmniBOLT #6: Automatic Market Maker model, Liquidity Pool and DEX on Lightning Network
2 |
3 | * correct me: neo.carmack@gmail.com or join our slack channel to discuss: https://omnibolt.slack.com/archives/CNJ0PMUMV
4 | * Oct 04.2021: This work is in progress.
5 | * Apr 27.2022: Mechanism supports both discrete and continuous models in section 2.
6 | * Since Jun 23.2022, this work applies zero-knowledge proof to solve some security flaws in the original design.
7 |
8 | # Table of Contents
9 | * [introduction](#introduction)
10 | * [liquidity pool:from discrete to continuous space ](#liquidity-pool-from-discrete-to-continuous-space )
11 | * [continuous space](#continuous-space)
12 | * [limit order](#limit-order)
13 | * [coordinate charts and local invariant definition](#coordinate-charts-and-local-invariant-definition)
14 | * [example: constant function invariants](#example-constant-function-invariants)
15 | * [capital efficiency](#capital-efficiency)
16 | * [slipage estimation](#slipage-estimation)
17 | * [properties of local invariant model](#properties-of-local-invariant-model)
18 | * [signing an order](#signing-an-order)
19 | * [adding liquidity](#adding-liquidity)
20 | * [removing liquidity](#removing-liquidity)
21 | * [O(1) complexity of add and remove operations](#O1-complexity-of-add-and-remove-operations)
22 | * [channel state transition](#channel-state-transition)
23 | * [trackers running a matching engine](#trackers-running-a-matching-engine)
24 | * [example for matching orders](#example-for-matching-orders)
25 | * [token trading against liquidity pool](#token-trading-against-liquidity-pool)
26 | * [fee structure](#fee-structure)
27 | * [impermanent loss](#impermanent-loss)
28 | * [oracle](#oracle)
29 | * [differences from onchain AMM Swaps](#differences-from-onchain-AMM-Swaps)
30 | * [reference list](#reference-list)
31 |
32 |
33 |
34 | ## introduction
35 |
36 | The automatic market maker (AMM for short) model on lightning network holds significant advantages compared to the on-chain AMM[1,6] exchanges:
37 |
38 | 1. There is no gas fee for each swap.
39 | 2. Token swap is quick so that high-frequency trading is feasible.
40 | 3. Liquidity is for both payment and trading.
41 |
42 | Uniswap[2], Curve[3], and Balancer[4], which operate on an automated market maker (AMM) model, by defining a global constant invariant, ensure the closing certainty and the efficient use of capital for on-chain trading. Their smart contracts hold liquidity reserves of various token pairs and traders execute swaps directly against these reserves. In this model, prices are set automatically according to a constant product `x*y=k` model (or its variants), where `x` is the number of token A and `y` is the number of token B in a pool. When a trader sells out `x'` token A for `y'` token B, the amount of token A in the pool increases and the amount of token B decreases, but the product remains the same: `(x+x')*(y-y')=x*y=k`.
43 |
44 | Liquidity providers are incentivized by receiving the transaction fee (0.3% in general).
45 |
46 | This paper presents an AMM on the lightning network, which is more general than the current existing constant product/sum/mix models, and the infrastructure is completely different from the on-chain AMM. **It is an abstraction of the constant invariant model**: the curve is a 1-manifold, which is locally homeomorphic to the open unit circle, not predefined, but calculated during the system working. We don't make any assumptions about the pricing of underlying assets. At different price levels and with the changing of the intrinsic value of assets, the shape of the curve has to change. This model is not only for the lightning network, but also suitable for any layer 2 networks.
47 |
48 | We introduce the concept manifold here because the global curve is not proper to be predefined. Constant product or constant sum invariants are special cases of 1-manifold. The two models work because the arbitragers will exploit tiny price differences between different markets if the price deviates substantially from fair value. Without arbitragers, the curve itself can not price assets.
49 |
50 | This paper takes arbitrage into modeling and outlines the core mechanism of how AMM on LN works. We assume readers are familiar with both LN and AMM so we will omit the introduction to basic concepts. For the Bitcoin lightning network, we refer to lnd, and for the smart asset lightning network, we refer to Omnibolt.
51 |
52 | ## liquidity pool: from discrete to continuous space
53 |
54 | LN already has funded channels to support multi-hop HTLC payment. Channels funded by a certain token form a logical network, where Alice is able to pay Bob even if they don't have a direct channel. Nodes on the payment path offer liquidity and receive a portion of the fee if the payment is a success.
55 |
56 | In the AMM model, liquidity providers play a similar role: if a swap succeeds, one who deposits his tokens into the contract will get commission fee according to the proportion of his contribution to the token pool.
57 |
58 |
59 |
60 |
61 |
62 | Naturally, funded channels in lightning network form a global liquidity pool, the difference is that the whole lightning network is a pool, every node maintains a portion of liquidity, while onchain AMM uses a contract address to collect liquidity: all tokens are deposited into one address.
63 |
64 | ### continuous space
65 | Conceptually, an order book is a discrete space consisting of a series of orders at multiple prices. There must be a spread between the highest bid and the lowest ask, if the spread is too wide, then no transaction could be closed. If the order book dex is on-chain, makers will often take losses of miner fee.
66 |
67 | To gain the certainty of closing, we leverage the funded channels to fill the spreads between all prices. Thus we have a continuous space that covers the entire price space. When price moves, liquidity providers have an incentive to concentrate liquidity around the current price for higher commissions. They revoke old liquidity ranges and submit new liquidity ranges that cover the current price. This hedges against the liquidity sparsity of the order book model.
68 |
69 |
70 |
71 |
72 |
73 | All small ranges(`U_i`) patching together is homeomorphic to real 1-space (`R^(n), n=1`):
74 |
75 |
76 |
77 |
78 |
79 | For engineering practice, we can assume that the space is differentiable.
80 |
81 | After a node commits a liquidity range, it will receive a commission fee when swapping within the range. The Lightning Network has no contract to collect commissions fee for liquidity providers, but instead utilizes a routing protocol that enables liquidity providers' channel funds to be used for trading, hence these channels earn commission fees directly.
82 |
83 | We begin with a discussion of limited order, which acts similar to a small range which is defined in Uniswap V3[8] for precisely managing liquidity distribution.
84 |
85 | ### limit order
86 |
87 | A limit order is an extreme case of a liquidity range, where the lower bound equals the upper bound. Signing a limit order equals committing to the global liquidity pool:
88 |
89 | ```
90 | orderMessage
91 | {
92 | tokenSell: “USDT”
93 | amount: 20
94 | networkA: obd
95 | tokenBuy: “BTC”
96 | networkB: lnd
97 | ratio: {
98 | USDT: 60000
99 | BTC: 1
100 | }
101 | expirationTimestamp: 24*90 hours
102 | signature: signed by maker's private key
103 | nonce: to prevent replay attacks
104 | }
105 |
106 | ```
107 |
108 | **tokenSell**: The token for sale.
109 |
110 | **amount**: The amount of token for sale.
111 |
112 | **networkA**: the network name(ID) the token is issued.
113 |
114 | **tokenBuy**: The token wanted.
115 |
116 | **networkB**: the network name(ID) the token wanted is issued.
117 |
118 | **ratio**: The price.
119 |
120 | **expirationTimestamp**: If the order times out, it will be automatically cancelled.
121 |
122 | **signature**: All signatures of orders are deterministic, using RFC6979 (using HMAC-SHA256), and the maximum length is 73 bytes. Signature is constructed as in the section ["signing an order"](#signing-an-order) below.
123 |
124 | **nouce**: to prevent replay(repeat) attacks.
125 |
126 | If one token is denominated in the other token, then the price `P` is the ratio of the two tokens. A buyer's order is a left-closed and right-open interval `[P, $\infty$)`. The union of all buyers' intervals covers the space of Bitcoin buyer's liquidity, if tokenSell is USDT, and tokenBuy is Bitcoin:
127 |
128 |
129 |
130 |
131 |
132 | If the token amount on an intersection `$[P1, \infty) \cap [P2, \infty) = [P1, P2)$` ( which is still an interval ) is consumed by sellers' orders, then the price moves up from `P1` to the next limit `P2`.
133 |
134 | ### coordinate charts and local invariant definition
135 |
136 | For each `P_i = (x_i, y_i)` has a neighborhood `U_i` homeomorphic to an open circle. The basic formula above will change: token amount is continuous on any continuous interval included in the range.
137 |
138 |
139 |
140 |
141 |
142 | We build local charts around `(x_i, y_i), i=0,1,2,...` to cover the whole price space. Let the local liquidity function `y=f(x)`, assume `f(x)` is differentiable around a certain `(x_i, y_i)`. It has a power series based on a function's derivatives( under the convention 0^0 = 1 ):
143 |
144 |
145 |
146 |
147 |
148 | If we take `n=0,1` in the series and discard all others, then locally any curve approximates a line.
149 |
150 | ### example: constant function invariants
151 |
152 | #### example 1:
153 | If let:
154 |
155 |
156 |
157 |
158 |
159 | Where `C` is a constant. Then near any point, the invariant model is the constant sum model defined in Curve[3](Curve is the project name, not the geometry object).
160 |
161 | #### example 2:
162 |
163 | If let:
164 |
165 |
166 |
167 |
168 | Then near any point, this is the constant product model defined in Uniswap[2]. It also models the ranged liquidity in V3.
169 |
170 | Derivatives in the above expansion can be calculated from the trading data around the point. Trading data includes orders posted and ranged liquidity deposited. Apparently, piece-wise invariants can be glued(a topological operation) together to form a global curve, as shown in the above graph.
171 |
172 |
173 | ### capital efficiency
174 | TO DO(Ben, Neo)
175 |
176 | ### slipage estimation
177 |
178 | In a regular market, sometimes the more you buy the higher the marginal exchange rate that you have to pay for additional units, sometimes the exchange rate is stable, and you don't need to pay higher prices when you buy more. This totally depends on the liquidity provided by the sellers(counterparties).
179 |
180 |
181 |
182 |
183 |
184 | the two market states fit into two different curves. On the left market, the exchange rate won't grow fast as you buy more. But on the right side market, the slippage will be very large. The right market does not offer a deep market depth for large orders.
185 |
186 | TO BE DONE(Ben, Neo)
187 |
188 |
189 | ### properties of local invariant model
190 |
191 | TO DO(Ben, Carmack):
192 |
193 | 1. Local invariant model make no assumption about pricing of underlying assets.
194 | 2. Constant function(sum/product) invariants are special cases of local invariant model.
195 | 3. Curvature measures how quickly the price changes.
196 | 4. Liquidity and orders determines the curvature.
197 | 5. Global (covers all price space) expression of the curve for all token pairs is unknown, and may not exist.
198 | 6. Arbitragers help prices go around fair values.
199 | 7. We should carefully calculate the parameters, to obtain lower slipage.
200 |
201 |
202 | ## signing an order
203 |
204 |
205 |
206 |
207 |
208 | 1. Alice gets the ratio(price) from a tracker or an oracle and signs the order.
209 | 2. Alice post this order to a tracker.
210 |
211 | All signatures of orders are deterministic, using [RFC6979 (Deterministic Usage of the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA))](https://datatracker.ietf.org/doc/html/rfc6979)[11].
212 |
213 | The signature is constructed as:
214 | ```
215 | ECDSA(H(H(H(H(H(H(H(tokenSell | tokenBuy) | amount) | networkA) | networkB) | ratio) | expirationTimestamp) | nonce), PrivateKey)
216 | ```
217 |
218 | `H` is a hash function. Users should choose a hash function that the tracker network supports, for example, Pedersen hash function, when signing their order.
219 |
220 | The tracker network must verify the signature. If all is correct, then sync the order to neighbors, find out matching orders and push them to the maker's node.
221 |
222 | ## adding liquidity
223 | TO DO(Ben, Neo): (add formular for ranges in this chapter or chapter 2)
224 |
225 | Adding liquidity to the lightning network is simple: just open a channel with your counterparty and fund it. The lightning network discovers new channels and updates the network graph so that your channels will contribute to the global payment liquidity.
226 |
227 | But adding liquidity to an AMM pool is different. Not all the tokens funded in channels can be market maker liquidity reserves. Users need to sign ranged liquidity of pair (x, y) and post it to a tracker they connect to. At least two channels have to be opened and funded.
228 |
229 | The exchange rate is calculate from global `x/y`, feed by trackers:
230 |
231 | **Step 1**: Suppose Alice funded her BTC channel `x'`, then she should fund her USDT according to the current local invariant, for example, `y'= y(x+x')/x - y`.
232 |
233 | **Step 2**: If she deposits more or less USDT, the extra tokens, USDT or BTC, will be marked as the payment liquidity reserve.
234 |
235 | **Step 3**: Alice signs and syncs her funding and specified range to her trackers, which record Alice's AMM liquidity for BTC and USDT.
236 |
237 | The first AMM liquidity provider could deposit any amount of BTC and USDT, the tracker will calculate how much BTC or USDT will be marked as AMM liquidity according to the price feed from an oracle.
238 |
239 | Funding a channel costs BTC gas fees. But adding(removing) liquidity has no cost.
240 |
241 | In section [impermanent loss](#impermanent-loss), there is a data simulation to help liquidity providers set appropriate ranges, minimize impermanent losses, and earn reliable trading fees.
242 |
243 |
244 |
245 | ## removing liquidity
246 |
247 | There are two ways to remove liquidity:
248 | 1. withdraw signed and submitted orders and ranged liquidity.
249 | 2. close the channel and withdraw tokens to the mainchain.
250 |
251 |
252 | Trackers calculate the remaining tokens in the global liquidity reserve, and the extra tokens will be marked payment liquidity reserve, according to exchange rate at the moment of closing channel:
253 |
254 | Suppose Alice closes her channel of `x'` BTCs, then the BTC-USDT pair will have redundant USDT in the pool. Its tracker randomly selects some USDT channels in the graph and marks a portion of channel fund `y'` to be the payment liquidity reserve, to make sure the global price `x/y = BTC/USDT` is unchanged. For example, `y' = y - y(x-x')/x`, if the current local invariant is constant product.
255 |
256 | There is no protocol fee taken during closing a channel. Only gas fee in BTC occurs.
257 |
258 | ## O(1) complexity of add and remove operations
259 |
260 | TO DO(Ben, Neo): apply binary tree and hash table to store ranged liquidity and limit orders, which has `O(1)` time complexity in adding and removing.
261 |
262 | ## channel state transition
263 |
264 | We use **AMM balance** and **payment balance** to distinguish the two states of channel funds.
265 |
266 |
267 |
268 |
269 |
270 | ```
271 | for a 75 USDT channel: [Alice, 75 USDT, Bob]
272 | e.g. Alice's local balance: 50 USDT before signing an order.
273 | Bob's local balance: 25 USDT as payment balance.
274 | ```
275 |
276 |
277 |
278 | **Step 1**: After signing an order to sell out 20 USDT for BTCs, the channel state changes to:
279 | ```
280 | Alice's local balance: 20 USDT as AMM balance, and 30 USDT as payment balance.
281 | Bob's local balance: 25 USDT as payment balance.
282 | ```
283 |
284 | **Step 2**: After successfully selling out the 20 USDT, and getting Bitcoins in another channel, the channel state changes to:
285 | ```
286 | Alice's local balance: 30 USDT as payment balance.
287 | Bob's local balance: 20 USDT as AMM balance, 25 USDT as payment balance.
288 | ```
289 |
290 | **OR**
291 |
292 | **Step 2**: Alice withdraws the order, then the channel state changes back to the origin.
293 |
294 |
295 | The global AMM liquidity will not change if Bob doesn't manually mark the 20 USDT as the payment balance.
296 |
297 | ## trackers running a matching engine
298 |
299 | Trackers, in the design of the OmniBOLT network, not only maintain graph topology, but also maintain the global constant product model.
300 |
301 | When an OmniBOLT node is online, it has to announce itself to the network via a tracker it connects, as the rendezvous, notifying its neighbors to update its token type, amount of channels, and liquidity reserves. Omnibolt applies a tracker network to register nodes, and update the status of the nodes graph. Any tracker can be a rendezvous[5] that allows nodes to connect.
302 |
303 |
304 | Please go to the document of [Tracker network](https://omnilaboratory.github.io/obd/#/Architecture?id=tracker-network) to understand how it works.
305 |
306 | After a node sign and submit an order to a tracker, the tracker takes 6 steps to process the order:
307 |
308 |
309 |
310 |
311 |
312 |
313 | 1. When receiving an order A from obd 1, the tracker searches its local order book database for matching.
314 | 2. If can not find matching orders, it seeks its neighbors in the DHT network for order A.
315 | 3. If the tracker collects matching orders that can (partially) fill the order A, it pushes the node's addresses and matching orders to obd 1.
316 | 4. obd 1, 3, and 4 check price via an oracle. If the price gap is found to exceed the predefined threshold, the transaction is rejected.
317 | 5. obd 1 Processes atomic swaps to obd 3 and 4.
318 | 6. The remaining of the order will be saved in the tracker's local order book database, waiting for further deals.
319 |
320 | ### example for matching orders
321 |
322 |
323 |
324 |
325 |
326 |
327 | The matching engine picks a ratio between 60000:1 to 60500:1, for example, 60200:
328 |
329 | 1. Alice sells 1 BTC for 60000 USDT, then the result is more than expected.
330 | 2. Bob plans to sell 60500 USDT for 1 BTC, then the result is more than his expectation either. He only pays 60200 USDT.
331 | 3. An order may be partially filled. For example: if B sells 121000 USDT for 2 BTC.
332 |
333 | ### token trading against liquidity pool
334 |
335 | Then a tracker maintains "almost" all nodes' balances and hence it is able to calculate the token price for a trade:
336 |
337 | Alice plans to sell out `x'` token A for a certain number of token B at the fee rate of `0.3%`. So that the pool will have `(x+x')` token A and `(y-y')` token B. The price after trade will be updated to `price(B) = (x+x')/(y-y')`.
338 |
339 | **Step 1**. Alice queries a tracker for the liquidity(all available orders) for both token A and token B networks. The tracker calculates the `y'` hence decides how much token B that Alice can get:
340 |
341 | ```
342 | fee = x * 0.3%
343 | A pool = x + x' - 0.3%x'
344 | B pool = x*y/(A pool)
345 |
346 | y' = y - B pool
347 |
348 | ratio = x'/y'
349 | ```
350 |
351 |
352 | **Step 2**: The tracker seeks multiple nodes, which together can provide `y'` token B, returns Alice the payment paths.
353 |
354 | **Step 3**. Alice creates [atomic swaps](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-05-Atomic-Swap-among-Channels.md#swap)[7] and sends them to these nodes respectively, where `ratio` is the price of token B at the moment of the trade.
355 |
356 | **Step 4**. Alice and all her counterparties finish the atomic swaps with all these nodes, and get `y'` tokens in the local **AMM balance**.
357 |
358 | ```
359 | Suppose x'/y' = 2, Alice sells out 10 A:
360 |
361 | |--atomic swap---> Bob: 2 A for 4 B
362 | |
363 | Alice ----|--atomic swap---> David: 4.5 A for 9 B
364 | |
365 | |--atomic swap---> Carol: 3.5 A for 7 B
366 |
367 | ```
368 |
369 | Fees are allocated to all nodes on the paths, and are still in the **AMM balance** of each node:
370 |
371 | ```
372 | A pool = x + x'
373 | B pool = x*y/(x + x' - 0.3%x')
374 |
375 | new invariant = (A pool) * (B pool) = (x + x')*x*y/(x + x' - 0.3%x')
376 | ```
377 |
378 |
379 |
380 | **Like the characteristics of the lightning network, AMM is suitable for small transactions as well.**
381 |
382 |
383 |
384 |
385 | ## fee structure
386 |
387 | Token A to token B trades: 0.3% fee paid in A. This fee will be apportioned among the nodes in [atomic swap payment path](https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-05-Atomic-Swap-among-Channels.md)[7], which means although the pool has many many liquidity providers, for each transaction, not all the providers get paid.
388 |
389 | Trackers balance the workload of the whole network: If one node is busy handling HTLC, another node will be selected to be a hop and earns the swap fee.
390 |
391 | If a liquidity provider thinks the tracker he connects is not fair enough, he may choose another one. Each tracker shall publish its path/node selection policy.
392 |
393 |
394 | ## impermanent loss
395 |
396 | Payment liquidity providers will never expose to any loss. Potential losses are only possible for AMM LPs who wish to use liquidity to earn trading fees.
397 |
398 | It is AMM LP's decision to offer a wider liquidity range to earn more trading fees, or a narrow liquidity range to be less exposed to potential impermanent losses.
399 |
400 | Examples showing how impermanent loss happens and how much a loss could be can be found in [9,10]. The following graph and summary of losses compared to holding are from [10]:
401 |
402 |
403 |
404 |
405 |
406 | a 1.25x price change results in a 0.6% loss relative to HODL(Hold On for Dear Life)
407 | a 1.50x price change results in a 2.0% loss relative to HODL
408 | a 1.75x price change results in a 3.8% loss relative to HODL
409 | a 2x price change results in a 5.7% loss relative to HODL
410 | a 3x price change results in a 13.4% loss relative to HODL
411 | a 4x price change results in a 20.0% loss relative to HODL
412 | a 5x price change results in a 25.5% loss relative to HODL
413 |
414 |
415 | We use 1.50x price change as an example, given the trading fee of 0.3%. If the price stays within the 1.0X to 1.5x range for a month, suppose the transaction volume during this period is 100 times the liquidity in this range, then the expected earning is `0.3% * 100 = 30%`, which is significantly great than 2.0% loss.
416 |
417 | Concentrated liquidity has 4000x capital efficiency as claimed in uniswap V3, which means LPs can fund much less liquidity to earn significantly higher fees. If the price fluctuates in a narrow range for a long time, then the impermanent losses are negligible compared to the profitable trading fees. If the Bitcoin price rises quickly out of the range, all the liquidity will be entirely denominated in USDT, then the impermanent loss equals the Bitcoin liquidity funded, and no trading fee will be earned anymore.
418 |
419 |
420 | LP's strategy could be sticking the liquidity to the price movement. It all depends on the liquidity provider's prediction of the future market trend.
421 |
422 |
423 | ## oracle
424 | Oracle is involved to feed the real-time external price for trading. Although trackers give prices at any moment a trade occurs, obd should verify it from at least one oracle before the moment of executing this swap. If the price is below the expectation of the order signed, obd should reject the trade.
425 |
426 | ## differences from onchain AMM Swaps
427 |
428 | 1. Price is from trackers who maintain statistics of global liquidity, but to avoid price manipulation, obd node should verify price from external oracles when trading tokens.
429 |
430 | 2. Trackers maintain the global prices for all token pairs, but they have no permission to execute any trade. The lightning network has no global contract that executes transactions. Every obd node should verify the incoming order to avoid price manipulation. Obd does not have to trust any tracker.
431 |
432 | 3. On-chain swaps use smart contracts to collect and allocate fees for liquidity providers. But the Lightning Network has no contract. We instead utilize a routing protocol that enables liquidity providers' channel funds to be used for trading, hence these channels earn commission fees directly.
433 |
434 |
435 |
436 | ## reference list
437 |
438 | 1. Vitalik Buterin. The x*y=k market maker model. https://ethresear.ch/t/improving-front-running-resistance-of-x-y-k-market-makers.
439 | 2. Uniswap. https://uniswap.org/
440 | 3. Michael Egorov. Curve. Automatic market-making with dynamic peg. https://curve.fi/files/crypto-pools-paper.pdf
441 | 4. Fernando Martinelli, Nikolai Mushegian. A non-custodial portfolio manager, liquidity provider, and price sensor. https://balancer.finance/
442 | 5. [Connect to a tracker](https://omnilaboratory.github.io/obd/#/OBD-README?id=step-2-connect-to-a-tracker): https://omnilaboratory.github.io/obd/#/OBD-README?id=step-2-connect-to-a-tracker
443 | 6. Uniswap whitepaper. https://uniswap.org/whitepaper.pdf
444 | 7. Atomic swap. https://github.com/omnilaboratory/OmniBOLT-spec/blob/master/OmniBOLT-05-Atomic-Swap-among-Channels.md#swap
445 | 8. Hayden Adams, Noah Zinsmeister, et. Uniswap V3 white paper. https://uniswap.org/whitepaper-v3.pdf
446 | 9. Impermanent Loss Explained. https://academy.binance.com/en/articles/impermanent-loss-explained
447 | 10. Pintail. Uniswap: A Good Deal for Liquidity Providers?. https://pintail.medium.com/uniswap-a-good-deal-for-liquidity-providers-104c0b6816f2
448 | 11. rfc6979(Request for Comments: 6979): Deterministic Usage of the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA). https://datatracker.ietf.org/doc/html/rfc6979
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
--------------------------------------------------------------------------------
/OmniBOLT-03-RSMC-and-OmniLayer-Transactions.md:
--------------------------------------------------------------------------------
1 | # OmniBOLT #3: RSMC and OmniLayer Transaction
2 |
3 | Sometimes we use "money" instead of Omni assets for illustration purposes. Readers just imagine that what we fund, transfer or trade is USDT, an important asset issued on Omnilayer.
4 |
5 | From this chapter on, our context is Omnilayer, not only bitcoin anymore.
6 |
7 | RMSC pays tokens to the counterparty directly without any locker. The receiver is only passively receiving, and does not need any unlocking or confirming actions. This protocol can be applied to the following classic scenarios:
8 |
9 | 1. peer-to-peer instant message system
10 | 2. Send red packets in social networks
11 | 3. air drop
12 |
13 | # Table of Contents
14 | * [Omnilayer Class C Transaction](#Omnilayer-Class-C-Transaction)
15 | * [op return](#op_return)
16 | * [payload](#payload)
17 | * [string to int64](#string-to-int64)
18 | * [BTC_funding and asset_funding](#The-btc_funding_created-btc_funding_signed-asset_funding_created-and-asset_funding_signed-Messages)
19 | * [Commitment_tx, revoke and acknowledge](#The-commitment_tx-and-revoke-and-acknowledge-Message)
20 | * [Diagram and messages](#diagram-and-messages)
21 | * [Omni RSMC transaction construction](#OMNI-RSMC-transaction-construction)
22 | * [Funding and to_remote transaction](#Funding-and-to-remote-transactions)
23 | * [Commitment transaction](#Commitment-Transaction)
24 | * [Breach remedy transaction](#Breach-remedy-transaction)
25 | * [Message data](#message-data)
26 | * [Cheat and Punishment](#Cheat-and-Punishment)
27 | * [Close_channel](#The-close_channel-Message )
28 | * [Unit test vectors](#unit-tests)
29 | * [References](#references)
30 |
31 | ## Omnilayer Class C Transaction
32 |
33 | Omnibolt defines and transfers tokens in lightning network subject to the [omni specification version 0.7](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc). Specifically, [the class C transaction](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc#65-class-c-transactions-op_return-method) is mainly used in the omnibolt. The golang implementation is under the [`omnicore`](https://github.com/omnilaboratory/obd/tree/master/omnicore) directory in the obd project. An example of constructing simple send raw transaction([the class c tx in omni protocol](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc#65-class-c-transactions-op_return-method)) offline is [here](https://github.com/omnilaboratory/obd/tree/master/omnicore#construct-simple-send-transaction).
34 |
35 | Validators (e.g the counterparty) must use omnicore(integrated by tracker) full nodes to verify the correctness of received transactions.
36 |
37 | ### op_return
38 | By definition, [the class C transaction](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc#65-class-c-transactions-op_return-method) [embeds a payload in an OP_RETURN output](https://github.com/omnilaboratory/obd/blob/master/omnicore/CreateRawOmniTransactionOpreturn.go#L170-L208), prefixed with a transaction marker "omni", to a raw bitcoin transaction:
39 | ```
40 | vin: [...]
41 | out: [
42 | {op_return_out:{value:0, pkScript:opReturn_encode}},
43 | {normal_out:{value:546, pkScript: pkHash}}
44 | ]
45 | ```
46 | Where `op_return_out` has to be less than 83 bytes and is encoded as:
47 | ```go
48 | /*
49 | * Embeds a payload in an OP_RETURN output, prefixed with a transaction marker "omni".
50 | *
51 | * The request is rejected, if the size of the payload with marker is larger than
52 | * the allowed data carrier size ("-datacarriersize=n").
53 | */
54 |
55 | //"omni"
56 | vchOmBytes := []byte{0x6f, 0x6d, 0x6e, 0x69}
57 |
58 | s := make([][]byte, 2)
59 |
60 | s[0] = vchOmBytes
61 | s[1] = payload_bytes
62 |
63 | sep := []byte("")
64 | omni_payload := bytes.Join(s, sep)
65 |
66 | if (uint(len(omni_payload))) > nMaxDatacarrierBytes {
67 | fmt.Println("omni_payload is too long, only 83 bytes are allowed")
68 | return nil
69 | }
70 |
71 | //add op code, which is OP_RETURN in this case, and data .
72 | op_return_data := make([][]byte, 2)
73 | op_return_data[0] = []byte{OP_RETURN}
74 | op_return_data[1] = addOpCodeData(omni_payload)
75 | op_return := bytes.Join(op_return_data, sep)
76 |
77 | return op_return
78 |
79 | ```
80 |
81 | The [byte array payload_bytes](https://github.com/omnilaboratory/obd/blob/master/omnicore/rpcpayload.go#L94-L114) defines the property ID and the amount to be paid:
82 |
83 | ### payload
84 |
85 | Transaction type 0 is used in:
86 | * funding asset to a channel,
87 | * pay the `to_remote` output and in RSMC and HTLC,
88 | * construct breach remedy transactions,
89 |
90 |
91 |
92 | | size | Field | type | Example |
93 | | -------- |-----------------------| ---------------- | ---------------- |
94 | | 2 bytes | Transaction version | [Transaction version](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc#field-transaction-version) | 0 |
95 | | 2 bytes | Transaction type | [Transaction type](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc#field-transaction-type) | 0 |
96 | | 4 bytes | Currency identifier | [Currency identifier](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc#field-currency-identifier) | 1(omni) |
97 | | 8 bytes | Amount to transfer | [Amount](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc#field-number-of-coins) | 100 |
98 |
99 |
100 | And the [transaction type 7](https://gist.github.com/dexX7/1138fd1ea084a9db56798e9bce50d0ef) is used in commitment trsactions that constructs 2 or 3 outputs in RSMC and HTLC respectively:
101 |
102 | | size | Field | Type | Example |
103 | | -------- | ----------------------- | ------------------- | ------------------- |
104 | | 2 bytes | Transaction version | Transaction version | 0 |
105 | | 2 bytes | Transaction type | Transaction type | 7 (= Send-to-Many) |
106 | | 4 bytes | Token identifier to send | Token identifier | 31 (= USDT ) |
107 | | 1 byte | Number of outputs | Integer-one byte | 3 |
108 | | 1 byte | Receiver output # | Integer-one byte | 1 (= vout 1) |
109 | | 8 bytes | Amount to send | Number of tokens | 20 0000 0000 (= 20.0) |
110 | | 1 byte | Receiver output # | Integer-one byte | 2 (= vout 2) |
111 | | 8 bytes | Amount to send | Number of tokens | 15 0000 0000 (= 15.0) |
112 | | 1 byte | Receiver output # | Integer-one byte | 4 (= vout 4) |
113 | | 8 bytes | Amount to send | Number of tokens | 30 0000 0000 (= 30.0) |
114 |
115 | The above may changes according to the update of omnicore.
116 |
117 |
118 | The transaction version used by OmniBOLT are both 0.
119 |
120 | If on little endian systems, use `SwapByteOrder16(...)`, `SwapByteOrder32(...)`, `SwapByteOrder64(...)` to swap the bit order:
121 | ```go
122 | func SwapByteOrder16(us uint16) uint16 {
123 | if IsLittleEndian() {
124 | us = (us >> 8) |
125 | (us << 8)
126 | }
127 | return us
128 | }
129 |
130 | func SwapByteOrder32(ui uint32) uint32 {
131 | if IsLittleEndian() {
132 | ui = (ui >> 24) |
133 | ((ui << 8) & 0x00FF0000) |
134 | ((ui >> 8) & 0x0000FF00) |
135 | (ui << 24)
136 | }
137 | return ui
138 | }
139 |
140 | func SwapByteOrder64(ull uint64) uint64 {
141 | if IsLittleEndian() {
142 | ull = (ull >> 56) |
143 | ((ull << 40) & 0x00FF000000000000) |
144 | ((ull << 24) & 0x0000FF0000000000) |
145 | ((ull << 8) & 0x000000FF00000000) |
146 | ((ull >> 8) & 0x00000000FF000000) |
147 | ((ull >> 24) & 0x0000000000FF0000) |
148 | ((ull >> 40) & 0x000000000000FF00) |
149 | (ull << 56)
150 | }
151 |
152 | return ull
153 | }
154 |
155 | ```
156 |
157 | And use `Uint16ToBytes(...)`, `Uint32ToBytes(...)`, `Uint64ToBytes(...)` to transform int to byte array to be embeded:
158 | ```go
159 | func Uint16ToBytes(n uint16) []byte {
160 | return []byte{
161 | byte(n),
162 | byte(n >> 8),
163 | }
164 | }
165 | func Uint32ToBytes(n uint32) []byte {
166 | return []byte{
167 | byte(n),
168 | byte(n >> 8),
169 | byte(n >> 16),
170 | byte(n >> 24),
171 | }
172 | }
173 | func Uint64ToBytes(n uint64) []byte {
174 | return []byte{
175 | byte(n),
176 | byte(n >> 8),
177 | byte(n >> 16),
178 | byte(n >> 24),
179 | byte(n >> 32),
180 | byte(n >> 40),
181 | byte(n >> 48),
182 | byte(n >> 56),
183 | }
184 | }
185 | ```
186 |
187 | Ties together to create a payload. For type 0:
188 |
189 | ```go
190 |
191 | func OmniCreatePayloadSimpleSend(property_id uint32, amount uint64) []byte {
192 |
193 | var messageType uint16 = 0
194 | var messageVer uint16 = 0
195 | messageType = SwapByteOrder16(messageType)
196 | messageVer = SwapByteOrder16(messageVer)
197 | property_id = SwapByteOrder32(property_id)
198 | amount = SwapByteOrder64(amount)
199 |
200 | len := 4
201 | s := make([][]byte, len)
202 |
203 | s[0] = Uint16ToBytes(messageType)
204 | s[1] = Uint16ToBytes(messageVer)
205 | s[2] = Uint32ToBytes(property_id)
206 | s[3] = Uint64ToBytes(amount)
207 |
208 | sep := []byte("")
209 | return bytes.Join(s, sep)
210 |
211 | }
212 |
213 | ```
214 |
215 | And for [type 7](https://github.com/omnilaboratory/obd/blob/lnd/omnicore/rpcpayloadSendToMany.go#L50):
216 |
217 | ```
218 | var messageType uint16 = 7
219 | var messageVer uint16 = 0
220 | messageType = SwapByteOrder16(messageType)
221 | messageVer = SwapByteOrder16(messageVer)
222 | property_id = SwapByteOrder32(property_id)
223 |
224 | var outputs_count byte = 0
225 | var total_value_out int64 = 0
226 |
227 | receivers := make([][]byte, 0)
228 |
229 | for j := 0; j < len(receivers_array); j++ {
230 | outputs_count += 1
231 | amount := StrToInt64(receivers_array[j].Amount, divisible)
232 | amount_uint64 := uint64(amount)
233 | size := 2
234 | one_receiver := make([][]byte, size)
235 | one_receiver[0] = OneByte(receivers_array[j].Output)
236 | one_receiver[1] = Uint64ToBytes(SwapByteOrder64(amount_uint64))
237 |
238 | seperator := []byte("")
239 | one_receiver_in_byts := bytes.Join(one_receiver, seperator)
240 |
241 | receivers = append(receivers, one_receiver_in_byts)
242 | total_value_out = total_value_out + AmountFromValue(receivers_array[j].Amount)
243 | }
244 |
245 | len := 4 + outputs_count
246 | s := make([][]byte, len)
247 |
248 | s[0] = Uint16ToBytes(messageVer)
249 | s[1] = Uint16ToBytes(messageType)
250 | s[2] = Uint32ToBytes(property_id)
251 | s[3] = OneByte(outputs_count)
252 |
253 | for i := byte(4); i < len; i++ {
254 | s[i] = receivers[i-4]
255 | }
256 |
257 | sep := []byte("")
258 |
259 | payload := bytes.Join(s, sep)
260 | return payload, HexStr(payload)
261 |
262 | ```
263 |
264 | ### string to int64
265 | The token amount in floating number is represented in a string, which has to be [converted to a usable int64](https://github.com/omnilaboratory/obd/blob/master/omnicore/ParseString.go#L21-L95). 8 decimal is allowed and can be recognized. If the decimal is less than 8, pad zeros on right. If there are too many decimals, truncate after 8:
266 |
267 |
268 | ```go
269 | pos := strings.Index(strAmount, ".")
270 | if pos == -1 {
271 | // no decimal point but divisible so pad 8 zeros on right
272 | pad_eight_zero := "00000000"
273 | strAmount = strings.Join([]string{strAmount, pad_eight_zero}, "")
274 |
275 | } else {
276 | // check for existence of second decimal point, if so invalidate amount
277 |
278 | posSecond := strings.LastIndex(strAmount, ".")
279 | if posSecond != pos {
280 | return 0
281 | }
282 |
283 | if (len(strAmount) - pos) < 9 {
284 | // there are decimals either exact or not enough, pad as needed
285 |
286 | strRightOfDecimal := strAmount[pos+1 : len(strAmount)]
287 | zerosToPad := 8 - len(strRightOfDecimal)
288 | //fmt.Println(strRightOfDecimal)
289 |
290 | // do we need to pad?
291 | if zerosToPad > 0 {
292 | for it := 0; it != zerosToPad; it++ {
293 | strAmount += "0"
294 | }
295 | }
296 | } else {
297 | // there are too many decimals, truncate after 8
298 | // strAmount = strAmount.substr(0, pos + 9);
299 | strAmount = strAmount[0 : pos+9]
300 | }
301 | str1 := strAmount[0:pos]
302 | str2 := strAmount[pos+1 : len(strAmount)]
303 | strAmount = strings.Join([]string{str1, str2}, "")
304 | }
305 |
306 |
307 | nAmount, _ = strconv.ParseInt(strAmount, 10, 64)
308 | ```
309 |
310 |
311 | ## The `btc_funding_created`, `btc_funding_signed`, `asset_funding_created` and `asset_funding_signed` Messages
312 |
313 | The four messages describe the outpoint that the funder has created for the initial commitment transactions. After receiving the peer's signature, via `funding_signed`, it will broadcast the funding transaction to the Omnilayer network.
314 |
315 | We focus on omni assets in founding creation: Alice and Bob create a 2-2 P2SH payment to `scriptPubKey`, which is the hash of the **Redeem Script**.
316 |
317 | All transactions, besides the BTC funding transaction, are omni class C transactions.
318 |
319 |
320 | ```
321 | +-------+ +-------+
322 | | |---(1)------------- open_channel ---------->| |
323 | | |<--(2)------------ accept_channel ------------| |
324 | | | | |
325 | | A |---(3)------- btc_funding_created(3400 ) -------->| B |
326 | | |<--(4)------- btc_funding_signed(3500) ---------| |
327 | | | | |
328 | | |---(5)-------- asset_funding_created(34) -------->| |
329 | | |<--(6)-------- asset_funding_signed(35) ---------| |
330 | | | | |
331 | | |---(7)------------ funding_locked ------------->| |
332 | | |<--(8)------------ funding_locked --------------| |
333 | | | | |
334 | | |<---------------- wait for close ------------->| |
335 | +-------+ +-------+
336 |
337 | - where node Alice is 'funder' and node Bob is 'fundee'. Same to BOLT, the fundee is not allowed to fund the channel. This is because of the limitation of the current BTC implementation.
338 | - Of course, each of them can withdraw money if the counterparty agrees, as long as the two parties sign the correct Revocable Sequence Maturity Contracts for these on-chain transactions.
339 |
340 | ```
341 |
342 | **2-2 P2SH**:
343 |
344 | In order to avoid a malicious counterparty who rejects to sign any payment out of the P2SH transaction, so that the money is forever locked in the channel, the funder must construct a Commitment Transaction by which he is able to revoke his funding transaction. This is the first place we introduce the Revocable Sequence Maturity Contract (RSMC), invented by Poon and Dryja in their white paper, in this specification.
345 |
346 | So the `funding_created` message does not mean both parties really deposit money into the channel. The first round of communication just simply set up a P2SH address, construct an unbroadcast funding transaction, construct an RSMC, and exchange signatures. After that, Alice or Bob can broadcast the funding transaction to transfer real Omni assets into the channel.
347 |
348 | The following diagram shows the steps we MUST do before any participants broadcast the funding/commitment transactions. BR1a (Breach Remedy) can be created later before the next commitment transaction is constructed.
349 |
350 |
351 |
352 |
353 |
354 |
355 | Alice's OBD constructs a promised transaction and a refund transaction: C1a/RD1a (Revocable Delivery), which pays out from the 2-2 P2SH transaction output:
356 |
357 | step 1: Alice constructs a temporary 2-2 multi-sig address using Alice's temporary private key Alice2 and waits for Bob's signature: Alice2 & Bob.
358 |
359 | step 2: Alice constructs a promise payment C1a out of Alice & Bob, one output is 60 USDT to `Alice2 & Bob`, and the other output is 40 USDT to Bob.
360 |
361 | step 3: RD1a is the first output of C1a, which pays Alice 60 USDT, but with a sequence number preventing immediate payment if Alice cheats.
362 |
363 | step 4: Bob signs C1a and RD1a, constructs the symmetric C1b/RD1b, and hands Alice for signature.
364 |
365 | step 5: Alice signs C1b/RD1b and sends it back to bob.
366 |
367 | Both sides verify the signed transactions, if all are correct, Alice and Bob update their local database. Alice broadcasts the funding transaction. C1a and C1b cost the same output, only one can enter the blockchain.
368 |
369 | Any side broadcasts C1a/C1b, the counterparty immediately gets the output1 of C1a/C1b but has to wait for a seq=1000 to get his fund. If C1a/C1b are revoked but broadcasted, the counterparty can broadcast BR1a or BR1b immediately and get the remaining funds in the channel immediately.
370 |
371 |
372 | 1. type: -3400 (btc_funding_created)
373 | 2. data:
374 | * [`32*byte`:`amount`]: total satoshis funded by Alice. The minimum amount is `7*546`, where `546` is the dust for an output.
375 | * [`32*byte`:`funding_btc_hex`]: BTC funding transaction hex, used by Bob to validate the transaction.
376 | * [`byte_array`:`funding_redeem_hex`]: funding redeem hex.
377 | * [`sha256`:`funding_txid`]: funding transaction id.
378 | * [`32*byte`:`temporary_channel_id`]: the same as the `temporary_channel_id` in the `open_channel` message.
379 |
380 | Alice notifies Bob that she created the BTC funding transaction by payloads packed in this message -3400.
381 |
382 |
383 | 1. type: -3500 (btc_funding_signed)
384 | 2. data:
385 | * [`byte`:`approval`]: true to confirm the btc funding transaction.
386 | * [`byte_array`:`funding_redeem_hex`]: funding redeem hex.
387 | * [`sha256`:`funding_txid`]: funding transaction id.
388 | * [`32*byte`:`temporary_channel_id`]: the `temporary_channel_id` which will be replaced by channel_id in the following messeges.
389 |
390 |
391 | Bob's OBD verifies the btc funding transaction by its hex and replies to Alice that he knows the funding of BTC by message -3500.
392 |
393 | 1. type: -34 (asset_funding_created)
394 | 2. data:
395 | * [`byte_array`:`c1a_rsmc_hex`]: The constructed first rsmc transaction hex.
396 | * [`byte_array`:`funding_omni_hex`]: The funding omni asset transaction hex, with which Bob can extract all the asset information, including funding output indx, amount, token, etc. Bob then is able to verify the funding transaction. Be noticed that in [BOLT-02-funding_created message](https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#the-funding_created-message), funder sends fundee a funding_output_index for validation.
397 | * [`32*byte`:`rsmc_temp_address_pub_key`]: Internal multisig address used by c1a.
398 | * [`32*byte`:`temporary_channel_id`]: the same as the `temporary_channel_id` in the `open_channel` message.
399 |
400 |
401 | Alice creates the asset funding transaction and asks Bob to verify and sign this transaction.
402 |
403 | 1. type: -35 (asset_funding_signed)
404 | 2. data:
405 | * [`channel_id`:`channel_id`]: generated by exclusive-OR of the funding_txid and the funding_output_index from the asset_funding_created message.
406 | * [`byte_array`:`rd_hex`]: The hex of revockable delivery(RD1a) transaction.
407 | * [`32*byte`:`fundee_pubKey`]: the omni address of fundee Bob.
408 | * [`byte_array`:`rsmc_signed_hex`]: rsmc signed by Bob.
409 |
410 |
411 | Bob signs, and send the `asset_funding_signed` message back to Alice, hence Alice knows the 2-2 P2SH address has been created, but not broadcasted.
412 |
413 | ## The `commitment_tx` and `revoke and acknowledge` Message
414 |
415 | The two messages describe an RSMC payment inside one channel created by Alice and Bob. We introduce HTLC and corresponding messages in the next chapter.
416 |
417 | ### diagram and messages
418 | ```
419 | +-------+ +-------+
420 | | |--(1)------- commitment_tx(351) ---------->| |
421 | | | for asset 1 | |
422 | | |--(1)------- commitment_tx(351) ---------->| |
423 | | | for asset 2 | |
424 | | |--(1)------- commitment_tx(351) ---------->| |
425 | | | for asset 3 | |
426 | | |<-(2)----- commitment_tx_signed (352) -------| |
427 | | | for asset 1 | |
428 | | A | Revoke and Acknowledge, | B |
429 | | | construct BR1a, C2a and RD2a | |
430 | | | and the mirror transactions | |
431 | | | on Bob's OBD | |
432 | | | | |
433 | | |<-(2)----- commitment_tx_signed (352) -------| |
434 | | | for asset 2 | |
435 | | | | |
436 | | |<-(2)----- commitment_tx_signed (352) -------| |
437 | | | for asset 3 | |
438 | | | | |
439 | | |--(3)-------------- (353) ------------------>| |
440 | | | send back signed transactions in C2B | |
441 | | | for asset 2 | |
442 | | |--(3)-------------- (353) ------------------>| |
443 | | | for asset 1 | |
444 | | |--(3)-------------- (353) ------------------>| |
445 | | | for asset 3 | |
446 | +-------+ +-------+
447 |
448 | ```
449 |
450 | Each node has multiple asset channels, it can simultaneously send out transactions, and wait for the counterparty to respond.
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 | There are two outputs of a commitment transaction:
459 | to_rsmc([to local](https://github.com/lightningnetwork/lightning-rfc/blob/master/03-transactions.md#to_local-output)): 0. Alice2 & Bob 60,
460 | [to remote](https://github.com/lightningnetwork/lightning-rfc/blob/master/03-transactions.md#to_remote-output): 1. Bob 40.
461 |
462 | In the revockable delivery(RD) branch, the `to_rsmc` output sends funds back to the owner of this commitment transaction and thus must be time-locked using (for example) sequence number =1000, and must have breach remedy(BR) transaction for Bob in the case that Alice broadcasts a revoked commitment transaction.
463 |
464 | The RD and BR are written in a redeem script, which locks the to_local output. Put the redeem script and the omni class C transaction together to construct the commitment transaction:
465 |
466 |
467 |
468 | ### OMNI RSMC transaction construction
469 |
470 | #### Funding and `to remote` transactions
471 |
472 | ```
473 | version: 2
474 | locktime: 0
475 | tx input:
476 | * outpoint: the vout of funding transaction.
477 | * : to spend the funding transaction.
478 |
479 | tx output:
480 | * op_return:{value:0, pkScript:opReturn_encode},
481 | * receiver/reference:{value:dust, pkScript: pubkey script},
482 | * change:{value:change in satoshis, pkScript: the channel pubkey script }
483 | ```
484 |
485 | Where:
486 | `opReturn_encode`: the [encoded tx version( = 0 ), tx type( = 0 ), token id and amount](#payload), prefixed by "omni".
487 |
488 | `change`: change = satoshis in channel - dust - miner fee. By default, we set dust 546 satoshis.
489 |
490 | Fees are calculated as in [fee calculation](https://github.com/lightning/bolts/blob/master/03-transactions.md#fee-calculation), and must add the `op_return` byte numbers.
491 |
492 | The outputs are sorted into the order by omnicore spec.
493 |
494 | #### Commitment Transaction
495 | ```
496 | version: 2
497 | locktime: 0
498 | tx input:
499 | * outpoint: the vout of funding transaction.
500 | * : to spend the funding transaction.
501 |
502 | tx output:
503 | * op_return:{value:0, pkScript:opReturn_encode},
504 | * to_rsmc/reference1:{value:dust, pkScript: RSMC redeem script},
505 | * to_remote/reference2:{value:dust, pkScript: pubkey script},
506 | * change:{value:change satoshis, pkScript: the channel pubkey script }
507 | ```
508 | Where:
509 | `opReturn_encode`: the [encoded tx version( = 0 ), tx type( = 7 ), token id and amount](#payload), prefixed by "omni".
510 |
511 | The payload on sender side is:
512 |
513 | | size | Field | Sender Value |
514 | | -------- | ----------------------- | ------------------- |
515 | | 2 bytes | Transaction version | 0 |
516 | | 2 bytes | Transaction type | 7 (= Send-to-Many) |
517 | | 4 bytes | Token identifier to send | 31 (= USDT ) |
518 | | 1 byte | Number of receivers | 2 |
519 | | 1 byte | Receiver output # | 1 (= vout 1) |
520 | | 8 bytes | Amount to send | to_rsmc (e.g. 45) |
521 | | 1 byte | Receiver output # | 2 (= vout 2) |
522 | | 8 bytes | Amount to send | to_remote (= 55) |
523 |
524 | The payload on receiver side is:
525 |
526 | | size | Field | Receiver Value |
527 | | -------- | ----------------------- | ------------------- |
528 | | 2 bytes | Transaction version | 0 |
529 | | 2 bytes | Transaction type | 7 (= Send-to-Many) |
530 | | 4 bytes | Token identifier to send | 31 (= USDT ) |
531 | | 1 byte | Number of receivers | 2 |
532 | | 1 byte | Receiver output # | 1 (= vout 1) |
533 | | 8 bytes | Amount to send | to_rsmc (e.g. 55) |
534 | | 1 byte | Receiver output # | 2 (= vout 2) |
535 | | 8 bytes | Amount to send | to_remote (= 45) |
536 |
537 |
538 | `to_rsmc` and `to_remote` are two outputs that allocate the balance of the channel. `to_remote` is locked by the pubkey script and `to_rsmc` is locked by the following `redeem script`:
539 |
540 | ```bat
541 | OP_IF
542 | # Breach Remedy(BR) branch, execute the penalty transaction
543 |
544 | OP_ELSE
545 | # Revockable Delivery(RD) branch
546 | `to_self_delay`
547 | OP_CHECKSEQUENCEVERIFY
548 | OP_DROP
549 |
550 | OP_ENDIF
551 | OP_CHECKSIG
552 | ```
553 |
554 | `change`: change = satoshis in channel - dust - miner fee. By default, we set dust 546 satoshis.
555 |
556 | In the script, readers should notice that the 2-of-2 multisig as the revocation mechanism was replaced with the elliptic curve point multiplication technique. The updated version is of the form:
557 | ```
558 | OP_CHECKSIG
559 | ```
560 |
561 | The outputs are sorted into the order by omnicore spec.
562 |
563 | #### Breach remedy transaction
564 |
565 | The BR transaction can be constructed and broadcast without delay when the counter party broadcasts an revocked commitment.
566 |
567 | ```
568 | version: 2
569 | locktime: 0
570 | tx input:
571 | * outpoint: the vout of funding transaction.
572 | * : to spend the funding transaction.
573 |
574 | tx output:
575 | * op_return:{value:0, pkScript:opReturn_encode},
576 | * receiver/reference:{value:dust, pkScript: pubkey script},
577 | * change:{value:change in satoshis, pkScript: the channel pubkey script }
578 | ```
579 |
580 | Where:
581 | `opReturn_encode`: the [encoded tx version( = 0 ), tx type( = 0 ), token id and amount](#payload), prefixed by "omni".
582 |
583 | The receiver is Bob is Alice cheats.
584 |
585 | The amount is the tokens funded in the channel.
586 |
587 | ### message data
588 |
589 | Alice must send the hex `rsmc_hex` of the transaction based on `to_rsmc output` to Bob to verify and sign. The transaction based on `to_remote output` is named `to_counterparty_tx`, and Alice must send the hex `to_counterparty_tx_hex` to Bob to sign as well. In message `-352`, the signed arguments are `signed_to_counterparty_tx_hex` and `signed_rsmc_hex` respectively.
590 |
591 | Bob constructs the symmetric transaction C2b and hands it back to Alice for signing.
592 |
593 |
594 | 1. type: -351 (commitment_tx)
595 | 2. data:
596 | * [`32*byte`:`channel_id`]: the global channel id.
597 | * [`4*byte`:`asset_id`]: asset id.
598 | * [`32*byte`:`amount`]: amount of the payment.
599 | * [`byte_array`:`commitment_tx_hash`]: C(n+1)a's commitment transaction hash, if Alice is the payer.
600 | * [`32*byte`:`last_temp_address_private_key`]: When C(n+1)a created, the payer shall give up the private key of the previous temp multi-sig address in C(n)a. as an example in the above diagram.
601 | * [`byte_array`:`rsmc_hex`]: the hex of RSMC transaction. From the hex, payment information can be extracted and verified by the counterparty.
602 | * [`byte_array`:`to_counterparty_tx_hex`]: The hex of the transaction that pays the counterparty money.
603 |
604 | For example, Alice pays Bob the `amount` of omni asset by sending `rsmc_Hex`. Her OBD constructs BR(1)a(Breach Remedy) and sends it to Bob. Bob checks Alice2's signature in BR1a to verify if the private key is correct. If it is, Bob signs C2a/RD2a.
605 |
606 |
607 | 1. type: -352 (Revoke and Acknowledge Commitment Transaction)
608 | 2. data:
609 | * [`32*byte`:`channel_id`]: the global channel id.
610 | * [`4*byte`:`asset_id`]: asset id.
611 | * [`byte`:`approval`]: payee accepts or rejects this payment.
612 | * [`32*byte`:`amount`]: amount of the payment.
613 | * [`byte_array`:`commitment_tx_hash`]: Payer's commitement tx hash.
614 | * [`32*byte`:`last_temp_address_private_key`]: payee gives up the private key of his previous temp multi-sig address in C(n)b.
615 | * [`32*byte`:`curr_temp_address_pub_key`]: payee's current temp address pubkey.
616 | * [`byte_array`:`signed_to_counterparty_tx_hex`]: payee signs the `to_counterparty_tx_hex` sent by payer.
617 | * [`byte_array`:`signed_rsmc_hex`]: payee signs the `rsmc_hex` sent by payer.
618 | * [`byte_array`:`rsmc_hex`]: payee's rsmc transaction hex, used in constructing mirror transaction on payee's obd.
619 | * [`byte_array`:`to_counterparty_tx_hex`]: payee's to_counterparty_tx_hex, used in constructing mirror transaction on payee's obd.
620 | * [`byte_array`:`payer_rd_hex`]: payee signs based on `signed_rsmc_hex`, and send it back to payer to construct the RD transaction.
621 |
622 |
623 | 1. type: -353 (send back signed transactions in C2B)
624 | 2. data: to be added
625 |
626 |
627 | In all the above messages, if `asset_id = 0`, then OmniBOLT processes bitcoin lightning network, and is compatible with the current bitcoin-only lightning network. Other assets, for example, `OMNI` has asset id `1`, USDT has asset id `31` on the mainnet.
628 |
629 |
630 | If a node receives a commitment transaction for a certain asset, which is not the asset(ID) that the channel(ID) is built for, then the node has to close the connection with the remote party. In addition, a node must check if the asset id is the same in the transaction `op_return` payload. If not, the node has to close the connection.
631 |
632 | Alice can only update the local state database after receiving all the signatures of C(n)a from Bob. Otherwise, if any message in the process is interrupted, Alice must cancel the established transaction and return to the state of the previous commitment tx. On Bob's side, the same logic is applied, the local state database is updated only after all Alice's signatures are received.
633 |
634 | ## Cheat and Punishment
635 |
636 | All penalties are implemented through breach remedy transactions and Seq timelocks. If Alice tries to broadcast C1a(the older transaction) to claim more money after she pays by C2a, then by broadcasting the breach remedy transaction, this money will be sent to Bob without delay.
637 |
638 | In the above [diagram](#diagram-and-messages), the payer Alice's OBD constructs C2a, and simultaneously, Alice gives up the ownership of C1a by sending her temporary private key of Alice2 to Bob. This is a critical step for Bob to be able to punish fraudulent behavior.
639 |
640 | There has to be a daemon process that monitors Alice's behavior. If it detects that Alice broadcasts C1a, it has to notify Bob to broadcast the punishment transaction BR1a using Alice2's private key. If Bob does not broadcast BR1a before the sequence number expires, Alice will succeed in cheating and get the 60 USDT.
641 |
642 |
643 | ## The `close_channel` Message
644 |
645 | **Rationale**
646 |
647 | This message indicates how to withdraw money from a channel, by broadcasting a `C(n)a`, which is the latest commitment transaction in this channel. It comprises the following steps:
648 |
649 | 1. Allice raises a request, to withdraw her money in P2SH, with her proof of her balance.
650 | 2. Alice waits for OBD to approval:
651 | 2.1 if they are correct, Alice raises a transaction paying from S2SH to Alice's omni address.
652 | 2.2 if they are wrong/incorrect, OBD rejects the request and notifies Bob.
653 |
654 |
655 | Before closing a channel, all HTLCs pending in this channel shall be removed, after which `close_channel` can be successfully executed.
656 |
657 | 1. type: -38 (close_channel)
658 | 2. data:
659 | * [`channel_id`:channel_id]
660 | * [`u16`:`len`]
661 | * [`len`*`byte:scriptpubkey`]
662 | * [`signature`:`signature`]: the signature of Alice or Bob.
663 |
664 | ## unit tests
665 |
666 | ### Class C transaction test vectors
667 | Sender: "1K6JtSvrHtyFmxdtGZyZEF7ydytTGqasNc"
668 | Receiver: "1Njbpr7EkLA1R8ag8bjRN7oks7nv5wUn3o"
669 | Sender pays 0.1 token(2) to the receiver, where miner fee is 0.0006, and changes return to the sender.
670 |
671 | ```
672 | unspent outputs for sender:
673 | [
674 | ...,
675 | {
676 | "txid" : "c23495f6e7ba24705d43583edd69ff25a354c18e69fd8514c07ec6f47cb995de",
677 | "vout" : 0,
678 | "address" : "1K6JtSvrHtyFmxdtGZyZEF7ydytTGqasNc",
679 | "account" : "",
680 | "scriptPubKey" : "76a914c6734676a08e3c6438bd95fa62c57939c988a17b88ac",
681 | "amount" : 0.00100000,
682 | "confirmations" : 0,
683 | "spendable" : true
684 | },
685 | {
686 | "txid" : "ee1673b09b0edaf7aaf8eb0bfd53a5a2757eb3e342e731bfc960b869aa0ab6b3",
687 | "vout" : 2,
688 | "address" : "1K6JtSvrHtyFmxdtGZyZEF7ydytTGqasNc",
689 | "account" : "",
690 | "scriptPubKey" : "76a914c6734676a08e3c6438bd95fa62c57939c988a17b88ac",
691 | "amount" : 0.00835660,
692 | "confirmations" : 1416,
693 | "spendable" : true
694 | }
695 | ]
696 |
697 |
698 |
699 | payload:
700 |
701 | | size | Field | value |
702 | | -------- |-----------------------| ------- |
703 | | 16bits | Transaction version | 0 |
704 | | 16bits | Transaction type | 0 |
705 | | 32bits | Currency identifier | 2 |
706 | | 64bits | Amount to transfer | 0.1 |
707 |
708 |
709 | expected encoded payload: 00000000000000020000000000989680
710 |
711 | expected transaction hex: 0100000002de95b97cf4c67ec01485fd698ec154a325ff69dd3e58435d7024bae7f69534c20000000000ffffffffb3b60aaa69b860c9bf31e742e3b37e75a2a553fd0bebf8aaf7da0e9bb07316ee0200000000ffffffff036a5a0d00000000001976a914c6734676a08e3c6438bd95fa62c57939c988a17b88ac0000000000000000166a146f6d6e690000000000000002000000000098968022020000000000001976a914ee692ea81da1b12d3dd8f53fd504865c9d843f5288ac00000000
712 |
713 | ```
714 |
715 | ### RSMC test vectors
716 |
717 | to be added.
718 |
719 | ## references
720 |
721 | 1. Omni specification version 0.7, [https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc#omni-protocol-specification](https://github.com/OmniLayer/spec/blob/master/OmniSpecification.adoc#omni-protocol-specification)
722 | 2. Omni specification for sendtomany, [https://gist.github.com/dexX7/1138fd1ea084a9db56798e9bce50d0ef](https://gist.github.com/dexX7/1138fd1ea084a9db56798e9bce50d0ef)
723 | 3. Fee calculation, [https://github.com/lightning/bolts/blob/master/03-transactions.md#fee-calculation](https://github.com/lightning/bolts/blob/master/03-transactions.md#fee-calculation)
724 |
725 |
726 |
--------------------------------------------------------------------------------