---
# System prepended metadata

title: STAN. Модель процессинга

---

# STAN. Модель процессинга


**STAN**
Итак - с UXTO все более менее устаканилось и стало ясно. Система разделена на две части, первая инкапсулирует торговую логику и выполнение заявок пользователей, вторая предоставляет систему обработки запросов авторизации и генерации ответов авторизации перевода средств внутри канала и между слоями. Все каналы используют модель UXTO.  подробнее об этом ниже.

На данном этапе - считаем что канал - это труба соеденяющая процессинг и трейдера. В дальнейшем это будет труба между любыми пользователями системы. Труба работает в два приема - (1)запрос, в котором передаются подготовленные для оформления транзакции артефакты и (2)ответ системы подготовленной и подписанной транзакцией. 

Такой дизайн обеспечит достижение трех целей:

1. сохранение асинхронный, высокопроизводительный дизайн **exchange_engine**, исключение блокировок между системами
2. сокрытие внутри системы интерфейсов **processing_engine**, смягчение его режима работы
3. гибкую модель расширения функционала как с точки зрения технологий работы с каналами, так и с точки зрения обработки типов заявок, отличных от market/limit order
  


![оригинал](https://paper-attachments.dropbox.com/s_EBC0F651BC125C9769DE7D0BB192980A833264473A3018FBDB6E908CA3F25CE5_1581139148655_file.png)




Итак имеем ~~три~~ четыре системы, плохо осведомленные друг о друге:

- `**execution_engine**`      - это система обмена активами во втором слое, при которой продавец соглашается продать, а покупатель соглашается купить ценную бумагу в рамках транзакции.  Расчет - это фактический обмен денег или какой-либо иной стоимости ценных бумаг. Работает в модели “учетной записи” в которой оперирует идентификатором канала(xpub реестра, инкапсулирующий все каналы пользователя в конкретном реестре), генерируемым для каждого реестра первого слоя - `user_ledger_id`.
- `**clearing_engine**- UXTO **реестр второго слоя**, это процесс обновления счетов участников торгов, которые приводят к расчету - блокировка средств обеспечения постановленной заявки, создания транзакции нового состояния после матчинга заявки. Отвечает за работу внутри каналов для всех реестров первого слоя, вне зависимости от фактического количества каналов у пользователя - наружу он предлагает интерфейс управления абстрактным каналом, идентифицирующего пользователя/реестр первого слоя(`user_ledger_id`). 
- `**settlement_engine**` **-** служба поставки транзакций открытия, закрытия и рефинансирования каналов от имени биржи, также живет в мире UXTO, оперирует `user_channel_id`
- `**revocation_engine**` **-** эта служба ****публикует ****транзакции отзыва в случае обнаружения в реестрах первого слоя транзакций установки устаревшего состояния, опубликованных трейдерами, оперирует `user_channel_id` оповещает `**clearing_engine**`


> Важный момент - придерживаемся стратегии проверки структуры транзакций и подписей к ней в **execution и clearing** системах, это выглядит избыточным - но на данном этапе главная задача обойти возможные проблемы - после достижения функциональности системы оптимизируем эту часть. Вероятно придется распределить эти проверки между системами исходя из времени выполнения.


**PS -** в случае достижения рабочей системы, следущая фаза будет нацелена на добавление функционала в торговую систему и апдейт механник работы каналов, также уже сейчас важно понимать, что я планирую использовать `**revocation_engine**` как часть инфраструктуры `**keyless_one**` в виде службы охраняющих интересы пользователей от попыток злоупотребления со стороны биржи 

**Важно учесть что биржевая система имеет компоненты критичные к задержкам:** 


- `**execution_engine**` - эта часть процессинга, включенная в exchange_engine // 

**Компоненты не критичные к задержкам:**

- `**clearing_engine**` - отвечает за корректную смену состояния между пользователями(не забывая о комисии биржи) // 
- `**settlement_engine**` - отвечает за открытие/закрытие/ребалансировку каналов // 
- `**revocation_engine**` - система предотвращения публикации отмененных состояний 


Функционал биржи, который призван обеспечить STAN -> обмен между трейдерами актива А на актив Б, для обеспечения гибкости все средства обеспечивающие заявки в стакане - переходят на баланс `**clearing_engine**`, после исполнения(match) заявки средства обеспечивающие исполнения переходят на баланс трейдера. Для получения транзакции смены состояния трейдеру необходимо воспользоваться интерфейсом веб-терминала и запросить ее. В автоматическом режиме трейдер получает оповещение об исполнении в общем потоке. 

Процессы системы оптимальней всего воспринимать как конвейер трансформаций над заявкой. (Постановка, Исполнение, Запрос актуального состояния, Ре-балансировка канала, Перевод средств на холодные счета)

**1. Процесс {регистрации | аутентификации} на бирже:**

![](https://paper-attachments.dropbox.com/s_EBC0F651BC125C9769DE7D0BB192980A833264473A3018FBDB6E908CA3F25CE5_1581187129737_auth.svg)


**2. Процесс постановки заявки на обмен:**        

![](https://paper-attachments.dropbox.com/s_EBC0F651BC125C9769DE7D0BB192980A833264473A3018FBDB6E908CA3F25CE5_1581153611017_place_order.svg)


                  ****
**2. Исполнение выставленной заявки**:

**3. Запрос актуальных commit_tx на канал пользовтеля:**

**4. Ре-балансировка(открытия/закрытия/изменения сальдо) канала:**

**5. Внутренний процесс перевода средств биржи с горячих каналов на холодные:**

**5. Процесс открытия канала**
6**. Процесс закрытия канала**




## Исходя из всего вышесказанного предлагаемые интерфейсы 

Типы данных:
```
- tx
    {
      inputs: [{
          outpoint: {
            hash: "", // хеш транзакции
            index: 0  // индекс выхода транзакции
          },
          ScriptSig: "",   // подпись скрипта
          Sequence: 0xFFFFFFFF //дефолтное значение
        },
        ...
      ],
      outputs: [{
          ScriptPubKey: "",  // redeem-script (multisig)
          Value: 90,  // сумма для финансирования
        },
        {
          ScriptPubKey: "",  // дефолтный скрипт ()
          Value: 10,  // сдача
        }
      ]
    }
- segwit_tx
    {
      inputs: [{
          outpoint: {
            hash: "", // хеш транзакции (всегда транзакции финансирования)
            index: 1  // индекс выхода транзакции
          },
          ScriptSig: "",   // пустая строка
          Sequence: 0xFFFFFFFF, //дефолтное значение
          Witnessess: [
            "",  // пустая
            "",  // подпись иницирующей стороны
            "",  // подпись второй стороны
            ""   // redeem скрипт (из транзакции финансирования)
          ]
        } // строго один
      ],
      outputs: [{
          ScriptPubKey: "",  // скрипт
          Value: 90,  // сумма
        },
        {
          ScriptPubKey: "",  // скрипт
          Value: 10,  // сумма
        }
      ] // строго 2 (в нашем случае)
    }
```
интерфейсы:

| Вызывающая сторона | Вызываемая сторона | Интерфейс                                                                                                                                                                    | Описание                                                                                                   |
| ------------------ | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| USER               | **execution**      | **login(**<br>string stan_public_master_key,<br>string[] exchange_public_master_keys)                                                                                        | Логин                                                                                                      |
| USER               | **execution**      | **open_channel(**<br>string trader_ledger_ID,<br>tx funding_tx,<br>segwit_tx init_commit_tx)                                                                                 | Открытие канала и создание транзакции финансирования                                                       |
| **execution**      | **settlement**     | **open_channel(**<br>string trader_ledger_ID,<br>tx funding_tx,<br>segwit_tx init_commit_tx)                                                                                 | Открытие канала и создание транзакции финансирования (в response вся нужная инфа)                          |
| **settlement**     | **revocation**     | **listen_tx(**<br>tx funding_tx,<br>channel_ID)                                                                                                                              | Указание revocation-демону слушать транзу                                                                  |
| **execution**      | **clearing**       | **hold_channe****l****(** <br>string trader_ledger_ID, <br>segwit_tx trader_signed_tx, <br>string trader_rev_secret)                                                         | Изменение состояния в пользу биржи, вызывается при блокировке средств, обеспечивающих выставленную заявку. |
| **clearing**       | **revocation**     | **add_rev_key(**<br>segwit_tx commit_tx,<br>int channel_ID,<br>string rev_key)                                                                                               | Сообщение revocation с новым ключом отмены                                                                 |
| **execution**      | **clearing**       | **match_netting(**<br>string buyer_ledger_ID, <br>string seller_ledger_ID, <br>segwit_tx buyer_commit_tx, <br>segwit_tx seller_commit_tx**,** <br>string[] rev_secrets **)** | запрос на генерацию транзакций состояния, увеличивающих баланс пользователей                               |
| **clearing**       | **execution**      | **block_channel**(<br>string user_ledger_ID,<br>int reason_code)                                                                                                             | аварийное выключение канала пользователя                                                                   |
| **revocation**     | **clearing**       | **block_channel**(<br>int channel_ID, <br>int reason_code)                                                                                                                   | аварийное выключение канала пользователя                                                                   |
| USER               | **execution**      | **withdraw_request(**<br>int channel_ID,<br>segwit_tx close_tx)                                                                                                              | Запрос на вывод средств с канала                                                                           |
| **execution**      | **settlement**     | **withdraw_request(**<br>int channel_ID,<br>segwit_tx close_tx)                                                                                                              | Запрос на вывод средств с канала                                                                           |
| USER               | **settlement**     | **deposit_request(channel_ID)**                                                                                                                                              | Запрос на пополнение канала                                                                                |

`**settlement**` **-** работа между первым и вторым слоем
`**clearing**` - работа в канале(во втором слое)
`**revocation**` **-** предохранитель, формирует транзакцию для первого слоя, оповещает второй о событии
`**execution**` - предоставление сревиса обмена к активам, транзакции которых предоставляет первые три сервиса.



## STAN взгляд с обоих сторон

Учитывая разные парадигмы построения архитектуры приложений, вкупе с разными моделями построения реестров, для исключения недопонимания нужно устаканить этот ньюанс: 

для otp_actors система выглядит так:

**Внутренние****:**

- `**order_processing_app**` - обработка заявок
- `**trade_processing_app**` - обработка матчей
- `**common_processing_app**` — обработка не связанных с торговлей сервисов авторизации(аутентификация пользователя на бирже, депонирования чат-а, депонирование торгового баланса для HFT)
- `**exchange_app**` - двигатель сопоставления заявок

**Внешние****:**

- `**clearing_app**` - смена состояний в канале
- `**settlement_app**` - открытие/закрытие/ре-финансирование каналов
- `**revocation_app**` - обработка форс-мажорных ситуаций

для micro_services система выглядит так:


>  `emitter` - тот, что испускает, `collector` - тот что принимает 

**Внутренние:**

- `**offchain_tx_emmiter**`     производитель транзакций смены состояния
- `**offchain_tx_collector**` получатель запросов на производство транзакций смены состояния
- `**blockchain_tx_emitter**` производитель транзакций открытия/закрытия каналов
- `**blockchain_tx_collector**`  получатель запросов на производство транзакций открытия/закрытия каналов

**Внешние:**
****???  - 

## Каналы реестров на основе учетной записи

Для мимикрирования каналов состояний реестров построенных по модели учетной записи под модель UXTO мы используем механизм мета-транзакций, который позволяет определить пользовательский интерфейс контракта фиксации состояний, как атрибуты вызова методов контракта. Для устранения проблемы коммисий за публикацию в дорогих сетях - при открытии/закрытии канала необходимо взымать средства которых будет достаточно для публикации транзакции состояния, подписанной пользователем, но опубликованной с помощью оракла биржи. 
 `TBA`

## Телеметрия 

Для решения задач отладки/профилирования/общего наблюдения за системой необходимо начать внедрять в обоих системах opentelemetry - стандарт сбора логов и метрик в едином формате, помимо наших систем также собирается телеметрия с ядрах хостовой ОС - этой информации должно быть достаточно для отлова узких мест при тестировании и наблюдением за производственным ландшафтом. С точки зрения golang - проблем не должно быть - основной вендор тут Uber, у них все на go. С точки зрения OTP - вроде уже все прояснили.   

## API интеграциионной шины

- [Глоссарий](#глоссарий)
- [Общая информация](#общая-информация)
- [Структуры (классы)](#структуры)
- [Логин](#логин)
- [Открытие канала](#открытие-канала)
    * [open_channel_user_execution](#open_channel_user_execution)
    * [open_channel_execution_settlement](#open_channel_execution_settlement)
    * [open_channel_settlement_revocation](#open_channel_settlement_revocation)
    * [Требования к транзакции финансирования](#требования-к-транзакции-финансирования)
    * [Требования к транзакции установки состояния](#требования-к-транзакции-установки-состояния)
- [Создание ордера](#создание-ордера)
    * [create_order_user_execution](#create_order_user_execution)
    * [create_order_execution_clearing](#create_order_execution_clearing)
- [Матчинг ордера](#матчинг-ордера)
    * [match_netting_execution_settlement](#match_netting_execution_settlement)
- [Выключение канала](#выключение-канала)
    * [block_channel_revocation_execution](#block_channel_revocation_execution)
- [Закрытие канала](#вывод-средств)
    * [withdraw_request_user_execution](#withdraw_request_user_execution)
    * [withdraw_request_execution_settlement](#withdraw_request_execution_settlement)
    * [withdraw_request_settlement_revocation](#withdraw_request_settlement_revocation)
    * [Требования к транзакции закрытия](#требования-к-транзакции-закрытия)
- [ER-модель для clearing/settlement/revocation](#er-модель)
## Глоссарий
* **user** - клиент на фронте
* **execution** - движок биржи
* **clearing** - установка состояний в каналах
* **revocation** - наблюдение за транзакциями и отмена при необходимости
* **settlement** - создание/закрытие каналов
## Общая информация
Пока делаем общение между всеми через websocket (???)

Имена методов содержатся в заголовках третьего уровня и обычно строятся по схеме
`общее_название_метода_вызывающая_вызываемая`

Пока предполагаю, что бинарный формат транзакций не используем, но можно впоследствии им воспользоваться.
## Структуры
### Request
Для запросов предлагаю воспользоваться такой JSON - структурой
```javascript
{
	method: string,       // метод запроса
	id: variable,         // id запроса, variable означает неопределенный тип, то есть пользоваться можно чем-угодно, можем туда nonce прикрутить потом
	params: variable[]    // массив параметров произвольного типа. Не уверен насколько хорошая идея, так как усложняется валидация из-за такого подхода, но зато компактно
}
```
### Response
Результат. Все далее описанные ошибки явялются значением поля `error` с этой структуры
```javascript
{
	method: string,    // метод запроса (тот же, что и в запросе)
	id: varibale,      // id, указанный в запросе
	result: variable,  // результат произвольного типа
	error: {           // ошибка, null при отсутствии
		code: int,          // код ошибки
		message: string     // сообщение об ошибке
	}
}
```
### Transaction
```javascript
{
	version: int,               // обычно 2, но мало ли, лучше оставлю
	lockTime: long(int64),      // 
	segwit: bool,               // использовался ли segwit
	inputs: {                   // входы 		 
		hash: string,           // хеш транзакции (с которой берется выход)
		index: int,             // индекс выхода в исходной транзакции
		scriptSig: string,      // подпись к скрипту
		sequence: int,          // здесь либо дефолтное значение 0xFFFFFFFF, либо (в случае использования в скрипте CHECK_SEQUENCE_VERIFY) другое число
		witnesses: []string     // подписи при segwit
	}[],
	outputs: {                  // выходы
		scriptPubKey: string,   // скрипт
		value: long(int64)      // сумма на выходе
	}[]
}
```
### Enum(coins)
Поскольку enum'ы везде по-разному работают, пишу втупую (список еще дополню)
```javascript
BTC = 1
LTC = 2
```
### Enum(reasonCode)
```javascript
OK = 0
FAILED = 1
```
## Логин
Клиент должен передать xpub мастер-ключ (ключи) от своего аккаунта.
Если такого xpub не найдено, необходимо создать "учетную запись" и мастер-ключи,
отвечающие этому пользователю (я думаю, что генерить отвечающие ключи лучше в сервисах(акторах)((микро-сервисах)),
 отвечающих за работу с криптой, чтобы **execution** знать не знал о каких-то ключах и
 мог оперировать аккаунтами и каналами без сложностей с ключами. С другой стороны,
 ключи нужно передавать только при создании канала, что вроде не очень сложно). 
 Если учетка уже существует нужно проверить появление новых ключей для токенов
 и в случае наличия таковых запросить у settlement генерацию (или сгенерировать у себя)
### login_user_execution
##### Параметры
|тип|описание|ограничения|
|:-:|:------:|:---------:|
|string|xpub биржи|соответствие структуре xpub (префикс, длина)|
|string[]|xpub'ы для работы с различными токенами|соответствие структуре xpub|
##### Результат

##### Ошибки

### login_user_settlement
##### Параметры
|тип|описание|ограничения|
|:-:|:------:|:---------:|
|string[]|xpub'ы для работы с различными токенами|соответствие структуре xpub|
##### Результат
```javascript
{
	keys: string[]
}
```
##### Ошибки
* неверный формат xpub
```json
{
    "code": 400,
    "message": "wrong xpub"
}
```
## Открытие канала
Для открытия канала **user** должен прислать xpub ключ соответствующей монеты для авторизации,
 подписанную транзакцию финансирования с корректными входами и скриптом в выходах,
 транзакцию установки начального состояния с корректным скриптом и своей подписью.
**Execution** устанавливает номер нового канала и делает запрос в **settlement**.
 **settlement**, в свою очередь, посылает информацию о создании канала в **clearing** и **revocation**.
### open_channel_user_execution
##### Параметры
|тип|описание|ограничения|
|:-:|:------:|:---------:|
|Coins(enum)|номер токена|-|
|string|xpub (для конкретной монеты)|соответствие структуре xpub (префикс, длина)|
|transaction(serialized)|транзакция финансирования|Описаны [здесь](#требования-к-транзакции-финансирования)|
|transaction(serialized)|транзакция установки начального состояния|Описаны [здесь](#требования-к-транзакции-установки-состояния)|
##### Результат
```javascript
{
	init: transaction (serialized)   // подписанная init транзакция
}
```
##### Ошибки

### open_channel_execution_settlement
##### Параметры
|тип|описание|ограничения|
|:-:|:------:|:---------:|
|int64|id клиента|-|
|Coins(enum)|номер токена|-|
|int|индекс канала (в пространстве клиент-монета)|номер строго следущий по порядку|
|string|xpub (для конкретной монеты)|соответствие структуре xpub (префикс, длина)|
|transaction(serialized)|транзакция финансирования|Описаны [здесь](#требования-к-транзакции-финансирования)|
|transaction(serialized)|транзакция установки начального состояния|Описаны [здесь](#требования-к-транзакции-установки-состояния)|
##### Результат
```javascript
{
	init: transaction (serialized)   // подписанная init транзакция
}
```
##### Ошибки
* неправильный скрипт в транзакции финансирования (установки начального состояния). Например, скрипт не той формы или не те public-ключи в нем
```json
{
	"code": 400,
	"message": "wrong funding(init) script"
}
```
* неправильная подпись в транзакции финансирования (установки начального состояния)
```json
{
	"code": 400,
	"message": "wrong funding(init) signature"
}
```
* входы не найдены
```json
{
	"code": 400,
	"message": "wrong inputs funding(init) transaction"
}
```
* все страшно сломалось
```json
{
	"code": 500,
	"message": "internal error"
}
```
### open_channel_settlement_revocation
##### Параметры
|тип|описание|ограничения|
|:-:|:------:|:---------:|
|string|xprv для канала|соответствие структуре xprv (префикс, длина)|
|string|адрес redeem-скрипта|соответствие структуре адреса скрипта|
##### Результат
```javascript
{
	success: true
}
```
##### Ошибки
```json
{
	"code": 500,
	"message": "internal error"
}
```
### Требования к транзакции финансирования
##### Входы
Все входы должны быть корректно подписаны
##### Выходы
Должен быть ровно один выход со специальным multisig-скриптом
##### Скрипт
`OP_2 <client_pub_key> <exchange_pub_ley> OP_2 OP_CHECKMULTISIG`
### Требования к транзакции установки состояния
##### Входы
Все входы - выходы транзакций финансирования с multisig-скриптом
##### Выходы
Один выход - на баланс биржи

Второй выход - выход со специальным скриптом с замком
##### Скрипт
`<exchange_pub_ley> OP_CHECKSIG OP_IF <revoke_pub_key> OP_CHECKSIG OP_ELSE OP_N OP_CHECKSEQUENCEVERIFY OP_DROP <client_public_key> OP_CHECKSIG OP_ENDIF`
## Создание ордера
Пока (временно) будем считать, что ордер меняет состояние только одного канала.
### create_order_user_execution
##### Параметры
|тип|описание|ограничения|
|:-:|:------:|:---------:|
|int64|сумма|-|
|Coins(enum)|токен|-|
|transaction(serialized)|транзакция установки следующего состояния|Описаны [здесь](#требования-к-транзакции-установки-состояния)|
|string|ключ отмены предыдущей транзакции|hex private key|
##### Результат

##### Ошибки

### create_order_execution_clearing
##### Параметры
|тип|описание|ограничения|
|:-:|:------:|:---------:|
|int64|id клиента|-|
|Coins(enum)|токен|-|
|int64|сумма|-|
|transaction(serialized)|транзакция установки следующего состояния|Описаны [здесь](#требования-к-транзакции-установки-состояния)|
|string|ключ отмены предыдущей транзакции|hex private key|
##### Результат
```javascript
{
	commit: transaction (serialized)
}
```
##### Ошибки
* неправильный ключ отмены предыдущей транзакции
```json
{
    "code": 400,
    "message": "wrong revoke key"
}
```
* неправильный скрипт в транзакции. Например, скрипт не той формы или не те public-ключи в нем
```json
{
	"code": 400,
	"message": "wrong commit script"
}
```
* неправильная подпись в транзакции
```json
{
	"code": 400,
	"message": "wrong commit signature"
}
```
* входы не найдены
```json
{
	"code": 400,
	"message": "wrong inputs commit transaction"
}
```
## Матчинг ордера
Для матчинга ордеров создается канал. Инициатор - биржа. Канал создается и тут же закрывается.
Трейдер получит при следующем заходе эти транзакции, подпишет их и запушит в блокчейн. 
### match_netting_execution_settlement
##### Параметры
|тип|описание|ограничения|
|:-:|:------:|:---------:|
|string|xpub клиента|соответствие структуре xpub (префикс, длина)|
|Coin(enum)|индекс токена|-|
|long(int64)|сумма|-|
##### Результат
```javascript
{
	funding: transaction,   // транзакция финансирования
	init: transaction,      // транзакция утсановки начального состояния
	close: transaction      // транзакция закрытия канала
}
```
##### Ошибки
* не нашлось баланса для финансирования
```json
{
    "code": 400,
    "message": "insufficient funds"
}
```
## Выключение канала
Аварийное выключение канала в случае жульничества со стороны трейдера или
в результате пуша транзакции последнего состояния (что вполне нормально,
 просто теперь можно канал только закрыть)
### block_channel_revocation_execution
##### Параметры
|тип|описание|ограничения|
|:-:|:------:|:---------:|
|int64|id клиента|-|
|Coin(enum)|индекс токена|-|
|int|индекс канала|-|
|ReasonCode(enum)|reasonCode|-|
##### Результат
```json
{
	"success": true
}
```
##### Ошибки
* все поломалось
```json
{
	"code": 500,
	"message": "internal error"
}
```
## Вывод средств
Вывод средств - создание транзакции закрытия и ее подпись
### withdraw_request_user_execution
##### Параметры
|тип|описание|ограничения|
|:-:|:------:|:---------:|
|Coin(enum)|индекс токена|-|
|int|индекс канала|-|
|transaction(serialized)|транзакция закрытия|Описаны [здесь](#требования-к-транзакции-закрытия)|
##### Результат
```javascript
{
	close: transaction (serialized)
}
```
##### Ошибки

### withdraw_request_execution_settlement
##### Параметры
|тип|описание|ограничения|
|:-:|:------:|:---------:|
|int|id клиента|-|
|Coin(enum)|индекс токена|-|
|int|индекс канала|-|
|transaction(serialized)|транзакция закрытия|Описаны [здесь](#требования-к-транзакции-закрытия)|
##### Результат
```javascript
{
	close: transaction
}
```
##### Ошибки
* нет выхода на биржу
```json
{
	"code": 400,
	"message": "missing exchange output"
}
```
* неправильная подпись в транзакции
```json
{
	"code": 400,
	"message": "wrong close signature"
}
```
* неправильный вход
```json
{
	"code": 400,
	"message": "wrong inputs close transaction"
}
```
### withdraw_request_settlement_revocation
##### Параметры
|тип|описание|ограничения|
|:-:|:------:|:---------:|
|string|адрес redeem-скрипта|соответствие структуре адреса скрипта|
##### Результат
```json
{
	"success": true
}
```
##### Ошибки
* все поломалось
```json
{
	"code": 500,
	"message": "internal error"
}
```
### Требования к транзакции закрытия
##### Входы
Строго один - выход транзакции финансирования с multisig-скриптом
##### Выходы
Один из них обязательно на адрес биржи
##### Скрипт
Дополнительных требований нет
### ER модель
![](./img/er.png)

##  Ландшафт 

В общем виде имеем `DEV → QA → QC → PRD` // QC для внешних аудиторов

Для оптимизации комуникации в удаленной команде - предлагаю договорится и как можно быстрее подготовить прототип рабочей среды для DEV системы, дающей возможность запускать все компоненты всем участникам


**DEV среда**
Предлагаемая конфигурация среды на основе контейнеров, запускаемая и собираемая в соответствии со сценарием роя

Network - 10.10.0.1/24

| **runtime_type**  | **runtime_name**               | **domain**   | **runtime_adr** | **runtime_ports** | **runtime_env** |
| ----------------- | ------------------------------ | ------------ | --------------- | ----------------- | --------------- |
| state_less_nginx  | {dash, handler, modal}.keyless | Keyless      | 10.10.0.1       |                   |                 |
| state_less_nginx  | web.terminal.stan              | Stan         | 10.10.0.2       |                   |                 |
| state_full_chains | regtest.chains.stan            | Stan/Keyless | 10.10.0.3       |                   |                 |
| state_less_erlang | pre_check.execution.stan       | Stan         | 10.10.0.4       |                   |                 |
| state_less_erlang | matching.execution.stan        | Stan         | 10.10.0.5       |                   |                 |
| state_less_erlang | common.stan                    | Stan         | 10.10.0.6       |                   |                 |
| state_less_erlang | api.stan                       | Stan         | 10.10.0.7       |                   |                 |
| state_less_golang | emitter.blockchain.stan        | Stan         | 10.10.0.8       |                   |                 |
| state_less_golang | collector.blockchain.stan      | Stan         | 10.10.0.9       |                   |                 |
| state_less_golang | emmiter.off_chain.stan         | Stan         | 10.10.0.10      |                   |                 |
| state_less_golang | collector.off_chain.stan       | Stan         | 10.10.0.11      |                   |                 |
| state_full_psql   | accounts.storage.stan          | Stan         | 10.10.0.12      |                   |                 |
| state_full_golang | regtest.blockbook.keyless      | Stan/Keyless | 10.10.0.13      |                   |                 |
| state_less_nginx  | ui.portainer.stan              | Stan/Keyless | 10.10.0.14      |                   |                 |
| state_less_nginx  | ui.admin.stan                  | Stan         | 10.10.0.15      |                   |                 |



**QA среда // задачи после устаканивания DEV**
Внтреннее тестирование, в процессе интеграции и перед внешним аудитом. В данном ландшафте, в целях исключения досадных ошибок придерживаемся стратегии максимальной мимикрирования под QC/PRD
Виртуальные машины для e_otp/базы, контейнерная среда для Golang микросервисов + единый контейнер для локальных тестовых блокчейн узлов


- e2e, нагрузочное и интеграционного(с публичными тест-нетами) тестирование, выявление граничной производительности компонентов системы, составление плана на работы следующего этапа 

**QC среда**
Среда для внешнего тестирования, интеграция системы оркестрации клиента


- Внешний аудит, публичная тестовая среда

**PRD среда**


- Производство // **TBA**




