Данная статья будет посвящена адресам в сети Ethereum. Адрес неразрывно связан с такими понятиями, как приватный и публичный ключ, хэш-функция, аккаунт. В статье я продемонстрирую эту связь, а так же приведу практический пример по формированию адреса. В конце мы посмотрим на некоторые служебные адреса, а так же обратим внимание на особенности хэш-функции применяемой в Ethereum.
Итак, приступим!
Адрес
Адрес идентифицирует аккаунт в сети Ethereum и имеет следующий вид:
0x690B9A9E9aa1C9dB991C7721a92d351Db4FaC990
Длина адреса:
160 бит | 20 байт | 40 символов (hexadecimal)
Для шестнадцатеричного представления (далее hexadecimal) каждый байт кодируется двумя символами, поэтому для определения длины в байтах нужно количество символов в строке поделить на два. При подсчёте длины строки мы не учитываем префикс 0х перед адресом, так как он несёт лишь информацию о том, что строка справа представляет собой hexadecimal-последовательность.
Кстати, адрес в примере выше, это реальный адрес из главной сети Ethereum. На момент написания статьи стостояние его аккаунта выглядело так:
Перейдём к описанию процесса формирования адреса.
Формирование адреса
Прежде чем приступить к рассмотрению процесса формирования адреса, необходимо уточнить, что в сети Ethereum существуют два типа аккаунта:
-
Externally-owned account (EOA)
-
Contract account
Поскольку назначение этих контрактов отличается, то и адреса к ним формируются по-разному. Приведу основные различия этих аккаунтов:
|
Externally-owned account (EOA) |
Contract account |
|
Только EOA обладает приватным ключом. EOA управляется тем, кто владеет приватным ключом. |
Не обладает приватным ключом, управляется логикой кода смарт-контракта, который задеплоен по этому адресу. |
|
Инициатором транзакций в сети Ethereum может быть только EOA. |
Контракты тоже могут осуществлять транзакции, но первоначальным инициатором всё равно будет EOA. |
|
Создание EOA абсолютно бесплатное. |
Списывается пошлина в виде Gas за storage, которое используется контрактом. |
Далее мы рассмотрим отдельно как формируется адрес для Externally-owned account и для Contract account.
A. Формирование адреса для EOA
Процесс формирования выглядит следующим образом: сперва генерируется приватный ключ, затем на основании приватного ключа генерируется публичный ключ, далее вычисляется хэш публичного ключа и берутся последние 20 байт от вычисленного хэша — это и будет адрес EOA.
Разберём процесс более детально.
Шаг 1. Генерация приватного ключа.
Пример приватного ключа:
0xb533ffad9736e46ef0fbe34018fb0a30572fbe477bcc3a4e641c210ecc3ed8b5
Длина приватного ключа:
256 бит | 32 байта | 64 символа (hexadecimal)
Шаг 2. Генерация публичного ключа.
На основании приватного ключа при помощи алгоритма ECDSA (Elliptic Curve Digital Signature Algorithm) генерируется публичный ключ.
Пример публичного ключа:
0x2e308d25d27f4c595c4a7543253f3c2350c9d323bcd50229c837681f08da6a33b8ab238faecd9cf2a7359e6a69089710876ab136ab017f88505c03516cc099c6
Длина публичного ключа:
512 бит | 64 байта | 128 символов (hexadecimal)
Шаг 3. Вычисляем хэш публичного ключа
Используя хэш-функцию Keccak-256 получаем хэш публичного ключа:
0x0c2be79367ba0c0b59460475b90d65a624909bc36eee6bffdecf3c5acd7774c0
Длина хэша:
256 бит | 32 байта | 64 символа (hexadecimal)
Шаг 4. Берём последние 20 байт от хэша публичного ключа
Отсчитываем последние 40 символов от хэша, который был получен на предыдущем шаге:
0xb90d65a624909bc36eee6bffdecf3c5acd7774c0
Эти 20 байт и будут нашим адресом.
После рассмотрения всех шагов, попробуем сгенерировать адрес самостоятельно.
Практический пример получения адреса для EOA
Для генерации адреса EOA я воспользуюсь библиотекой helpeth. Команда keyGenerate сгенерирует приватный и публичный ключ, а также сам адрес:
$ mkdir ecdsa-keypair $ cd ecdsa-keypair $ npm install helpeth $ ./node_modules/helpeth/helpeth keyGenerate
Вывод:
Address: 0xb90d65a624909bc36eee6bffdecf3c5acd7774c0 Address (checksum): 0xb90d65a624909BC36eee6bFfdeCF3c5ACd7774C0 ICAP: XE06 LM6K C69E YWIP 77CP 2N3X 1ECC H6O2 1MO Public key: 0x2e308d25d27f4c595c4a7543253f3c2350c9d323bcd50229c837681f08da6a33b8ab238faecd9cf2a7359e6a69089710876ab136ab017f88505c03516cc099c6 Private key: 0xb533ffad9736e46ef0fbe34018fb0a30572fbe477bcc3a4e641c210ecc3ed8b5
Готово. Мы получили как ключи, так и сам адрес. Единственное, вызов команды keyGenerate не отображает хэш публичного ключа, так как хэш является промежуточным шагом для получения адреса. Но для наглядности я покажу как мы можем вычислить хэш самостоятельно командой keccak256 на вход которой мы подадим публичный ключ:
$ ./node_modules/helpeth/helpeth keccak256 0x2e308d25d27f4c595c4a7543253f3c2350c9d323bcd50229c837681f08da6a33b8ab238faecd9cf2a7359e6a69089710876ab136ab017f88505c03516cc099c6
Вывод:
Input data: 0x2e308d25d27f4c595c4a7543253f3c2350c9d323bcd50229c837681f08da6a33b8ab238faecd9cf2a7359e6a69089710876ab136ab017f88505c03516cc099c6 Data hash: 0c2be79367ba0c0b59460475b90d65a624909bc36eee6bffdecf3c5acd7774c0
Видим, что последние 40 символов хэша действительно отражают адрес нашего аккаунта:
b90d65a624909bc36eee6bffdecf3c5acd7774c0
Подытожив, можно прийти к выводу, что в EOA аккаунте, и публичный ключ и адрес производны от приватного ключа. Вы спокойно можете забыть адрес аккаунта и его публичный ключ. Чтобы восстановить эти данные вам достаточно иметь приватный ключ. Путём математических преобразований вы снова можете получить тот же публичный ключ и тот же адрес. Однако потеряв приватный ключ, вы утратите доступ к аккаунту, а средства на его балансе будут навсегда заморожены в сети Ethereum, либо будут присвоены злоумышленником, который завладел вашим приватным ключом.
Отлично, мы познакомились с получением адреса для Externally-owned account, и теперь пришло время взглянуть на получение адреса для Contract account.
B. Формирование адреса для Contract account
Как было отмечено выше, у Contract account нет приватного ключа, поэтому его адрес формируется из адреса EOA-аккаунта, с которого он был создан, и поля nonce этого аккаунта. Про поле nonce я рассказывал в одной из своих предыдущих статей.
Если изобразить функцию создания адреса на псевдокоде, то она будет выглядеть следующим образом:
contract_address = keccak_256(rlp_encode(creator_address, nonce))
Разберём детально по шагам, что же здесь происходит:
-
Берется адреc EOA аккаунта, который отправил транзакцию на создание контракта
-
Берётся поле
nonceиз транзакции на создание контракта -
Адрес отправителя и
nonceсериализуются при помощи RLP-кодека -
Вычисляется Keccak-256 хэш от сериализованного знания
-
Последние 160 бит хэша и будут адресом нашего контракта
Таким образом, адрес одного и того же контракта, повторно созданного с одного и того же аккаунта будет всегда различаться, так как с каждой новой транзакцией поле nonce увеличивается на 1 и меняет хэш адреса-отправителя.
Одно важное уточнение. У созданного аккаунта смарт-контракта тоже есть поле nonce, но в отличие от EOA аккаунта, оно инициализируется единицей, тогда как у EOA поле nonce инициализируется нулём. Изначально у обеих типов аккаунтов поле nonce инициализировалось нулём, но затем были внесены правки.
Помимо адресов, созданных участниками блокчейна, существуют ещё и служебные адреса, которые принадлежат самому блокчейну. Давайте рассмотрим парочку таких адресов.
Служебные адреса
Адрес создания смарт-контракта
Выше я упомянул, что контракт создаётся при помощи транзакции. У любой транзакции должен быть отправитель и получатель, и если с отправителем всё более менее понятно, то не совсем понятен адрес получателя при создании контракта. Если вдуматься, то на момент отправки такой транзакции блокчейн ещё ничего не знает о новом контракте, а соответсвенно в сети нет его адреса. На какой же адрес отправляется эта транзакция? Ответ прост — на нулевой адрес. Нулевой адрес — это служебный адрес сети Ethereum, который предназначен для создания контрактов.
Вот так выглядит нулевой адрес:
BurnffdfЕсли присмотреться, то можно обнаружить, что на нулевом адресе лежит довольно крупная сумма Ether. На момент написания статьи, сумма была эквивалентна 21 миллионам долларов США. Глядя на эту сумму, можно ошибочно предположить, что здесь аккумулируются пошлины за создание каждого смарт-контракта. Но это не так. Как ни странно, это навсегда замороженные средства, которые были намеренно или по ошибке отправлены на нулевой адрес. Ошибиться мог как человек, забывший указать поле адреса-получателя, и оно было интерпретировано как нулевой адрес, так и программист, который неверно инициализировал адрес получателя. Почитать подробнее про причину появления средств на нулевом адресе можно здесь и здесь.
Адрес для уничтожения Ether
Кстати, если вы немерено решили уничтожить свои средства, то для этого в сети Ethereum существует специальный Burn адрес:
Окончание адреса говорит само за себя. Как видно, желающих намеренно отказаться от токенов или Ether оказалось даже больше, чем тех, кто это сделал по ошибке. Средства, отправленные на этот адрес будут навсегда утеряны. На самом деле токены и Ether уничтожаются не просто так, для этого есть множество экономических причин, одна из которых — сократить общее предложение, тем самым повысив спрос.
Кстати, у нулевого и dead аккаунтов нет приватного ключа, поэтому никто не имеет к ним доступ. Если же вам всё же удастся подобрать приватный ключ к ним, то технически вам ничто не мешает распоряжаться средствами на этих аккаунтах.
В заключение я бы хотел коснуться хэш-функции Keccak-256 в Ethereum.
Keccak-256 vs SHA-3
Стандарт SHA-3 реализован по алгоритму хэширования Keccak-256. Но между реализацией алгоритма Keccak-256 в стандарте SHA-3 и в сети Ethereum есть различия.
Данный факт может внести путаницу при использовании библиотек, так как хэши полученные от одного и того же значения у этих двух реализаций будут разными.
Чтобы точно определить какая перед вами реализация, есть эталонные хэши от пустой строки:
Ethereum Keccak256("") = c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 SHA3("") = a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a
Почему команда Ethereum решила написать свою реализацию алгоритма Keccak-256? Для этого обратимся к истории создания этих двух реализаций.
Алгоритм хэширования Keccak-256 стал победителем среди алгоритмов претендующих на страндарт семейства Secure Hash Algorithm (SHA), и был стандартизован как FIPS-202 SHA-3 standard в 2015 году .
Уже после завершения процесса стандартизации, и перед самым опубликованием стандарта, National Institute of Standards and Technology (NIST) решил скорректировать некоторые параметры алгоритма, предположительно для улучшения его эффективности.
Всё это произошло в то же самое время, когда Эдвард Сноуден обнародовал документы, которые пролили свет на тот факт, что National Security Agency (NSA) могло повлиять на NIST, чтобы намеренно ослабить стандарт генератора случайных чисел Dual_EC_DRBG, фактически поместив бэкдор в стандартный генератор случайных чисел.
После огласки, выход реализации стандарта SHA-3 пришлось отложить. Ethereum в этот момент был ещё на стадии разработки. Чтобы не останавливать разработку, а так же иметь более прозрачную реализацию алгоритма, команда Ethereum решила самостоятельно реализовать оригинальный алгоритм Keccak-256.
Более подробно про SHA3 и Keccak-256 можно почитать здесь.
На этом пожалуй всё. В этот раз мы познакомились со всеми этапами формирования адреса в сети Ethereum, а заодно затронули такие важные понятия, как приватный и публичный ключ, хэш-функцию и служебные адреса.
ссылка на оригинал статьи https://habr.com/ru/articles/739958/
Добавить комментарий