Skip to content

Commit

Permalink
Merge pull request #102 from HerodotusDev/starknet_syscall_handler
Browse files Browse the repository at this point in the history
Adds Starknet data syscall support
  • Loading branch information
petscheit authored Nov 28, 2024
2 parents cba7fa7 + 5708c11 commit eb54e20
Show file tree
Hide file tree
Showing 45 changed files with 20,588 additions and 13,372 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ jobs:
./tools/make/python_format_check.sh
- name: Check Python tests
env:
RPC_URL_MAINNET: ${{ secrets.RPC_URL_MAINNET }}
PROVIDER_URL_STARKNET: ${{ secrets.PROVIDER_URL_STARKNET }}
RPC_URL: ${{ secrets.RPC_URL }}
run: |
source venv/bin/activate
pytest tools/*
Expand All @@ -56,6 +60,8 @@ jobs:
- name: Run Unit Cairo tests
env:
RPC_URL_MAINNET: ${{ secrets.RPC_URL_MAINNET }}
PROVIDER_URL_STARKNET: ${{ secrets.PROVIDER_URL_STARKNET_TESTNET }}
RPC_URL: ${{ secrets.RPC_URL }}
run: |
source venv/bin/activate
./tools/make/cairo_tests.sh
Expand Down
1 change: 1 addition & 0 deletions cairo1_syscall_binding/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod evm;
pub mod starknet;

#[derive(Serde, Drop)]
pub struct HDP {
Expand Down
2 changes: 2 additions & 0 deletions cairo1_syscall_binding/src/starknet.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod header;
pub mod storage;
117 changes: 117 additions & 0 deletions cairo1_syscall_binding/src/starknet/header.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
use hdp_cairo::StarknetMemorizer;
use starknet::syscalls::call_contract_syscall;
use starknet::{SyscallResult, SyscallResultTrait};

const HEADER: felt252 = 0;

// Function selectors matching StarknetStateFunctionId from Python
const HEADER_GET_BLOCK_NUMBER: felt252 = 0;
const HEADER_GET_STATE_ROOT: felt252 = 1;
const HEADER_GET_SEQUENCER_ADDRESS: felt252 = 2;
const HEADER_GET_BLOCK_TIMESTAMP: felt252 = 3;
const HEADER_GET_TRANSACTION_COUNT: felt252 = 4;
const HEADER_GET_TRANSACTION_COMMITMENT: felt252 = 5;
const HEADER_GET_EVENT_COUNT: felt252 = 6;
const HEADER_GET_EVENT_COMMITMENT: felt252 = 7;
const HEADER_GET_PARENT_BLOCK_HASH: felt252 = 8;
const HEADER_GET_STATE_DIFF_COMMITMENT: felt252 = 9;
const HEADER_GET_STATE_DIFF_LENGTH: felt252 = 10;
const HEADER_GET_L1_GAS_PRICE_IN_WEI: felt252 = 11;
const HEADER_GET_L1_GAS_PRICE_IN_FRI: felt252 = 12;
const HEADER_GET_L1_DATA_GAS_PRICE_IN_WEI: felt252 = 13;
const HEADER_GET_L1_DATA_GAS_PRICE_IN_FRI: felt252 = 14;
const HEADER_GET_RECEIPTS_COMMITMENT: felt252 = 15;
const HEADER_GET_L1_DATA_MODE: felt252 = 16;
const HEADER_GET_PROTOCOL_VERSION: felt252 = 17;

#[derive(Serde, Drop)]
pub struct HeaderKey {
pub chain_id: felt252,
pub block_number: felt252,
}

#[generate_trait]
pub impl HeaderImpl of HeaderTrait {
fn header_get_block_number(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
self.call_memorizer(HEADER_GET_BLOCK_NUMBER, key)
}

fn header_get_state_root(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
self.call_memorizer(HEADER_GET_STATE_ROOT, key)
}

fn header_get_sequencer_address(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
self.call_memorizer(HEADER_GET_SEQUENCER_ADDRESS, key)
}

fn header_get_block_timestamp(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
self.call_memorizer(HEADER_GET_BLOCK_TIMESTAMP, key)
}

// fn header_get_transaction_count(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
// self.call_memorizer(HEADER_GET_TRANSACTION_COUNT, key)
// }

fn header_get_transaction_commitment(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
self.call_memorizer(HEADER_GET_TRANSACTION_COMMITMENT, key)
}

// fn header_get_event_count(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
// self.call_memorizer(HEADER_GET_EVENT_COUNT, key)
// }

fn header_get_event_commitment(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
self.call_memorizer(HEADER_GET_EVENT_COMMITMENT, key)
}

fn header_get_parent_block_hash(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
self.call_memorizer(HEADER_GET_PARENT_BLOCK_HASH, key)
}

fn header_get_state_diff_commitment(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
self.call_memorizer(HEADER_GET_STATE_DIFF_COMMITMENT, key)
}

// fn header_get_state_diff_length(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
// self.call_memorizer(HEADER_GET_STATE_DIFF_LENGTH, key)
// }

fn header_get_l1_gas_price_in_wei(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
self.call_memorizer(HEADER_GET_L1_GAS_PRICE_IN_WEI, key)
}

fn header_get_l1_gas_price_in_fri(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
self.call_memorizer(HEADER_GET_L1_GAS_PRICE_IN_FRI, key)
}

fn header_get_l1_data_gas_price_in_wei(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
self.call_memorizer(HEADER_GET_L1_DATA_GAS_PRICE_IN_WEI, key)
}

fn header_get_l1_data_gas_price_in_fri(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
self.call_memorizer(HEADER_GET_L1_DATA_GAS_PRICE_IN_FRI, key)
}

fn header_get_receipts_commitment(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
self.call_memorizer(HEADER_GET_RECEIPTS_COMMITMENT, key)
}

// fn header_get_l1_data_mode(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
// self.call_memorizer(HEADER_GET_L1_DATA_MODE, key)
// }

// fn header_get_protocol_version(self: @StarknetMemorizer, key: HeaderKey) -> felt252 {
// self.call_memorizer(HEADER_GET_PROTOCOL_VERSION, key)
// }

fn call_memorizer(self: @StarknetMemorizer, selector: felt252, key: HeaderKey) -> felt252 {
let value = call_contract_syscall(
HEADER.try_into().unwrap(),
selector,
array![*self.dict.segment_index, *self.dict.offset, key.chain_id, key.block_number]
.span()
)
.unwrap_syscall();
(*value[0]).try_into().unwrap()
}
}
35 changes: 35 additions & 0 deletions cairo1_syscall_binding/src/starknet/storage.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use hdp_cairo::StarknetMemorizer;
use starknet::syscalls::call_contract_syscall;
use starknet::{SyscallResult, SyscallResultTrait};

const STORAGE: felt252 = 1;
const STORAGE_GET_SLOT: felt252 = 0;

#[derive(Serde, Drop)]
pub struct StorageKey {
pub chain_id: felt252,
pub block_number: felt252,
pub address: felt252,
pub storage_slot: felt252,
}

#[generate_trait]
pub impl StorageImpl of StorageTrait {
fn storage_get_slot(self: @StarknetMemorizer, key: StorageKey) -> felt252 {
let value = call_contract_syscall(
STORAGE.try_into().unwrap(),
STORAGE_GET_SLOT,
array![
*self.dict.segment_index,
*self.dict.offset,
key.chain_id,
key.block_number,
key.address,
key.storage_slot,
]
.span()
)
.unwrap_syscall();
(*value[0]).try_into().unwrap()
}
}
11 changes: 11 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,20 @@ def run(self):
"tools.py.providers",
"tools.py.types",
"tools.py.types.evm",
"tools.py.types.starknet",
"tools.py.providers.evm",
"tools.py.providers.starknet",
"contract_bootloader",
"contract_bootloader.contract_class",
"contract_bootloader.dryrun_syscall_memorizer_handler",
"contract_bootloader.dryrun_syscall_memorizer_handler.evm",
"contract_bootloader.dryrun_syscall_memorizer_handler.starknet",
"contract_bootloader.memorizer",
"contract_bootloader.memorizer.evm",
"contract_bootloader.memorizer.starknet",
"contract_bootloader.syscall_memorizer_handler",
"contract_bootloader.syscall_memorizer_handler.evm",
"contract_bootloader.syscall_memorizer_handler.starknet",
],
install_requires=requirements,
package_dir={
Expand All @@ -59,4 +64,10 @@ def run(self):
],
},
cmdclass={"install": PostInstallCommand},
develop=True,
options={
"develop": {
"build_dir": "build",
}
},
)
22 changes: 15 additions & 7 deletions src/contract_bootloader/contract.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ from starkware.cairo.common.cairo_builtins import (
SignatureBuiltin,
EcOpBuiltin,
)
from contract_bootloader.contract_class.compiled_class import CompiledClass, compiled_class_hash
from starkware.cairo.common.uint256 import Uint256
from contract_bootloader.contract_bootloader import run_contract_bootloader, compute_program_hash
from src.contract_bootloader.contract_class.compiled_class import CompiledClass, compiled_class_hash
from src.contract_bootloader.contract_bootloader import (
run_contract_bootloader,
compute_program_hash,
)
from starkware.cairo.common.uint256 import Uint256, felt_to_uint256
from starkware.cairo.common.dict_access import DictAccess
from starkware.cairo.common.memcpy import memcpy
from starkware.cairo.common.registers import get_fp_and_pc
Expand All @@ -36,7 +39,7 @@ func compute_contract{
// Fetch contract data form hints.
%{
from starkware.starknet.core.os.contract_class.compiled_class_hash import create_bytecode_segment_structure
from contract_bootloader.contract_class.compiled_class_hash_utils import get_compiled_class_struct
from src.contract_bootloader.contract_class.compiled_class_hash_utils import get_compiled_class_struct
bytecode_segment_structure = create_bytecode_segment_structure(
bytecode=compiled_class.bytecode,
Expand Down Expand Up @@ -90,7 +93,12 @@ func compute_contract{
);
}

assert retdata_size = 2;
local result: Uint256 = Uint256(low=retdata[0], high=retdata[1]);
return (result=result, program_hash=program_hash);
if (retdata_size == 1) {
let result = felt_to_uint256(retdata[0]);
return (result=result, program_hash=program_hash);
} else {
assert retdata_size = 2;
let result = Uint256(low=retdata[0], high=retdata[1]);
return (result=result, program_hash=program_hash);
}
}
6 changes: 3 additions & 3 deletions src/contract_bootloader/contract_bootloader.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ from starkware.cairo.common.cairo_builtins import (
EcOpBuiltin,
)
from starkware.cairo.common.registers import get_fp_and_pc
from contract_bootloader.contract_class.compiled_class import CompiledClass
from src.contract_bootloader.contract_class.compiled_class import CompiledClass
from starkware.starknet.builtins.segment_arena.segment_arena import new_arena, SegmentArenaBuiltin
from starkware.starknet.core.os.builtins import (
BuiltinEncodings,
Expand All @@ -18,9 +18,9 @@ from starkware.starknet.core.os.builtins import (
SelectableBuiltins,
)
from starkware.cairo.common.builtin_poseidon.poseidon import poseidon_hash_many
from contract_bootloader.execute_entry_point import execute_entry_point
from starkware.starknet.core.os.constants import ENTRY_POINT_TYPE_EXTERNAL
from contract_bootloader.execute_syscalls import ExecutionContext, ExecutionInfo
from src.contract_bootloader.execute_entry_point import execute_entry_point
from src.contract_bootloader.execute_syscalls import ExecutionContext, ExecutionInfo
from starkware.cairo.common.dict_access import DictAccess
from starkware.cairo.common.alloc import alloc

Expand Down
40 changes: 24 additions & 16 deletions src/contract_bootloader/contract_dry_run.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ from starkware.cairo.common.uint256 import Uint256
from starkware.cairo.common.dict_access import DictAccess
from starkware.cairo.common.default_dict import default_dict_new, default_dict_finalize
from starkware.cairo.common.builtin_keccak.keccak import keccak, keccak_bigend
from contract_bootloader.contract_class.compiled_class import CompiledClass, compiled_class_hash
from contract_bootloader.contract_bootloader import run_contract_bootloader, compute_program_hash
from src.contract_bootloader.contract_class.compiled_class import CompiledClass, compiled_class_hash
from src.contract_bootloader.contract_bootloader import (
run_contract_bootloader,
compute_program_hash,
)
from starkware.cairo.common.memcpy import memcpy

func main{
Expand All @@ -35,6 +38,8 @@ func main{
%{
from tools.py.schema import HDPDryRunInput
print("Starting Dry Run")
# Load the dry run input
dry_run_input = HDPDryRunInput.Schema().load(program_input)
dry_run_output_path = dry_run_input.dry_run_output_path
Expand All @@ -56,7 +61,7 @@ func main{
// Fetch contract data form hints.
%{
from starkware.starknet.core.os.contract_class.compiled_class_hash import create_bytecode_segment_structure
from contract_bootloader.contract_class.compiled_class_hash_utils import get_compiled_class_struct
from src.contract_bootloader.contract_class.compiled_class_hash_utils import get_compiled_class_struct
bytecode_segment_structure = create_bytecode_segment_structure(
bytecode=compiled_class.bytecode,
Expand Down Expand Up @@ -99,7 +104,7 @@ func main{
local pow2_array: felt* = nondet %{ segments.add() %};

%{
from contract_bootloader.dryrun_syscall_handler import DryRunSyscallHandler
from src.contract_bootloader.dryrun_syscall_handler import DryRunSyscallHandler
if '__dict_manager' not in globals():
from starkware.cairo.common.dict import DictManager
Expand Down Expand Up @@ -129,26 +134,29 @@ func main{
);
}

assert retdata_size = 2;
local result: Uint256 = Uint256(low=retdata[0], high=retdata[1]);

%{
print("result.low", hex(ids.result.low))
print("result.high", hex(ids.result.high))
%}

%{
import json
list = list()
dictionary = dict()
dictionary["fetch_keys"] = syscall_handler.fetch_keys_dict()
dictionary["result"] = {
"low": hex(ids.result.low),
"high": hex(ids.result.high)
}
if ids.retdata_size == 2:
dictionary["result"] = {
"low": hex(memory[ids.retdata]),
"high": hex(memory[ids.retdata + 1])
}
else:
high, low = divmod(memory[ids.retdata], 2**128)
dictionary["result"] = {
"low": hex(low),
"high": hex(high)
}
dictionary["program_hash"] = hex(ids.program_hash)
print("Dry Run Result", dictionary["result"])
list.append(dictionary)
with open(dry_run_output_path, 'w') as json_file:
Expand Down
Loading

0 comments on commit eb54e20

Please sign in to comment.