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

Block generation period #491

Merged
merged 48 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
f72fc13
pending_state refactor
Jun 3, 2024
03e79a0
use starknet.pending_state
Jun 4, 2024
c701a02
Update mod.rs
Jun 4, 2024
953f9f8
update tests
Jun 4, 2024
7910c4d
Fix block on demand test
Jun 5, 2024
7a5c7b5
fix abort_block_state_revert test
Jun 5, 2024
4033e8a
Add get_nonce_of_first_predeployed_account
Jun 5, 2024
027d3b2
Update blocks.md
Jun 5, 2024
aecaf78
Merge branch 'main' into get-nonce-fix
Jun 5, 2024
9d3e256
update test
Jun 5, 2024
f7c2357
Update test_blocks_on_demand.rs
Jun 5, 2024
b6c9aa7
rename blocks_on_demand to block_generation
Jun 5, 2024
c9189ad
rename ON_DEMAND to on_demand
Jun 5, 2024
6ef93af
Fix tests
Jun 6, 2024
71d8b4f
Merge branch 'main' into block-generation-period
Jun 6, 2024
5636895
Adapt to --block-generation-on demand
Jun 7, 2024
5e37136
remove optional in block_generation
Jun 7, 2024
3453d84
Merge branch 'main' into block-generation-period
Jun 7, 2024
b59553f
add periodic_task problem
Jun 10, 2024
03783e8
Add BlockGeneration::Interval
Jun 10, 2024
4525c53
apply formatting
Jun 10, 2024
ccebd18
Add tokio join task logic
Jun 12, 2024
c48aa5c
remove prints and refactor
Jun 12, 2024
e066887
Add tests
Jun 12, 2024
f3ddcc5
Rename blocks on demand to blocks generation
Jun 12, 2024
f4011a6
Merge branch 'main' into block-generation-period
Jun 12, 2024
5f31865
remove prints
Jun 12, 2024
d532b07
remove test added via merge
Jun 12, 2024
f161834
rename timestamp to seconds
Jun 14, 2024
f8802ab
rename BlockGeneration to BlockGenerationOn
Jun 14, 2024
7b31780
Add error propagation
Jun 14, 2024
6741c29
add formatting
Jun 14, 2024
e07f02f
add generating block on time interval info
Jun 14, 2024
7fdd5f4
rename UniqueAutoDeletableFile
Jun 17, 2024
54396d5
rename UniqueAutoDeletableFile
Jun 17, 2024
6a42221
Add blocks_on_interval_transactions
Jun 17, 2024
3fcfd34
change arg help
Jun 17, 2024
619a440
Update mint_token.rs
Jun 17, 2024
48f3828
revert of 0.0.6 doc
Jun 17, 2024
30ecabb
Add of Automatic periodic block creation
Jun 17, 2024
c1290f7
Add cli block-generation-on tests
Jun 17, 2024
4c2d1d9
use try_join
Jun 17, 2024
bf85700
Revert "use try_join"
Jun 18, 2024
0ebca85
Revert "Revert "use try_join""
Jun 18, 2024
6008680
use join_all
Jun 18, 2024
1ea8817
apply formatting
Jun 18, 2024
77d6f20
Merge branch 'main' into block-generation-period
Jun 18, 2024
7e91216
Update Cargo.toml
Jun 18, 2024
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions crates/starknet-devnet-core/src/starknet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use blockifier::transaction::transactions::ExecutableTransaction;
use starknet_api::block::{BlockNumber, BlockStatus, BlockTimestamp, GasPrice, GasPricePerToken};
use starknet_api::core::SequencerContractAddress;
use starknet_api::transaction::Fee;
use starknet_config::BlockGenerationOn;
use starknet_rs_core::types::{
BlockId, BlockTag, ExecutionResult, MsgFromL1, TransactionExecutionStatus,
TransactionFinalityStatus,
Expand Down Expand Up @@ -475,8 +476,8 @@ impl Starknet {

self.transactions.insert(transaction_hash, transaction_to_add);

// create new block from pending one, only if block on-demand mode is disabled
if !self.config.blocks_on_demand {
// create new block from pending one, only in block generation transaction mode
if self.config.block_generation_on == BlockGenerationOn::Transaction {
self.generate_new_block_and_state(state_diff)?;
}

Expand Down
35 changes: 33 additions & 2 deletions crates/starknet-devnet-core/src/starknet/starknet_config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::num::NonZeroU128;

use clap::Error;
use serde::{Serialize, Serializer};
use starknet_types::chain_id::ChainId;
use starknet_types::contract_class::ContractClass;
Expand Down Expand Up @@ -30,6 +31,36 @@ pub enum StateArchiveCapacity {
Full,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum BlockGenerationOn {
Transaction,
Demand,
Interval(u64),
}

impl std::str::FromStr for BlockGenerationOn {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"transaction" => Ok(BlockGenerationOn::Transaction),
"demand" => Ok(BlockGenerationOn::Demand),
value => {
let interval_value = value
.parse::<u64>()
.map_err(|_| Error::new(clap::error::ErrorKind::InvalidValue))?;

if interval_value > 0 {
Ok(BlockGenerationOn::Interval(interval_value))
} else {
Err(Error::new(clap::error::ErrorKind::InvalidValue))
}
}
}
}
}

#[derive(Debug, Clone, Default, Serialize)]
pub struct ForkConfig {
#[serde(serialize_with = "serialize_config_url")]
Expand Down Expand Up @@ -79,7 +110,7 @@ pub struct StarknetConfig {
pub chain_id: ChainId,
pub dump_on: Option<DumpOn>,
pub dump_path: Option<String>,
pub blocks_on_demand: bool,
pub block_generation_on: BlockGenerationOn,
pub lite_mode: bool,
/// on initialization, re-execute loaded txs (if any)
#[serde(skip_serializing)]
Expand Down Expand Up @@ -109,7 +140,7 @@ impl Default for StarknetConfig {
chain_id: DEVNET_DEFAULT_CHAIN_ID,
dump_on: None,
dump_path: None,
blocks_on_demand: false,
block_generation_on: BlockGenerationOn::Transaction,
lite_mode: false,
re_execute_on_init: true,
state_archive: StateArchiveCapacity::default(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,7 @@ pub async fn mint(
.await
.map_err(|err| HttpApiError::MintingError { msg: err.to_string() })?;

let block_tag =
if starknet.config.blocks_on_demand { BlockTag::Pending } else { BlockTag::Latest };

let new_balance = get_balance(&mut starknet, request.address, erc20_address, block_tag)
let new_balance = get_balance(&mut starknet, request.address, erc20_address, BlockTag::Pending)
.map_err(|err| HttpApiError::MintingError { msg: err.to_string() })?;

Ok(Json(MintTokensResponse { new_balance: new_balance.to_str_radix(10), unit, tx_hash }))
Expand Down
1 change: 1 addition & 0 deletions crates/starknet-devnet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ url = { workspace = true }

# async
tokio = { workspace = true, features = ["signal"] }
futures = { workspace = true }

# tracing
tracing = { workspace = true }
Expand Down
52 changes: 43 additions & 9 deletions crates/starknet-devnet/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use starknet_core::constants::{
use starknet_core::contract_class_choice::{AccountClassWrapper, AccountContractClassChoice};
use starknet_core::random_number_generator::generate_u32_random_number;
use starknet_core::starknet::starknet_config::{
DumpOn, ForkConfig, StarknetConfig, StateArchiveCapacity,
BlockGenerationOn, DumpOn, ForkConfig, StarknetConfig, StateArchiveCapacity,
};
use starknet_types::chain_id::ChainId;
use tracing_subscriber::EnvFilter;
Expand Down Expand Up @@ -157,10 +157,16 @@ pub(crate) struct Args {
#[arg(help = "Specify the path to dump to;")]
dump_path: Option<String>,

#[arg(long = "blocks-on-demand")]
#[arg(env = "BLOCKS_ON_DEMAND")]
#[arg(help = "Introduces block generation on demand via /create_block endpoint;")]
blocks_on_demand: bool,
#[arg(long = "block-generation-on")]
#[arg(env = "BLOCK_GENERATION_ON")]
#[arg(default_value = "transaction")]
#[arg(help = "Specify when to generate a new block. Possible values are:
- \"transaction\" - new block generated on each transaction
- \"demand\" - new block creatable solely by sending a POST request to /create_block
- <INTERVAL> - a positive integer indicating after how many seconds a new block is generated

Sending POST /create_block is also an option in modes other than \"demand\".")]
block_generation_on: BlockGenerationOn,

#[arg(long = "state-archive-capacity")]
#[arg(env = "STATE_ARCHIVE_CAPACITY")]
Expand Down Expand Up @@ -220,7 +226,7 @@ impl Args {
chain_id: self.chain_id,
dump_on: self.dump_on,
dump_path: self.dump_path.clone(),
blocks_on_demand: self.blocks_on_demand,
block_generation_on: self.block_generation_on,
lite_mode: self.lite_mode,
re_execute_on_init: true,
state_archive: self.state_archive,
Expand Down Expand Up @@ -268,7 +274,7 @@ mod tests {
use starknet_core::constants::{
CAIRO_0_ERC20_CONTRACT_PATH, CAIRO_1_ACCOUNT_CONTRACT_SIERRA_PATH,
};
use starknet_core::starknet::starknet_config::StateArchiveCapacity;
use starknet_core::starknet::starknet_config::{BlockGenerationOn, StateArchiveCapacity};
use tracing_subscriber::EnvFilter;

use super::{Args, RequestResponseLogging};
Expand Down Expand Up @@ -528,6 +534,7 @@ mod tests {
("--fork-network", "FORK_NETWORK", "http://dummy.com"),
("--fork-block", "FORK_BLOCK", "42"),
("--request-body-size-limit", "REQUEST_BODY_SIZE_LIMIT", "100"),
("--block-generation-on", "BLOCK_GENERATION_ON", "demand"),
];

let mut cli_args = vec!["--"];
Expand Down Expand Up @@ -557,8 +564,7 @@ mod tests {
#[test]
FabijanC marked this conversation as resolved.
Show resolved Hide resolved
#[serial_test::serial]
fn test_boolean_param_specification_via_env_vars() {
let config_source =
[("--lite-mode", "LITE_MODE"), ("--blocks-on-demand", "BLOCKS_ON_DEMAND")];
let config_source = [("--lite-mode", "LITE_MODE")];

let mut cli_args = vec!["--"];
for (cli_param, _) in config_source {
Expand Down Expand Up @@ -586,4 +592,32 @@ mod tests {
std::env::remove_var(var_name);
}
}

#[test]
fn not_allowing_invalid_values_as_block_generation_interval() {
for interval in ["", "0", "-1", "abc"] {
match Args::try_parse_from(["--", "--block-generation-on", interval]) {
Err(_) => (),
Ok(parsed) => panic!("Should fail for {interval}; got: {parsed:?}"),
}
}
}

#[test]
fn allowing_valid_values_as_block_generation_interval() {
match Args::try_parse_from(["--", "--block-generation-on", "1"]) {
Ok(args) => assert_eq!(args.block_generation_on, BlockGenerationOn::Interval(1)),
Err(e) => panic!("Should have passed; got: {e}"),
}

match Args::try_parse_from(["--", "--block-generation-on", "demand"]) {
Ok(args) => assert_eq!(args.block_generation_on, BlockGenerationOn::Demand),
Err(e) => panic!("Should have passed; got: {e}"),
}

match Args::try_parse_from(["--", "--block-generation-on", "transaction"]) {
Ok(args) => assert_eq!(args.block_generation_on, BlockGenerationOn::Transaction),
Err(e) => panic!("Should have passed; got: {e}"),
}
}
}
62 changes: 55 additions & 7 deletions crates/starknet-devnet/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use anyhow::Ok;
use std::future::IntoFuture;
use std::result::Result::Ok;
use std::time::Duration;

use clap::Parser;
use cli::Args;
use futures::future::join_all;
use server::api::json_rpc::RPC_SPEC_VERSION;
use server::api::Api;
use server::server::serve_http_api_json_rpc;
Expand All @@ -9,7 +13,7 @@ use starknet_core::constants::{
CAIRO_1_ERC20_CONTRACT_CLASS_HASH, ETH_ERC20_CONTRACT_ADDRESS, STRK_ERC20_CONTRACT_ADDRESS,
UDC_CONTRACT_ADDRESS, UDC_CONTRACT_CLASS_HASH,
};
use starknet_core::starknet::starknet_config::{DumpOn, ForkConfig};
use starknet_core::starknet::starknet_config::{BlockGenerationOn, DumpOn, ForkConfig};
use starknet_core::starknet::Starknet;
use starknet_rs_core::types::{BlockId, BlockTag, MaybePendingBlockWithTxHashes};
use starknet_rs_providers::jsonrpc::HttpTransport;
Expand All @@ -18,6 +22,9 @@ use starknet_types::chain_id::ChainId;
use starknet_types::rpc::state::Balance;
use starknet_types::traits::ToHexString;
use tokio::net::TcpListener;
use tokio::signal::unix::{signal, SignalKind};
use tokio::task::{self};
use tokio::time::interval;
use tracing::{info, warn};
use tracing_subscriber::EnvFilter;

Expand Down Expand Up @@ -198,20 +205,61 @@ async fn main() -> Result<(), anyhow::Error> {

info!("Starknet Devnet listening on {}", address);

if starknet_config.dump_on == Some(DumpOn::Exit) {
server.with_graceful_shutdown(shutdown_signal(api.clone())).await?
} else {
server.await?
let mut tasks = vec![];

if let BlockGenerationOn::Interval(seconds) = starknet_config.block_generation_on {
// use JoinHandle to run block interval creation as a task
let block_interval_handle = task::spawn(create_block_interval(api.clone(), seconds));

tasks.push(block_interval_handle);
}

// run server also as a JoinHandle
let server_handle =
task::spawn(server.with_graceful_shutdown(shutdown_signal(api.clone())).into_future());
FabijanC marked this conversation as resolved.
Show resolved Hide resolved
tasks.push(server_handle);

// wait for ctrl + c signal (SIGINT)
shutdown_signal(api.clone()).await;

// join all tasks
let results = join_all(tasks).await;

// handle the results of the tasks
for result in results {
result??;
}

Ok(())
}

async fn create_block_interval(api: Api, block_interval: u64) -> Result<(), std::io::Error> {
let mut interval = interval(Duration::from_secs(block_interval));
let mut sigint = signal(SignalKind::interrupt()).expect("Failed to setup SIGINT handler");

loop {
tokio::select! {
_ = interval.tick() => {
let mut starknet = api.starknet.write().await;
info!("Generating block on time interval");

starknet.create_block_dump_event(None).map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?
}
_ = sigint.recv() => {
return Ok(())
}
}
}
}

pub async fn shutdown_signal(api: Api) {
tokio::signal::ctrl_c().await.expect("Failed to install CTRL+C signal handler");
FabijanC marked this conversation as resolved.
Show resolved Hide resolved

// dump on exit scenario
let starknet = api.starknet.read().await;
starknet.dump_events().expect("Failed to dump starknet transactions");
if starknet.config.dump_on == Some(DumpOn::Exit) {
starknet.dump_events().expect("Failed to dump starknet transactions");
}
}

#[cfg(test)]
Expand Down
5 changes: 3 additions & 2 deletions crates/starknet-devnet/tests/general_integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ mod general_integration_tests {
"timeout": 121,
"request_body_size_limit": 1000,
},
"blocks_on_demand": true,
"block_generation_on": "demand",
"lite_mode": false,
"disable_account_impersonation": false,
});
Expand Down Expand Up @@ -112,7 +112,8 @@ mod general_integration_tests {
&expected_config["dump_on"].as_str().unwrap(),
"--dump-path",
&expected_config["dump_path"].as_str().unwrap(),
"--blocks-on-demand",
"--block-generation-on",
"demand",
"--state-archive-capacity",
&expected_config["state_archive"].as_str().unwrap(),
"--host",
Expand Down
18 changes: 10 additions & 8 deletions crates/starknet-devnet/tests/test_advancing_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,11 @@ mod advancing_time_tests {
}

#[tokio::test]
async fn set_time_in_past_block_on_demand_mode() {
let devnet = BackgroundDevnet::spawn_with_additional_args(&["--blocks-on-demand"])
.await
.expect("Could not start Devnet");
async fn set_time_in_past_block_generation_on_demand() {
let devnet =
BackgroundDevnet::spawn_with_additional_args(&["--block-generation-on", "demand"])
.await
.expect("Could not start Devnet");

set_time_in_past(&devnet).await;
}
Expand Down Expand Up @@ -322,10 +323,11 @@ mod advancing_time_tests {
}

#[tokio::test]
async fn set_time_in_future_block_on_demand_mode() {
let devnet = BackgroundDevnet::spawn_with_additional_args(&["--blocks-on-demand"])
.await
.expect("Could not start Devnet");
async fn set_time_in_future_block_generation_on_demand() {
let devnet =
BackgroundDevnet::spawn_with_additional_args(&["--block-generation-on", "demand"])
.await
.expect("Could not start Devnet");

set_time_in_future(&devnet).await;
}
Expand Down
Loading