Confidential balances в Solana
Еще давно в солане появился Token 2022 - стандарт spl токена, с расширяемой логикой(extensions). Там есть такие же функции на передачу, минт, заморозку, разморозку, сжигание, но в них можешь добавлять еще действия: комиссию (как это сделали в something.cool), проверку на вайтлист, интерест модель, нон трансферабл токенсы, и множество других штук (https://solana.com/ru/docs/tokens/extensions). Недавно запустили расширение с confidential transactions.
Это особенность, благодаря которой скрывается баланс у юзера, а также скрывается размер транзакции (перевода, минта и сжигания). По сути единственное что будет видно это вызов функций (и упоминание програм), а все что происходит внутри скрыто (как в zcash с их z layer). И единственные кто могут увидеть свои балансы это сами юзеры, а также возможное отдельное лицо, называемое аудитором, который может смотреть с помощью определенного приватного ключа.
Математика внутри
Для начала пойдем в то как оно работает. Чтобы скрыть балансы и переводы и все остальное, используется шифрование public key (по сути своей как и работают все блокчейны с публичным и приватным ключом).
Есть алгоритм ElGamal, и в базовой версии он работает следующим образом - зашифрованные числа можно умножать, при этом после расшифровки финального числа оно равно обычному перемножению. a*b = c = decrypt(enc(a) * enc(b)). Основная защита данного алгоритма в дискретном логарифме.
В Solana же используется Twisted ElGamal, позволяющий складывать зашифрованные числа. a+b = c = decrypt( enc(a) * enc(b))
Зная публичный ключ человека, которому мы передаем баланс, мы можем зашифровать число, которое мы передаем, с помощью публичного ключа данного человека. И можем к этому зашифрованному балансу прибавить другое зашифрованное число, его же публичным ключом, и тем самым произвести увеличение его баланса. А это же число, которое хотим передать, зашифруем у себя своим публичным ключом, и вычтем у себя.
При этом, одним twisted ElGamal дело не заканчивается, внутри сети же никто ничего не знает, а значит есть сопутствующие данные и проверки.
Доказательство валидного перевода
В рамках обычного спл очень легко проверить изменение балансов и этим занимаются валидаторы. Тут же идея что этого не увидит никто, а значит нужно доказать что такой перевод имеет место быть, для этого используются zero knowledge proofs:
- Range proof - доказываем, что числа (после трансфера и сам трансфер) находятся в 0<=x<=2^48 (отсюда и информация в дешифрование twisted ElGamal что эти числа легко перебрать(относительно))
- Validity proof - здесь мы доказываем, что числа (для сложения и вычитания) зашифрованы валидно. При этом не раскрывается ни сама сумма, ни оставшийся баланс.
- Equality proof - Пруф того что все зашифрованные числа равны (в незашифрованном виде)
Генерация ключей
Для использования шифрований нужно как-то сгенерировать эти ключи, а они отличаются от стандартного шифрования в солане (построенного на эллиптической кривой ed25519), а значит нужно сгенерировать новые ключи и управлять ими.
- Они генерируются на базе твоего приватного ключа под твой аккаунт, не под каждый минт. Результат подписи с сидом "ElGamalSecretKey" идет как сид в генератор случайных чисел и на базе него мы получаем приватный ключ (а от него и публичный). Полностью детерминированная система.
- Единственная сложность шифра twisted ElGamal состоит в том что при дешифровке числа, ты получаешь не само число, а g^private_number (поэтому он и называется скрученный, и позволяющий делать операцию сложения) а значит, каждый раз проводить вычисления чтобы посмотреть баланс. Каждый раз вычислять его неудобно и долго, поэтому было добавлено еще одно число в сам аккаунт, но уже зашифрованное AES (шифр nist). Данный шифр позволяет хранить числа зашифрованными, и всегда легко и быстро понимать чему они равны и только юзер сможет это прочитать (и изменить). Для этого нужно знать ключ от данного AES шифра, и ключ генерируется аналогично как для twisted ElGamal, только тут сидом является "AeKey".
"Аудитор" в токене
- Так как сама по себе солана есть компания из us, она не может сделать одностороннюю зашифрованную систему. Аудитор, в рамках spl ct, это такой наблюдатель со стороны, который может посмотреть баланс юзеров (зашифрованный публичным ключом аудитора). На этом его возможности заканчиваются.
- Принцип работы следующий: при каждом обновлении баланса(трансфере, минте, берне), кроме того чтобы обновить свой зашифрованный баланс своим публичным ключом и чужой(если трансфер), также ты обновляешь свой и чужой баланс, зашифрованный уже публичным ключом аудитора. Используется одно число для двух балансов, так как шифруется публичным ключом аудитора,
- А уже сам аудитор может расшифровать, но это опция, а не необходимость, и далеко не на каждый токен такое нужно(но для любого большого, а-ля shielded usdt, думаю нужно, иначе вопросы возникнут).
Гарантия консистентности
Так как используются zero-knowledge proofs, то получается, что пока ты создаешь пруфы, отправляешь транзу, и она попадает в блок, тебя могут кто-то обогнать и увеличить твой баланс. А твоя транзакция этого не учитывает и пруфы упадут.
Поэтому существует разделение баланса в виде pending (ожидающий) и available(доступный). В рамках транзакции от своего аккаунта ты всегда используешь доступный баланс, и если уж тебе надо то ты можешь сам обновить свой баланс транзакцией apply. В этой же транзакции обновляется и AES баланс, так как он показывает только available баланс и может обновляться только самим юзером.
- Spl token 2022 расширение с confidential transfers. В рамках данного расширения, балансы скрываются гомоморфным шифрованием twisted ElGamal, позволяющим складывать скрытые числа.
- Для проверки данных чисел в момент транзакций используется zero knowledge proofs (validity proof(легитимность транзакции), range proof(легитимность размера трансфера), equality proof(проверка на одинаковое шифрование)).
- Есть публичный ключ "аудитора", хранящийся в токене, с помощью которого "аудитор" может посмотреть чужие балансы, но не влиять на них.
- Чтобы гарантировать консистентность балансов при действиях, используется разделение балансов на доступные (на которые влияет сам пользователь) и ожидающие(куда перечисляют токены другие адреса).
- Для упрощения вычислять скрытый баланс аккаунта используются AES шифрованные балансы, которые не позволяют гомоморфно складывать шифр тексты, но позволяют хранить и быстро шифровать и расшифровывать для быстрого доступа к балансу.
- Все ключи, используемые в twisted ElGamal и AES, привязываются к приватному ключу аккаунта, а не к токену(минту) и вычисляются детерминированно. По 1 связке на каждый аккаунт.