MetaMask и доступ в стиле Ethereum
Ключ Ethereum может управлять аккаунтом ZooBC, адрес которого — обычный адрес этого ключа 0x… (тип аккаунта 4, см. Ключи и типы аккаунтов). MetaMask не нужно ничего знать о ZooBC: он подписывает обычную транзакцию Ethereum, которая передаётся внутри транзакции ZooBC и проверяется каждым узлом. На аккаунте лежат настоящие ZBC. Не участвуют ни мост, ни обёрнутая монета, ни дополнительный ключ.
Как проходит перевод
- MetaMask подписывает обычный перевод Ethereum: EIP-1559, EIP-2930 или legacy с EIP-155, с пустым списком доступа.
- Подписанная транзакция Ethereum помещается в поле сообщения транзакции ZooBC SendZBC с аккаунта 0x отправителя на аккаунт 0x получателя.
- Каждый узел разбирает транзакцию Ethereum, восстанавливает её подписанта по подписи и требует трёх условий: подписант — аккаунт-отправитель, адрес
toв Ethereum — получатель, а сумма совпадает с суммой в ZBC.
На этом пути узел проверяет подпись Ethereum вместо собственного дайджеста транзакции ZooBC. Передаваемая транзакция может занимать до 4 096 байт сообщения.
Адаптер в каждом узле
Каждый узел содержит встроенный адаптер JSON-RPC для Ethereum. По умолчанию он включён (eth_rpc_enabled), по умолчанию слушает порт 8545 на собственной машине узла (loopback) и переадресует запросы в API узла, тоже через loopback. Он отвечает на вызовы, которые делает кошелёк вроде MetaMask:
- цепочка и узел:
eth_chainId,net_version,web3_clientVersion,eth_syncing,eth_mining,eth_hashrate,eth_coinbase,eth_accounts; - состояние:
eth_blockNumber,eth_getBalance,eth_getTransactionCount,eth_getCode,eth_call; - комиссии:
eth_estimateGas,eth_gasPrice,eth_maxPriorityFeePerGas; - транзакции и блоки:
eth_sendRawTransaction,eth_getTransactionReceipt,eth_getTransactionByHash,eth_getBlockByNumber,eth_getBlockByHash.
Упаковку выполняет eth_sendRawTransaction. Он собирает SendZBC между двумя аккаунтами типа 4, устанавливает сумму равной значению в wei, делённому на 10^10, берёт комиссию из gasLimit × gasPrice, делённых на 10^10, поднимая её до минимальной комиссии узла, если она ниже, и помещает сырую транзакцию Ethereum в сообщение.
Идентификатор цепочки выводится из хеша генезиса цепочки, поэтому каждая цепочка ZooBC предъявляет собственный идентификатор. Если eth_rpc_chain_id равен 0, адаптер вычисляет:
chain id = (0x0883 << 16) | first two bytes of the genesis hash
От wei к атомарным единицам
MetaMask считает 18 знаков после запятой: одна отображаемая монета для него — 10^18 wei. ZooBC считает 8: 1 ZBC — это 10^8 атомарных единиц (монета ZBC и её единицы). Поэтому одна атомарная единица — это 10^10 wei, а 1 ZBC отображается в MetaMask как 10^18 wei.
Деление выполняется с полной точностью; любой остаток меньше одной атомарной единицы отбрасывается, а значение, слишком большое для знаковой 64-битной суммы, отклоняется. Проверка узла и адаптер используют один и тот же пересчёт, поэтому всегда согласны друг с другом.
Привязка адреса Ethereum к группе аккаунтов
Веб-кошелёк использует MetaMask и помимо переводов. С помощью eth_requestAccounts и personal_sign он просит MetaMask подписать согласие, которое привязывает адрес Ethereum к группе аккаунтов.
Адаптер в стиле Bitcoin тоже есть
Узлы также включают RPC-адаптер в стиле Bitcoin Core. По умолчанию он выключен, при включении слушает порт 8332 и требует учётных данных, которые задаёт оператор узла.