Реализация мультиподписи (Multisig) в мобильном криптокошельке
Multisig на мобильном — не просто «нужно N из M подписей». Это координация между устройствами или людьми, управление состоянием подписания, хранение pending-транзакций и UX, при котором пользователь понимает где он находится в процессе. Стек и сложность сильно зависят от того, что именно под словом «мультиподпись».
Два совершенно разных подхода
Smart contract multisig (Safe/Gnosis). Смарт-контракт проверяет N подписей перед исполнением. Транзакция хранится в контракте как pending. Каждый подписант независимо подтверждает через approveHash. Простое решение для командного кошелька. Мобильное приложение — это клиент к Safe Transaction Service API (safe-transaction-service), который хранит pending-транзакции офчейн.
MPC (Multi-Party Computation). Приватный ключ физически никогда не собирается в одном месте. Каждая сторона хранит shard ключа, подпись генерируется совместно через протоколы GG20 или CGGMP21 (Threshold ECDSA). Сложнее в реализации, нет onchain-следа, работает с любым контрактом.
Для потребительских кошельков чаще нужен MPC (1 shard на устройстве, 1 на сервере — схема 2-of-2 для защиты от кражи устройства). Для корпоративных — Safe 3-of-5.
Реализация Safe multisig на мобильном
Интеграция через Safe{Core} SDK:
import { SafeFactory, SafeAccountConfig } from '@safe-global/protocol-kit'
const safeAccountConfig: SafeAccountConfig = {
owners: [owner1Address, owner2Address, owner3Address],
threshold: 2,
}
const safeFactory = await SafeFactory.create({ ethAdapter })
const safe = await safeFactory.deploySafe({ safeAccountConfig })
Для подписания pending-транзакции:
const safeTransaction = await safe.createTransaction({
transactions: [{ to, data, value }]
})
const txHash = await safe.getTransactionHash(safeTransaction)
const signature = await safe.signTransactionHash(txHash)
await safeTxService.proposeTransaction({
safeAddress, safeTransactionData: safeTransaction.data,
safeTxHash: txHash, senderSignature: signature.data
})
Второй подписант получает push-уведомление, видит детали транзакции, подтверждает своей подписью. Когда набралось N — приложение отправляет executeTransaction.
MPC: что реализуем нативно
Для схемы 2-of-2 (телефон + сервер) используем библиотеки с открытым кодом: tss-lib (Go), multi-party-ecdsa (Rust). На мобильном — нативный модуль (Swift/Kotlin) с биндингами к Rust через UniFFI или C FFI.
Keygen — однократный обмен сообщениями между устройством и сервером через WebSocket. Результат: каждая сторона получает свой shard, хранит у себя, полный ключ не существует нигде.
Подпись транзакции: interactive signing round (2–4 round-trip сообщения), занимает 200–500мс при хорошем соединении. Это приемлемо, но нужно показывать прогресс.
Управление pending-транзакциями в UI
Список транзакций со статусами: pending_signatures (сколько из N собрано), ready (можно исполнять), executed, rejected. Каждая транзакция — детали: адрес получателя, сумма, данные вызова (декодированные если известен ABI). Уведомление подписантам через FCM/APNs.
Процесс
Аудит требований: Safe vs MPC, количество подписантов, flow уведомлений. Safe-интеграция — 1–2 недели (SDK + Safe Transaction Service + UI). MPC с нативными библиотеками — 1–3 месяца (keygen, signing, тестирование корректности, аудит безопасности). Стоимость рассчитывается индивидуально.







