-
Notifications
You must be signed in to change notification settings - Fork 15
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
[paused] feat: snos job #50
Changes from 11 commits
412aeec
f41eeb9
7d898cd
3676b1b
b2ede88
82b04d4
2f1dab2
799ce7e
b50c5df
0a99bdb
e9c3df5
2eab368
9ee833e
b9e4569
9705039
e8ababa
a57698e
2f3b1d8
708991d
8919ed0
5ade4f7
8d2a124
98b3d51
4e82e2f
df2f0d6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
//! A Dummy state that does nothing. | ||
//! It just implements the State and StateReader trait provided by Blockifier. | ||
//! | ||
//! This module needs to be deleted as soon as we can import the structure from | ||
//! Madara code. | ||
//! Currently, we have version conflicts between snos <=> deoxys <=> cairo-vm. | ||
//! This is an issue that needs to be tackled on its own. | ||
|
||
use std::collections::HashSet; | ||
|
||
use blockifier::execution::contract_class::ContractClass; | ||
use blockifier::state::cached_state::CommitmentStateDiff; | ||
use blockifier::state::errors::StateError; | ||
use blockifier::state::state_api::{State, StateReader, StateResult}; | ||
use indexmap::IndexMap; | ||
use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; | ||
use starknet_api::hash::StarkFelt; | ||
use starknet_api::state::StorageKey; | ||
|
||
pub struct DummyState; | ||
|
||
impl StateReader for DummyState { | ||
fn get_storage_at(&mut self, _contract_address: ContractAddress, _key: StorageKey) -> StateResult<StarkFelt> { | ||
Ok(StarkFelt::ZERO) | ||
} | ||
|
||
fn get_nonce_at(&mut self, _contract_address: ContractAddress) -> StateResult<Nonce> { | ||
Ok(Nonce::default()) | ||
} | ||
|
||
fn get_class_hash_at(&mut self, _contract_address: ContractAddress) -> StateResult<ClassHash> { | ||
Ok(ClassHash::default()) | ||
} | ||
|
||
fn get_compiled_contract_class(&mut self, _class_hash: ClassHash) -> StateResult<ContractClass> { | ||
Err(StateError::OutOfRangeContractAddress) | ||
} | ||
|
||
fn get_compiled_class_hash(&mut self, _class_hash: ClassHash) -> StateResult<CompiledClassHash> { | ||
Ok(CompiledClassHash::default()) | ||
} | ||
} | ||
|
||
impl State for DummyState { | ||
fn set_storage_at( | ||
&mut self, | ||
_contract_address: ContractAddress, | ||
_key: StorageKey, | ||
_value: StarkFelt, | ||
) -> StateResult<()> { | ||
Ok(()) | ||
} | ||
|
||
fn increment_nonce(&mut self, _contract_address: ContractAddress) -> StateResult<()> { | ||
Ok(()) | ||
} | ||
|
||
fn set_class_hash_at(&mut self, _contract_address: ContractAddress, _class_hash: ClassHash) -> StateResult<()> { | ||
Ok(()) | ||
} | ||
|
||
fn set_contract_class(&mut self, _class_hash: ClassHash, _contract_class: ContractClass) -> StateResult<()> { | ||
Ok(()) | ||
} | ||
|
||
fn set_compiled_class_hash( | ||
&mut self, | ||
_class_hash: ClassHash, | ||
_compiled_class_hash: CompiledClassHash, | ||
) -> StateResult<()> { | ||
Ok(()) | ||
} | ||
|
||
fn to_state_diff(&mut self) -> CommitmentStateDiff { | ||
CommitmentStateDiff { | ||
address_to_class_hash: IndexMap::default(), | ||
address_to_nonce: IndexMap::default(), | ||
storage_updates: IndexMap::default(), | ||
class_hash_to_compiled_class_hash: IndexMap::default(), | ||
} | ||
} | ||
|
||
fn add_visited_pcs(&mut self, _class_hash: ClassHash, _pcs: &HashSet<usize>) {} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,35 @@ | ||
mod dummy_state; | ||
|
||
use std::collections::HashMap; | ||
use std::num::NonZeroU128; | ||
|
||
use async_trait::async_trait; | ||
use blockifier::block::{pre_process_block, BlockInfo, BlockNumberHashPair, GasPrices}; | ||
use blockifier::context::{ChainInfo, FeeTokenAddresses}; | ||
use blockifier::versioned_constants::VersionedConstants; | ||
use cairo_vm::types::layout_name::LayoutName; | ||
use cairo_vm::Felt252; | ||
use color_eyre::eyre::eyre; | ||
use color_eyre::Result; | ||
use num::FromPrimitive; | ||
use snos::execution::helper::ExecutionHelperWrapper; | ||
use snos::io::input::StarknetOsInput; | ||
use snos::run_os; | ||
use starknet::providers::jsonrpc::JsonRpcRequest; | ||
use starknet_api::block::{BlockHash, BlockNumber, BlockTimestamp}; | ||
use starknet_api::hash::StarkFelt; | ||
use starknet_core::types::FieldElement; | ||
use uuid::Uuid; | ||
|
||
use utils::time::get_current_timestamp_in_secs; | ||
|
||
use crate::config::Config; | ||
use crate::jobs::snos_job::dummy_state::DummyState; | ||
use crate::jobs::types::{JobItem, JobStatus, JobType, JobVerificationStatus}; | ||
use crate::jobs::Job; | ||
|
||
use super::constants::JOB_METADATA_SNOS_BLOCK; | ||
|
||
pub struct SnosJob; | ||
|
||
#[async_trait] | ||
|
@@ -29,28 +51,133 @@ impl Job for SnosJob { | |
}) | ||
} | ||
|
||
async fn process_job(&self, _config: &Config, _job: &mut JobItem) -> Result<String> { | ||
async fn process_job(&self, config: &Config, job: &mut JobItem) -> Result<String> { | ||
// 0. Get block number from metadata | ||
let block_number = self.get_block_number_from_metadata(job)?; | ||
|
||
// 1. Fetch SNOS input data from Madara | ||
// 2. Import SNOS in Rust and execute it with the input data | ||
let snos_input: StarknetOsInput = self.get_snos_input_from_madara(config, &block_number)?; | ||
|
||
// 2. Build the required inputs for snos::run_os | ||
// TODO: import BlockifierStateAdapter from Madara RPC and use it here | ||
let mut state = DummyState {}; | ||
|
||
let block_number_and_hash = BlockNumberHashPair { | ||
number: block_number, | ||
hash: BlockHash(StarkFelt::from( | ||
FieldElement::from_bytes_be(&snos_input.block_hash.clone().to_bytes_be()) | ||
.expect("Could not convert Felt to FieldElement"), | ||
)), | ||
}; | ||
|
||
let block_info = BlockInfo { | ||
block_number, | ||
// TODO: Assert that we really want current_timestamp? | ||
block_timestamp: BlockTimestamp(get_current_timestamp_in_secs()), | ||
sequencer_address: snos_input.general_config.sequencer_address, | ||
// TODO: retrieve prices from Madara? | ||
gas_prices: GasPrices { | ||
eth_l1_gas_price: NonZeroU128::new(0).unwrap(), | ||
eth_l1_data_gas_price: NonZeroU128::new(0).unwrap(), | ||
strk_l1_gas_price: NonZeroU128::new(0).unwrap(), | ||
strk_l1_data_gas_price: NonZeroU128::new(0).unwrap(), | ||
}, | ||
use_kzg_da: snos_input.general_config.use_kzg_da, | ||
}; | ||
|
||
let chain_info = ChainInfo { | ||
chain_id: snos_input.general_config.starknet_os_config.chain_id.clone(), | ||
fee_token_addresses: FeeTokenAddresses { | ||
eth_fee_token_address: snos_input.general_config.starknet_os_config.fee_token_address, | ||
// TODO: assert that the STRK fee token address is deprecated_fee_token_address | ||
strk_fee_token_address: snos_input.general_config.starknet_os_config.deprecated_fee_token_address, | ||
}, | ||
}; | ||
|
||
let block_context = match pre_process_block( | ||
&mut state, | ||
Some(block_number_and_hash), | ||
block_info, | ||
chain_info, | ||
VersionedConstants::latest_constants().clone(), | ||
) { | ||
Ok(block_context) => block_context, | ||
Err(e) => return Err(eyre!("pre_process_block failed for block #{}: {}", block_number, e)), | ||
}; | ||
|
||
// TODO: contract_storage_map should be retrieved from where? | ||
let contract_storage_map = HashMap::default(); | ||
let execution_helper = ExecutionHelperWrapper::new( | ||
contract_storage_map, | ||
vec![], // TODO: vec of TransactionExecutionInfo, how to get it? | ||
&block_context, | ||
(Felt252::from_u64(block_number.0).unwrap(), snos_input.block_hash), | ||
); | ||
|
||
// 3. Import SNOS in Rust and execute it with the input data | ||
let (_cairo_pie, _snos_output) = match run_os( | ||
// TODO: what is this path? | ||
String::from("PATH/TO/THE/OS"), | ||
// TODO: which layout should we choose? | ||
LayoutName::plain, | ||
snos_input, | ||
block_context, | ||
execution_helper, | ||
) { | ||
Ok((cairo_pie, snos_output)) => (cairo_pie, snos_output), | ||
Err(e) => return Err(eyre!("Could not run SNOS for block #{}: {}", block_number, e)), | ||
}; | ||
|
||
// 3. Store the received PIE in DB | ||
// TODO: Store the PIE & the SnosOutput once S3 is implemented | ||
todo!() | ||
} | ||
|
||
async fn verify_job(&self, _config: &Config, _job: &mut JobItem) -> Result<JobVerificationStatus> { | ||
// No need for verification as of now. If we later on decide to outsource SNOS run | ||
// to another servicehow a, verify_job can be used to poll on the status of the job | ||
todo!() | ||
Ok(JobVerificationStatus::Verified) | ||
} | ||
|
||
fn max_process_attempts(&self) -> u64 { | ||
todo!() | ||
1 | ||
} | ||
|
||
fn max_verification_attempts(&self) -> u64 { | ||
todo!() | ||
// TODO: isn't 10 a lot? | ||
10 | ||
} | ||
|
||
fn verification_polling_delay_seconds(&self) -> u64 { | ||
todo!() | ||
// TODO: what is an average run time for SNOS? | ||
60 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we don't know the runtime yet but in the current implementation looks like we run in synchronously so verification delay can be like 1s There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah yes true - updated |
||
} | ||
} | ||
|
||
impl SnosJob { | ||
/// Get the block number that needs to be run with SNOS for the current | ||
/// job. | ||
fn get_block_number_from_metadata(&self, job: &JobItem) -> Result<BlockNumber> { | ||
let block_number: u64 = job | ||
.metadata | ||
.get(JOB_METADATA_SNOS_BLOCK) | ||
.ok_or_else(|| eyre!("Block number to run with SNOS must be specified (snos job #{})", job.internal_id))? | ||
.parse()?; | ||
Ok(BlockNumber(block_number)) | ||
} | ||
|
||
/// Retrieves the [StarknetOsInput] for the provided block number from Madara. | ||
fn get_snos_input_from_madara(&self, _config: &Config, block_number: &BlockNumber) -> Result<StarknetOsInput> { | ||
let raw_request = format!( | ||
r#"{{ | ||
"id": 1, | ||
"jsonrpc": "2.0", | ||
"method": "madara_getSnosInput", | ||
"params": [{{ "block_number": {} }}] | ||
}}"#, | ||
block_number | ||
); | ||
let _rpc_request = serde_json::from_str::<JsonRpcRequest>(&raw_request).expect("unable to parse request"); | ||
unimplemented!("Handler for madara_getSnosInput has not been implemented") | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
use rstest::rstest; | ||
|
||
#[cfg(test)] | ||
pub mod snos_job; | ||
|
||
#[cfg(test)] | ||
pub mod da_job; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ya if there's no verification then 10 would be a lot :)