Учетные записи Глобальное общее состояние платформы Эфириум состоит из множества небольших объектов – учетных записей, которые взаимодействуют между собой за счет парадигмы обмена сообщениями. У каждой учетной записи есть определенное состояние и 20-байтовый адрес. Адресом в Эфириум является 160-битный идентификатор, используемый для идентификации любой из учетных записей. Всего существует два вида учетных записей: Внешние учетные записи, контролируются с помощью закрытых ключей. При этом такие записи не имеют никакого кода, связанного с ними. Контрактные учетные записи, контролируются специальным кодом, указанным в условиях контракта, и имеющие связанный с ними код. Внешние и контрактные учетные записи Давайте разберемся с основными отличиями между внешними и контрактными учетными записями. Для внешней учетной записи предусмотрена возможность отправлять сообщения другим внешним учетным записям, а также другим контрактным учетным записям. Для данной цели необходимо создать и зарегистрировать новую транзакцию, используя закрытый ключ. Сообщение между двумя внешними учетными записями является всего лишь значением для передачи. С другой стороны, сообщение, отправленное от внешней учетной записи к контрактной, подразумевает активацию кода контрактной учетной записи, при этом появляется возможность совершения определенных действий (например, с помощью такого сообщения можно переводить токены, записывать значения во встроенную память, создавать токены, выполнять некоторые вычисления, создавать новые контракты и т. д.). С помощью контрактных учетных записей, в отличие от внешних, самостоятельно инициировать новые транзакции невозможно. Вместо этого с помощью контрактных учетных записей можно только запускать транзакции в ответ на другие полученные транзакции (например, полученные из внешней учетной записи или из другой контрактной учетной записи). Более подробно о вызовах между контрактными учетными записями мы остановимся в разделе «Транзакции и сообщения». Каждое действие в блокчейне Эфириума происходит благодаря транзакциям, инициируемым внешне контролируемыми учетными записями. Состояние учетных записей Состояние каждой из учетных записей, вне зависимости от их типа, может принимать одно из четырех значений: nonce: Если настоящая учетная запись соответствует внешней учетной записи, то полученное число представляет собой количество транзакций, которые были отправлены с адреса учетной записи. Если учетная запись является контрактной учетной записью, то элемент nonce – это количество контрактов, созданных в данной учетной записи. balance: общее количество wei, приобретенных данной учетной записью. Например, каждый эфир, который является обменной единице Эфириума, содержит 10^18 wei – дробных частей эфира. storageRoot: хэш корневого узла префиксного дерева Меркла (что собой представляет дерево Меркла мы рассмотрим немного позже). Дерево Меркла кодирует хэш содержимого данной учетной записи, при этом по умолчанию оно является пустым. codeHash: хэш EVM-кода (от англ. Ethereum Virtual Machine; что это такое я расскажу немного позже) учетной записи. Для контрактных учетных записей данное поле является кодом, который хэшируется и хранится в виде codeHash. Общее состояние системы Итак, мы разобрались, что глобальное состояние Эфириума – это сопоставление адресам учетной записи состояний счета. Это сопоставление хранится в структуре данных – префиксного дерева Меркла. Дерево Меркла (или «Merkle trie») представляет собой тип двоичного файла, состоящего из набора узлов, которые включают: определенное количество листовых узлов, которые располагаются в нижней части дерева, содержащего базовые данные; набор промежуточных узлов, при этом каждый узел представляет собой хэш двух его дочерних узлов один корневой узел, также образованный из хэша двух дочерних узлов, который представляет вершину дерева Данные, находящиеся в нижней части дерева, создаются путем разделения тех данных, которые мы хотим сохранить, на отдельные фрагменты. Далее такие фрагменты размещаются в корзинах хранения данных, после чего происходит их хэширование и аналогичный процесс повторяется до тех пор, пока общее число хэшей не будет равно единице или корневому хэшу. Для каждого значения, хранящегося внутри данного дерева, вам потребуется ввести определенный ключ. Для получения соответствующего значения, хранящегося в листовых узлах, вы должны получить команду ключа: цепочки какого дочернего узла необходимо придерживаться. Что касается Эфириума, то отображение ключа/значения, необходимого для дерева состояний, находится между адресами и связанными с ними учетными записями, в том числе balance, nonce, codeHash, а также storageRoot для каждой из учетных записей, при этом storageRoot является деревом. Подобная структура префиксного дерева также может применяться для хранения как транзакций, так и страницы приема оплаты. Если останавливаться на этом более подробно, то каждый блок имеет так называемый «header» или заголовочный файл, в котором хранится хэш корневого узла трех разных структур дерева Меркла, в том числе: Состояние префиксного дерева Транзакции префиксного дерева Страницы приема оплаты для префиксного дерева Возможность эффективного хранения данной информации в префиксном дереве Меркла Эфириума является невероятно практичным решением для так называемых тонких клиентов или тонких узлов. Необходимо также отметить, что поддержка блокчейна осуществляется с помощью набора узлов. Простыми словами: всего существует два вида узлов: полный и тонкий. Полный узел архива выполняет синхронизацию блокчейна с помощью загрузки всей цепочки от блока первоначального состояния до текущего блока, содержащего заголовочный файл, при этом происходит выполнение всех располагающихся в нем транзакций. Как правило, майнеры хранят полный узел архива, поскольку без последнего у них не будет возможности участвовать в процессе майнинга. Кроме того, вы также может загрузить полный узел, при этом в выполнении каждой отдельной транзакции нет необходимости. Также стоит отметить, что каждый полный узел всегда содержит полную цепочку. В том случае если для узла нет необходимости выполнять каждую отдельную транзакцию или запрашивать накопленные данные, то хранение полной цепочки может оказаться излишним. Именно в данном случае мы сталкиваемся с таким понятием как тонкий узел. Вместо загрузки и хранения полной цепочки, а также выполнения всех транзакций, тонкие узлы загружают только цепочку заголовочных файлов из блока первоначального состояния в текущий заголовок, при этом не происходит выполнения каких-либо транзакций. Поскольку у тонких узлов имеется доступ к заголовкам блоков, содержащих хэш трех префиксных деревьев, они могут с легкостью создавать и получать соответствующие ответы, касающиеся транзакций, событий, баланса и т.д. Хэш в дереве Меркла распространяется от нижних ветвей к верхним, и если злоумышленник попытается заменить оригинальную транзакцию на поддельную в нижней части дерева Меркла, то это приведет к изменению хэша верхнего узла, а это, в свою очередь, приведет к изменению хэша располагающегося над ним узла и так до тех пор, пока, в конечном итоге, это не приведет к изменению корня. Любой узел, для которого требуется проверка какой-либо части данных, использует так называемое «доказательством Меркла». Последнее состоит из: Фрагмента данных, который должен быть проверен Корневого хэша дерева Так называемой «ветви» – всех хэшей, от проверяемого фрагмента данных до корня. Каждый пользователь, считывающий такое доказательство, может проверить, является ли хеширование для определенной ветви соответствующим на всем участке дерева, а также занимает ли данный фрагмент соответствующее положение в этом дереве. Таким образом, можно сделать вывод, что преимущество применения префиксного дерева Меркла заключается в том, что корневой узел данной структуры является криптографически зависимым от данных, хранящихся в дереве. Следовательно, хэш корневого узла может быть использован в качестве безопасного идентификатора для этих данных. Ввиду того, что в заголовок блока включен корневой хэш деревьев, а также их состояния, транзакции и информацию о приходе оплаты, любой из узлов может проверять ту или иную часть состояния Эфириума без необходимости хранения всех состояний, которые могут быть потенциально неограниченным по размеру.
Pro Бизнес
Часть 2
Учетные записи
Глобальное общее состояние платформы Эфириум состоит из множества небольших объектов – учетных записей, которые взаимодействуют между собой за счет парадигмы обмена сообщениями. У каждой учетной записи есть определенное состояние и 20-байтовый адрес. Адресом в Эфириум является 160-битный идентификатор, используемый для идентификации любой из учетных записей.
Всего существует два вида учетных записей:
Внешние учетные записи, контролируются с помощью закрытых ключей. При этом такие записи не имеют никакого кода, связанного с ними.
Контрактные учетные записи, контролируются специальным кодом, указанным в условиях контракта, и имеющие связанный с ними код.
Внешние и контрактные учетные записи
Давайте разберемся с основными отличиями между внешними и контрактными учетными записями. Для внешней учетной записи предусмотрена возможность отправлять сообщения другим внешним учетным записям, а также другим контрактным учетным записям. Для данной цели необходимо создать и зарегистрировать новую транзакцию, используя закрытый ключ. Сообщение между двумя внешними учетными записями является всего лишь значением для передачи. С другой стороны, сообщение, отправленное от внешней учетной записи к контрактной, подразумевает активацию кода контрактной учетной записи, при этом появляется возможность совершения определенных действий (например, с помощью такого сообщения можно переводить токены, записывать значения во встроенную память, создавать токены, выполнять некоторые вычисления, создавать новые контракты и т. д.).
С помощью контрактных учетных записей, в отличие от внешних, самостоятельно инициировать новые транзакции невозможно. Вместо этого с помощью контрактных учетных записей можно только запускать транзакции в ответ на другие полученные транзакции (например, полученные из внешней учетной записи или из другой контрактной учетной записи). Более подробно о вызовах между контрактными учетными записями мы остановимся в разделе «Транзакции и сообщения».
Каждое действие в блокчейне Эфириума происходит благодаря транзакциям, инициируемым внешне контролируемыми учетными записями.
Состояние учетных записей
Состояние каждой из учетных записей, вне зависимости от их типа, может принимать одно из четырех значений:
nonce: Если настоящая учетная запись соответствует внешней учетной записи, то полученное число представляет собой количество транзакций, которые были отправлены с адреса учетной записи. Если учетная запись является контрактной учетной записью, то элемент nonce – это количество контрактов, созданных в данной учетной записи.
balance: общее количество wei, приобретенных данной учетной записью. Например, каждый эфир, который является обменной единице Эфириума, содержит 10^18 wei – дробных частей эфира.
storageRoot: хэш корневого узла префиксного дерева Меркла (что собой представляет дерево Меркла мы рассмотрим немного позже). Дерево Меркла кодирует хэш содержимого данной учетной записи, при этом по умолчанию оно является пустым.
codeHash: хэш EVM-кода (от англ. Ethereum Virtual Machine; что это такое я расскажу немного позже) учетной записи. Для контрактных учетных записей данное поле является кодом, который хэшируется и хранится в виде codeHash.
Общее состояние системы
Итак, мы разобрались, что глобальное состояние Эфириума – это сопоставление адресам учетной записи состояний счета. Это сопоставление хранится в структуре данных – префиксного дерева Меркла.
Дерево Меркла (или «Merkle trie») представляет собой тип двоичного файла, состоящего из набора узлов, которые включают:
определенное количество листовых узлов, которые располагаются в нижней части дерева, содержащего базовые данные;
набор промежуточных узлов, при этом каждый узел представляет собой хэш двух его дочерних узлов
один корневой узел, также образованный из хэша двух дочерних узлов, который представляет вершину дерева
Данные, находящиеся в нижней части дерева, создаются путем разделения тех данных, которые мы хотим сохранить, на отдельные фрагменты. Далее такие фрагменты размещаются в корзинах хранения данных, после чего происходит их хэширование и аналогичный процесс повторяется до тех пор, пока общее число хэшей не будет равно единице или корневому хэшу.
Для каждого значения, хранящегося внутри данного дерева, вам потребуется ввести определенный ключ. Для получения соответствующего значения, хранящегося в листовых узлах, вы должны получить команду ключа: цепочки какого дочернего узла необходимо придерживаться. Что касается Эфириума, то отображение ключа/значения, необходимого для дерева состояний, находится между адресами и связанными с ними учетными записями, в том числе balance, nonce, codeHash, а также storageRoot для каждой из учетных записей, при этом storageRoot является деревом.
Подобная структура префиксного дерева также может применяться для хранения как транзакций, так и страницы приема оплаты. Если останавливаться на этом более подробно, то каждый блок имеет так называемый «header» или заголовочный файл, в котором хранится хэш корневого узла трех разных структур дерева Меркла, в том числе:
Состояние префиксного дерева
Транзакции префиксного дерева
Страницы приема оплаты для префиксного дерева
Возможность эффективного хранения данной информации в префиксном дереве Меркла Эфириума является невероятно практичным решением для так называемых тонких клиентов или тонких узлов. Необходимо также отметить, что поддержка блокчейна осуществляется с помощью набора узлов. Простыми словами: всего существует два вида узлов: полный и тонкий.
Полный узел архива выполняет синхронизацию блокчейна с помощью загрузки всей цепочки от блока первоначального состояния до текущего блока, содержащего заголовочный файл, при этом происходит выполнение всех располагающихся в нем транзакций. Как правило, майнеры хранят полный узел архива, поскольку без последнего у них не будет возможности участвовать в процессе майнинга. Кроме того, вы также может загрузить полный узел, при этом в выполнении каждой отдельной транзакции нет необходимости. Также стоит отметить, что каждый полный узел всегда содержит полную цепочку.
В том случае если для узла нет необходимости выполнять каждую отдельную транзакцию или запрашивать накопленные данные, то хранение полной цепочки может оказаться излишним. Именно в данном случае мы сталкиваемся с таким понятием как тонкий узел. Вместо загрузки и хранения полной цепочки, а также выполнения всех транзакций, тонкие узлы загружают только цепочку заголовочных файлов из блока первоначального состояния в текущий заголовок, при этом не происходит выполнения каких-либо транзакций. Поскольку у тонких узлов имеется доступ к заголовкам блоков, содержащих хэш трех префиксных деревьев, они могут с легкостью создавать и получать соответствующие ответы, касающиеся транзакций, событий, баланса и т.д.
Хэш в дереве Меркла распространяется от нижних ветвей к верхним, и если злоумышленник попытается заменить оригинальную транзакцию на поддельную в нижней части дерева Меркла, то это приведет к изменению хэша верхнего узла, а это, в свою очередь, приведет к изменению хэша располагающегося над ним узла и так до тех пор, пока, в конечном итоге, это не приведет к изменению корня.
Любой узел, для которого требуется проверка какой-либо части данных, использует так называемое «доказательством Меркла». Последнее состоит из:
Фрагмента данных, который должен быть проверен
Корневого хэша дерева
Так называемой «ветви» – всех хэшей, от проверяемого фрагмента данных до корня.
Каждый пользователь, считывающий такое доказательство, может проверить, является ли хеширование для определенной ветви соответствующим на всем участке дерева, а также занимает ли данный фрагмент соответствующее положение в этом дереве.
Таким образом, можно сделать вывод, что преимущество применения префиксного дерева Меркла заключается в том, что корневой узел данной структуры является криптографически зависимым от данных, хранящихся в дереве. Следовательно, хэш корневого узла может быть использован в качестве безопасного идентификатора для этих данных. Ввиду того, что в заголовок блока включен корневой хэш деревьев, а также их состояния, транзакции и информацию о приходе оплаты, любой из узлов может проверять ту или иную часть состояния Эфириума без необходимости хранения всех состояний, которые могут быть потенциально неограниченным по размеру.