Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate slots to U256 #328

Merged
merged 13 commits into from
Jun 10, 2024
35 changes: 35 additions & 0 deletions ethereum/circuits/lib/src/uint256.nr
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use dep::std::ops::Add;
use crate::misc::types::Bytes32;
use crate::misc::bytes32::field_to_bytes32;
use crate::misc::arrays::memcpy_up_to_length;

global uint128_overflow_value = 340282366920938463463374607431768211456; // 2^128

Expand All @@ -19,6 +22,38 @@ impl U256 {
fn one() -> Self {
Self { high: U128::from_integer(0), low: U128::from_integer(1) }
}

fn from_field(field: Field) -> Self {
U256::from(field_to_bytes32(field))
}
}

impl From<Bytes32> for U256 {
fn from(bytes: Bytes32) -> Self {
let mut high_bytes = [0; 16];
memcpy_up_to_length(&mut high_bytes, bytes, 16, 16);
let high = U128::from_le_bytes(high_bytes);

let mut low_bytes = [0; 16];
memcpy_up_to_length(&mut low_bytes, bytes, 0, 16);
let low = U128::from_le_bytes(low_bytes);

U256::new(high, low)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not inline?

}

impl Into<Bytes32> for U256 {
fn into(self) -> Bytes32 {
let mut bytes = [0; 32];
memcpy_up_to_length(&mut bytes, self.low.to_le_bytes(), 0, 16);

let high_bytes = self.high.to_le_bytes();
for i in 0..16 {
bytes[i + 16] = high_bytes[i];
}

bytes
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not inline?

}

impl Eq for U256 {
Expand Down
97 changes: 82 additions & 15 deletions ethereum/circuits/lib/src/uint256_test.nr
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,64 @@ fn zero_and_one() {
assert_eq(one.low, U128::one());
}

mod from_bytes32 {
use crate::uint256::U256;
global high = U128::from_integer(0x10000000000000000000000000000000);
global low = U128::zero();
global limit = U128::from_integer(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);

global big_number = U256 { high, low };
global limit_u256 = U256 {high: limit, low:limit};

#[test]
fn zero() {
let bytes = [0x00; 32];
assert_eq(U256::from(bytes), U256::zero());
}

#[test]
fn success() {
let mut bytes = [0x00; 32];
bytes[31] = 0x10;
assert_eq(U256::from(bytes), big_number);
}

#[test]
fn u256_limit() {
let bytes = [0xff; 32];
assert_eq(U256::from(bytes), limit_u256);
}
}

mod into_bytes32 {
use crate::uint256::U256;
global high = U128::from_integer(0x10000000000000000000000000000000);
global low = U128::zero();
global limit = U128::from_integer(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);

global big_number = U256 { high, low };
global limit_u256 = U256 {high: limit, low:limit};

#[test]
fn zero() {
let bytes = [0x00; 32];
assert_eq(U256::into(U256::zero()), bytes);
}

#[test]
fn success() {
let mut bytes = [0x00; 32];
bytes[31] = 0x10;
assert_eq(U256::into(big_number), bytes);
}

#[test]
fn u256_limit() {
let bytes = [0xff; 32];
assert_eq(U256::into(limit_u256), bytes);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more tests pls :)


#[test]
fn eq() {
assert_eq(big_number, big_number);
Expand All @@ -47,23 +105,32 @@ fn not_eq() {
assert(big_number != big_number3);
}

#[test]
fn sum() {
let sum = big_number + big_number;
mod trait_add {
use crate::uint256::U256;
global high = U128::from_integer(0x10000000000000000000000000000000);
global low = U128::zero();
global limit = U128::from_integer(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);

assert_eq(sum, U256 { high: U128::from_integer(0x20000000000000000000000000000000), low });
}
global big_number = U256 { high, low };
global limit_u256 = U256 {high: limit, low:limit};

#[test]
fn sum_with_carry() {
let big_number = U256 { high, low: limit };
let sum = big_number + U256::one();
#[test]
fn sum() {
let sum = big_number + big_number;

assert_eq(sum, U256 { high: U128::from_integer(0x10000000000000000000000000000001), low });
}
assert_eq(sum, U256 { high: U128::from_integer(0x20000000000000000000000000000000), low });
}

#[test]
fn sum_with_carry() {
let big_number = U256 { high, low: limit };
let sum = big_number + U256::one();

assert_eq(sum, U256 { high: U128::from_integer(0x10000000000000000000000000000001), low });
}

#[test(should_fail_with="attempt to add with overflow")]
fn sum_overflow() {
let limit_number = U256 { high: limit, low: limit };
let _ = limit_number + U256::one();
#[test(should_fail_with="attempt to add with overflow")]
fn sum_overflow() {
let _ = limit_u256 + U256::one();
}
}
7 changes: 4 additions & 3 deletions vlayer/ethereum/circuits/lib/src/nft.nr
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use dep::ethereum::{
account_with_storage::get_account_with_storage,
misc::types::{Address, Bytes32, ADDRESS_LENGTH, BYTES32_LENGTH}, misc::arrays::subarray_inferred_len
misc::{types::{Address, Bytes32, ADDRESS_LENGTH, BYTES32_LENGTH}, arrays::subarray_inferred_len},
uint256::U256
};

struct ERC721Token {
address: Address,
token_id_to_slot: fn (Bytes32) -> Bytes32,
token_id_to_slot: fn (Bytes32) -> U256,
chain_id: Field
}

Expand All @@ -16,7 +17,7 @@ trait ERC721 {
impl ERC721 for ERC721Token {
fn get_owner(self, token_id: Bytes32, block_number: u64) -> Address {
let storage_key = (self.token_id_to_slot)(token_id);
let account = get_account_with_storage(self.chain_id, block_number, self.address, storage_key);
let account = get_account_with_storage(self.chain_id, block_number, self.address, U256::into(storage_key));
subarray_inferred_len(account.values[0], BYTES32_LENGTH - ADDRESS_LENGTH)
}
}
14 changes: 7 additions & 7 deletions vlayer/ethereum/circuits/lib/src/nft_list.nr
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ mod mainnet {
use crate::chain_id;
use crate::slot::{struct_slot, dynamic_array_with_precalculated_slot, mapping};
use dep::std::field::bytes32_to_field;
use dep::ethereum::misc::{types::Bytes32, bytes32::field_to_bytes32};
use dep::ethereum::{misc::{types::Bytes32, bytes32::field_to_bytes32}, uint256::U256};

pub fn BORED_APE_YACHT_CLUB() -> ERC721Token {
ERC721Token {
Expand All @@ -12,9 +12,9 @@ mod mainnet {
],
token_id_to_slot: |token_id| {
let BORED_APE_YACHT_CLUB_MAX_TOKEN_ID: u64 = 9999;
let BORED_APE_YACHT_CLUB_TOKEN_OWNERS_INNER_ENTRIES_SLOT = [
let BORED_APE_YACHT_CLUB_TOKEN_OWNERS_INNER_ENTRIES_SLOT = U256::from([
0x40, 0x57, 0x87, 0xfa, 0x12, 0xa8, 0x23, 0xe0, 0xf2, 0xb7, 0x63, 0x1c, 0xc4, 0x1b, 0x3b, 0xa8, 0x82, 0x8b, 0x33, 0x21, 0xca, 0x81, 0x11, 0x11, 0xfa, 0x75, 0xcd, 0x3a, 0xa3, 0xbb, 0x5a, 0xce
];
]);
let VALUE_INDEX = 1;

assert(bytes32_to_field(token_id) as u64 <= BORED_APE_YACHT_CLUB_MAX_TOKEN_ID, "Token ID is too high");
Expand All @@ -32,7 +32,7 @@ mod mainnet {
],
token_id_to_slot: |token_id| {
let CRYPTO_PUNK_MAX_TOKEN_ID: u64 = 9999;
let CRYPTO_PUNK_TOKEN_OWNERS_INNER_ENTRIES_SLOT = field_to_bytes32(10);
let CRYPTO_PUNK_TOKEN_OWNERS_INNER_ENTRIES_SLOT = U256::from_field(10);

assert(bytes32_to_field(token_id) as u64 <= CRYPTO_PUNK_MAX_TOKEN_ID, "Token ID is too high");
mapping(CRYPTO_PUNK_TOKEN_OWNERS_INNER_ENTRIES_SLOT, token_id)
Expand All @@ -47,7 +47,7 @@ mod sepolia {
use crate::chain_id;
use crate::slot::{struct_slot, dynamic_array_with_precalculated_slot};
use dep::std::field::bytes32_to_field;
use dep::ethereum::misc::{types::Bytes32, bytes32::field_to_bytes32};
use dep::ethereum::{misc::{types::Bytes32, bytes32::field_to_bytes32}, uint256::U256};

// free mint: https://sepolia.etherscan.io/address/0x80d97726548fedae6ad7cf8df4f2b514fd24afba#readContract
fn FAKE_BORED_APE_YACHT_CLUB() -> ERC721Token {
Expand All @@ -57,9 +57,9 @@ mod sepolia {
],
token_id_to_slot: |token_id| {
let BORED_APE_YACHT_CLUB_MAX_TOKEN_ID: u64 = 9999;
let BORED_APE_YACHT_CLUB_TOKEN_OWNERS_INNER_ENTRIES_SLOT = [
let BORED_APE_YACHT_CLUB_TOKEN_OWNERS_INNER_ENTRIES_SLOT = U256::from([
0x40, 0x57, 0x87, 0xfa, 0x12, 0xa8, 0x23, 0xe0, 0xf2, 0xb7, 0x63, 0x1c, 0xc4, 0x1b, 0x3b, 0xa8, 0x82, 0x8b, 0x33, 0x21, 0xca, 0x81, 0x11, 0x11, 0xfa, 0x75, 0xcd, 0x3a, 0xa3, 0xbb, 0x5a, 0xce
];
]);
let VALUE_INDEX = 1;

assert(bytes32_to_field(token_id) as u64 <= BORED_APE_YACHT_CLUB_MAX_TOKEN_ID, "Token ID is too high");
Expand Down
19 changes: 10 additions & 9 deletions vlayer/ethereum/circuits/lib/src/slot.nr
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary import bytes32::field_to_bytes32 can be removed

Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,26 @@ use dep::ethereum::misc::{
bytes::add_bigint
};
use dep::std::hash::keccak256;
use dep::ethereum::uint256::U256;

global STORAGE_KEY_HASH_INPUT_LENGTH = 64;

pub(crate) fn mapping(slot: Bytes32, key: Bytes32) -> Bytes32 {
pub(crate) fn mapping(slot: U256, key: Bytes32) -> U256 {
let mut vector: BoundedVec<u8, STORAGE_KEY_HASH_INPUT_LENGTH> = BoundedVec::new();
vector.extend_from_array(key);
vector.extend_from_array(slot);
keccak256(vector.storage(), STORAGE_KEY_HASH_INPUT_LENGTH)
vector.extend_from_array(U256::into(slot));
U256::from(keccak256(vector.storage(), STORAGE_KEY_HASH_INPUT_LENGTH))
}

pub(crate) fn dynamic_array(slot: Bytes32, size: Field, index: Field) -> Bytes32 {
let start = keccak256(slot, 32);
pub(crate) fn dynamic_array(slot: U256, size: Field, index: Field) -> U256 {
let start: U256 = U256::from(keccak256(U256::into(slot), 32));
dynamic_array_with_precalculated_slot(start, size, index)
}

pub(crate) fn dynamic_array_with_precalculated_slot(slot: Bytes32, size: Field, index: Field) -> Bytes32 {
add_bigint(slot, field_to_bytes32(size * index))
pub(crate) fn dynamic_array_with_precalculated_slot(slot: U256, size: Field, index: Field) -> U256 {
slot + U256::from_field(size * index)
}

pub(crate) fn struct_slot(slot: Bytes32, offset: Field) -> Bytes32 {
add_bigint(slot, field_to_bytes32(offset))
pub(crate) fn struct_slot(slot: U256, offset: Field) -> U256 {
slot + U256::from_field(offset)
}
Loading
Loading