mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-10 01:33:07 +00:00
146 lines
4.8 KiB
NASM
146 lines
4.8 KiB
NASM
// Note: currently, these methods do not check that RLP input is in canonical
|
|
// form; for example a single byte could be encoded with the length-of-length
|
|
// form. Technically an EVM must perform these checks, but we aren't really
|
|
// concerned with it in our setting. An attacker who corrupted consensus could
|
|
// prove a non-canonical state, but this would just temporarily stall the bridge
|
|
// until a fix was deployed. We are more concerned with preventing any theft of
|
|
// assets.
|
|
|
|
// Parse the length of a bytestring from RLP memory. The next len bytes after
|
|
// pos' will contain the string.
|
|
//
|
|
// Pre stack: pos, retdest
|
|
// Post stack: pos', len
|
|
global decode_rlp_string_len:
|
|
JUMPDEST
|
|
// stack: pos, retdest
|
|
DUP1
|
|
%mload_current(@SEGMENT_RLP_RAW)
|
|
// stack: first_byte, pos, retdest
|
|
DUP1
|
|
%gt_const(0xb6)
|
|
// stack: first_byte >= 0xb7, first_byte, pos, retdest
|
|
%jumpi(decode_rlp_string_len_large)
|
|
// stack: first_byte, pos, retdest
|
|
DUP1
|
|
%gt_const(0x7f)
|
|
// stack: first_byte >= 0x80, first_byte, pos, retdest
|
|
%jumpi(decode_rlp_string_len_medium)
|
|
decode_rlp_string_len_small:
|
|
// String is a single byte in the range [0x00, 0x7f].
|
|
%stack (first_byte, pos, retdest) -> (retdest, pos, 1)
|
|
JUMP
|
|
decode_rlp_string_len_medium:
|
|
// String is 0-55 bytes long. First byte contains the len.
|
|
// stack: first_byte, pos, retdest
|
|
%sub_const(0x80)
|
|
// stack: len, pos, retdest
|
|
SWAP1
|
|
%add_const(1)
|
|
// stack: pos', len, retdest
|
|
decode_rlp_string_len_large:
|
|
// String is >55 bytes long. First byte contains the len of the len.
|
|
// stack: first_byte, pos, retdest
|
|
%sub_const(0xb7)
|
|
// stack: len_of_len, pos, retdest
|
|
SWAP1
|
|
%add_const(1)
|
|
// stack: pos', len_of_len, retdest
|
|
%jump(decode_int_given_len)
|
|
|
|
// Parse a scalar from RLP memory.
|
|
// Pre stack: pos, retdest
|
|
// Post stack: pos', scalar
|
|
//
|
|
// Scalars are variable-length, but this method assumes a max length of 32
|
|
// bytes, so that the result can be returned as a single word on the stack.
|
|
// As per the spec, scalars must not have leading zeros.
|
|
global decode_rlp_scalar:
|
|
JUMPDEST
|
|
// stack: pos, retdest
|
|
PUSH decode_int_given_len
|
|
// stack: decode_int_given_len, pos, retdest
|
|
SWAP1
|
|
// stack: pos, decode_int_given_len, retdest
|
|
// decode_rlp_string_len will return to decode_int_given_len, at which point
|
|
// the stack will contain (pos', len, retdest), which are the proper args
|
|
// to decode_int_given_len.
|
|
%jump(decode_rlp_string_len)
|
|
|
|
// Parse the length of an RLP list from memory.
|
|
// Pre stack: pos, retdest
|
|
// Post stack: pos', len
|
|
global decode_rlp_list_len:
|
|
JUMPDEST
|
|
// stack: pos, retdest
|
|
DUP1
|
|
%mload_current(@SEGMENT_RLP_RAW)
|
|
// stack: first_byte, pos, retdest
|
|
SWAP1
|
|
%add_const(1) // increment pos
|
|
SWAP1
|
|
// stack: first_byte, pos', retdest
|
|
// If first_byte is >= 0xf7, it's a > 55 byte list, and
|
|
// first_byte - 0xf7 is the length of the length.
|
|
DUP1
|
|
%gt_const(0xf6) // GT is native while GE is not, so compare to 0xf6 instead
|
|
// stack: first_byte >= 0xf7, first_byte, pos', retdest
|
|
%jumpi(decode_rlp_list_len_big)
|
|
decode_rlp_list_len_small:
|
|
// The list length is first_byte - 0xc0.
|
|
// stack: first_byte, pos', retdest
|
|
%sub_const(0xc0)
|
|
// stack: len, pos', retdest
|
|
%stack (len, pos, retdest) -> (retdest, pos, len)
|
|
JUMP
|
|
decode_rlp_list_len_big:
|
|
JUMPDEST
|
|
// The length of the length is first_byte - 0xf7.
|
|
// stack: first_byte, pos', retdest
|
|
%sub_const(0xf7)
|
|
// stack: len_of_len, pos', retdest
|
|
SWAP1
|
|
// stack: pos', len_of_len, retdest
|
|
%jump(decode_int_given_len)
|
|
|
|
// Parse an integer of the given length. It is assumed that the integer will
|
|
// fit in a single (256-bit) word on the stack.
|
|
// Pre stack: pos, len, retdest
|
|
// Post stack: pos', int
|
|
decode_int_given_len:
|
|
JUMPDEST
|
|
%stack (pos, len, retdest) -> (pos, len, pos, retdest)
|
|
ADD
|
|
// stack: end_pos, pos, retdest
|
|
SWAP1
|
|
// stack: pos, end_pos, retdest
|
|
PUSH 0 // initial accumulator state
|
|
// stack: acc, pos, end_pos, retdest
|
|
decode_int_given_len_loop:
|
|
JUMPDEST
|
|
// stack: acc, pos, end_pos, retdest
|
|
DUP3
|
|
DUP3
|
|
ISZERO
|
|
// stack: pos == end_pos, acc, pos, end_pos, retdest
|
|
%jumpi(decode_int_given_len_finish)
|
|
// stack: acc, pos, end_pos, retdest
|
|
%shl_const(8)
|
|
// stack: acc << 8, pos, end_pos, retdest
|
|
DUP2
|
|
// stack: pos, acc << 8, pos, end_pos, retdest
|
|
%mload_current(@SEGMENT_RLP_RAW)
|
|
// stack: byte, acc << 8, pos, end_pos, retdest
|
|
ADD
|
|
// stack: acc', pos, end_pos, retdest
|
|
// Increment pos.
|
|
SWAP1
|
|
%add_const(1)
|
|
SWAP1
|
|
// stack: acc', pos', end_pos, retdest
|
|
%jump(decode_int_given_len_loop)
|
|
decode_int_given_len_finish:
|
|
JUMPDEST
|
|
%stack (acc, pos, end_pos, retdest) -> (retdest, pos, acc)
|
|
JUMP
|