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

Deserialize function in a Serde trait #264

Merged
merged 15 commits into from
May 10, 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
6 changes: 6 additions & 0 deletions ethereum_history_api/circuits/lib/src/account.nr
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ struct AccountWithinBlock {
block_hash: Bytes32,
}

impl Eq for AccountWithinBlock {
fn eq(self, other: Self) -> bool {
(self.account == other.account) & (self.block_hash == other.block_hash)
}
}

type AccountWithStateProof = (Account, StateProof);

pub fn get_account(chain_id: Field, block_no: u64, address: Address) -> AccountWithinBlock {
Expand Down
12 changes: 12 additions & 0 deletions ethereum_history_api/circuits/lib/src/account_with_storage.nr
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ struct Account {
code_hash: Bytes32,
}

impl Eq for Account {
fn eq(self, other: Self) -> bool {
(self.nonce == other.nonce) & (self.balance == other.balance) & (self.storage_root == other.storage_root) & (self.code_hash == other.code_hash)
}
}

struct StateProof {
key: Address,
value: [u8; MAX_ACCOUNT_STATE_LENGTH],
Expand Down Expand Up @@ -43,6 +49,12 @@ struct StorageWithinBlock<N> {
values: [Bytes32; N],
}

impl Eq for StorageWithinBlock<1> {
fn eq(self, other: Self) -> bool {
(self.block_hash == other.block_hash) & (self.account == other.account) & (self.values[0] == other.values[0])
}
}

pub fn get_account_with_storage(
chain_id: Field,
block_number: u64,
Expand Down
4 changes: 2 additions & 2 deletions ethereum_history_api/circuits/lib/src/lib.nr
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ mod log;
mod transaction;
mod misc;
mod chain;
mod serialize;
mod serialize_test;
mod serde;
LogvinovLeon marked this conversation as resolved.
Show resolved Hide resolved
mod serde_test;

mod fixtures;
mod verifiers;
Expand Down
6 changes: 6 additions & 0 deletions ethereum_history_api/circuits/lib/src/misc/fragment.nr
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ impl<MAX_DATA_LEN, T> Fragment<MAX_DATA_LEN, T> {
self.data[self.offset - 1]
}

pub fn pop_front_array<LEN>(&mut self) -> [T; LEN] {
assert(self.length >= LEN as u64, "Cannot pop array: fragment is too short");
let mut res: [T; LEN] = zeroed();
res.map(|_| self.pop_front())
}

pub fn push_back(&mut self, value: T) {
assert(self.offset + self.length + 1 <= MAX_DATA_LEN, "Cannot push: fragment is full");
self.data[self.offset + self.length] = value;
Expand Down
25 changes: 25 additions & 0 deletions ethereum_history_api/circuits/lib/src/misc/fragment_test.nr
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,31 @@ mod pop_front {
}
}

mod pop_front_array {

use crate::misc::fragment::Fragment;

#[test]
fn success() {
let mut fragment = Fragment::new(1, 2, [1, 2, 3]);
assert(fragment.pop_front_array() == [2, 3]);
assert(fragment.length == 0);
}

#[test(should_fail_with="Cannot pop array: fragment is too short")]
fn fail() {
let mut fragment = Fragment::new(1, 1, [1, 2, 3]);
assert(fragment.pop_front_array() == [2]);
assert(fragment.pop_front_array() == [3]);
}
LogvinovLeon marked this conversation as resolved.
Show resolved Hide resolved

#[test(should_fail_with="Cannot pop array: fragment is too short")]
fn partial_fail() {
let mut fragment = Fragment::new(1, 1, [1, 2, 3]);
assert(fragment.pop_front_array() == [2, 3]);
}
}

mod push_back {

use crate::misc::fragment::Fragment;
Expand Down
113 changes: 113 additions & 0 deletions ethereum_history_api/circuits/lib/src/serde.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
use crate::account::AccountWithinBlock;
use crate::account_with_storage::{StorageWithinBlock, Account};
use crate::misc::{fragment::Fragment, types::{BYTES32_LENGTH, Bytes32, ADDRESS_LENGTH, Address}};
use dep::std::unsafe::zeroed;

trait Serde<LEN> {
fn serialize(self) -> [Field; LEN];
fn deserialize(data: [Field; LEN]) -> Self;
}
LogvinovLeon marked this conversation as resolved.
Show resolved Hide resolved

global U128_SERIALIZED_LEN = 2;

impl Serde<U128_SERIALIZED_LEN> for U128 {
fn serialize(self) -> [Field; U128_SERIALIZED_LEN] {
[self.lo, self.hi]
}

fn deserialize(data: [Field; U128_SERIALIZED_LEN]) -> Self {
U128 { lo: data[0], hi: data[1] }
}
}

impl Serde<BYTES32_LENGTH> for Bytes32 {
fn serialize(self) -> [Field; BYTES32_LENGTH] {
self.map(|x: u8| x as Field)
}

fn deserialize(data: [Field; BYTES32_LENGTH]) -> Self {
data.map(|x: Field| x as u8)
}
}

impl Serde<ADDRESS_LENGTH> for Address {
fn serialize(self) -> [Field; ADDRESS_LENGTH] {
self.map(|x: u8| x as Field)
}

fn deserialize(data: [Field; ADDRESS_LENGTH]) -> Self {
data.map(|x: Field| x as u8)
}
}
LogvinovLeon marked this conversation as resolved.
Show resolved Hide resolved

global ACCOUNT_LEN = 1 + 1 + BYTES32_LENGTH + BYTES32_LENGTH;

impl Serde<ACCOUNT_LEN> for Account {
fn serialize(self) -> [Field; ACCOUNT_LEN] {
let mut data: BoundedVec<Field, ACCOUNT_LEN> = BoundedVec::new();
data.push(self.nonce as Field);
data.push(self.balance);
data.extend_from_array(self.storage_root.serialize());
data.extend_from_array(self.code_hash.serialize());
data.storage
}

fn deserialize(data: [Field; ACCOUNT_LEN]) -> Self {
let mut fragment = Fragment::new_focused(data);
let nonce = fragment.pop_front() as u64;
let balance = fragment.pop_front();
let storage_root = fragment.pop_front_array().deserialize();
let code_hash = fragment.pop_front_array().deserialize();
Account {
nonce,
balance,
storage_root,
code_hash,
}
}
}

global ACCOUNT_BLOCK_LEN = ACCOUNT_LEN + BYTES32_LENGTH;

impl Serde<ACCOUNT_BLOCK_LEN> for AccountWithinBlock {
fn serialize(self) -> [Field; ACCOUNT_BLOCK_LEN] {
let mut data: BoundedVec<Field, ACCOUNT_BLOCK_LEN> = BoundedVec::new();
data.extend_from_array(self.account.serialize());
data.extend_from_array(self.block_hash.serialize());
data.storage
}

fn deserialize(data: [Field; ACCOUNT_BLOCK_LEN]) -> Self {
let mut fragment = Fragment::new_focused(data);
let account = Account::deserialize(fragment.pop_front_array());
let block_hash = fragment.pop_front_array().deserialize();
AccountWithinBlock {
account,
block_hash,
}
}
}

global STORAGE_BLOCK_LEN = BYTES32_LENGTH + ACCOUNT_LEN + BYTES32_LENGTH;

impl Serde<STORAGE_BLOCK_LEN> for StorageWithinBlock<1> {
fn serialize(self) -> [Field; STORAGE_BLOCK_LEN] {
let mut data: BoundedVec<Field, STORAGE_BLOCK_LEN> = BoundedVec::new();
data.extend_from_array(self.block_hash.serialize());
data.extend_from_array(self.account.serialize());
data.extend_from_array(self.values[0].serialize());
data.storage
}

fn deserialize(data: [Field; STORAGE_BLOCK_LEN]) -> Self {
let mut fragment = Fragment::new_focused(data);
let block_hash = fragment.pop_front_array().deserialize();
let account = Account::deserialize(fragment.pop_front_array());
let values = [fragment.pop_front_array().deserialize()];
StorageWithinBlock {
block_hash,
account,
values,
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod U128_ {

use crate::serialize::U128_SERIALIZED_LEN;
use crate::serde::U128_SERIALIZED_LEN;

#[test]
fn simple() {
Expand All @@ -9,6 +9,7 @@ mod U128_ {

assert_eq(serialized[0], value.lo);
assert_eq(serialized[1], value.hi);
assert_eq(U128::deserialize(serialized), value);
}
}

Expand All @@ -21,6 +22,7 @@ mod bytes32 {
let serialized: [Field; BYTES32_LENGTH] = bytes.serialize();
let expected: [Field; BYTES32_LENGTH] = [1; BYTES32_LENGTH];
assert_eq(serialized, expected);
assert_eq(serialized.deserialize(), bytes);
}
}

Expand All @@ -33,58 +35,61 @@ mod address {
let serialized: [Field; ADDRESS_LENGTH] = address.serialize();
let expected: [Field; ADDRESS_LENGTH] = [1; ADDRESS_LENGTH];
assert_eq(serialized, expected);
assert_eq(serialized.deserialize(), address);
}
}

mod account {
use crate::account_with_storage::Account;
use crate::serialize::ACCOUNT_SERIALIZED_LEN;
use crate::serde::ACCOUNT_LEN;
use crate::misc::arrays::sub_array_equals;
use crate::fixtures::mainnet::london::vitalik_balance::account::account;

#[test]
fn simple() {
let serialized: [Field; ACCOUNT_SERIALIZED_LEN] = account.serialize();
let serialized: [Field; ACCOUNT_LEN] = account.serialize();

assert_eq(serialized[0], account.nonce as Field);
assert_eq(serialized[1], account.balance);
assert(sub_array_equals(account.storage_root.serialize(), serialized, 2));
assert(sub_array_equals(account.code_hash.serialize(), serialized, 34));
assert_eq(Account::deserialize(serialized), account);
}
}

mod account_within_block {
use crate::serialize::{ACCOUNT_WITHIN_BLOCK_SERIALIZED_LEN, ACCOUNT_SERIALIZED_LEN};
use crate::serde::{ACCOUNT_BLOCK_LEN, ACCOUNT_LEN};
use crate::account::AccountWithinBlock;
use crate::fixtures::mainnet::london::vitalik_balance::{account::account, header::hash};
use crate::misc::arrays::sub_array_equals;

#[test]
fn simple() {
let account_within_block = AccountWithinBlock { account, block_hash: hash };
let serialized: [Field; ACCOUNT_WITHIN_BLOCK_SERIALIZED_LEN] = account_within_block.serialize();
let serialized: [Field; ACCOUNT_BLOCK_LEN] = account_within_block.serialize();

assert(sub_array_equals(account_within_block.account.serialize(), serialized, 0));
assert(
sub_array_equals(
account_within_block.block_hash.serialize(),
serialized,
ACCOUNT_SERIALIZED_LEN
ACCOUNT_LEN
)
);
assert_eq(AccountWithinBlock::deserialize(serialized), account_within_block);
}
}

mod storage_within_block {
use crate::serialize::{STORAGE_WITHIN_BLOCK_1_SERIALIZED_LEN, ACCOUNT_SERIALIZED_LEN};
use crate::serde::{STORAGE_BLOCK_LEN, ACCOUNT_LEN};
use crate::account_with_storage::StorageWithinBlock;
use crate::fixtures::mainnet::paris::usdc_circle::{account::account, header::hash, storage_proof_new::proofs, storage::values};
use crate::misc::{types::BYTES32_LENGTH, arrays::sub_array_equals};

#[test]
fn simple() {
let storage_within_block = StorageWithinBlock { block_hash: hash, account, values };
let serialized: [Field; STORAGE_WITHIN_BLOCK_1_SERIALIZED_LEN] = storage_within_block.serialize();
let serialized: [Field; STORAGE_BLOCK_LEN] = storage_within_block.serialize();

assert(sub_array_equals(storage_within_block.block_hash.serialize(), serialized, 0));
assert(
Expand All @@ -98,8 +103,9 @@ mod storage_within_block {
sub_array_equals(
storage_within_block.values[0].serialize(),
serialized,
BYTES32_LENGTH + ACCOUNT_SERIALIZED_LEN
BYTES32_LENGTH + ACCOUNT_LEN
)
);
assert_eq(StorageWithinBlock::deserialize(serialized), storage_within_block);
}
}
64 changes: 0 additions & 64 deletions ethereum_history_api/circuits/lib/src/serialize.nr

This file was deleted.

Loading