Pull to refresh

Иерархия мультиподписных кошельков (Доверительная система)

Reading time 19 min
Views 1.1K
Original author: Viktorov Konstantin
В данном тексте описывается абстракция доверительной системы, которая позволяет интегрировать в любую сферу экономических отношений сервисы условного депонирования.
Депонирование средств является фундаментальной частью любой сделки. Если контрагенты не знают друг о друге достоверную информацию, то риск мошенничества возрастает. Данная асбтракция позволяет запрограммировать в децентрализованной сети модель разрешения споров, модель проведения автоматических транзакций, защищенных сделок и т. д. При этом такая модель доверительной системы явялется открытой. Все сделки проведённые с участием иерархии мультиподписных кошельков позволяют верефицировать рейтинг контрагента, а также защититься от мошеннических схем новых участников экономических отношений.

Содержание


1 Введение
2 Описание мультиподписного кошелька
3 Способы построения иерархии кошельков
4 Интерфейс иерархии мультиподнисных кошельков
5 Потоки взаимодействий
5.1 Стандартный поток взаимодействия
5.2 Защищенный поток взаимодействия
5.3 Спорный поток взаимодействия
6 Протокол ESCB9
7 Интеграция доверительной системы и умных контрактов реализующих протокол ESCB9
8 Примеры контрактов которые реализуют ESCB9
8.1 Умный контракт для рынка аренды частной недвижимости по примеру AirBnb
8.2 Умный контракт для обмена любой криптовалюты на фиатные деньги и обратно в децентрализованном режиме
9 Арбитражные узлы
10 Словарь

1. Введение


Главной проблемой для сервисов условного депонирования является создание доверительных отношений между всеми участниками. При этом сами участники не должны быть обязательно известны каждому субъекту отношений. Для обобщения всех случаев будем принимать в виду, что все они анонимны. Для такой доверительной системы отношений важно регулировать отношения новых участников со старыми. Старые участники уже имеют определенный рейтинг в системе отношений и таким образом вызывают больше доверия. Так как в доверительной системе никто никого не знает — это вызывает проблемы верификации предыдущего рейтинга. В данном документе изложено описание доверительной системы на базе мультиподписных криптокошельков. Такая система может быть запрограммирована в умный контракт. В виду широкого распространения платформы Ethereum, выберем эту платформу в качестве платформы для описания всех умных контрактов в данном документе.

2. Описание мультиподписного кошелька


Абстракция которая позволяет подтверждать или отменять транзакции только при условии достижения консенсуса между полномочными участниками для принятия такого решения называется мультиподписным кошельком. Транзакция в данном контексте является атомарной операцией запрограммированной на выполнение метода в другом или этом же умном контракте.

Интерфейс для Умного контракта такой абстракции может быть представлен в виде:

  1. конструктор принимает адреса участников-основателей и число обязательных минимальных подтверждений для выполнения транзакций
    constructor(address[]:members, uint256:requiredConfirmationCount)
    

  2. Интерфейс для работы с полномочными участниками
    1. получение списка участников
      static getMembers() -> address[]:address
      

    2. просмотр адреса участника
      static getMember(uint256:indexNumber) -> address:address
      

    3. проверка адреса на принадлежность участнику
      static isMember(address:address) -> bool:value
      

    4. получение максимального количества участников для кошелька
      static  getMaxMemberCount() -> uint256:value
      

    5. получение минимального количества подтверждений для консенсуса
      static getRequiredConfirmationCount() -> uint256:value
      

    6. событие добавления нового участника
      event MemberAddition() -> address:member
      

    7. событие удаления участника
      event MemberRemoval() -> address:member
      

    8. событие изменения обязательного количество подтверждений для выполнения
      event RequiredConfirmationCountChange() -> uint256:count
      

    9. добавление участника
      execute addMember(address:member) -> void:value
      

    10. удаление участника
      execute removeMember(address:member) -> void:value
      

    11. замена участника
      execute replaceMember(address:currentMember, address:newMember) -> void:value
      
    12. изменение количества обязательных подтверждений для выполнения
      execute changeRequiredConfirmationCount(uint256:count) -> void:value
      


  3. Интерфейс для работы с транзакциями
    1. проверка подтверждения транзакции по адресу участника
      static getConfirmationByAddress(uint256:indexNumber, address:addressMember) -> bool:value
      

    2. получение информации из транзакции
      static getTransactionInfo(uint256:indexNumber)  -> [address:destination, uint256:value, bytes:data, bool:executed]
      
    3. получение общего количества транзакций в этом кошельке
      static getTransactionCount() -> uint256:value
      
    4. получение статуса подтверждения транзакции
      static isConfirmed(uint256:transactionId) -> bool:value
      
    5. получение количества подтверждений
      static getConfirmationCount(uint256:transactionId) -> uint256:count
      
    6. получение количества транзакций по типам
      static getTransactionCount(bool:pending, bool:executed) -> uint256:count
      
    7. получение списка участников, подтвердивших транзакцию
      static getConfirmations(uint256:transactionId) -> address[]:confirmations
      
    8. получение списка id транзакций по типу в определённом промежутке времени
      static getTransactionIds(uint256:from, uint256:to, bool:pending, bool:executed) -> uint256[]:transactionIds
      
    9. событие подтверждения транзакции участником
      event Confirmation() -> [address:sender, uint256:transactionId, uint256:timeStamp]
      
    10. событие отзыва подтверждения участником до выполнения транзакции
      event Revocation() -> [address:sender, uint256:transactionId, uint256:timeStamp]
      
    11. событие добавления транзакции в очередь
      event Submission() -> [uint256:transactionId]
      
    12. событие выполнения транзакции
      event Execution() ->  [uint256:transactionId]
      
    13. событие об ошибке при выполнении транзакции
      event ExecutionFailure -> [uint256:transactionId]
      
    14. событие пополнения кошелька
      event Deposit -> [address:sender, uint256:amount]
      
    15. добавление транзакции участником
      execute submitTransaction(address:destination, uint256:value, bytes:data) -> uint256:transactionId
      
    16. подтверждение транзакции участником
      execute confirmTransaction(uint256:transactionId) -> void:value
      
    17. отзыв подтверждения участником
      execute revokeConfirmation(uint256:transactionId) -> void:value
      
    18. ручное выполнение транзакции
      execute executeTransaction(uint256:transactionId) -> void:value
      



3 Способы построения иерархии кошельков


Имеются два основных пути построения доверительной системы. Вертикальный и горизонтальный. Горизонтальный путь построения подразумевает создание одним главным родителем списка дочерних кошельков. Вертикальный путь построения подразумевает под собой цепочку состоящую из дочерних кошельков с привязкой к родительскому. При этом родительский кошелек может быть дочерним к другому родительскому кошельку.
Как мы видим горизонтальный путь построения может являться подвидом вертикального пути построения. Поэтому далее оставим этот подход без внимания.

4 Интерфейс иерархии мультиподнисных кошельков


Для построения доверительной системы необходимо расширить простой интерфейс мультиподписного кошелька, описанного выше, добавив механизмы регуляции иерархии и автоматических выполнений подтверждений, а также возможность отложенного выполнения.
  1. Конструктор принимает адрес родительского кошелька, адреса участников-основателей, число обязательных минимальных подтверждений для выполнения транзакций, стандартное время автоматических подтверждений в секундах
    constructor(address:parent, address[]:members, uint256:requiredConfirmationCount, uint256:standardTimeAutoConfirmation)
    

  2. Интерфейс для работы с участниками
    1. получение списка участников
      static getMembers() -> address[]:address
      

    2. функция для просмотра адреса участника
      static getMember(uint256:indexNumber) -> address:address
      

    3. проверка адреса на принадлежность участнику
      static isMember(address:address) -> bool:value
      

    4. получение максимального количество участников кошелька
      static getMaxMemberCount() -> uint256:value
      

    5. получение минимального количество подтверждений для консенсуса
      static getRequiredConfirmationCount() -> uint256:value
      

    6. событие добавления нового участника
      event memberAddition() -> address:member
      

    7. событие удаления участника
      event memberRemoval() -> address:member
      

    8. событие изменения обязательного количество подтверждений для выполнения
      event requiredConfirmationCountChange() -> uint256:count
      

    9. добавление участника
      execute addMember(address:member) -> void:value
      

    10. удаление участника
      execute removeMember(address:member) -> void:value
      

    11. замена участника
      execute replaceMember(address:currentMember, address:newMember) -> void:value
      

    12. изменение количества обязательных подтверждений для выполнения
      execute changeRequiredConfirmationCount(uint256:count) -> void:value
      


  3. Интерфейс для работы с иерархией
    1. получение списка дочерних кошельков
      static getChildren() -> address[]:wallets
      

    2. проверка является ли адрес кошелька дочерним по отношению к текущему
      static isChild() -> bool:value
      

    3. проверка является ли адрес кошелька родительским по отношению к текущему производится через isChild путём противопоставления.
    4. событие прикрепления дочернего кошелька
      event childAttachment() -> [address:address,uint256:timeStamp]
      

    5. событие удаления дочернего кошелька
      event childRemoval() -> [address:address,uint256:timeStamp]
      

    6. прикрепление дочернего кошелька
      execute attachChild(addres:child) -> void:value
      

    7. удаление дочернего кошелька
      execute removeChild(address:address) -> void:value
      

    8. изменение одного дочернего кошелька на другой
      execute replaceChild(address:newAddress) -> void:value
      


  4. Интерфейс для работы с транзакциями
    1. проверка статуса транзакции
      static getTransactionStatus(uint256:transactionId) -> enum:{submitted,completed,frozen,disputed,reverted}
      

    2. проверка статуса транзакции на соответствие
      static isTransactionStatus(uint256:transactionId, uint256:enumStatusNumber) -> bool:value
      

    3. проверка подтверждения транзакции по адресу участника
      static getConfirmationByAddress(uint256:transactionId, address:addressMember) -> bool:value
      

    4. получение информации из транзакции
      static getTransactionInfo(uint256:transactionId)  -> [address:destination, uint256:value, bytes:data, bool:executed]
      

    5. получение общего количества транзакций в кошельке
      static getTransactionCount() -> uint256:value
      

    6. получение статуса подтверждения транзакции
      static isConfirmed(uint256:transactionId) -> bool:value
      

    7. получение количества подтверждений
      static getConfirmationCount(uint256:transactionId) -> uint256:count
      

    8. получение количества транзакций по типам
      static getTransactionCount(bool:pending, bool:executed) -> uint256:count
      

    9. получение списка участников, подтвердивших транзакцию
      static getConfirmations(uint256:transactionId) -> address[]:confirmations
      

    10. получение времени для автоподтверждения
      static getTimeAutoConfirmation(uint256:transactionId) -> uint256:timestamp
      

    11. получение списка id транзакций по типу в определённом промежутке времени
      static getTransactionIds(uint256:from, uint256:to, bool:pending, bool:executed) -> uint256[]:transactionIds
      

    12. событие подтверждения транзакции участником
      event Confirmation() -> [address:sender, uint256:transactionId, uint256:timeStamp]
      

    13. событие автоматического подтверждения транзакции
      event AutoConfirmation() -> [uint256:transactionId, uint256:timeStamp]
      

    14. событие отзыва подтверждения участником до выполнения транзакции
      event Revocation() -> [address:sender, uint256:transactionId, uint256:timeStamp]
      

    15. событие добавления транзакции в очередь
      event Submission() -> [uint256:transactionId]
      

    16. событие выполнения транзакции
      event Execution() -> [uint256:transactionId]
      

    17. событие об ошибке при выполнении транзакции
      event ExecutionFailure -> [uint256:transactionId]
      

    18. событие изменения статуса транзакции на замороженный
      event TransactionFrozen -> [uint256:transactionId]
      

    19. событие изменения статуса транзакции на спорный
      event TransactionDisputed -> [uint256:transactionId]
      

    20. событие изменения статуса транзакции на возвращенный
      event TransactionReverted -> [uint256:transactionId]
      

    21. событие пополнения кошелька
      event Deposit -> [address:sender, uint256:amount]
      

    22. добавление транзакции для выполнение
      execute submitTransaction(address:destination, uint256:value, uint256:TimeAutoConfirmation, bytes:data) -> uint256:transactionId
      

    23. подтверждение транзакции
      execute confirmTransaction(uint256:transactionId) -> void:value
      

    24. отзыв подтверждения
      execute revokeConfirmation(uint256:transactionId) -> void:value
      

    25. изменение статуса транзакции на замороженный
      execute setTransactionStatus(uint256:transactionId, uint256:enumStatusNumber) -> void:value
      

    26. ручное выполнение транзакции
      execute executeTransaction(uint256:transactionId) -> void:value
      


  5. Управление рейтингом
    1. получение рейтинга по адресу
      static getRatingByAddress(address:agent) -> [uint256:negativeRating, uint256:positiveRating, uint256:countRatingRecords]
      

    2. получение истории рейтинга по адресу и порядковому номеру
      static getRatingRecordForAddress(address:agent, uint256:indexNumber) -> void:value
      

    3. событие добавления записи в рейтинг по адресу
      event RatingRecordAdded -> [address:author, address:agent, bytes32:smartContractAddress, bool:positiveOrNegative, uin256:ratingNumber, bytes:comment, uint256:indexNumber]
      

    4. добавление записи в рейтинг для адресу
      execute addRatingRecord(address:agent, bytes32:smartContractAddress, bool:positiveOrNegative, uin256:ratingNumber, bytes:comment) -> void:value
      


  6. Интеграция с ESCB9 протоколом
    1. проверка по адресу является ли умный контракт, прикрепленным к данному кошельку умным контрактом с ESCB9 имплементацией
      	static isAttachedESCB9SmartContract(address:smartContract) -> bool:result
      

    2. проверка состояния депозита для умного контракта с ESCB9, прикрепленного к данному кошельку
      	static getDepositStatusForESCB9SmartContract(address:smartContract) -> enum:{awaiting,founded,returned}
      

    3. событие прикрепления умного контракта с ESCB9 имплементацией к кошельку
      event AttachingESCB9SmartContract -> [address:smartContract]
      

    4. событие внесения депозита для умного контракта с ESCB9 имплементацией прикрепленного к кошельку
      event ConfirmationForDepositESCB9SmartContract -> [address:smartContract, uint256:sum, bytes:notice]
      

    5. прикрепление умного контракта с имплементацией ESCB9 к кошельку
      execute attachESCB9SmartContract(address:smartContract) -> void:value
      

    6. подтверждение депозита для умного контракта с имплементацией ESCB9. Если депозит находится во внешней системе, то в notice будет метка. Если депозит в ETH, то сумма депозита отправляется при выполнение метода.
      execute fundDepositForESCB9SmartContract(address:smartContract, uint256:sum, bytes:notice) -> void:value
      




5 Потоки взаимодействий


Любой умный контракт может быть интегрирован в систему иерархии мультиподписных кошельков. Такая интеграция будет иметь потоки взаимодействий. В общем виде выделим несколько видов потоков:
  • Стандартный. В этом виде сделка проходит в автоматическом режиме. Без участия полномочных участников иерархии кошельков.
  • Защищенный. В этом виде время сделки может быть увеличено со стандартного для автоматического подтверждения времени до необходимого. В этом случае необходимо участие полномочных участников иерархии кошельков.
  • Спорный. В этом виде участник сделки может заморозить транзакцию. В этом случае необходимо участие полномочных участников иерархии кошельков для выработки консенсуса.

Каждый кошелек в доверительной системе имеет в себе ряд полномочных участников, которые и выносят вердикт. Для просты рассуждения объединим всех полномочных участников кошелька в одно понятие — арбитр.

5.1 Стандартный поток взаимодействия


Для простоты изложения приведем понятия товара и услуги к понятию объекта передачи (объект), а понятие фиатных денег, криптовалюты к понятию средства передачи (средства).
Контрагент, владелец объекта заключает сделку с контрагентом, владельцем средств, с целью обмена. В этом случае владелец объекта создаёт умный контракт условного депонирования путем направления стандартизированной транзакции на один из уполномоченных кошельков в иерархии мультиподписных кошельков. В этом случае происходит регистрация сделки третьей стороной в качестве доверительной системы. На каждую сделку определяется стандартное время для ее проведения. Контрагент, владелец средств делает депозит по сделке путем передачи средств доверительной системе. После этого владелец объекта передает объект владельцу средств. Владелец средств проверяет качество объекта. Если до окончания времени на проведение сделки, он не подтвердил качество, то средства передаются владельцу объекта в рамках сделки. Оба контрагента выставляют рейтинги комфорта друг другу. Таким образом владелец средств может изменить поток взаимодействия до окончания сделки. После передачи средств владельцу объекта, владелец средств может обратиться в вышестоящий по уровню иерархии кошелек для разрешения споров в течении определенного регламентом времени. После истечения этого времени рейтинги для сделки применяются к обеим сторонам и сделка становится невозвратной.

5.2 Защищенный поток взаимодействия


Если по каким-то независящим от контрагентов причинам срок для совершения сделки необходимо продлить, то по согласованию сторон кошелек мультиподписной иерархии (арбитр) может изменить время, отведенное на сделку. После изменения времени отводимое на сделку поток взаимодействия возвращается на уровень логики стандартного потока.

5.3 Спорный поток взаимодействия


В случае если качество объекта при проведении сделки не устраивает контрагента, владельца средства, которые он вносит в доверительную систему иерархии мультиподписных кошельков, сделка может быть заморожена. В этом случае депозит не передается контрагенту, владельцу объекта до вынесения вердикта по сделке. Сторона владения средств должна предоставить весомые доказательства арбитру сделки. После этого арбитр выносит вердикт в пользу одного из контрагентов. Если какая либо сторона сделки не удовлетворяется вердиктом, она обращается в вышестоящий кошелек по порядку следования в иерархии мультиподписных кошельков. Пройдя все инстанции по иерархии какая либо из сторон может запросить публичное голосование. Эта исключительная мера может быть назначена только кошельком абсолютной инстанции.

6 Протокол ESCB9


Пример протокола ESCB9 на языке Solidity в качестве абстрактного умного контракта (протокол находится в разработке и может быть изменен)
contract ESCB9 {
  /**
   * Modificator for arbitrage
   */
    modifier onlyArbitrage() {
        require(msg.sender == arbitrage());
        _;
    }
  /**
   * Modificator for checking deposit status
   */
   modifier isDeposited {
       uint i;
       bytes memory _funcName = bytes4(keccak256("getDepositStatusForESCB9SmartContract(address)"));
       bytes memory _concat = new bytes(_funcName.length + 32);
       for(i=0; i < address(this).length; i++) {
           _concat[i] = address(this)[i];
       }
       require(arbitrage().call.value(0)(_concat) == 1); // “founded” for enum
       _;
  }
  event confirmed(uint256 unixtimestamp, bytes32 notice);
  event frozen(uint256 unixtimestamp, bytes32 notice);
  event disputed(uint256 unixtimestamp, bytes32 notice);
  event canceled(uint256 unixtimestamp, bytes32 notice);
  /**
   * @notice Function to approve escrow deal and confirm success
   * @return Success of operation
  **/
  function confirm(notice) public onlyArbitrage returns(bool);
  /**
   * @notice Function to freeze escrow deal
   * @return Success of operation
  **/
  function freeze(notice) public onlyArbitrage returns(bool);
  /**
   * @notice Function to dispute escrow deal
   * @return Success of operation
  **/
  function dispute(notice) public onlyArbitrage returns(bool);
  /**
   * @notice Function to cancel escrow deal and confirm fail
   * @return Success of operation
  **/
  function cancel(notice) public onlyArbitrage returns(bool);
  /**
   * @notice Function to get seller's address
   * @return Seller's address
  **/
  function seller() public returns(address);
  /**
   * @notice Function to get custom type for ESCB9 smart contract
   * @return Type
  **/
  function type() public returns(bytes);
  /**
   * @notice Function to get buyer's address
   * @return Buyer's address
  **/
  function buyer() public returns(address);
 /**
   * @notice Function to get sum for deal
   * @return Sum of deal in wei
  **/
  function depositedSum() public returns(uint256);
  /**
   * @notice Function to get arbitrage's address
   * @return Arbitrage's address
  **/
  function arbitrage() public returns(address);
}


7 Интеграция доверительной системы и умных контрактов реализующих протокол ESCB9


Для использования доверительной системы иерархии мультиподписных кошельков в собственном проекте необходимо создать умный контракт, которые реализует стандарт ESCB9 и прикрепить такой умный контракт к одному из арбитров, который не имеет под собой дочерних кошельков. Такие кошельки в мультиподписной иерархии называются “входными узлами”. Все вышестоящие мультиподписные кошельки называются “арбитражными узлами”.

8 Примеры контрактов которые реализуют ESCB9


8.1 Умный контракт для рынка аренды частной недвижимости по примеру AirBnb


// Don't use this code, it can be not working or contain the vulnerability, for demonstration purpose only
pragma solidity ^0.4.21;
/// @title rentMyApartmentESCB9 - Allows rent object on market with escrow service. The safe way to do deal for counterparties.
/// @author Konstantin Viktorov - <ceo@escrowblock.net>
contract rentMyApartmentESCB9 is ESCB9 {
  // 2018-05-10 18:25 in unix timestamp
  uint256 constant public checkInTime  = 1525965900; 
  // 2018-05-20 18:25 in unix timestamp
  uint256 constant public checkOutTime = 1526829900;
  // Coordinates in bytes format. For example 56.865129,35.881540
  bytes constant public coordinates    = "0x35362e3836353132392c33352e383831353430";
  // Google maps link, as example, but better add Url to landing page
  bytes constant public externalUrl    = "0x68747470733a2f2f676f6f2e676c2f6d6170732f6e783563396b6737384170";  
  /**
   * Encrypted information, see https://github.com/ethereumjs/ethereumjs-wallet and 
   * https://github.com/pubkey/eth-crypto/blob/master/tutorials/encrypted-message.md
   * For example you can leave here information about pin-code for smart lock
  **/
  bytes constant private privateInformation = '0x0dfef623523483245687234';
  modifier only_before_check_in {
    require(getNow() < checkInTime);
    _;
  }
  modifier only_after_check_out {
    require(getNow() > checkOutTime);
    _;
  }
  modifier only_during_renting {
    require(getNow() > checkInTime && getNow() < checkOutTime);
    _;
  }
  modifier only_not_in_during_renting {
    require(getNow() < checkInTime && getNow() > checkOutTime);
    _;
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to get address of apartment owner
   * @return Seller's address
  **/
  function seller() public returns(address) {
    return "0x27a36731337cdee360d99b980b73e24f6e188618";
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to get custom type for ESCB9 smart contract
   * @return Type
  **/
  function type() public returns(bytes) {
    return "rent";
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to get address of renter
   * @return Buyer's address
  **/
  function buyer() public returns(address) {
    return "0xb582baaF7e749d6aA98A22355A9d08B4c4d013C8";
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to get sum for deal
   * @return Sum of deal in wei
  **/
  function depositedSum() public returns(uint256) {
    return 1000000000000000000; //1 ETH in weis
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to get arbitrage's address
   * @return Arbitrage's address
  **/
  function arbitrage() public returns(address) {
    return "0xe91065d8bb2392121a8fbe6a81e79782fbc89dd4";
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to approve escrow deal and confirm success
   * @param Some comment
   * @return Success of operation
  **/
  function confirm(notice) public onlyArbitrage only_after_check_out returns(bool) {
    confirmed(getNow(), notice);
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to freeze escrow deal
   * @param Some comment
   * @return Success of operation
  **/
  function freeze(notice) public onlyArbitrage only_during_renting returns(bool) {
    frozen(getNow(), notice);
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to dispute escrow deal
   * @return Success of operation
  **/
  function dispute() public onlyArbitrage only_after_check_out returns(bool) {
    disputed(getNow(), notice);
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to cancel escrow deal and confirm fail
   * @return Success of operation
  **/
  function cancel() public onlyArbitrage only_not_in_during_renting returns(bool) {
    canceled(getNow(), notice);
  }
  /**
   * @notice Get current unix time stamp
  **/
  function getNow()
     constant
     public
     returns (uint) {
       return now;
  }
  /**
   * @notice Get private information when renter will pay deposit
  **/
  function getPrivateInformation() 
    constant
    isDeposited
    public
    returns (bytes) {
      return privateInformation;
  }
}


8.2 Умный контракт для обмена любой криптовалюты на фиатные деньги и обратно в децентрализованном режиме


Изложенный ниже пример Умного контракта позволяет обменивать BTC на фиатные деньги прямым путем, без участия обменников и сторонних сервисов. Продавец BTC переводит на депозит в блокчейне BTC заложенную в умный контракт сумму. Покупатель после подтверждения депозита арбитром в автоматическом режиме переводит заложенную в контракте сумму на заложенный в контракте счет или номер пластиковой карты. Арбитр может вмешаться в процесс сделки после обращения одного из участников. Первоначально депозит будет заморожен и если стороны не договорятся путем консенсуса, то такой контракт перейдет в статус спорный с дальнейшем разрешением по потоку спорного взаимодействия.
// Don't use this code, it can be not working or contain the vulnerability, for demonstration purpose only
pragma solidity ^0.4.21;
/// @title p2pExchangeESCB9 - Allows exchanging any cryptocurrencies on fiat money and back, directly between users. The safe way to do deal for counterparties.
/// @desc  This example shows as exchange fiat money on BTC (forward flow)
/// @author Konstantin Viktorov - <ceo@escrowblock.net>
contract p2pExchangeESCB9 is ESCB9 {
  // in minimal decimals, for example, 500.000 rubles is equal 50000000 kopeks
  uint256 constant public inputAmount  = 50000000; 
  // RUR in bytes
  bytes constant public inputCurrency  = "0x525552"; 
  // in minimal decimals, for example, 1 BTC is equal 100000000 satoshi
  uint256 constant public outputAmount = "100000000";   
  // BTC in bytes
  bytes constant public outputCurrency = "0x425443"; 
  // Deposit can be place only before this time
  const bytes public closeTime              = "1526829900";
  // use "forward" way, when output currency will be deposited or "backward" if input currency will be deposited
  uint256 constant public depositWay   = "forward";   
  /**
   * Encrypted information, see https://github.com/ethereumjs/ethereumjs-wallet and 
   * https://github.com/pubkey/eth-crypto/blob/master/tutorials/encrypted-message.md
  **/
  /**
   * Encrypted information for placing deposit, for example BTC address
  **/
  bytes private externalDepositAddress = "0x3139333978476346484d6f464b465845564754415761706b3537694e6a3579556b52";
  /**
   * Encrypted information for the amount of deposit, for example for BTC 8 decimals can be added 2-3 chars from 0-9 as pin-code for deal. See more in EscrowBlock WhitePaper
   * If output amount is equal 100000000, then deposited amount can be 100000123
  **/
  bytes private externalDepositAmount = "0x5f5e17b";
  /**
   * Encrypted information for sending amount to seller, for example credit card number or bank account, for example 4242424242424242
  **/
  bytes private externalIncomingAddress = "0xf12765df4c9b2";
  modifier only_before_close_time {
    require(getNow() < closeTime);
    _;
  }
  modifier only_after_close_time {
    require(getNow() > closeTime);
    _;
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to get address of apartment owner
   * @return Seller's address
  **/
  function seller() public returns(address) {
    return "0x27a36731337cdee360d99b980b73e24f6e188618";
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to get custom type for ESCB9 smart contract
   * @return Type
  **/
  function type() public returns(bytes) {
    return "exchange";
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to get address of renter
   * @return Buyer's address
  **/
  function buyer() public returns(address) {
    return "0xb582baaF7e749d6aA98A22355A9d08B4c4d013C8";
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to get sum for deal
   * @return Sum of deal in minimal decimals
  **/
  function depositedSum() public returns(uint256) {
    rerurn outputAmount;
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to get arbitrage's address
   * @return Arbitrage's address
  **/
  function arbitrage() public returns(address) {
    return "0xe91065d8bb2392121a8fbe6a81e79782fbc89dd4";
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to approve escrow deal and confirm success
   * @param Some comment
   * @return Success of operation
  **/
  function confirm(notice) public onlyArbitrage only_after_close_time returns(bool) {
    confirmed(getNow(), notice);
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to freeze escrow deal
   * @param Some comment
   * @return Success of operation
  **/
  function freeze(notice) public onlyArbitrage only_after_close_time returns(bool) {
    frozen(getNow(), notice);
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to dispute escrow deal
   * @return Success of operation
  **/
  function dispute() public onlyArbitrage only_after_close_time returns(bool) {
    disputed(getNow(), notice);
  }
  /**
   * @notice ESCB9 interface
   * @notice Function to cancel escrow deal and confirm fail
   * @return Success of operation
  **/
  function cancel() public onlyArbitrage only_before_close_time returns(bool) {
    canceled(getNow(), notice);
  }
  /**
   * @notice Get current unix time stamp
  **/
  function getNow()
    constant
    public
    returns (uint) {
      return now;
  }
  /**
   * @notice Get private information for buyer when seller sent deposit
  **/
  function getExternalIncomingAddress() 
    constant
    isDeposited
    public
    returns (bytes) {
      return externalIncomingAddress;
  }
  /**
   * @notice Get private information about amount for seller for sending deposit
  **/
  function getExternalDepositAmount() 
    constant
    public
    returns (bytes) {
      return externalDepositAmount;
  }
  /**
   * @notice Get private information about address for seller for sending deposit
  **/
  function getExternalDepositAddress() 
    constant
    public
    returns (bytes) {
      return externalDepositAddress;
  } 
}


9 Арбитражные узлы


Для поддержания работы доверительной системы и вводится иерархия мультиподписных кошельков. Арбитражные узлы, то есть такие кошельки в иерархии, которые имеет под собой дочернее кошельки выступают в качестве гарантов разрешения споров. Полномочные участники для таких узлов могут быть назначены только вышестоящим по иерархии арбитром. Каждый полномочный участник получает вознаграждение путем распределения дивидендов и бонусов за работу со спорными потоками взаимодействия. Размер бонусов определяется консенсусом.
Для получения статуса уполномоченного участника арбитражного узла необходимо иметь определенную консенсусом сумму токенов на адресе уполномоченного участника. Таким образом гарантируется стабильное получения дивидендов всеми участниками арбитражных узлов. Чем выше по иерархии находится мультиподписной кошелек, тем больше необходимых токенов должно присутствовать на адресе уполномоченного участника.

10 Словарь


Ethereum – технология с открытым исходным кодом, которая позволяет создавать децентрализованную неизменную цепочку транзакций. Каждая транзакция может быть выполнена с определенными условиями, записанными в умном контракте.
Умный контракт – написанная на языке Solidity, логика, выполняемая в виртуальной машине Ethereum, которая позволяет расширять логику транзакций.
Мультиподписной кошелек (арбитр) – специальный умный контракт, контролируемый группой уполномоченных участников, которые могут подтверждать или отменять транзакции. Используя механизм мультиподписных кошельков, можно создать цепочку шлюзов для транзакций и своевременно контролировать выполнение или возврат средств.
Владелец объекта – является арендодателем, поставщиком, разработчиком программного продукта и т. д. То есть лицо, которое реализует объект и получает в конечном счете депозит в качестве вознаграждения.
Владелец средств – является арендатором, покупателем, заказчиком программного продукта и т. д. То есть лицо, которое размещает депозит на объект для покупки продукта или услуги.
Tags:
Hubs:
+3
Comments 0
Comments Leave a comment

Articles