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

refactor: bytes_i_to_uint256 #1042

Merged
merged 16 commits into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/kakarot/instructions/push_operations.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ namespace PushOperations {
let out_of_bounds = is_le(evm.message.bytecode_len, pc + i);
local len = (1 - out_of_bounds) * i + out_of_bounds * (evm.message.bytecode_len - pc);

let stack_element = Helpers.bytes_i_to_uint256(evm.message.bytecode + pc, len);
let stack_element = Helpers.bytes_to_uint256(len, evm.message.bytecode + pc);
Stack.push_uint256(stack_element);

let evm = EVM.increment_program_counter(evm, len);
Expand Down
10 changes: 5 additions & 5 deletions src/kakarot/precompiles/modexp.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ namespace PrecompileModExpUint256 {
let b_size: Uint256 = Helpers.bytes32_to_uint256(input);
let e_size: Uint256 = Helpers.bytes32_to_uint256(input + MOD_EXP_BYTES_LEN);
let m_size: Uint256 = Helpers.bytes32_to_uint256(input + MOD_EXP_BYTES_LEN * 2);
let b: Uint256 = Helpers.bytes_i_to_uint256(input + MOD_EXP_BYTES_LEN * 3, b_size.low);
let e: Uint256 = Helpers.bytes_i_to_uint256(
input + MOD_EXP_BYTES_LEN * 3 + b_size.low, e_size.low
let b: Uint256 = Helpers.bytes_to_uint256(b_size.low, input + MOD_EXP_BYTES_LEN * 3);
let e: Uint256 = Helpers.bytes_to_uint256(
e_size.low, input + MOD_EXP_BYTES_LEN * 3 + b_size.low
);
let m: Uint256 = Helpers.bytes_i_to_uint256(
input + MOD_EXP_BYTES_LEN * 3 + b_size.low + e_size.low, m_size.low
let m: Uint256 = Helpers.bytes_to_uint256(
m_size.low, input + MOD_EXP_BYTES_LEN * 3 + b_size.low + e_size.low
);
with_attr error_message("Kakarot: modexp failed") {
let (result) = ModExpHelpersUint256.uint256_mod_exp(b, e, m);
Expand Down
6 changes: 3 additions & 3 deletions src/utils/eth_transaction.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ namespace EthTransaction {
let destination = Helpers.try_parse_destination_from_bytes(
sub_items[3].data_len, sub_items[3].data
);
let amount = Helpers.bytes_i_to_uint256(sub_items[4].data, sub_items[4].data_len);
let amount = Helpers.bytes_to_uint256(sub_items[4].data_len, sub_items[4].data);
let payload_len = sub_items[5].data_len;
let payload = sub_items[5].data;
let chain_id = Helpers.bytes_to_felt(sub_items[6].data_len, sub_items[6].data);
Expand Down Expand Up @@ -89,7 +89,7 @@ namespace EthTransaction {
let destination = Helpers.try_parse_destination_from_bytes(
sub_items[4].data_len, sub_items[4].data
);
let amount = Helpers.bytes_i_to_uint256(sub_items[5].data, sub_items[5].data_len);
let amount = Helpers.bytes_to_uint256(sub_items[5].data_len, sub_items[5].data);
let payload_len = sub_items[6].data_len;
let payload = sub_items[6].data;

Expand Down Expand Up @@ -140,7 +140,7 @@ namespace EthTransaction {
let destination = Helpers.try_parse_destination_from_bytes(
sub_items[5].data_len, sub_items[5].data
);
let amount = Helpers.bytes_i_to_uint256(sub_items[6].data, sub_items[6].data_len);
let amount = Helpers.bytes_to_uint256(sub_items[6].data_len, sub_items[6].data);
let payload_len = sub_items[7].data_len;
let payload = sub_items[7].data;
let (access_list: felt*) = alloc();
Expand Down
70 changes: 28 additions & 42 deletions src/utils/utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ from starkware.cairo.common.alloc import alloc
from starkware.cairo.common.math import assert_le, split_felt, assert_nn_le, unsigned_div_rem
from starkware.cairo.common.math_cmp import is_le, is_nn
from starkware.cairo.common.memcpy import memcpy
from starkware.cairo.common.pow import pow
from starkware.cairo.common.uint256 import Uint256, uint256_check
from starkware.cairo.common.registers import get_label_location
from starkware.cairo.common.cairo_secp.bigint import BigInt3, bigint_to_uint256, uint256_to_bigint
Expand Down Expand Up @@ -102,36 +101,32 @@ namespace Helpers {
let res = Uint256(low=low, high=high);
return res;
}
// @notice This function is used to convert a sequence of i bytes to Uint256.
// @param val: pointer to the first byte.
// @param i: sequence size.
// @notice This function is used to convert bytes array in big-endian to Uint256.
// @dev The function is limited to 32 bytes or less.
// @param bytes_len: bytes array length.
// @param bytes: pointer to the first byte of the bytes array.
// @return res: Uint256 representation of the given input in bytes.
func bytes_i_to_uint256{range_check_ptr}(val: felt*, i: felt) -> Uint256 {
func bytes_to_uint256{range_check_ptr}(bytes_len: felt, bytes: felt*) -> Uint256 {
alloc_locals;

if (i == 0) {
if (bytes_len == 0) {
let res = Uint256(0, 0);
return res;
}

let is_sequence_32_bytes_or_less = is_le(i, 32);
with_attr error_message("number must be shorter than 32 bytes") {
assert is_sequence_32_bytes_or_less = 1;
}

let is_sequence_16_bytes_or_less = is_le(i, 16);
let is_bytes_len_16_bytes_or_less = is_le(bytes_len, 16);

// 1 - 16 bytes
if (is_sequence_16_bytes_or_less != FALSE) {
let (low) = compute_half_uint256(val=val, i=i, res=0);
if (is_bytes_len_16_bytes_or_less != FALSE) {
let low = bytes_to_felt(bytes_len, bytes);
let res = Uint256(low=low, high=0);

return res;
}

// 17 - 32 bytes
let (low) = compute_half_uint256(val=val + i - 16, i=16, res=0);
let (high) = compute_half_uint256(val=val, i=i - 16, res=0);
let low = bytes_to_felt(16, bytes + bytes_len - 16);
let high = bytes_to_felt(bytes_len - 16, bytes);
let res = Uint256(low=low, high=high);

return res;
Expand Down Expand Up @@ -169,15 +164,6 @@ namespace Helpers {
return (res=quotient);
}

func compute_half_uint256{range_check_ptr}(val: felt*, i: felt, res: felt) -> (res: felt) {
if (i == 1) {
return (res=res + [val]);
}
let (temp_pow) = pow(256, i - 1);
let (res) = compute_half_uint256(val + 1, i - 1, res + [val] * temp_pow);
return (res=res);
}

// @notice This function is used to convert a sequence of 8 bytes to a felt.
// @param val: pointer to the first byte.
// @return: felt representation of the input.
Expand Down Expand Up @@ -316,23 +302,23 @@ namespace Helpers {
return pow256_rev_address[i];

pow256_rev_table:
dw 340282366920938463463374607431768211456;
dw 1329227995784915872903807060280344576;
dw 5192296858534827628530496329220096;
dw 20282409603651670423947251286016;
dw 79228162514264337593543950336;
dw 309485009821345068724781056;
dw 1208925819614629174706176;
dw 4722366482869645213696;
dw 18446744073709551616;
dw 72057594037927936;
dw 281474976710656;
dw 1099511627776;
dw 4294967296;
dw 16777216;
dw 65536;
dw 256;
dw 1;
dw 256 ** 16;
dw 256 ** 15;
dw 256 ** 14;
dw 256 ** 13;
dw 256 ** 12;
dw 256 ** 11;
dw 256 ** 10;
dw 256 ** 9;
dw 256 ** 8;
dw 256 ** 7;
dw 256 ** 6;
dw 256 ** 5;
dw 256 ** 4;
dw 256 ** 3;
dw 256 ** 2;
dw 256 ** 1;
dw 256 ** 0;
}

// @notice Splits a felt into `len` bytes, big-endian, and outputs to `dst`.
Expand Down
33 changes: 9 additions & 24 deletions tests/src/utils/test_utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,19 @@ from starkware.cairo.common.memset import memset
from utils.utils import Helpers
from kakarot.constants import Constants

func test__bytes_i_to_uint256{range_check_ptr}() {
func test__bytes_to_uint256{range_check_ptr}() -> Uint256 {
alloc_locals;

let (bytecode) = alloc();
assert bytecode[0] = 0x01;
assert bytecode[1] = 0x02;

let uint256 = Helpers.bytes_i_to_uint256(bytecode, 1);

assert_uint256_eq(uint256, Uint256(0x01, 0));

let uint256 = Helpers.bytes_i_to_uint256(bytecode, 2);

assert_uint256_eq(uint256, Uint256(0x0102, 0));

let (bytecode) = alloc();
memset(bytecode, 0xFF, 20);
let uint256 = Helpers.bytes_i_to_uint256(bytecode, 20);

assert_uint256_eq(uint256, Uint256(Constants.UINT128_MAX, 0xFFFFFFFF));

let (bytecode) = alloc();
memset(bytecode, 0xFF, 16);
let uint256 = Helpers.bytes_i_to_uint256(bytecode, 16);
tempvar word_len;
let (word) = alloc();
%{
ids.word_len = len(program_input["word"])
segments.write_arg(ids.word, program_input["word"])
%}

assert_uint256_eq(uint256, Uint256(Constants.UINT128_MAX, 0));
let res = Helpers.bytes_to_uint256(word_len, word);

return ();
return res;
}

func test__bytes_to_bytes4_array{range_check_ptr}() {
Expand Down
13 changes: 12 additions & 1 deletion tests/src/utils/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from math import ceil

import pytest
from hypothesis import given, settings
from hypothesis import strategies as st
Expand Down Expand Up @@ -50,13 +52,22 @@
0x726C6400,
],
),
("test__bytes_i_to_uint256", [], []),
],
)
def test_utils(cairo_run, test_case, data, expected):
cairo_run(test_case, data=data, expected=expected)


@given(word=st.integers(min_value=0, max_value=2**256 - 1))
@settings(max_examples=20, deadline=None)
def test_bytes_to_uint256(cairo_run, word):
output = cairo_run(
"test__bytes_to_uint256",
word=int.to_bytes(word, ceil(word.bit_length() / 8), byteorder="big"),
)
assert int(output, 16) == word


@given(word=st.integers(min_value=0, max_value=2**128 - 1))
@settings(max_examples=20, deadline=None)
def test_should_return_bytes_used_in_128_word(cairo_run, word):
Expand Down
Loading