-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- We need to access this normally with a feature gate, but just to rush getting something going, we're going to copy it in for now.
- Loading branch information
Showing
8 changed files
with
746 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
use std::ops::Add; | ||
|
||
use ethereum_types::{BigEndianHash, H256, U256}; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
pub type Bit = bool; | ||
|
||
#[derive( | ||
Copy, Clone, Deserialize, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Debug, | ||
)] | ||
pub struct Bits { | ||
/// The number of bits in this sequence. | ||
pub count: usize, | ||
/// A packed encoding of these bits. Only the first (least significant) | ||
/// `count` bits are used. The rest are unused and should be zero. | ||
pub packed: U256, | ||
} | ||
|
||
impl From<U256> for Bits { | ||
fn from(packed: U256) -> Self { | ||
Bits { count: 256, packed } | ||
} | ||
} | ||
|
||
impl From<H256> for Bits { | ||
fn from(packed: H256) -> Self { | ||
Bits { | ||
count: 256, | ||
packed: packed.into_uint(), | ||
} | ||
} | ||
} | ||
|
||
impl Add for Bits { | ||
type Output = Self; | ||
|
||
fn add(self, rhs: Self) -> Self::Output { | ||
assert!(self.count + rhs.count <= 256, "Overflow"); | ||
Self { | ||
count: self.count + rhs.count, | ||
packed: self.packed * (U256::one() << rhs.count) + rhs.packed, | ||
} | ||
} | ||
} | ||
|
||
impl Bits { | ||
pub fn empty() -> Self { | ||
Bits { | ||
count: 0, | ||
packed: U256::zero(), | ||
} | ||
} | ||
|
||
pub fn is_empty(&self) -> bool { | ||
self.count == 0 | ||
} | ||
|
||
pub fn pop_next_bit(&mut self) -> Bit { | ||
assert!(!self.is_empty(), "Cannot pop from empty bits"); | ||
let b = !(self.packed & U256::one()).is_zero(); | ||
self.packed >>= 1; | ||
self.count -= 1; | ||
b | ||
} | ||
|
||
pub fn get_bit(&self, i: usize) -> Bit { | ||
assert!(i < self.count, "Index out of bounds"); | ||
!(self.packed & (U256::one() << (self.count - 1 - i))).is_zero() | ||
} | ||
|
||
pub fn push_bit(&mut self, bit: Bit) { | ||
self.packed = self.packed * 2 + U256::from(bit as u64); | ||
self.count += 1; | ||
} | ||
|
||
pub fn add_bit(&self, bit: Bit) -> Self { | ||
let mut x = *self; | ||
x.push_bit(bit); | ||
x | ||
} | ||
|
||
pub fn common_prefix(&self, k: &Bits) -> (Self, Option<(Bit, Bit)>) { | ||
let mut a = *self; | ||
let mut b = *k; | ||
while a.count > b.count { | ||
a.pop_next_bit(); | ||
} | ||
while a.count < b.count { | ||
b.pop_next_bit(); | ||
} | ||
if a == b { | ||
return (a, None); | ||
} | ||
let mut a_bit = a.pop_next_bit(); | ||
let mut b_bit = b.pop_next_bit(); | ||
while a != b { | ||
a_bit = a.pop_next_bit(); | ||
b_bit = b.pop_next_bit(); | ||
} | ||
assert_ne!(a_bit, b_bit, "Sanity check."); | ||
(a, Some((a_bit, b_bit))) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
use std::collections::HashMap; | ||
|
||
use super::smt::{Key, Node}; | ||
|
||
pub trait Db: Default { | ||
fn get_node(&self, key: &Key) -> Option<&Node>; | ||
fn set_node(&mut self, key: Key, value: Node); | ||
} | ||
|
||
#[derive(Debug, Clone, Default)] | ||
pub struct MemoryDb { | ||
pub db: HashMap<Key, Node>, | ||
} | ||
|
||
impl Db for MemoryDb { | ||
fn get_node(&self, key: &Key) -> Option<&Node> { | ||
self.db.get(key) | ||
} | ||
|
||
fn set_node(&mut self, key: Key, value: Node) { | ||
self.db.insert(key, value); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
#![allow(clippy::needless_range_loop)] | ||
|
||
/// This module contains functions to generate keys for the SMT. | ||
/// See https://github.com/0xPolygonHermez/zkevm-commonjs/blob/main/src/smt-utils.js for reference implementation. | ||
use ethereum_types::{Address, U256}; | ||
use plonky2::{field::types::Field, hash::poseidon::Poseidon}; | ||
|
||
use super::smt::{Key, F}; | ||
|
||
const HASH_ZEROS: [u64; 4] = [ | ||
4330397376401421145, | ||
14124799381142128323, | ||
8742572140681234676, | ||
14345658006221440202, | ||
]; | ||
|
||
const SMT_KEY_BALANCE: u64 = 0; | ||
const SMT_KEY_NONCE: u64 = 1; | ||
const SMT_KEY_CODE: u64 = 2; | ||
const SMT_KEY_STORAGE: u64 = 3; | ||
const SMT_KEY_LENGTH: u64 = 4; | ||
|
||
pub fn key_balance(addr: Address) -> Key { | ||
let mut arr = [F::ZERO; 12]; | ||
for i in 0..5 { | ||
arr[i] = F::from_canonical_u32(u32::from_be_bytes( | ||
addr.0[16 - 4 * i..16 - 4 * i + 4].try_into().unwrap(), | ||
)); | ||
} | ||
|
||
arr[6] = F::from_canonical_u64(SMT_KEY_BALANCE); | ||
arr[8..12].copy_from_slice(&HASH_ZEROS.map(F::from_canonical_u64)); | ||
|
||
Key(F::poseidon(arr)[0..4].try_into().unwrap()) | ||
} | ||
|
||
pub fn key_nonce(addr: Address) -> Key { | ||
let mut arr = [F::ZERO; 12]; | ||
for i in 0..5 { | ||
arr[i] = F::from_canonical_u32(u32::from_be_bytes( | ||
addr.0[16 - 4 * i..16 - 4 * i + 4].try_into().unwrap(), | ||
)); | ||
} | ||
|
||
arr[6] = F::from_canonical_u64(SMT_KEY_NONCE); | ||
arr[8..12].copy_from_slice(&HASH_ZEROS.map(F::from_canonical_u64)); | ||
|
||
Key(F::poseidon(arr)[0..4].try_into().unwrap()) | ||
} | ||
|
||
pub fn key_code(addr: Address) -> Key { | ||
let mut arr = [F::ZERO; 12]; | ||
for i in 0..5 { | ||
arr[i] = F::from_canonical_u32(u32::from_be_bytes( | ||
addr.0[16 - 4 * i..16 - 4 * i + 4].try_into().unwrap(), | ||
)); | ||
} | ||
|
||
arr[6] = F::from_canonical_u64(SMT_KEY_CODE); | ||
arr[8..12].copy_from_slice(&HASH_ZEROS.map(F::from_canonical_u64)); | ||
|
||
Key(F::poseidon(arr)[0..4].try_into().unwrap()) | ||
} | ||
|
||
pub fn key_storage(addr: Address, slot: U256) -> Key { | ||
let mut arr = [F::ZERO; 12]; | ||
for i in 0..5 { | ||
arr[i] = F::from_canonical_u32(u32::from_be_bytes( | ||
addr.0[16 - 4 * i..16 - 4 * i + 4].try_into().unwrap(), | ||
)); | ||
} | ||
|
||
arr[6] = F::from_canonical_u64(SMT_KEY_STORAGE); | ||
let capacity: [F; 4] = { | ||
let mut arr = [F::ZERO; 12]; | ||
for i in 0..4 { | ||
arr[2 * i] = F::from_canonical_u32(slot.0[i] as u32); | ||
arr[2 * i + 1] = F::from_canonical_u32((slot.0[i] >> 32) as u32); | ||
} | ||
F::poseidon(arr)[0..4].try_into().unwrap() | ||
}; | ||
arr[8..12].copy_from_slice(&capacity); | ||
|
||
Key(F::poseidon(arr)[0..4].try_into().unwrap()) | ||
} | ||
|
||
pub fn key_code_length(addr: Address) -> Key { | ||
let mut arr = [F::ZERO; 12]; | ||
for i in 0..5 { | ||
arr[i] = F::from_canonical_u32(u32::from_be_bytes( | ||
addr.0[16 - 4 * i..16 - 4 * i + 4].try_into().unwrap(), | ||
)); | ||
} | ||
|
||
arr[6] = F::from_canonical_u64(SMT_KEY_LENGTH); | ||
arr[8..12].copy_from_slice(&HASH_ZEROS.map(F::from_canonical_u64)); | ||
|
||
Key(F::poseidon(arr)[0..4].try_into().unwrap()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
//! REMOVE THIS MODULE BEFORE MERGING INTO DEVELOP!!! THIS IS ONLY INTENDED TO | ||
//! PUT OFF THE HARD TASK OF FEATURE GATING THE BRANCH `feat/type2`!! | ||
mod bits; | ||
mod db; | ||
pub(crate) mod keys; | ||
pub(crate) mod smt; | ||
mod utils; |
Oops, something went wrong.