Skip to content

feat: ensure snos program hash is checked #46

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

Merged
merged 5 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from 3 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
145 changes: 122 additions & 23 deletions bindings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -763,7 +763,8 @@ cairo_serde :: CairoSerde for LogStateTransitionFact
old_program_hash : starknet :: core :: types :: Felt, pub new_program_hash
: starknet :: core :: types :: Felt, pub old_config_hash : starknet ::
core :: types :: Felt, pub new_config_hash : starknet :: core :: types ::
Felt
Felt, pub old_snos_program_hash : starknet :: core :: types :: Felt, pub
new_snos_program_hash : starknet :: core :: types :: Felt
} impl cainome :: cairo_serde :: CairoSerde for ProgramInfoChanged
{
type RustType = Self; const SERIALIZED_SIZE : std :: option :: Option <
Expand All @@ -779,7 +780,11 @@ cairo_serde :: CairoSerde for LogStateTransitionFact
:: core :: types :: Felt ::
cairo_serialized_size(& __rust.old_config_hash); __size += starknet ::
core :: types :: Felt ::
cairo_serialized_size(& __rust.new_config_hash); __size
cairo_serialized_size(& __rust.new_config_hash); __size += starknet ::
core :: types :: Felt ::
cairo_serialized_size(& __rust.old_snos_program_hash); __size +=
starknet :: core :: types :: Felt ::
cairo_serialized_size(& __rust.new_snos_program_hash); __size
} fn cairo_serialize(__rust : & Self :: RustType) -> Vec < starknet ::
core :: types :: Felt >
{
Expand All @@ -793,7 +798,11 @@ cairo_serde :: CairoSerde for LogStateTransitionFact
__out.extend(starknet :: core :: types :: Felt ::
cairo_serialize(& __rust.old_config_hash));
__out.extend(starknet :: core :: types :: Felt ::
cairo_serialize(& __rust.new_config_hash)); __out
cairo_serialize(& __rust.new_config_hash));
__out.extend(starknet :: core :: types :: Felt ::
cairo_serialize(& __rust.old_snos_program_hash));
__out.extend(starknet :: core :: types :: Felt ::
cairo_serialize(& __rust.new_snos_program_hash)); __out
} fn
cairo_deserialize(__felts : & [starknet :: core :: types :: Felt],
__offset : usize) -> cainome :: cairo_serde :: Result < Self :: RustType >
Expand All @@ -813,11 +822,17 @@ cairo_serde :: CairoSerde for LogStateTransitionFact
:: types :: Felt :: cairo_serialized_size(& old_config_hash); let
new_config_hash = starknet :: core :: types :: Felt ::
cairo_deserialize(__felts, __offset) ? ; __offset += starknet :: core
:: types :: Felt :: cairo_serialized_size(& new_config_hash);
:: types :: Felt :: cairo_serialized_size(& new_config_hash); let
old_snos_program_hash = starknet :: core :: types :: Felt ::
cairo_deserialize(__felts, __offset) ? ; __offset += starknet :: core
:: types :: Felt :: cairo_serialized_size(& old_snos_program_hash);
let new_snos_program_hash = starknet :: core :: types :: Felt ::
cairo_deserialize(__felts, __offset) ? ; __offset += starknet :: core
:: types :: Felt :: cairo_serialized_size(& new_snos_program_hash);
Ok(ProgramInfoChanged
{
changed_by, old_program_hash, new_program_hash, old_config_hash,
new_config_hash
new_config_hash, old_snos_program_hash, new_snos_program_hash
})
}
} impl ProgramInfoChanged
Expand Down Expand Up @@ -1243,13 +1258,32 @@ AppchainEvent
("Could not deserialize field {} for {}: {:?}",
"new_config_hash", "ProgramInfoChanged", e)),
}; data_offset += starknet :: core :: types :: Felt ::
cairo_serialized_size(& new_config_hash); return
cairo_serialized_size(& new_config_hash); let
old_snos_program_hash = match starknet :: core :: types :: Felt ::
cairo_deserialize(& event.data, data_offset)
{
Ok(v) => v, Err(e) => return
Err(format!
("Could not deserialize field {} for {}: {:?}",
"old_snos_program_hash", "ProgramInfoChanged", e)),
}; data_offset += starknet :: core :: types :: Felt ::
cairo_serialized_size(& old_snos_program_hash); let
new_snos_program_hash = match starknet :: core :: types :: Felt ::
cairo_deserialize(& event.data, data_offset)
{
Ok(v) => v, Err(e) => return
Err(format!
("Could not deserialize field {} for {}: {:?}",
"new_snos_program_hash", "ProgramInfoChanged", e)),
}; data_offset += starknet :: core :: types :: Felt ::
cairo_serialized_size(& new_snos_program_hash); return
Ok(AppchainEvent ::
ConfigEvent(ConfigEvent ::
ProgramInfoChanged(ProgramInfoChanged
{
changed_by, old_program_hash, new_program_hash,
old_config_hash, new_config_hash
old_config_hash, new_config_hash, old_snos_program_hash,
new_snos_program_hash
})))
}; let selector = event.keys [0]; if selector == starknet :: core ::
utils ::
Expand Down Expand Up @@ -1783,13 +1817,32 @@ AppchainEvent
("Could not deserialize field {} for {}: {:?}",
"new_config_hash", "ProgramInfoChanged", e)),
}; data_offset += starknet :: core :: types :: Felt ::
cairo_serialized_size(& new_config_hash); return
cairo_serialized_size(& new_config_hash); let
old_snos_program_hash = match starknet :: core :: types :: Felt ::
cairo_deserialize(& event.data, data_offset)
{
Ok(v) => v, Err(e) => return
Err(format!
("Could not deserialize field {} for {}: {:?}",
"old_snos_program_hash", "ProgramInfoChanged", e)),
}; data_offset += starknet :: core :: types :: Felt ::
cairo_serialized_size(& old_snos_program_hash); let
new_snos_program_hash = match starknet :: core :: types :: Felt ::
cairo_deserialize(& event.data, data_offset)
{
Ok(v) => v, Err(e) => return
Err(format!
("Could not deserialize field {} for {}: {:?}",
"new_snos_program_hash", "ProgramInfoChanged", e)),
}; data_offset += starknet :: core :: types :: Felt ::
cairo_serialized_size(& new_snos_program_hash); return
Ok(AppchainEvent ::
ConfigEvent(ConfigEvent ::
ProgramInfoChanged(ProgramInfoChanged
{
changed_by, old_program_hash, new_program_hash,
old_config_hash, new_config_hash
old_config_hash, new_config_hash, old_snos_program_hash,
new_snos_program_hash
})))
}; let selector = event.keys [0]; if selector == starknet :: core ::
utils ::
Expand Down Expand Up @@ -2290,12 +2343,31 @@ impl cainome :: cairo_serde :: CairoSerde for ConfigEvent
("Could not deserialize field {} for {}: {:?}",
"new_config_hash", "ProgramInfoChanged", e)),
}; data_offset += starknet :: core :: types :: Felt ::
cairo_serialized_size(& new_config_hash); return
cairo_serialized_size(& new_config_hash); let
old_snos_program_hash = match starknet :: core :: types :: Felt ::
cairo_deserialize(& event.data, data_offset)
{
Ok(v) => v, Err(e) => return
Err(format!
("Could not deserialize field {} for {}: {:?}",
"old_snos_program_hash", "ProgramInfoChanged", e)),
}; data_offset += starknet :: core :: types :: Felt ::
cairo_serialized_size(& old_snos_program_hash); let
new_snos_program_hash = match starknet :: core :: types :: Felt ::
cairo_deserialize(& event.data, data_offset)
{
Ok(v) => v, Err(e) => return
Err(format!
("Could not deserialize field {} for {}: {:?}",
"new_snos_program_hash", "ProgramInfoChanged", e)),
}; data_offset += starknet :: core :: types :: Felt ::
cairo_serialized_size(& new_snos_program_hash); return
Ok(ConfigEvent ::
ProgramInfoChanged(ProgramInfoChanged
{
changed_by, old_program_hash, new_program_hash,
old_config_hash, new_config_hash
old_config_hash, new_config_hash, old_snos_program_hash,
new_snos_program_hash
}))
};
Err(format! ("Could not match any event from keys {:?}", event.keys))
Expand Down Expand Up @@ -2357,12 +2429,31 @@ impl cainome :: cairo_serde :: CairoSerde for ConfigEvent
("Could not deserialize field {} for {}: {:?}",
"new_config_hash", "ProgramInfoChanged", e)),
}; data_offset += starknet :: core :: types :: Felt ::
cairo_serialized_size(& new_config_hash); return
cairo_serialized_size(& new_config_hash); let
old_snos_program_hash = match starknet :: core :: types :: Felt ::
cairo_deserialize(& event.data, data_offset)
{
Ok(v) => v, Err(e) => return
Err(format!
("Could not deserialize field {} for {}: {:?}",
"old_snos_program_hash", "ProgramInfoChanged", e)),
}; data_offset += starknet :: core :: types :: Felt ::
cairo_serialized_size(& old_snos_program_hash); let
new_snos_program_hash = match starknet :: core :: types :: Felt ::
cairo_deserialize(& event.data, data_offset)
{
Ok(v) => v, Err(e) => return
Err(format!
("Could not deserialize field {} for {}: {:?}",
"new_snos_program_hash", "ProgramInfoChanged", e)),
}; data_offset += starknet :: core :: types :: Felt ::
cairo_serialized_size(& new_snos_program_hash); return
Ok(ConfigEvent ::
ProgramInfoChanged(ProgramInfoChanged
{
changed_by, old_program_hash, new_program_hash,
old_config_hash, new_config_hash
old_config_hash, new_config_hash, old_snos_program_hash,
new_snos_program_hash
}))
};
Err(format! ("Could not match any event from keys {:?}", event.keys))
Expand Down Expand Up @@ -3660,7 +3751,8 @@ UpgradeableEvent
} #[allow(clippy :: ptr_arg)] #[allow(clippy :: too_many_arguments)] pub
fn get_program_info(& self,) -> cainome :: cairo_serde :: call :: FCall <
A :: Provider,
(starknet :: core :: types :: Felt, starknet :: core :: types :: Felt) >
(starknet :: core :: types :: Felt, starknet :: core :: types :: Felt,
starknet :: core :: types :: Felt) >
{
use cainome :: cairo_serde :: CairoSerde; let mut __calldata = vec!
[]; let __call = starknet :: core :: types :: FunctionCall
Expand Down Expand Up @@ -3887,32 +3979,38 @@ UpgradeableEvent
} #[allow(clippy :: ptr_arg)] #[allow(clippy :: too_many_arguments)] pub
fn
set_program_info_getcall(& self, program_hash : & starknet :: core ::
types :: Felt, config_hash : & starknet :: core :: types :: Felt) ->
starknet :: core :: types :: Call
types :: Felt, config_hash : & starknet :: core :: types :: Felt,
snos_program_hash : & starknet :: core :: types :: Felt) -> starknet ::
core :: types :: Call
{
use cainome :: cairo_serde :: CairoSerde; let mut __calldata = vec!
[];
__calldata.extend(starknet :: core :: types :: Felt ::
cairo_serialize(program_hash));
__calldata.extend(starknet :: core :: types :: Felt ::
cairo_serialize(config_hash)); starknet :: core :: types :: Call
cairo_serialize(config_hash));
__calldata.extend(starknet :: core :: types :: Felt ::
cairo_serialize(snos_program_hash)); starknet :: core :: types :: Call
{
to : self.address, selector : starknet :: macros :: selector!
("set_program_info"), calldata : __calldata,
}
} #[allow(clippy :: ptr_arg)] #[allow(clippy :: too_many_arguments)] pub
fn
set_program_info(& self, program_hash : & starknet :: core :: types ::
Felt, config_hash : & starknet :: core :: types :: Felt) -> starknet ::
accounts :: ExecutionV1 < A >
Felt, config_hash : & starknet :: core :: types :: Felt, snos_program_hash
: & starknet :: core :: types :: Felt) -> starknet :: accounts ::
ExecutionV1 < A >
{
use cainome :: cairo_serde :: CairoSerde; let mut __calldata = vec!
[];
__calldata.extend(starknet :: core :: types :: Felt ::
cairo_serialize(program_hash));
__calldata.extend(starknet :: core :: types :: Felt ::
cairo_serialize(config_hash)); let __call = starknet :: core :: types
:: Call
cairo_serialize(config_hash));
__calldata.extend(starknet :: core :: types :: Felt ::
cairo_serialize(snos_program_hash)); let __call = starknet :: core ::
types :: Call
{
to : self.address, selector : starknet :: macros :: selector!
("set_program_info"), calldata : __calldata,
Expand Down Expand Up @@ -4117,8 +4215,9 @@ UpgradeableEvent
new(__call, self.provider(),)
} #[allow(clippy :: ptr_arg)] #[allow(clippy :: too_many_arguments)] pub
fn get_program_info(& self,) -> cainome :: cairo_serde :: call :: FCall <
P, (starknet :: core :: types :: Felt, starknet :: core :: types :: Felt)
>
P,
(starknet :: core :: types :: Felt, starknet :: core :: types :: Felt,
starknet :: core :: types :: Felt) >
{
use cainome :: cairo_serde :: CairoSerde; let mut __calldata = vec!
[]; let __call = starknet :: core :: types :: FunctionCall
Expand Down
19 changes: 14 additions & 5 deletions src/appchain.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -139,19 +139,28 @@ mod appchain {
self.reentrancy_guard.start();
self.config.assert_only_owner_or_operator();

let (
current_program_hash, current_config_hash, current_snos_program_hash
): (felt252, felt252, felt252) =
self
.config
.program_info
.read();

//Snos proof is wrapped in bootloader so 3rd element is program hash of
//bootloaded program in our case StarknetOs
let snos_program_hash = snos_output.at(2);
assert!(current_snos_program_hash == *snos_program_hash);

let snos_output_hash = poseidon_hash_span(snos_output);
let snos_output_hash_in_bridge_output = program_output.at(4);
assert!(snos_output_hash == *snos_output_hash_in_bridge_output);

let output_hash = poseidon_hash_span(program_output);

let mut snos_output_iter = snos_output.into_iter();
let program_output_struct = deserialize_os_output(ref snos_output_iter);

let (current_program_hash, current_config_hash): (felt252, felt252) = self
.config
.program_info
.read();

let data_availability_fact: DataAvailabilityFact = DataAvailabilityFact {
onchain_data_hash, onchain_data_size
};
Expand Down
24 changes: 18 additions & 6 deletions src/config/component.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ mod config_cpt {
struct Storage {
/// Appchain operators that are allowed to update the state.
operators: Map<ContractAddress, bool>,
/// Program info (StarknetOS), with program hash and config hash.
program_info: (felt252, felt252),
/// Program info layout bridge program hash, config hash and StarknetOs program hash.
program_info: (felt252, felt252, felt252),
/// Facts registry contract address.
facts_registry: ContractAddress,
}
Expand All @@ -47,6 +47,8 @@ mod config_cpt {
new_program_hash: felt252,
old_config_hash: felt252,
new_config_hash: felt252,
old_snos_program_hash: felt252,
new_snos_program_hash: felt252,
}

#[embeddable_as(ConfigImpl)]
Expand All @@ -72,11 +74,19 @@ mod config_cpt {
}

fn set_program_info(
ref self: ComponentState<TContractState>, program_hash: felt252, config_hash: felt252
ref self: ComponentState<TContractState>,
program_hash: felt252,
config_hash: felt252,
snos_program_hash: felt252
) {
self.assert_only_owner_or_operator();
let (old_program_hash, old_config_hash): (felt252, felt252) = self.program_info.read();
self.program_info.write((program_hash, config_hash));
let (
old_program_hash, old_config_hash, old_snos_program_hash
): (felt252, felt252, felt252) =
self
.program_info
.read();
self.program_info.write((program_hash, config_hash, snos_program_hash));
self
.emit(
ProgramInfoChanged {
Expand All @@ -85,11 +95,13 @@ mod config_cpt {
new_program_hash: program_hash,
old_config_hash: old_config_hash,
new_config_hash: config_hash,
old_snos_program_hash: old_snos_program_hash,
new_snos_program_hash: snos_program_hash,
}
);
}

fn get_program_info(self: @ComponentState<TContractState>) -> (felt252, felt252) {
fn get_program_info(self: @ComponentState<TContractState>) -> (felt252, felt252, felt252) {
self.program_info.read()
}

Expand Down
20 changes: 12 additions & 8 deletions src/config/interface.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,26 @@ trait IConfig<T> {
/// True if the address is an operator, false otherwise.
fn is_operator(self: @T, address: ContractAddress) -> bool;

/// Sets the information of the program that generates the
/// state transition trace (namely StarknetOS).
/// Sets the information of the program that generates
/// layout bridge (Cairo verifier ran with StarknetOs proof, wrapped in bootloader).
///
/// # Arguments
///
/// * `program_hash` - The program hash.
/// * `config_hash` - The program's config hash.
fn set_program_info(ref self: T, program_hash: felt252, config_hash: felt252);
/// * `program_hash` - The program hash of layout bridge program.
/// * `config_hash` - The SNOS's config hash.
/// * `snos_program_hash` - The SNOS program hash
fn set_program_info(
ref self: T, program_hash: felt252, config_hash: felt252, snos_program_hash: felt252
);

/// Gets the information of the program that generates the
/// state transition trace (namely StarknetOS).
/// layout bridge (Cairo verifier ran with StarknetOs proof, wrapped in bootloader),
/// and StarknetOs program hash
///
/// # Returns
///
/// The program hash and it's configuration hash.
fn get_program_info(self: @T) -> (felt252, felt252);
/// The layout bridge program hash, SNOS configuration hash and SNOS program hash.
fn get_program_info(self: @T) -> (felt252, felt252, felt252);

/// Sets the facts registry contract address, which is already
/// initialized with the verifier information.
Expand Down
Loading