Как разрешаются JUMP и JUMPDEST для байт-кода Ethereum?

Я искал информацию о том, как Ethereum справляется с прыжками и пунктами назначения прыжков. Из разных блогов и желтой бумаги я обнаружил следующее:

Операнд, взятый JUMP и первый из двух операндов, взятых JUMPI являются значением PC устанавливается на (предположим, первое значение стека!= 0 в случае JUMPI).

Однако, глядя на код создания этого контракта (как коды операций), первые несколько кодов операций / значений:

PUSH1 0x60 PUSH1 0x40 MSTORE CALLDATASIZE ISZERO PUSH2 0x00f8 JUMPI

Насколько я понимаю, это означает, что если значение помещается в стек ISZERO!= 0 тогда PC изменится на 0x00f8 как JUMPI берет два из стека, проверяет, является ли секунда 0 и если не устанавливает PC к значению своего первого операнда.

У меня проблема в том, что 0x00f8 в десятичном виде 248, Похоже, что 248-я позиция в контракте MSTORE и не JUMPDEST, что приведет к сбою контракта при его исполнении, так как JUMP* может указывать только на действительный JUMPDEST,

Предположительно контракты не переходят к недействительным пунктам назначения специально?

Если бы кто-нибудь мог объяснить, как разрешаются прыжки и места назначения прыжков, я был бы очень благодарен.

2 ответа

В случае, если это помогает другим:

Путаница возникла из чтения EVM побайтово, а не слово за словом.

Из примера в вопросе, 0x00f8 будет 248-й байт, а не 248-е слово.

Поскольку каждый код операции имеет длину 1 байт PC обычно увеличивается на 1 при чтении кода операции.

Однако в случае PUSH инструкция, информация о том, сколько из следующих байтов должно быть взято как его операнд, также включена.

Например PUSH2 занимает 2 байта, которые следуют за ним, PUSH6 занимает 6 байтов, которые следуют за ним, и так далее. Вот PC будет увеличен на 1 для PUSH а затем 2 или 6 соответственно для каждого байта данных, используемых PUSH,

Просто хочу отметить, что есть разница в JUMP и JUMPI.

JUMP просто берет 1 элемент из стека, т.е. пункт назначения. Как правило, это смещение в шестнадцатеричном формате, помещаемое в стек

JUMPI - это условный переход, который берет 2 верхних элемента из стека, т.е. назначение и условие.

В приведенном вами примере условие ISZERO (проверяет, равен ли самый верхний элемент стека 0 или нет).
Таким образом, если это возвращает true, оно будет JUMP к назначению, которое является смещением 0x00f8(248 в десятичном виде).

Если условие ложно, оно просто увеличит счетчик программы на 1.

В упомянутом вами контракте это код операции JUMPDEST по адресу (Счетчик программ)248.

Счетчик программы зависит от кода операции. Сколько байтов вставляет код операции в стек и т. Д. например

PUSH1 0x60  - PC[0]
PUSH1 0x40  - PC[2]
MSTORE      - PC[4]
CALLDATASIZE- PC[5]
ISZERO      - PC[6]
PUSH2 0x00f8- PC[7]
JUMPI       - PC[10]

Возможно, этот сайт поможет вам лучше понять коды операций https://ethervm.io/

Другие вопросы по тегам