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

Snos integration #45

Closed
wants to merge 16 commits into from
Closed
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/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ jobs:
- uses: actions/checkout@v4
- uses: asdf-vm/actions/install@v3
- run: scarb fmt --check
- run: scarb build
- run: scarb build --all-features
2 changes: 1 addition & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: asdf-vm/actions/install@v3
- run: snforge test
- run: scarb test --all-features
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
scarb 2.8.0
scarb 2.8.4
starknet-foundry 0.27.0
4 changes: 3 additions & 1 deletion Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2023_10"

[dependencies]
starknet = "2.8.0"
starknet = "2.8.4"
openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.16.0" }

[dev-dependencies]
Expand All @@ -25,3 +25,5 @@ sierra = true
[tool.fmt]
sort-module-level-items = true

[features]
messaging_test = []
2,721 changes: 1 addition & 2,720 deletions bindings/src/bindings.rs

Large diffs are not rendered by default.

70 changes: 34 additions & 36 deletions src/appchain.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ mod errors {
/// Appchain settlement contract on starknet.
#[starknet::contract]
mod appchain {
use core::iter::IntoIterator;
use core::poseidon::{Poseidon, PoseidonImpl, HashStateImpl, poseidon_hash_span};
use openzeppelin::access::ownable::{
OwnableComponent as ownable_cpt, OwnableComponent::InternalTrait as OwnableInternal,
interface::IOwnable
Expand All @@ -29,16 +31,13 @@ mod appchain {
encode_fact_with_onchain_data, DataAvailabilityFact
};
use piltover::config::{config_cpt, config_cpt::InternalTrait as ConfigInternal, IConfig};
use piltover::fact_registry::{IFactRegistryDispatcher, IFactRegistryDispatcherTrait};
use piltover::interface::IAppchain;
use piltover::messaging::{
messaging_cpt, messaging_cpt::InternalTrait as MessagingInternal, IMessaging,
output_process, output_process::{MessageToStarknet, MessageToAppchain},
};
use piltover::mocks::{
IFactRegistryMockDispatcher, IFactRegistryMockDispatcherTrait
}; // To change when Herodotus finishes implementing FactRegistry.
use piltover::snos_output::ProgramOutput;
use piltover::snos_output;
use piltover::snos_output::StarknetOsOutput;
use piltover::snos_output::deserialize_os_output;
use piltover::state::component::state_cpt::HasComponent;
use piltover::state::{state_cpt, state_cpt::InternalTrait as StateInternal, IState};
use starknet::{ContractAddress, ClassHash};
Expand Down Expand Up @@ -131,20 +130,31 @@ mod appchain {

#[abi(embed_v0)]
impl Appchain of IAppchain<ContractState> {
/// This function accepts two outputs due to the dynamic nature of the layout, which
/// prevents direct verification of the snos proof.
/// To ensure the correctness of `snos_output`, we compare its hash with the corresponding
/// hash in `program_output`, which serves as a layout bridge proof.
fn update_state(
ref self: ContractState,
snos_output: Array<felt252>,
program_output: Span<felt252>,
onchain_data_hash: felt252,
onchain_data_size: u256
) {
self.reentrancy_guard.start();
self.config.assert_only_owner_or_operator();

// Header size + 2 messages segments len.
assert(
program_output.len() > snos_output::HEADER_SIZE + 2,
errors::SNOS_INVALID_PROGRAM_OUTPUT_SIZE
);
let snos_output_span = snos_output.span();
let snos_output_hash = poseidon_hash_span(snos_output_span);
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
); //Custom deserialization function, inspired by
//https://github.com/starkware-libs/cairo-lang/blob/8e11b8cc65ae1d0959328b1b4a40b92df8b58595/src/starkware/starknet/core/aggregator/output_parser.py

let (current_program_hash, current_config_hash): (felt252, felt252) = self
.config
Expand All @@ -158,42 +168,30 @@ mod appchain {
program_output, data_availability_fact
);

let mut program_output_mut = program_output;
let program_output_struct: ProgramOutput = Serde::deserialize(ref program_output_mut)
.unwrap();
assert(
program_output_struct.config_hash == current_config_hash,
program_output_struct.starknet_os_config_hash == current_config_hash,
errors::SNOS_INVALID_CONFIG_HASH
);

let sharp_fact: u256 = keccak::keccak_u256s_be_inputs(
array![current_program_hash.into(), state_transition_fact].span()
);
assert(
IFactRegistryMockDispatcher { contract_address: self.config.get_facts_registry() }
.is_valid(sharp_fact),
errors::NO_STATE_TRANSITION_PROOF
let fact = poseidon_hash_span(array![current_program_hash, output_hash].span());
assert!(
*IFactRegistryDispatcher { contract_address: self.config.get_facts_registry() }
.get_all_verifications_for_fact_hash(fact)
.at(0)
.security_bits > 50
);

self.emit(LogStateTransitionFact { state_transition_fact });

// Perform state update
self.state.update(program_output);

let mut offset = snos_output::HEADER_SIZE;

// TODO(#7): We should update SNOS output to have the messages count
// instead of the messages segment len.
let messages_to_l1 = program_output_struct.messages_to_l1;
let messages_to_l2 = program_output_struct.messages_to_l2;

let mut messages_segments = program_output.slice(offset, program_output.len() - offset);
// Perform state update
self.state.update(program_output_struct);

let (messages_to_starknet, messages_to_appchain) =
output_process::gather_messages_from_output(
messages_segments
);
self.messaging.process_messages_to_starknet(messages_to_l1);
self.messaging.process_messages_to_appchain(messages_to_l2);

self.messaging.process_messages_to_starknet(messages_to_starknet);
self.messaging.process_messages_to_appchain(messages_to_appchain);
self.reentrancy_guard.end();

self
Expand Down
70 changes: 70 additions & 0 deletions src/fact_registry.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#[derive(Drop, Serde)]
struct VerificationListElement {
verification_hash: felt252,
security_bits: u32,
verifier_config: VerifierConfiguration
}
#[derive(Drop, Serde)]
struct VerifierConfiguration {
layout: felt252,
hasher: felt252,
stone_version: felt252,
cairo_version: felt252
}

#[starknet::interface]
trait IFactRegistry<T> {
fn get_all_verifications_for_fact_hash(
self: @T, fact: felt252
) -> Array<VerificationListElement>;
}

#[derive(Copy, Drop, starknet::Store, Serde)]
struct IFactRegistryContract {
pub contract_address: starknet::ContractAddress,
}

impl ISmartProofDispatcherImpl of IFactRegistry<IFactRegistryContract> {
fn get_all_verifications_for_fact_hash(
self: @IFactRegistryContract, fact: felt252
) -> Array<VerificationListElement> {
let mut __calldata__ = array![fact];

let mut __dispatcher_return_data__ = starknet::syscalls::call_contract_syscall(
*self.contract_address,
selector!("get_all_verifications_for_fact_hash"),
core::array::ArrayTrait::span(@__calldata__),
);
let mut __dispatcher_return_data__ = starknet::SyscallResultTrait::unwrap_syscall(
__dispatcher_return_data__
);
core::option::OptionTrait::expect(
core::serde::Serde::<
Array<VerificationListElement>
>::deserialize(ref __dispatcher_return_data__),
'Returned data too short',
)
}
}

#[starknet::contract]
mod fact_registry_mock {
#[storage]
struct Storage {}

#[abi(embed_v0)]
impl FactRegistryImplMock of super::IFactRegistry<ContractState> {
fn get_all_verifications_for_fact_hash(
self: @ContractState, fact: felt252
) -> Array<super::VerificationListElement> {
let verification_list_element = super::VerificationListElement {
verification_hash: 1,
security_bits: 60,
verifier_config: super::VerifierConfiguration {
layout: 1, hasher: 1, stone_version: 1, cairo_version: 1
}
};
array![verification_list_element]
}
}
}
1 change: 1 addition & 0 deletions src/interface.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ trait IAppchain<T> {
/// TODO: DA + facts.
fn update_state(
ref self: T,
snos_output: Array<felt252>,
program_output: Span<felt252>,
onchain_data_hash: felt252,
onchain_data_size: u256
Expand Down
4 changes: 1 addition & 3 deletions src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
mod appchain;
mod fact_registry;
mod interface;
mod mocks;
mod snos_output;

// Components
mod config {
mod component;
Expand All @@ -24,7 +23,6 @@ mod messaging {
mod hash;
mod interface;
mod mock;
mod output_process;
mod types;

use component::messaging_cpt;
Expand Down
Loading
Loading