Формирование транзакций
Last updated
Last updated
Есть правила формирования транзакций, заложенные в протокол Golos. Данные, подписываемые криптографическим ключом, должны соответствовать всем структурам и правилам бинарного представления, заложенным в код. В данном разделе вы узнаете как кодируются ключи, как происходит бинарное представление данных или их подготовка.
Структура данных, бинарное представление которой и нужно подписывать используя ключи соответствующих типов доступа используемых в аккаунтах вложенных операций, содержит следующие поля:
chain_id — идентификатор цепи, в Golos это fc::sha256::hash от строки GOLOS
: 782a3039b478c839e4cb0c941ff4eaeb7df40bdd68bd441afd444b9da763de12
. Стоит отметить, что fc::sha256::hash преобразует строку в c_str, добавляя в начало ее hex значения 56495A
длину строки, в итоге sha256 рассчитывается от hex значения 0356495A
;
tapos_link — заключается в том, чтобы каждая транзакция ссылалась на конкретный блок, который должен быть в цепи для ее работы. Бинарное представление является отображением параметров транзакции ref_block_num и ref_block_prefix.
expiration — unixtime экспирации транзакции (она должна быть включена в цепь до времени экспирации);
operations — массив операций находящихся в транзакции, бинарное представление каждой операции состоит из всех аттрибутов операции согласно протоколу;
extensions — массив служебных расширений транзакции (не используется, поэтому в бинарном формате представляет собой hex значение массива без элементов: 00
);
Открытый и свободный код блокчейн систем основанных на Graphene позволяют запускать новые цепочки, как без изменений, так и полностью переработанные с собственными механиками и экономикой. Более того, множество проектов запускают публичные тестовые цепочки для проверки изменений. Чтобы ноды не путались и транзакции из одной сети нельзя было применять в форке (или цепи с аналогичными аккаунтами и ключами) — существует идентификатор цепи, который присутствует как метка в каждой транзакции и операции подписи.
Приватные и публичные ключи в Golos находятся по (), и используют криптографию для проверки подписей набора данных. Многие разработчики не являясь специалистами в криптографии просто используют специализированные библиотеки, не вдаваясь в подробности.
Рассмотрим этапность преобразования приватного ключа (состоящего из 32 байт) в читаемый WIF формат:
Ключу добавляем бинарный префикс в hex представлении 80
;
Вычисляем sha256 хэш от sha256 хэша бинарного представления ключа для контрольной суммы (checksum);
Добавляем в конец ключа первые 8 байт от контрольной суммы;
Кодируем полученный бинарный результат через base58 алгоритм с использованием алфавита: 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
;
Этапность преобразование публичного ключа (состоящего из 32 байт) в читаемый формат:
Добавляем в конец ключа первые 8 байт от контрольной суммы;
Кодируем полученный бинарный результат через base58 алгоритм с использованием алфавита: 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
;
Добавляем префикс сети (строковое значение GOLOS
);
string — строковое значение в бинарном виде представляет собой байт содержащий длину строки и саму строку (например, строковое значение логина аккаунта escrow
будет соответствовать hex значению 06657363726f77
в бинарном представлении);
integer — числовое значение переворачивается в бинарном представлении и пустая размерность заполняется нулями (если задан тип значения). Например, процент апвоута указываемый в операции upvote
представляет собой uint16_t, для передачи которого достаточно 2 байта. Если необходимо передать значением 10.00%, то в целочисленном значении это будет 1000, в hex представлении 03EB
, перевернутое значение которого будет EB03
.
date — поля дат из JSON представления записаны в ISO формате (например, 2019-02-07T06:19:23
в часовом поясе UTC+0, он же GMT). Для их бинарного значения записывается в десятичном формате unixtime по правилам представления integer. Пример 2019-02-07T06:19:23
в unixtime будет 1549520363
(hex значение 5C5BCDEB
), который в бинарном значении будет представлять собой hex: EBCD5B5C
.
asset — бинарное значение токенов GOLOS представляет собой последовательность значений: целочисленный integer размерностью 8 байт без точности (0.012 будет представлять собой 12, 1.002 будет представлять собой 1002). Например: 1.002 GOLOS
в JSON значении внутри операции будет иметь бинарное представление в hex: EA030000000000000356495A
.
Разберем пример транзакции в формате JSON и её представление в бинарном виде:
ref_block_num — ссылка на номер блока после побитового «и» с hex ffff
(например, число 9023 в hex представлении 233F
, согласно представлению integer должно быть перевернуто, получаем 3F23
);
ref_block_prefix — 4 байта (5, 6, 7, 8) от бинарного состояния идентификатора блока в десятичном формате, которое можно получить API запросом get_block_header
с номером следующего блока (9024) к плагину database_api. Ответ будет содержать поле previous
с идентификатором 0000233F716D887523BB63AD3E6107C96EDCFD8A
искомого блока. Берем 716D8875
для бинарного представления, переворачиваем байты — 75886D71
и переводим в десятичный формат для JSON: 1971875185
.
expiration — unixtime экспирации транзакции. 2019-02-07T06:19:23
в unixtime будет 1549520363
(hex значение 5C5BCDEB
), который в бинарном значении будет перевернут и представлять собой hex: EBCD5B5C
.
operations — массив операций (так как в массиве один элемент, hex: 01
);
transfer — операция перевода токенов (по нумерации операции в протоколе hex: 02
);
from — логин аккаунта отправителя (длина строки test1
и hex представление: 057465737431
);
to — логин аккаунта получателя (длина строки test2
и hex представление: 057465737432
);
amount — передаваемое количество токенов GOLOS (1.002 GOLOS
в hex: EA030000000000000356495A00000000
);
memo — заметка для получателя (длина строки <3
и hex представление: 023C33
);
extensions — массив служебных расширений транзакции (так как не используется и не имеет элементов, то имеет представление 00
).
Итоговое бинарное представление данных транзакции в hex: 3F23716D8875EBCD5B5C0102057465737431057465737432EA030000000000000356495A00000000023C3300
;
Чтобы отправить транзакцию в блокчейн, необходимо дополнить данное представление chain_id в начале и подписать приватным ключом. Полученную подпись необходимо добавить в JSON поле массив signatures
, например:
И передать этот JSON через API запрос broadcast_transaction
плагину network_broadcast_api
.
Получают данные о состоянии системы через API запрос get_dynamic_global_properties
к плагину database_api
;
Используя значение поля head_block_number
минус 3 блока устанавливают для какого блока будут формировать ref_block_num и запрашивать его идентификатор;
Получают идентификатор используемого блока, выполняя API запрос get_block_header
к плагину database_api
, запрашивая искомый блок плюс один блок (так как заголовок каждого блока содержит ссылку на идентификатор прошлого блока, искомый идентификатор находится в следующем);
Из идентификатора формируют ref_block_prefix.
Большинство библиотек которые содержат абстракции для упрощения вызовов и трансляции транзакции в блокчейн делают это самостоятельно.
Именно там можно изучить типы параметров и их требуемый порядок в операции. Внимание! Порядок параметров в структуре операции не совпадает с порядком параметров в самой операции. Рассмотрим пример на операции escrow_transfer_operation
, структура операции (часто перед операцией присутствует комментарий её описывающий):
Порядок параметров в операции задается уже в конце файла методом:
Большинство операций проверяют наличие подписи соответствующих полномочий, например в структуре escrow_transfer_operation
присутствует проверка подписи инициатора операции (поле from
) активных полномочий в методе get_required_active_authorities
.
Получаем контрольную сумму хэшированием бинарного представления ключа ;
В библиотеке golos-lib-js используется модуль auth
(), который позволяет предустановленными методами работать с ключами и подписывать данные.
public_key — значение публичного ключа в бинарном представлении содержит 33 байта, первый байт — значение для восстанавления публичного ключа (), 16 байт — координаты точки публичного ключа по оси X, последние 16 байт по оси Y. Например, бинарное значение 026a1dbaacb805f145f9276025627102152840bb1aa09b7fac580f892d93b572b4
соответствует приватному ключу с recovery_id равным 02
и точке с координатами X в hex представлении 6a1dbaacb805f145f927602562710215
и Y в hex представлении 2840bb1aa09b7fac580f892d93b572b4
. Что соответствует публичному ключу GLS5hDwvV1PPUTmehSmZecaxo1ameBpCMNVmYHKK2bL1ppLGRvh85
.
operation_type — тип операции представляет собой целочисленное значение номера операции по протоколу GOLOS записанное в 1 байт (подробнее читайте в разделе ). Например, операция transfer
в бинарном виде будет иметь запись в hex 02
.
Нода блокчейна хранит идентификаторы последних 65537 блоков (подробнее читайте ). Обычно разработчики ссылаются на один из последних блоков, обычно, выполняя очередь действий:
Пример получения ref_block_num
и ref_block_prefix
на PHP в .
Все операции и их параметры записаны в протоколе GOLOS и находятся .
Кроме описания структуры операции есть еще обработка параметров в методе validate
, найти который можно :