В посте про историю развития смарт-контрактов целый раздел мы посвятили такому понятию, как конфиденциальные смарт-контракты. У блокчейна есть целый ряд преимуществ, которые делают его привлекательных для реализации конфиденциальных систем. Но данные смарт-контрактов, формирующих бизнес-логику блокчейна, по умолчанию хранятся в открытом виде и доступны для всех. Этот конфликт решают конфиденциальные смарт-контракты (КСК) — они стали для нас одной из основных фичей платформы, запланированных на 2023 год, и успешно дошли до релиза. Далее мы раскроем подробности реализации КСК и приведем пример контракта, который вы легко сможете развернуть на оpen-source инстансе нашей сети.
Идея реализации конфиденциальных смарт-контрактов стала созревать в ходе нашего проекта с ФНС, Федеральной налоговой службой. Подробней о нем рассказывал наш CTO Денис еще в прошлом году; актуальный кейс можно посмотреть у нас на сайте. Если вкратце, то на наших блокчейн-технологиях работает центральная платформа распределенного реестра ФНС: через нее проходили все заявки на выдачу беспроцентных кредитов от малого и среднего бизнеса по программе беспроцентного кредитования, утвержденной в Постановлениях Правительства во время пандемии.
Информация о заемщике внутри этой системы должна быть сразу доступна для всех организаций — иначе заемщик, пользуясь рассинхронизацией системы, сумеет набрать много беспроцентных кредитов в разных банках. Но сумма кредитов конкретным заемщикам при этом должна быть закрыта, так как по закону эти сведения составляют коммерческую тайну.
Общий кейс
Обобщим описанное выше. Представим, что существует некая центральная организация BaseOrg, которая находится в одной сети с организациями Org1, Org2, Org3… и взаимодействует с ними по одной и той же модели. Но некоторые детали и результаты этих взаимодействий должны быть доступны не всем, а только центральной организации и выбранным другим.
Посмотрим на это в ракурсе смарт-контрактов. Технически все взаимодействия головной организации должны быть реализованы в рамках одного смарт-контракта. Стейт этого смарт-контракта единый, на одном contractId. У каждой пары BaseOrg+Org1, BaseOrg+Org2, BaseOrg+Org3 в стейте контракта записаны ключи, доступные только нодам в паре. Помимо этого, есть, конечно, и ключи, доступные всем участникам.
Если наложить «конфиденциальные смарт-контракты» на описанную конфигурацию, то вот какие требования мы должны реализовать:
создание приватных групп, в рамках которых участники сети могут обмениваться конфиденциальной информацией, фиксируемой в транзакциях в закрытом виде;
распространение приватных параметров вызова смарт-контракта и приватных результатов исполнения между участниками приватной группы;
валидация успешного исполнения смарт-контракта с приватными результатами в рамках группы, а затем в рамках общего консенсуса по результатам исполнения смарт-контракта.
Три способа достижения конфиденциальности
Конфиденциальные смарт-контракты не единственный способ реализовать конфиденциальность в нашем кейсе. Всего здесь можно выделить три подхода.
Конфиденциальные транзакции — данные по транзакции доступны только определенному количеству участников. Так мы переносим задачу с уровня смарт-контрактов на уровень транзакций и решаем задачу более точечно. Но для транзакций у нас уже реализован механизм передачи конфиденциальных данных, в рамках которого мы создаем группы доступа к данным,
отправляемые в сеть через gRPC или REST API. Если реализовать конфиденциальность на уровне транзакций, придется изменить весь этот подход так, чтобы приватность работала нативно для большей части транзакций. Нас вполне устраивает текущая схема, так что оценим другие варианты.
Конфиденциальные данные в транзакциях — транзакции публичные, но данные в них скрыты как минимум частично. Это путь наименьших доработок, который минимально меняет текущие механизмы обменов. Но тогда невозможно будет сохранить анонимность или конфиденциальность самих операций. И в целом такой способ решает, скорее, не общий кейс, а частный кейс с ФНС, который мы описали в начале поста.
Конфиденциальные смарт-контракты — доступ к вызову контракта и получению результатов есть только у некоторых участников. Этот подход реализуется на сравнительно более высоком уровне и, соответственно, на уровне концепции возникает минимум нюансов. Мы просто вызываем смарт-контракт и получаем валидный конфиденциальный результат. Так можно скрыть не только данные, но и сам смарт-контракт, а также транзакцию с результатом. Реализация также выглядит вполне доступной, так как мы работаем на уровне смарт-контрактов и не затрагиваем более глубокие слои блокчейна.
Третий вариант, как вы уже догадались, и пошел в разработку. Здесь надо отдельно подумать об инфраструктуре смарт-контрактов, ведь если в проектах будет задействовано большое количество P2P-обменов, мы рискуем перегрузить более сложными смарт-контрактами. Может помочь параллельное исполнение смарт-контрактов — мы тоже писали о нем в посте об истории развития этих инструментов. Наконец, стоит продумать, как смарт-контракты будут вызывать друг друга (об этом, кстати, будет следующий пост в нашем блоге). Некоторые из этих вопросов мы будем решать уже в 2024 году, а пока расскажем о том, что у нас получилось к концу года минувшего.
Итоговая реализация
Мы выбрали довольно простой вариант реализации смарт-контрактов. Единственное архитектурное изменение по сравнению с обычными смарт-контрактами — это введение новых групп, которым можно давать входные данные для контракта и получать выходные данные в ответ.
Взаимодействие с конфиденциальными смарт-контрактами, как и с обычными, проходит в три этапа: создание, вызов и обновление. Вот какие новые инструменты мы добавили для этого.
CreateContractTransactionV6 — новая транзакция создания контракта, включающая новые поля:
isConfidential — является ли смарт-контракт конфиденциальным или нет;
groupParticipants — участники приватной группы;
groupOwners — администраторы приватной группы.
UpdateContractTransactionV5 — новая транзакция обновления смарт-контракта, с новыми полями groupOwners и groupParticipants, выполняющими те же функции.
Также для конфиденциальных контрактов мы прописали отдельные вызовы:
через REST API — POST confidential-contracts/call
через gRPC — ConfidentialCall
Создаем конфиденциальный смарт-контракт
Попробовать конфиденциальные смарт-контракты можно на open-source версии нашей платформы. Развернуть ее несложно, гайд мы публиковали. Вот для примера простой конфиденциальный смарт-контракт:
val image = createContractImage() // cоздание образа контракта
// создание группы, которая имеет доступ к конфиденциальным данным
val participants = nodes.map(node => Address.fromString(node.address).explicitGet()).toSet
// генерация и отправка запроса на создание контракта с поддержкой конфиденциальных данных
val request = createSignedCreateContractRequestV6(txSender,
image,
List.empty,
isConfidential = true,
groupParticipants = participants,
groupOwners = Set(txSender.toAddress))
val createTxId = txSenderNode.signedCreateContractV6(request).id
// конфиденциальные данные
val expectedInput = List(IntegerDataEntry("test", 1))
val request = ConfidentialContractCallRequest(
sender = txSender.toAddress.toString,
contractId = contractId,
contractVersion = 1,
params = expectedInput,
timestamp = System.currentTimeMillis(),
fee = callContractFee,
commitment = None,
commitmentKey = None
)
// вызов контракта
val callResponse = txSenderNode.confidentialCall(request, broadcast = true)
val callTransactionId = (callResponse \ "callContractTransactionV6" \ "id").as[String]
// проверка, что данные не доступны публично
val executedTransactionFromPublic = txSenderNode.executedTxFor(callTransactionId)
executedTransactionFromPublic.results shouldBe List.empty
val confidentialInputAndOutput = txSenderNode.confidentialTxWithInputAndOutput(callTransactionId)
val expectedOutput = List(IntegerDataEntry("sum", 1))
val actualConfidentialInput = (confidentialInputAndOutput \ "confidentialInput").as[ConfidentialInput]
val actualConfidentialOutput = (confidentialInputAndOutput \ "confidentialOutput").as[ConfidentialOutput]
// проверка, что для нужных участников данные возвращаются
actualConfidentialInput.entries shouldBe expectedInput
actualConfidentialOutput.entries shouldBe expectedOutput
/* как изменяется контракт для поддержки конфиденциальности определенного ключа - просто ставится проверка на версию транзакции */
private def handleCallTransaction(
tx: ContractTransaction,
authToken: String
): Unit = {
if (tx.version >= 6) {
tx.params.extractStringParam("confidential-parameter")
} else {
// do something else
}
}
Некоторые моменты стоит пояснить дополнительно. Конфиденциальность смарт-контракта прописывается в момент получения транзакции call. В самом контракте необходимо прописать проверку версии транзакции (шестая или более поздняя) и уже после этого проводить манипуляции с ключом. Это предотвращает использование ключей приватных групп неконфиденциальными транзакциями.
А вот как, в общих чертах, отработает приведенный выше смарт-контракт:
Произойдет вызов конфиденциального смарт-контракта.
Участник группы participants, регламентированной через политику валидации, передаст в контракт конфиденциальные данные.
Смарт-контракт отправит конфиденциальные выходные данные в отдельный инстанс RocksDB, где его смогут прочитать только участники группы participants.
В самом смарт-контракте при этом будет доступна только логика и названия ключей
Развитие конфиденциальных смарт-контрактов
В 2024 году мы планируем в рамках конфиденциальных смарт-контрактов внедрить атомарные транзакции. Возможно, как и в обычных смарт-контрактах, добавим поддержку MVCC (управление параллельным доступом посредством многоверсионности). Другие фичи конфиденциальных смарт-контрактов будут появляться в соответствии с потребностями конкретных проектов.
Комментарии (4)
MAXH0
18.01.2024 15:39Насколько конфиденциальные контракты действительно конфиденциальны? Вот для биткойна сейчас черные лебеди, ставящие под сомнение его анонимность, просто стаями летят. Как вообще у Вас дела с реальной анонимностью. Или здесь блокчейн - это именно открытый гроссбух, который "помнит всё"...
vassabi
то есть это обычный контракт с whitelist-ом ?
Noizefan
ну как же? еще невероятно тщательно скрывается его адрес.
aaart
kind of, в обычном контракте всем доступны вход и выход, здесь только тем, кто в whitelist, это ключевое отличие