Перевод
Это вольный перевод статьи: https://medium.com/mark3d-xyz/how-to-attach-an-encrypted-file-to-your-nft-7d6232fd6d34
Введение
Начиная Mark3d — проект для 3D NFTs в Metaverse, мы планировали его возможности.
В какой-то момент мы подумали, что было бы неплохо иметь некоторый приватный контент, связанный с NFT, чтобы решить проблему Ctrl+c — Ctrl+v. Мы провели некоторые исследования и поняли, что не существует таких технологий, чтобы иметь приватный контент и возможность передавать его, оставаясь скрытым от мира. После этого мы решили разработать и реализовать протокол для приватного NFT с использованием шифрования.
В этой статье будет описан наш путь к решению и приведено много технических деталей, поэтому читающий эту статью должен быть знаком с основными концепциями шифрования, такими как симметричное и асимметричное шифрование, стандартами NFT, такими как ERC721 и ERC1155, и языком Solidity, потому что кода будет очень много!
Весь код проекта Mark3d является открытым исходным кодом, его можно найти на нашем Github. Демо-версия нашей платформы также уже доступна.
Основная концепция
Нашей главной целью было сделать протокол полностью децентрализованным, что привело нас к требованию неизменности файлов, поскольку при повторном шифровании содержимое файла может быть изменено после майнинга. Поэтому мы решили зашифровать файл любым симметричным шифром и хранить результат.
Таким образом, процесс передачи будет состоять из передачи ключа симметричного шифрования.
Конечно, мы не можем передать ключ прямым способом, поэтому он также должен быть зашифрован. Мы решили, что асимметричное шифрование подходит нам больше всего, так как получатель будет скрывать свой закрытый ключ, а отправитель сможет зашифровать ключ симметричного шифрования единственным открытым ключом получателя.
Итак, наша первая базовая концепция выглядит следующим образом:
Проверка на мошенничество
Случай подтверждения перевода получателем не требует дополнительного внимания, но случай отказа подразумевает, что с файлом что-то не так. Существует несколько возможных вариантов:
- Зашифрованный ключ файла не действителен (например, пустая строка или расшифрованные данные не являются действительным ключом).
- Зашифрованный ключ действителен, но результатом расшифровки является не тот файл, который был первоначально зашифрован. Чтобы проверить этот факт, файл конкатенируется с его хэшем во время шифрования.
- Если ни одно из этих условий не выполняется, но получатель отклонил передачу, то это мошенничество со стороны получателя, поскольку он получил доступ к зашифрованному файлу, но не принял передачу, и эта передача может быть частью какой-либо транзакции, например, продажи NFT.
- Следовательно, протокол должен предусматривать разрешение споров в случае отказа от передачи. То есть, необходима какая-то доверенная третья сторона, которая будет осуществлять проверку в этом случае. Схематично это выглядит следующим образом:
Децентрализованная проверка мошенничества
Наша следующая задача — сделать доверенную третью сторону децентрализованной. Для этого технология реализации должна обладать следующими свойствами:
- Иметь доступ к хранилищу данных;
- Уметь выполнять операции шифрования и дешифрования;
- С её помощью должна быть возможна реализация NFT.
Filecoin обладает всеми этими свойствами:
- От акторов FVM есть доступ к хранилищу данных Filecoin;
- Язык реализации акторов FVM — Rust делает удобным использование протоколов шифрования. Использовать Solidity для реализации шифрования сложно и неэффективно — такие операции будут иметь высокую стоимость в газе и длительное время выполнения из-за большого количества операций с памятью (подробнее об этой проблеме можно прочитать в одной из моих предыдущих статей);
- FVM позволяет нам использовать Solidity-реализации стандартов NFT, таких как ERC-721 или ERC-1155, в то время как вся работа по шифрованию будет выполняться акторами FVM.
С Filecoin наш протокол выглядит следующим образом:
Процесс разработки
Изначально мы решили разделить разработку на две части:
- FVM акторы для работы с файлами и шифрованием;
- смарт-контракты FEVM Solidity NFT.
Мы вошли в программу FVM Early Builders и приняли участие в хакатоне FEVM (к сожалению, не прошли в финал). На момент начала разработки (август 2022 года) FVM еще не был полностью завершён, поэтому мы решили, что нам следует реализовать смарт-контракты Solidity, которые мы развернем в Polygon, и сервер Rust, который будет прослушивать блокчейн и ждать сообщений о мошенничестве, после чего будет проводить попытку расшифровки. Этот сервер Rust сможет вызывать методы смарт-контракта, отвечающие за разрешение споров. Выбор языка Rust здесь не случаен, он нужен для того, чтобы в будущем нам было проще преобразовать этот сервер в FVM-актор.
Итак, версия Polygon с сервером Rust выглядит следующим образом:
И мы решили упаковать смарт-контракты Solidity в стандарт и определить их как интерфейсы. Мы назвали этот стандарт Encrypted File Token или EFT. Далее мы рассмотрим стандарт более подробно.
Стандарт Encrypted File Token
Итак, основные требования к нашему стандарту:
- Он должен реализовывать конвейер передачи токенов.
- Должна быть возможность использовать актор FVM для проверки на мошенничество, когда результат проверки получается за один вызов, и использовать простой смарт-контракт EVM (управляемый сервером Rust) в качестве источника разрешения споров.
- Должна быть возможность запускать некоторые события при отмене или завершении перевода. Это необходимо для создания других высокоуровневых приложений, взаимодействующих со стандартом EFT, поскольку передача EFT не может быть атомарной операцией.
Для выполнения этих требований мы определяем 3 интерфейса:
- IEncryptedFileToken — основной стандарт для зашифрованного NFT.
- IFraudDecider — интерфейс для контракта fraud decider. Этот интерфейс необходим для возможности использования FVM-актора и EVM-контракта (для полигонной версии нашей системы), которые будут вызываться с сервера Rust.
- IEncryptedFileTokenCallbackReceiver — интерфейс для реализации контрактов для возможности совершать некоторые действия при отмене передачи финиша.
Начнём с IEncryptedFileTokenCallbackReceiver, так как это самый простой стандарт.
pragma solidity ^0.8.0;
/// @dev Interface for third party to receive transfer updates from token contract instances
interface IEncryptedFileTokenCallbackReceiver {
/// @dev This function MUST be called if transfer is cancelled
/// @param tokenId Id of token for which transfer was cancelled
function transferCancelled(uint256 tokenId) external;
/// @dev This function MUST be called if transfer is finished successfully
/// @param tokenId Id of token for which transfer was finished
function transferFinished(uint256 tokenId) external;
/// @dev This function MUST be called if transfer is finished with fraud report
/// @param tokenId Id of token for which transfer was finished
/// @param approved indicates if there was really fact of the fraud
function transferFraudDetected(uint256 tokenId, bool approved) external;
}
Интерфейс IFraudDecider определён таким образом, чтобы экземпляры EFT могли взаимодействовать как с актором FVM, так и взаимодействовать со смарт-контрактом Polygon, управляемым нашим бэкендом. Для этого функция проверки на мошенничество возвращает два булевых значения — первое определяет, было ли принято решение, а второе принимает значение true, если действительно имеет место акт мошенничества.
pragma solidity ^0.8.0;
interface IFraudDecider {
/// @dev Decide if there was a fact of fraud
function decide(
uint256 tokenId,
string calldata cid,
bytes calldata publicKey,
bytes calldata privateKey,
bytes calldata encryptedPassword
) external returns (bool, bool);
}
И, наконец, сам стандарт токена. Мы опустили некоторые очевидные комментарии, такие как «ДОЛЖЕН возвращаться, если токен не существует» в этом Gist, чтобы сократить его. Также был опущен блок с передачей ERC721 и инструкциями, чтобы заставить их всегда возвращаться. Полное определение интерфейса и эталонную реализацию можно найти в нашем репозитории.
Примеры
Для лучшего понимания рассмотрим несколько важных примеров: реализацию IFraudDecider в нашей текущей версии, которая управляется нашим сервером Rust, и реализацию простейшего биржевого контракта для продажи EFT.
IFraudDecider
FraudDeciderWeb2 — контракт, реализующий интерфейс IFraudDecider. У него есть специальный метод lateDecision, который вызывается с нашего сервера Rust. Он вызывается, когда была предпринята попытка расшифровать файл, и вердикт передаётся в аргументах.
Обмен EFT
Mark3dExchange — пример простой биржи для продажи EFT. Создается ордер, и в этот момент создается EFT-перевод для блокировки токена (создание любых других переводов будет невозможно до завершения отмены ордера). С помощью функции fulfillOrder покупатель фиксирует свой адрес для получения EFT и блокирует средства, а функции интерфейса IEncryptedFileTokenCallbackReceiver позволяют контракту биржи разблокировать средства при успешном или неуспешном завершении перевода.
Что дальше?
После MVP-версии нашими двумя основными целями являются:
- Реализовать наш протокол на FVM/FEVM.
- Создать инструменты разработчика для простого использования нашего стандарта EFT.
Мы продолжим разработку и будем рады поделиться результатами в будущих частях этой серии статей. Спасибо за чтение и да пребудет с вами сила!
Примечание Menaskop
К этой теме мы ещё вернёмся и не раз, а пока всё и
До!