Skip to content

Latest commit

 

History

History
64 lines (46 loc) · 5.59 KB

contractsignatures.rst

File metadata and controls

64 lines (46 loc) · 5.59 KB

Контракты с подписью

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

К примеру, пусть имеется контракт перевода денег MoneyTransfer:

contract MoneyTransfer {
    data {
      Recipient int
      Amount    money
    }
    ...
}

Если в некотором контракте, запущенном пользователем, будет вписана строка MoneyTransfer(“Recipient,Amount”, 12345, 100), то будет осуществлен перевод 100 монет на кошелек 12345. При этом пользователь, подписывающий внешний контракт, останется не в курсе осуществленной транзакции. Исключить такую ситуацию возможно, если контракт MoneyTransfer будет требовать получения дополнительной подписи пользователя при вызове его из других контрактов. Для этого необходимо:

  1. Добавить в секцию data контракта MoneyTransfer поле с именем Signature с параметрами optional и hidden, которые позволяют не требовать дополнительной подписи при прямом вызове контракта, поскольку в поле Signature уже будет подпись.
contract MoneyTransfer {
    data {
      Recipient int
      Amount    money
      Signature string "optional hidden"
    }
    ...
}
  1. Добавить в таблицу Signatures запись содержащую:
  • имя контракта MoneyTransfer,
  • имена полей, значения которых будут показываться пользователю, и их текстовое описание,
  • текст, который будет выводиться при подтверждении.

В текущем примере достаточно указать два поля Receipient и Amount:

  • Title: Are you agree to send money this recipient?
  • Parameter: Receipient Text: Wallet ID
  • Parameter: Amount Text: Amount (qEGS)

Теперь если вставить вызов контракта MoneyTransfer(“Recipient, Amount”, 12345, 100), то будет получена системная ошибка “Signature is not defined”. Если же контракт будет вызван следующим образом *MoneyTransfer(“Recipient, Amount, Signature”, 12345, 100, ”xxx...xxxxx”), то возникнет ошибка при проверке подписи. При вызове контракта проверяется подпись следующих данных: "“время оригинальной транзакции, id пользователя, значение полей указанных в таблице signatures”", и подделать эту подпись невозможно.

Для того, чтобы пользователь при вызове контракта MoneyTransfer увидел подтверждение на перевод денег, во внешний контракт необходимо добавить поле с произвольным названием и типом string и дополнительным параметром signature:contractname. При вызове вложенного контракта MoneyTransfer необходимо просто передать этот параметр. Также следует иметь в виду, что параметры для вызова защищенного контракта должны также быть описаны в секции data внешнего контракта (они могут быть скрытыми, но они все равно будут отображаться при подтверждении). Например,

contract MyTest {
  data {
      Recipient int "hidden"
      Amount    money
      Signature string "signature:send_money"
  }
  func action {
      MoneyTransfer("Recipient,Amount,Signature",$Recipient,$Amount,$Signature)
  }
}

При отправке контракта MyTest, у пользователя будет запрошено дополнительное подтверждение для перевода суммы на указанный кошелек. Если во вложенном контракте будут указаны другие значения, например MoneyTransfer(“Recipient,Amount,Signature”,$Recipient, $Amount+10, $Signature), то будет получена ошибку, что подпись неверна.