Skip to content
This repository has been archived by the owner on Jan 9, 2025. It is now read-only.

Commit

Permalink
Refacto casting utils (#841)
Browse files Browse the repository at this point in the history
Following partial #840 merged after CI went ✅
  • Loading branch information
ClementWalter authored Dec 5, 2023
1 parent ce5d5ef commit 44e849e
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 140 deletions.
7 changes: 2 additions & 5 deletions src/kakarot/errors.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -485,9 +485,6 @@ namespace Errors {
alloc_locals;
let (error: felt*) = alloc();

let (gas_used_ascii_len, gas_used_ascii) = felt_to_ascii(gas_used);
let (gas_limit_ascii_len, gas_limit_ascii) = felt_to_ascii(gas_limit);

assert [error + 0] = 'K';
assert [error + 1] = 'a';
assert [error + 2] = 'k';
Expand All @@ -513,7 +510,7 @@ namespace Errors {
assert [error + 22] = 't';
assert [error + 23] = '=';

memcpy(error + 24, gas_limit_ascii, gas_limit_ascii_len);
let gas_limit_ascii_len = felt_to_ascii(error + 24, gas_limit);

assert [error + 24 + gas_limit_ascii_len + 0] = ',';
assert [error + 24 + gas_limit_ascii_len + 1] = ' ';
Expand All @@ -523,7 +520,7 @@ namespace Errors {
assert [error + 24 + gas_limit_ascii_len + 5] = 'd';
assert [error + 24 + gas_limit_ascii_len + 6] = '=';

memcpy(error + 24 + gas_limit_ascii_len + 7, gas_used_ascii, gas_used_ascii_len);
let gas_used_ascii_len = felt_to_ascii(error + 24 + gas_limit_ascii_len + 7, gas_used);

return (24 + gas_limit_ascii_len + 7 + gas_used_ascii_len, error);
}
Expand Down
2 changes: 1 addition & 1 deletion src/kakarot/execution_context.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ from kakarot.model import model
from kakarot.stack import Stack
from kakarot.state import State
from utils.utils import Helpers
from utils.bytes import felt_to_ascii

// @title ExecutionContext related functions.
// @notice This file contains functions related to the execution context.
namespace ExecutionContext {
Expand Down
14 changes: 3 additions & 11 deletions src/kakarot/instructions/environmental_information.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ from utils.utils import Helpers
from kakarot.constants import Constants
from utils.uint256 import uint256_to_uint160
from utils.array import slice
from utils.bytes import bytes_to_bytes8_little_endian

// @title Environmental information opcodes.
// @notice This file contains the functions to execute for environmental information opcodes.
namespace EnvironmentalInformation {
Expand Down Expand Up @@ -380,17 +382,7 @@ namespace EnvironmentalInformation {
}

let (local dest: felt*) = alloc();
// convert to little endian
Helpers.bytes_to_bytes8_little_endian(
bytes_len=account.code_len,
bytes=account.code,
index=0,
size=account.code_len,
bytes8=0,
bytes8_shift=0,
dest=dest,
dest_index=0,
);
bytes_to_bytes8_little_endian(dest, account.code_len, account.code);

let (keccak_ptr: felt*) = alloc();
local keccak_ptr_start: felt* = keccak_ptr;
Expand Down
12 changes: 2 additions & 10 deletions src/kakarot/instructions/sha3.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ from kakarot.execution_context import ExecutionContext
from kakarot.stack import Stack
from kakarot.errors import Errors
from utils.utils import Helpers
from utils.bytes import bytes_to_bytes8_little_endian

// @title Sha3 opcodes.
// @notice This file contains the keccak opcode.
Expand Down Expand Up @@ -55,16 +56,7 @@ namespace Sha3 {
let memory = Memory.load_n(ctx.memory, length.low, bigendian_data, offset.low);

let (local dest: felt*) = alloc();
Helpers.bytes_to_bytes8_little_endian(
bytes_len=length.low,
bytes=bigendian_data,
index=0,
size=length.low,
bytes8=0,
bytes8_shift=0,
dest=dest,
dest_index=0,
);
bytes_to_bytes8_little_endian(dest, length.low, bigendian_data);

let (keccak_ptr: felt*) = alloc();
local keccak_ptr_start: felt* = keccak_ptr;
Expand Down
39 changes: 6 additions & 33 deletions src/kakarot/instructions/system_operations.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ from utils.rlp import RLP
from utils.utils import Helpers
from utils.uint256 import uint256_to_uint160
from utils.array import slice

from utils.bytes import bytes_to_bytes8_little_endian
// @title System operations opcodes.
// @notice This file contains the functions to execute for system operations opcodes.
namespace SystemOperations {
Expand Down Expand Up @@ -594,23 +594,14 @@ namespace CreateHelper {
let (rlp_list_len: felt) = RLP.encode_list(packed_bytes_len, packed_bytes, rlp_list);

let (local packed_bytes8: felt*) = alloc();
Helpers.bytes_to_bytes8_little_endian(
bytes_len=rlp_list_len,
bytes=rlp_list,
index=0,
size=rlp_list_len,
bytes8=0,
bytes8_shift=0,
dest=packed_bytes8,
dest_index=0,
);
bytes_to_bytes8_little_endian(packed_bytes8, rlp_list_len, rlp_list);

with keccak_ptr {
let (create_hash) = cairo_keccak_bigend(inputs=packed_bytes8, n_bytes=rlp_list_len);
finalize_keccak(keccak_ptr_start=keccak_ptr_start, keccak_ptr_end=keccak_ptr);
}

finalize_keccak(keccak_ptr_start, keccak_ptr);

let create_address = uint256_to_uint160(create_hash);
return (create_address,);
}
Expand Down Expand Up @@ -638,16 +629,7 @@ namespace CreateHelper {
local keccak_ptr_start: felt* = keccak_ptr;

let (local bytecode_bytes8: felt*) = alloc();
Helpers.bytes_to_bytes8_little_endian(
bytes_len=bytecode_len,
bytes=bytecode,
index=0,
size=bytecode_len,
bytes8=0,
bytes8_shift=0,
dest=bytecode_bytes8,
dest_index=0,
);
bytes_to_bytes8_little_endian(bytecode_bytes8, bytecode_len, bytecode);
with keccak_ptr {
// get keccak hash of bytecode
let (bytecode_hash_bigend) = cairo_keccak_bigend(
Expand Down Expand Up @@ -693,16 +675,7 @@ namespace CreateHelper {
);
let (local packed_bytes8: felt*) = alloc();
Helpers.bytes_to_bytes8_little_endian(
bytes_len=packed_bytes_len,
bytes=packed_bytes,
index=0,
size=packed_bytes_len,
bytes8=0,
bytes8_shift=0,
dest=packed_bytes8,
dest_index=0,
);
bytes_to_bytes8_little_endian(packed_bytes8, packed_bytes_len, packed_bytes);
let (create2_hash) = cairo_keccak_bigend(
inputs=packed_bytes8, n_bytes=packed_bytes_len
Expand Down
80 changes: 75 additions & 5 deletions src/utils/bytes.cairo
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from starkware.cairo.common.alloc import alloc
from starkware.cairo.common.math import unsigned_div_rem, split_int, assert_nn
from starkware.cairo.common.math import unsigned_div_rem
from starkware.cairo.common.uint256 import Uint256
from starkware.cairo.common.memcpy import memcpy
from starkware.cairo.common.registers import get_label_location

from utils.array import reverse

func felt_to_ascii{range_check_ptr}(n: felt) -> (ascii_len: felt, ascii: felt*) {
func felt_to_ascii{range_check_ptr}(dst: felt*, n: felt) -> felt {
alloc_locals;
let (local ascii: felt*) = alloc();

Expand All @@ -32,8 +33,77 @@ func felt_to_ascii{range_check_ptr}(n: felt) -> (ascii_len: felt, ascii: felt*)
let ascii_len = [ap - 1];
let ascii = cast([fp], felt*);

let (rev: felt*) = alloc();
reverse(rev, ascii_len, ascii);
reverse(dst, ascii_len, ascii);

return (ascii_len, rev);
return ascii_len;
}

func bytes_to_bytes8_little_endian(dst: felt*, bytes_len: felt, bytes: felt*) -> felt {
alloc_locals;
if (bytes_len == 0) {
return (0);
}

let (local pow256) = get_label_location(pow256_table);

tempvar dst_index = 0;
tempvar bytes_index = bytes_len - 1;
tempvar bytes8 = 0;
tempvar bytes8_index = 7;

body:
let dst_index = [ap - 4];
let bytes_index = [ap - 3];
let bytes8 = [ap - 2];
let bytes8_index = [ap - 1];

let bytes_len = [fp - 4];
let bytes = cast([fp - 3], felt*);
let pow256 = cast([fp], felt*);
let current_byte = bytes[bytes_len - 1 - bytes_index];
let current_pow = pow256[bytes8_index];

tempvar bytes8 = bytes8 + current_byte * current_pow;

jmp next if bytes_index != 0;

assert [dst + dst_index] = bytes8;
return (dst_index + 1);

next:
jmp regular if bytes8_index != 0;

assert [dst + dst_index] = bytes8;

tempvar dst_index = dst_index + 1;
tempvar bytes_index = bytes_index - 1;
tempvar bytes8 = 0;
tempvar bytes8_index = 7;
static_assert dst_index == [ap - 4];
static_assert bytes_index == [ap - 3];
static_assert bytes8 == [ap - 2];
static_assert bytes8_index == [ap - 1];
jmp body;

regular:
tempvar dst_index = dst_index;
tempvar bytes_index = bytes_index - 1;
tempvar bytes8 = bytes8;
tempvar bytes8_index = bytes8_index - 1;
static_assert dst_index == [ap - 4];
static_assert bytes_index == [ap - 3];
static_assert bytes8 == [ap - 2];
static_assert bytes8_index == [ap - 1];
jmp body;

pow256_table:
dw 256 ** 7;
dw 256 ** 6;
dw 256 ** 5;
dw 256 ** 4;
dw 256 ** 3;
dw 256 ** 2;
dw 256 ** 1;
dw 256 ** 0;
}
23 changes: 3 additions & 20 deletions src/utils/eth_transaction.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ from starkware.cairo.common.memcpy import memcpy
from starkware.cairo.common.uint256 import Uint256
from utils.rlp import RLP
from utils.utils import Helpers
from utils.bytes import bytes_to_bytes8_little_endian

// @title EthTransaction utils
// @notice This file contains utils for decoding eth transactions
Expand Down Expand Up @@ -97,16 +98,7 @@ namespace EthTransaction {
// > To use this function, split the input into words of 64 bits (little endian).
// > Same as keccak, but outputs the hash in big endian representation.
// > Note that the input is still treated as little endian.
Helpers.bytes_to_bytes8_little_endian(
bytes_len=rlp_data_len,
bytes=rlp_data,
index=0,
size=rlp_data_len,
bytes8=0,
bytes8_shift=0,
dest=words,
dest_index=0,
);
bytes_to_bytes8_little_endian(words, rlp_data_len, rlp_data);
let (msg_hash) = cairo_keccak_bigend(inputs=words, n_bytes=rlp_data_len);
}
finalize_keccak(keccak_ptr_start, keccak_ptr);
Expand Down Expand Up @@ -220,16 +212,7 @@ namespace EthTransaction {
// > To use this function, split the input into words of 64 bits (little endian).
// > Same as keccak, but outputs the hash in big endian representation.
// > Note that the input is still treated as little endian.
Helpers.bytes_to_bytes8_little_endian(
bytes_len=rlp_len + 1,
bytes=signed_data,
index=0,
size=rlp_len + 1,
bytes8=0,
bytes8_shift=0,
dest=words,
dest_index=0,
);
bytes_to_bytes8_little_endian(words, rlp_len + 1, signed_data);
let (msg_hash) = cairo_keccak_bigend(inputs=words, n_bytes=rlp_len + 1);
}
finalize_keccak(keccak_ptr_start, keccak_ptr);
Expand Down
53 changes: 0 additions & 53 deletions src/utils/utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -623,59 +623,6 @@ namespace Helpers {
}
}

// @notice convert bytes to little endian
func bytes_to_bytes8_little_endian{range_check_ptr}(
bytes_len: felt,
bytes: felt*,
index: felt,
size: felt,
bytes8: felt,
bytes8_shift: felt,
dest: felt*,
dest_index: felt,
) {
alloc_locals;
if (index == size) {
return ();
}

local current_byte;
let out_of_bound = is_le(a=bytes_len, b=index);
if (out_of_bound != FALSE) {
current_byte = 0;
} else {
assert current_byte = [bytes + index];
}

let (pow256_address) = get_label_location(pow256_table);
let bit_shift = pow256_address[bytes8_shift];

let _bytes8 = bytes8 + bit_shift * current_byte;

let bytes8_full = is_le(a=7, b=bytes8_shift);
let end_of_loop = is_le(size, index + 1);
let write_to_dest = is_le(1, bytes8_full + end_of_loop);
if (write_to_dest != FALSE) {
assert dest[dest_index] = _bytes8;
return bytes_to_bytes8_little_endian(
bytes_len, bytes, index + 1, size, 0, 0, dest, dest_index + 1
);
}
return bytes_to_bytes8_little_endian(
bytes_len, bytes, index + 1, size, _bytes8, bytes8_shift + 1, dest, dest_index
);

pow256_table:
dw 1;
dw 256;
dw 65536;
dw 16777216;
dw 4294967296;
dw 1099511627776;
dw 281474976710656;
dw 72057594037927936;
}

// @notice transform a felt to big endian bytes
// @param value The initial felt
// @param bytes_len The number of bytes (used for recursion, set to 0)
Expand Down
17 changes: 15 additions & 2 deletions tests/src/utils/test_bytes.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,26 @@
%lang starknet

from starkware.cairo.common.cairo_builtins import HashBuiltin
from starkware.cairo.common.alloc import alloc

from utils.bytes import felt_to_ascii
from utils.bytes import felt_to_ascii, bytes_to_bytes8_little_endian

@external
func test__felt_to_ascii{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
n: felt
) -> (ascii_len: felt, ascii: felt*) {
let (ascii_len, ascii) = felt_to_ascii(n);
alloc_locals;
let (ascii: felt*) = alloc();
let ascii_len = felt_to_ascii(ascii, n);
return (ascii_len, ascii);
}

@external
func test__bytes_to_bytes8_little_endian{
syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr
}(bytes_len: felt, bytes: felt*) -> (res_len: felt, res: felt*) {
alloc_locals;
let (res: felt*) = alloc();
let res_len = bytes_to_bytes8_little_endian(res, bytes_len, bytes);
return (res_len, res);
}
Loading

0 comments on commit 44e849e

Please sign in to comment.