plonky2/evm/src/cpu/kernel/asm/rlp/encode.asm

128 lines
3.6 KiB
NASM
Raw Normal View History

// RLP-encode a scalar, i.e. a variable-length integer.
2022-08-03 21:56:25 -07:00
// Pre stack: pos, scalar, retdest
2022-08-14 09:12:16 -07:00
// Post stack: pos
global encode_rlp_scalar:
2022-08-14 09:12:16 -07:00
// stack: pos, scalar, retdest
// If scalar > 0x7f, this is the "medium" case.
DUP2
%gt_const(0x7f)
%jumpi(encode_rlp_scalar_medium)
2022-08-14 09:12:16 -07:00
// This is the "small" case, where the value is its own encoding.
// stack: pos, scalar, retdest
%stack (pos, scalar) -> (pos, scalar, pos)
// stack: pos, scalar, pos, retdest
%mstore_current(@SEGMENT_RLP_RAW)
// stack: pos, retdest
%add_const(1)
// stack: pos', retdest
SWAP1
JUMP
encode_rlp_scalar_medium:
// This is the "medium" case, where we write 0x80 + len followed by the
// (big-endian) scalar bytes. We first compute the minimal number of bytes
// needed to represent this scalar, then treat it as if it was a fixed-
// length string with that length.
// stack: pos, scalar, retdest
DUP2
%num_bytes
// stack: scalar_bytes, pos, scalar, retdest
%jump(encode_rlp_fixed)
// Convenience macro to call encode_rlp_scalar and return where we left off.
%macro encode_rlp_scalar
%stack (pos, scalar) -> (pos, scalar, %%after)
%jump(encode_rlp_scalar)
%%after:
%endmacro
// RLP-encode a fixed-length 160 bit (20 byte) string. Assumes string < 2^160.
2022-08-03 21:56:25 -07:00
// Pre stack: pos, string, retdest
2022-08-14 09:12:16 -07:00
// Post stack: pos
global encode_rlp_160:
2022-08-14 09:12:16 -07:00
PUSH 20
%jump(encode_rlp_fixed)
2022-08-14 09:12:16 -07:00
// Convenience macro to call encode_rlp_160 and return where we left off.
%macro encode_rlp_160
%stack (pos, string) -> (pos, string, %%after)
%jump(encode_rlp_160)
%%after:
%endmacro
// RLP-encode a fixed-length 256 bit (32 byte) string.
2022-08-03 21:56:25 -07:00
// Pre stack: pos, string, retdest
2022-08-14 09:12:16 -07:00
// Post stack: pos
global encode_rlp_256:
2022-08-14 09:12:16 -07:00
PUSH 32
%jump(encode_rlp_fixed)
// Convenience macro to call encode_rlp_256 and return where we left off.
%macro encode_rlp_256
%stack (pos, string) -> (pos, string, %%after)
%jump(encode_rlp_256)
%%after:
%endmacro
// RLP-encode a fixed-length string with the given byte length. Assumes string < 2^(8 * len).
encode_rlp_fixed:
// stack: len, pos, string, retdest
DUP1
%add_const(0x80)
// stack: first_byte, len, pos, string, retdest
DUP3
// stack: pos, first_byte, len, pos, string, retdest
%mstore_current(@SEGMENT_RLP_RAW)
// stack: len, pos, string, retdest
SWAP1
%add_const(1) // increment pos
// stack: pos, len, string, retdest
%stack (pos, len, string) -> (@SEGMENT_RLP_RAW, pos, string, len, encode_rlp_fixed_finish, pos, len)
GET_CONTEXT
// stack: context, segment, pos, string, len, encode_rlp_fixed, pos, retdest
%jump(mstore_unpacking)
encode_rlp_fixed_finish:
// stack: pos, len, retdest
ADD
// stack: pos', retdest
SWAP1
JUMP
// Get the number of bytes required to represent the given scalar.
// The scalar is assumed to be non-zero, as small scalars like zero should
// have already been handled with the small-scalar encoding.
num_bytes:
// stack: x, retdest
PUSH 0 // i
// stack: i, x, retdest
num_bytes_loop:
// stack: i, x, retdest
// If x[i] != 0, break.
DUP2 DUP2
// stack: i, x, i, x, retdest
BYTE
// stack: x[i], i, x, retdest
%jumpi(num_bytes_finish)
// stack: i, x, retdest
%add_const(1)
// stack: i', x, retdest
%jump(num_bytes_loop)
num_bytes_finish:
// stack: i, x, retdest
PUSH 32
SUB
%stack (num_bytes, x, retdest) -> (retdest, num_bytes)
JUMP
// Convenience macro to call num_bytes and return where we left off.
%macro num_bytes
%stack (x) -> (x, %%after)
%jump(num_bytes)
%%after:
%endmacro