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

memory-page #17

Merged
merged 3 commits into from
Aug 28, 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 .github/workflows/aptos_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ jobs:
with:
version: 4.0.0
- name: test_contract
run: (cd libs && aptos move test --skip-fetch-latest-git-deps --skip-attribute-checks) & (cd verifier && aptos move test --skip-fetch-latest-git-deps --skip-attribute-checks)
run: (cd libs && aptos move test --coverage --dev --skip-fetch-latest-git-deps --skip-attribute-checks) & (cd verifier && aptos move test --coverage --dev --skip-fetch-latest-git-deps --skip-attribute-checks)
58 changes: 1 addition & 57 deletions libs/sources/bytes.move
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,6 @@ module lib_addr::bytes {
use std::vector::{append, for_each_ref};
use aptos_std::from_bcs::to_u256;

// Pads a vector<u8> with a specified byte value up to the desired length
public fun pad(v: vector<u8>, desired_length: u64, pad_byte: u8, pad_left: bool): vector<u8> {
let current_length = vector::length(&v);

if (current_length >= desired_length) {
return v
};

let pad = vector::empty<u8>();
let pad_length = desired_length - current_length;

let i = 0;
while (i < pad_length) {
vector::push_back(&mut pad, pad_byte);
i = i + 1;
};

let padded = vector[];

if (pad_left) {
vector::append(&mut padded, v);
vector::append(&mut padded, pad);
} else {
vector::append(&mut padded, pad);
vector::append(&mut padded, v);
};

return padded
}

public fun reverse(x: vector<u8>): vector<u8> {
let result = vector::empty<u8>();
let length = vector::length(&x);
let i = 0;

while (i < length) {
let byte = vector::borrow(&x, length - 1 - i);
vector::push_back(&mut result, *byte);
i = i + 1;
};

return result
}

public fun vec_to_bytes_be<Element>(v: &vector<Element>): vector<u8> {
let bytes: vector<u8> = vector[];
for_each_ref(v, |e| {
Expand All @@ -73,19 +29,7 @@ module lib_addr::bytes {

#[test_only]
module lib_addr::bytes_test {
use std::bcs::to_bytes;
use std::vector;

use lib_addr::bytes::{pad, vec_to_bytes_be};

#[test]
fun test_padding() {
let value = 0x123456;
let v = to_bytes(&value);
let padded = pad(v, 32, 0x00, true);
assert!(vector::length(&padded) == 32, 1);
assert!(padded == to_bytes(&0x123456u256), 1);
}
use lib_addr::bytes::vec_to_bytes_be;

#[test]
fun test_vec_to_bytes_be() {
Expand Down
4 changes: 4 additions & 0 deletions libs/sources/prime_field_element_0.move
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ module lib_addr::prime_field_element_0 {
res
}

public inline fun fadd(a: u256, b: u256): u256 {
(a + b) % K_MODULUS
}

public inline fun fpow(val: u256, exp: u256): u256 {
expmod(val, exp, K_MODULUS)
}
Expand Down
190 changes: 190 additions & 0 deletions verifier/sources/cpu/memory_page_fact_registry.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
module verifier_addr::memory_page_fact_registry {
use std::vector::{borrow, for_each, length};
use aptos_std::aptos_hash::keccak256;
use aptos_framework::event::emit;

use lib_addr::bytes::{bytes32_to_u256, vec_to_bytes_be};
use lib_addr::prime_field_element_0::{fadd, fmul};
use verifier_addr::fact_registry::register_fact;

// This line is used for generating constants DO NOT REMOVE!
// 1
const CONTINUOUS_PAGE: u256 = 0x1;
// 4
const EINVALID_VALUE_OF_ALPHA: u64 = 0x4;
// 6
const EINVALID_VALUE_OF_START_ADDRESS: u64 = 0x6;
// 3
const EINVALID_VALUE_OF_Z: u64 = 0x3;
// 5
const EPRIME_IS_TOO_BIG: u64 = 0x5;
// 2
const ESIZE_OF_MEMORYPAIRS_MUST_BE_EVEN: u64 = 0x2;
// 1
const ETOO_MANY_MEMORY_VALUES: u64 = 0x1;
// 0
const REGULAR_PAGE: u256 = 0x0;
// 3618502788666131213697322783095070105623107215331596699973092056135872020481
const K_MODULUS: u256 = 0x800000000000011000000000000000000000000000000000000000000000001;
// End of generating constants!

#[event]
struct LogMemorypPageFactRegular has store, drop {
fact_hash: u256,
memory_hash: u256,
prod: u256
}

#[event]
struct LogMemoryPageFactContinuous has store, drop {
fact_hash: vector<u8>,
Draply marked this conversation as resolved.
Show resolved Hide resolved
memory_hash: u256,
prod: u256
}

struct Ptr has key, store {
addr: u256,
value_ptr: u64,
prod: u256
}

public fun register_regular_memorypage(
signer: &signer,
memory_pairs: vector<u256>,
z: u256,
alpha: u256,
prime: u256
): (u256, u256, u256) {
assert!(length(&memory_pairs) < (1 << 20), ETOO_MANY_MEMORY_VALUES);
assert!((length(&memory_pairs) & 1) == 0, ESIZE_OF_MEMORYPAIRS_MUST_BE_EVEN);
assert!(z < prime, EINVALID_VALUE_OF_Z);
assert!(alpha < prime, EINVALID_VALUE_OF_ALPHA);

let (fact_hash, memory_hash, prod) = compute_fact_hash(memory_pairs, z, alpha, prime);
emit(LogMemorypPageFactRegular { fact_hash, memory_hash, prod });

register_fact(signer, fact_hash);
(fact_hash, memory_hash, prod)
}

fun compute_fact_hash(
memory_pairs: vector<u256>,
z: u256,
alpha: u256,
prime: u256
): (u256, u256, u256) {
let n = length(&memory_pairs);
let memory_size = n / 2; // NOLINT: divide-before-multiply.

let prod = 1u256;
let memory_ptr = 0;
while (memory_ptr < n) {
// Compute address + alpha * value.
let address_value_lin_comb = fadd(
// address
*borrow(&memory_pairs, memory_ptr),
fmul(
// value
*borrow(&memory_pairs, memory_ptr + 1),
alpha)
);
prod = fmul(prod, z + prime - address_value_lin_comb);
memory_ptr = memory_ptr + 2;
};

let memory_hash = bytes32_to_u256(keccak256(vec_to_bytes_be(&memory_pairs)));
let fact_hash = bytes32_to_u256(keccak256(
vec_to_bytes_be(&vector[REGULAR_PAGE, prime, (memory_size as u256), z, alpha, prod, memory_hash, 0u256])
));
(fact_hash, memory_hash, prod)
}

/*
Receives a list of MemoryPageEntry. Each element in the list holds arguments for a seperate
call to registerContinuousMemoryPage.
*/
//TODO: assert admin
public entry fun register_continuous_page_batch(
s: &signer,
start_addr: vector<u256>,
values: vector<vector<u256>>,
z: u256,
alpha: u256,
prime: u256
) {
for (i in 0..length(&start_addr) ) {
register_continuous_memorypage(s, *borrow(&start_addr, i), *borrow(&values, i), z, alpha, prime);
}
}
/*
Registers a fact based on the given values, assuming continuous addresses.
values should be [value at startAddr, value at (startAddr + 1), ...].
*/
//TODO: assert admin
public entry fun register_continuous_memorypage(
s: &signer,
start_address: u256,
Draply marked this conversation as resolved.
Show resolved Hide resolved
values: vector<u256>,
z: u256,
alpha: u256,
prime: u256
) {
assert!(length(&values) < (1 << 20), ETOO_MANY_MEMORY_VALUES);
assert!(prime < (1u256 << 254), EPRIME_IS_TOO_BIG);
assert!(z < prime, EINVALID_VALUE_OF_Z);
assert!(alpha < prime, EINVALID_VALUE_OF_ALPHA);
// Ensure 'startAddr' less then prime and bounded as a sanity check (the bound is somewhat arbitrary).
assert!(start_address < prime && start_address < (1u256 << 64), EINVALID_VALUE_OF_START_ADDRESS);

let n_values = (length(&values) as u256);
// Initialize prod to 1.
let prod = 1;
// Initialize valuesPtr to point to the first value in the array.
let value_ptr = 0u64;

let minus_z = (prime - z) % prime;

// Start by processing full batches of 8 cells, addr represents the last address in each
// batch.
let addr = start_address + 7;
let last_addr = start_address + n_values;

while (addr < last_addr) {
// Compute the product of (lin_comb - z) instead of (z - lin_comb), since we're
// doing an even number of iterations, the result is the same.
for_each(vector[0u64, 2u64, 4u64, 6u64], |offset| {
prod = fmul(prod,
fmul(
addr - 7 + (offset as u256) + fmul(alpha, *borrow(&values, value_ptr + offset)) + minus_z,
addr - 7 + (offset as u256) + 1 + fmul(
alpha,
*borrow(&values, value_ptr + offset + 1)
) + minus_z
));
});
value_ptr = value_ptr + 8;
addr = addr + 8;
};

// Handle leftover.
// Translate addr to the beginning of the last incomplete batch.
addr = addr - 7;
while (addr < last_addr) {
let address_value_lin_comb = fadd(addr, fmul(*borrow(&values, value_ptr), alpha));
prod = fmul(prod, z + prime - address_value_lin_comb);
addr = addr + 1;
value_ptr = value_ptr + 1;
};

let memory_hash = bytes32_to_u256(keccak256(vec_to_bytes_be(&values)));
let fact_hash = keccak256(
vec_to_bytes_be(&vector[CONTINUOUS_PAGE, prime, n_values, z, alpha, prod, memory_hash, start_address])
);
emit(LogMemoryPageFactContinuous {
fact_hash,
memory_hash,
prod
});
register_fact(s, bytes32_to_u256(fact_hash));
}
}
51 changes: 51 additions & 0 deletions verifier/sources/test/test_memory_page_fact_registry.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#[test_only]
module verifier_addr::mpfr_test {
use std::signer::address_of;

use verifier_addr::fact_registry::is_valid;
use verifier_addr::memory_page_fact_registry::{register_continuous_memorypage,
register_continuous_page_batch
};

#[test(signer = @verifier_addr)]
fun test_register_continuous_memorypage(signer: &signer) {
register_continuous_memorypage(
signer,
2971260,
vector[
1723587082856532763241173775465496577348305577532331450336061658809521876102,
2479248348687909740970436565718726357572221543762678024250834744245756360726,
587272,
2177570517647428816133395681679456086343281988787809822104528418476218261377,
2590421891839256512113614983194993186457498815986333310670788206383913888162,
0,
0
],
3035248388910680138215389260643346358343414931640145853107361271346254998038,
220574768071472005565941019352306850224879407895315608807402130378653737764,
3618502788666131213697322783095070105623107215331596699973092056135872020481
);
}

#[test(s = @verifier_addr)]
// Transaction hash on ETH mainnet for this test: 0x6f59bed6f3df4b87c03c49f11e627e842ae5708a3670f428ddfb83c5b98d3754.
fun test_register_continuous_page_batch(s: &signer) {
register_continuous_page_batch(
s,
vector[1771799, 1771808],
vector[vector[1007, 1006, 1005, 1004, 1003, 1002, 1001],
vector[1008, 1007, 1006, 1005, 1004, 1003, 1002, 1001]],
3199940278565943790978406278706496237292797978280982699986488410844249594708,
195072032121178106591923000375621188629735561133807175660265096969353999946,
3618502788666131213697322783095070105623107215331596699973092056135872020481
);
is_valid(
address_of(s),
49238381412124717490517111631696093427076824100526472039743966257691104387218
);
is_valid(
address_of(s),
54205816271920378481316162362155116341907231556132238625024261418992095639341
);
}
}
Loading