Skip to content

Commit

Permalink
refacto: use common felt type
Browse files Browse the repository at this point in the history
  • Loading branch information
0xLucqs committed Feb 1, 2024
1 parent b70d655 commit 5bc6bb6
Show file tree
Hide file tree
Showing 13 changed files with 201 additions and 476 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ starknet-crypto = "0.5.1"
strum = "0.24.1"
strum_macros = "0.24.3"
thiserror = "1.0.31"
starknet-types-core = { git = "https://github.com/starknet-io/types-rs/", branch = "lucas/sw", features = ["hash", "serde", "num-traits", "papyrus-encoding"] }
num-traits = { version = "0.2.16", default-features = false }

[dev-dependencies]
assert_matches = "1.5.0"
10 changes: 6 additions & 4 deletions src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ mod block_test;

use derive_more::Display;
use serde::{Deserialize, Serialize};
use starknet_types_core::felt::Felt;
use starknet_types_core::hash::Poseidon;
use starknet_types_core::hash::StarkHash as StarkHashTrait;

use crate::core::{ContractAddress, GlobalRoot, SequencerPublicKey};
use crate::crypto::{verify_message_hash_signature, CryptoError, Signature};
use crate::hash::{poseidon_hash_array, StarkHash};
use crate::serde_utils::{BytesAsHex, PrefixedBytesAsHex};
use crate::transaction::{Transaction, TransactionHash, TransactionOutput};

Expand Down Expand Up @@ -75,7 +77,7 @@ pub enum BlockStatus {
Ord,
Display,
)]
pub struct BlockHash(pub StarkHash);
pub struct BlockHash(pub Felt);

/// The number of a [Block](`crate::block::Block`).
#[derive(
Expand Down Expand Up @@ -158,8 +160,8 @@ pub fn verify_block_signature(
state_diff_commitment: &GlobalRoot,
block_hash: &BlockHash,
) -> Result<bool, BlockVerificationError> {
let message_hash = poseidon_hash_array(&[block_hash.0, state_diff_commitment.0]);
verify_message_hash_signature(&message_hash.0, &signature.0, &sequencer_pub_key.0).map_err(
let message_hash = Poseidon::hash_array(&[block_hash.0, state_diff_commitment.0]);
verify_message_hash_signature(&message_hash, &signature.0, &sequencer_pub_key.0).map_err(
|err| BlockVerificationError::BlockSignatureVerificationFailed {
block_hash: *block_hash,
error: err,
Expand Down
35 changes: 19 additions & 16 deletions src/block_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ use super::verify_block_signature;
use crate::block::{BlockHash, BlockNumber, BlockSignature};
use crate::core::{GlobalRoot, SequencerPublicKey};
use crate::crypto::{PublicKey, Signature};
use crate::hash::StarkFelt;
use crate::stark_felt;
use starknet_types_core::felt::Felt;

#[test]
fn test_block_number_iteration() {
Expand All @@ -29,21 +28,25 @@ fn test_block_number_iteration() {
#[test]
fn block_signature_verification() {
// Values taken from Mainnet.
let block_hash =
BlockHash(stark_felt!("0x7d5db04c5ca2aea828180dc441afb1580e3cee7547a3567ced3aa5bb8b273c0"));
let state_commitment = GlobalRoot(stark_felt!(
"0x64689c12248e1110af4b3af0e2b43cd51ad13e8855f10e37669e2a4baf919c6"
));
let block_hash = BlockHash(
Felt::from_hex("0x7d5db04c5ca2aea828180dc441afb1580e3cee7547a3567ced3aa5bb8b273c0")
.unwrap(),
);
let state_commitment = GlobalRoot(
Felt::from_hex("0x64689c12248e1110af4b3af0e2b43cd51ad13e8855f10e37669e2a4baf919c6")
.unwrap(),
);
let signature = BlockSignature(Signature {
r: stark_felt!("0x1b382bbfd693011c9b7692bc932b23ed9c288deb27c8e75772e172abbe5950c"),
s: stark_felt!("0xbe4438085057e1a7c704a0da3b30f7b8340fe3d24c86772abfd24aa597e42"),
r: Felt::from_hex("0x1b382bbfd693011c9b7692bc932b23ed9c288deb27c8e75772e172abbe5950c")
.unwrap(),
s: Felt::from_hex("0xbe4438085057e1a7c704a0da3b30f7b8340fe3d24c86772abfd24aa597e42")
.unwrap(),
});
let sequencer_pub_key = SequencerPublicKey(PublicKey(stark_felt!(
"0x48253ff2c3bed7af18bde0b611b083b39445959102d4947c51c4db6aa4f4e58"
)));
let sequencer_pub_key = SequencerPublicKey(PublicKey(
Felt::from_hex("0x48253ff2c3bed7af18bde0b611b083b39445959102d4947c51c4db6aa4f4e58")
.unwrap(),
));

assert!(
verify_block_signature(&sequencer_pub_key, &signature, &state_commitment, &block_hash)
.unwrap()
);
assert!(verify_block_signature(&sequencer_pub_key, &signature, &state_commitment, &block_hash)
.unwrap());
}
99 changes: 51 additions & 48 deletions src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ use derive_more::Display;
use once_cell::sync::Lazy;
use primitive_types::H160;
use serde::{Deserialize, Serialize};
use starknet_crypto::FieldElement;
use starknet_types_core::felt::Felt;
use starknet_types_core::hash::{Pedersen, StarkHash as StarkHashTrait};

use crate::crypto::PublicKey;
use crate::hash::{pedersen_hash_array, StarkFelt, StarkHash};
use crate::serde_utils::{BytesAsHex, PrefixedBytesAsHex};
use crate::transaction::{Calldata, ContractAddressSalt};
use crate::{impl_from_through_intermediate, StarknetApiError};
Expand All @@ -32,7 +32,7 @@ impl ChainId {
// The block hash table is stored in address 0x1,
// this is a special address that is not used for contracts.
pub const BLOCK_HASH_TABLE_ADDRESS: ContractAddress = ContractAddress(PatriciaKey(StarkHash::ONE));
pub const BLOCK_HASH_TABLE_ADDRESS: ContractAddress = ContractAddress(PatriciaKey(Felt::ONE));
#[derive(
Debug,
Default,
Expand All @@ -49,9 +49,9 @@ pub const BLOCK_HASH_TABLE_ADDRESS: ContractAddress = ContractAddress(PatriciaKe
)]
pub struct ContractAddress(pub PatriciaKey);

impl From<ContractAddress> for StarkFelt {
fn from(contract_address: ContractAddress) -> StarkFelt {
**contract_address
impl From<ContractAddress> for Felt {
fn from(contract_address: ContractAddress) -> Felt {
contract_address.0.to_felt()
}
}

Expand All @@ -66,20 +66,19 @@ impl_from_through_intermediate!(u128, ContractAddress, u8, u16, u32, u64);
/// The maximal size of storage var.
pub const MAX_STORAGE_ITEM_SIZE: u16 = 256;
/// The prefix used in the calculation of a contract address.
pub const CONTRACT_ADDRESS_PREFIX: &str = "STARKNET_CONTRACT_ADDRESS";
pub const CONTRACT_ADDRESS_PREFIX: &[u8] = b"STARKNET_CONTRACT_ADDRESS";
/// The size of the contract address domain.
pub static CONTRACT_ADDRESS_DOMAIN_SIZE: Lazy<StarkFelt> = Lazy::new(|| {
StarkFelt::try_from(PATRICIA_KEY_UPPER_BOUND)
pub static CONTRACT_ADDRESS_DOMAIN_SIZE: Lazy<Felt> = Lazy::new(|| {
Felt::from_hex(PATRICIA_KEY_UPPER_BOUND)
.unwrap_or_else(|_| panic!("Failed to convert {PATRICIA_KEY_UPPER_BOUND} to StarkFelt"))
});
/// The address upper bound; it is defined to be congruent with the storage var address upper bound.
pub static L2_ADDRESS_UPPER_BOUND: Lazy<FieldElement> = Lazy::new(|| {
FieldElement::from(*CONTRACT_ADDRESS_DOMAIN_SIZE) - FieldElement::from(MAX_STORAGE_ITEM_SIZE)
});
pub static L2_ADDRESS_UPPER_BOUND: Lazy<Felt> =
Lazy::new(|| Felt::from(*CONTRACT_ADDRESS_DOMAIN_SIZE) - Felt::from(MAX_STORAGE_ITEM_SIZE));

impl TryFrom<StarkHash> for ContractAddress {
impl TryFrom<Felt> for ContractAddress {
type Error = StarknetApiError;
fn try_from(hash: StarkHash) -> Result<Self, Self::Error> {
fn try_from(hash: Felt) -> Result<Self, Self::Error> {
Ok(Self(PatriciaKey::try_from(hash)?))
}
}
Expand All @@ -91,18 +90,19 @@ pub fn calculate_contract_address(
constructor_calldata: &Calldata,
deployer_address: ContractAddress,
) -> Result<ContractAddress, StarknetApiError> {
let constructor_calldata_hash = pedersen_hash_array(&constructor_calldata.0);
let contract_address_prefix = format!("0x{}", hex::encode(CONTRACT_ADDRESS_PREFIX));
let mut address = FieldElement::from(pedersen_hash_array(&[
StarkFelt::try_from(contract_address_prefix.as_str())?,
*deployer_address.0.key(),
let constructor_calldata_hash = Pedersen::hash_array(&constructor_calldata.0);
let address: Felt = (&(Pedersen::hash_array(&[
Felt::from_bytes_be_slice(CONTRACT_ADDRESS_PREFIX),
deployer_address.to_felt(),
salt.0,
class_hash.0,
constructor_calldata_hash,
]));
address = address % *L2_ADDRESS_UPPER_BOUND;
])
.to_biguint()
% L2_ADDRESS_UPPER_BOUND.to_biguint()))
.into();

ContractAddress::try_from(StarkFelt::from(address))
ContractAddress::try_from(address)
}

/// The hash of a ContractClass.
Expand All @@ -121,7 +121,7 @@ pub fn calculate_contract_address(
Display,
derive_more::Deref,
)]
pub struct ClassHash(pub StarkHash);
pub struct ClassHash(pub Felt);

/// The hash of a compiled ContractClass.
#[derive(
Expand All @@ -138,7 +138,7 @@ pub struct ClassHash(pub StarkHash);
Ord,
Display,
)]
pub struct CompiledClassHash(pub StarkHash);
pub struct CompiledClassHash(pub Felt);

/// A general type for nonces.
#[derive(
Expand All @@ -155,16 +155,16 @@ pub struct CompiledClassHash(pub StarkHash);
Ord,
derive_more::Deref,
)]
pub struct Nonce(pub StarkFelt);
pub struct Nonce(pub Felt);

impl Nonce {
pub fn try_increment(&self) -> Result<Self, StarknetApiError> {
let current_nonce = FieldElement::from(self.0);

// Check if an overflow occurred during increment.
match StarkFelt::from(current_nonce + FieldElement::ONE) {
StarkFelt::ZERO => Err(StarknetApiError::OutOfRange { string: format!("{:?}", self) }),
incremented_felt => Ok(Self(incremented_felt)),
let new_nonce = self.0 + Felt::ONE;
if new_nonce == Felt::ZERO {
Err(StarknetApiError::OutOfRange { string: format!("{:?}", self) })
} else {
Ok(Self(new_nonce))
}
}
}
Expand All @@ -173,7 +173,7 @@ impl Nonce {
#[derive(
Debug, Copy, Clone, Default, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord,
)]
pub struct EntryPointSelector(pub StarkHash);
pub struct EntryPointSelector(pub Felt);

/// The root of the global state at a [Block](`crate::block::Block`)
/// and [StateUpdate](`crate::state::StateUpdate`).
Expand All @@ -191,7 +191,7 @@ pub struct EntryPointSelector(pub StarkHash);
Ord,
Display,
)]
pub struct GlobalRoot(pub StarkHash);
pub struct GlobalRoot(pub Felt);

/// A key for nodes of a Patricia tree.
// Invariant: key is in range.
Expand All @@ -208,34 +208,38 @@ pub struct GlobalRoot(pub StarkHash);
Ord,
derive_more:: Deref,
)]
pub struct PatriciaKey(StarkHash);
pub struct PatriciaKey(Felt);

// 2**251
pub const PATRICIA_KEY_UPPER_BOUND: &str =
"0x800000000000000000000000000000000000000000000000000000000000000";

impl PatriciaKey {
pub fn key(&self) -> &StarkHash {
pub fn as_felt(&self) -> &Felt {
&self.0
}

pub fn to_felt(&self) -> Felt {
self.0
}
}

impl From<u128> for PatriciaKey {
fn from(val: u128) -> Self {
PatriciaKey::try_from(StarkFelt::from(val)).expect("Failed to convert u128 to PatriciaKey.")
PatriciaKey::try_from(Felt::from(val)).expect("Failed to convert u128 to PatriciaKey.")
}
}

impl_from_through_intermediate!(u128, PatriciaKey, u8, u16, u32, u64);

impl TryFrom<StarkHash> for PatriciaKey {
impl TryFrom<Felt> for PatriciaKey {
type Error = StarknetApiError;

fn try_from(value: StarkHash) -> Result<Self, Self::Error> {
fn try_from(value: Felt) -> Result<Self, Self::Error> {
if value < *CONTRACT_ADDRESS_DOMAIN_SIZE {
return Ok(PatriciaKey(value));
}
Err(StarknetApiError::OutOfRange { string: format!("[0x0, {PATRICIA_KEY_UPPER_BOUND})") })
Err(StarknetApiError::OutOfRange { string: PATRICIA_KEY_UPPER_BOUND.to_string() })
}
}

Expand All @@ -250,7 +254,7 @@ impl Debug for PatriciaKey {
#[macro_export]
macro_rules! patricia_key {
($s:expr) => {
PatriciaKey::try_from(StarkHash::try_from($s).unwrap()).unwrap()
PatriciaKey::try_from(starknet_types_core::felt::Felt::from($s)).unwrap()
};
}

Expand All @@ -259,10 +263,9 @@ macro_rules! patricia_key {
#[macro_export]
macro_rules! class_hash {
($s:expr) => {
ClassHash(StarkHash::try_from($s).unwrap())
ClassHash(starknet_types_core::felt::Felt::from($s))
};
}

/// A utility macro to create a [`ContractAddress`] from a hex string / unsigned integer
/// representation.
#[cfg(any(feature = "testing", test))]
Expand All @@ -280,12 +283,12 @@ macro_rules! contract_address {
#[serde(try_from = "PrefixedBytesAsHex<20_usize>", into = "PrefixedBytesAsHex<20_usize>")]
pub struct EthAddress(pub H160);

impl TryFrom<StarkFelt> for EthAddress {
impl TryFrom<Felt> for EthAddress {
type Error = StarknetApiError;
fn try_from(felt: StarkFelt) -> Result<Self, Self::Error> {
const COMPLIMENT_OF_H160: usize = std::mem::size_of::<StarkFelt>() - H160::len_bytes();

let (rest, h160_bytes) = felt.bytes().split_at(COMPLIMENT_OF_H160);
fn try_from(felt: Felt) -> Result<Self, Self::Error> {
const COMPLIMENT_OF_H160: usize = std::mem::size_of::<Felt>() - H160::len_bytes();
let bytes = felt.to_bytes_be();
let (rest, h160_bytes) = bytes.split_at(COMPLIMENT_OF_H160);
if rest != [0u8; COMPLIMENT_OF_H160] {
return Err(StarknetApiError::OutOfRange { string: felt.to_string() });
}
Expand All @@ -294,12 +297,12 @@ impl TryFrom<StarkFelt> for EthAddress {
}
}

impl From<EthAddress> for StarkFelt {
impl From<EthAddress> for Felt {
fn from(value: EthAddress) -> Self {
let mut bytes = [0u8; 32];
// Padding H160 with zeros to 32 bytes (big endian)
bytes[12..32].copy_from_slice(value.0.as_bytes());
StarkFelt::new_unchecked(bytes)
Felt::from_bytes_be(&bytes)
}
}

Expand Down
Loading

0 comments on commit 5bc6bb6

Please sign in to comment.