Skip to content

Commit

Permalink
Katana RPC v0.6.0 (#1568)
Browse files Browse the repository at this point in the history
* wip

* v3 hash util funcs

* update

* update

* wip

* no errors

* fix test

* wip

* update

* update

* wip

* wip

* wip

* remove script
  • Loading branch information
kariy authored Feb 24, 2024
1 parent 8c5eecd commit 23e9234
Show file tree
Hide file tree
Showing 35 changed files with 1,305 additions and 408 deletions.
278 changes: 193 additions & 85 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,10 @@ semver = "1.0.5"
serde = { version = "1.0.192", features = [ "derive" ] }
serde_json = { version = "1.0", features = [ "arbitrary_precision" ] }
serde_with = "2.3.1"
similar-asserts = "1.5.0"
smol_str = { version = "0.2.0", features = [ "serde" ] }
sqlx = { version = "0.7.2", features = [ "chrono", "macros", "regexp", "runtime-async-std", "runtime-tokio", "sqlite", "uuid" ] }
starknet = "0.8.0"
starknet = "0.9.0"
starknet-crypto = "0.6.1"
starknet_api = "0.7.0-dev.0"
strum = "0.25"
Expand Down
38 changes: 29 additions & 9 deletions bin/katana/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ use clap_complete::Shell;
use common::parse::parse_socket_address;
use katana_core::backend::config::{Environment, StarknetConfig};
use katana_core::constants::{
DEFAULT_GAS_PRICE, DEFAULT_INVOKE_MAX_STEPS, DEFAULT_VALIDATE_MAX_STEPS,
DEFAULT_ETH_L1_GAS_PRICE, DEFAULT_INVOKE_MAX_STEPS, DEFAULT_SEQUENCER_ADDRESS,
DEFAULT_STRK_L1_GAS_PRICE, DEFAULT_VALIDATE_MAX_STEPS,
};
use katana_core::sequencer::SequencerConfig;
use katana_primitives::block::GasPrices;
use katana_primitives::chain::ChainId;
use katana_primitives::genesis::allocation::DevAllocationsGenerator;
use katana_primitives::genesis::constant::DEFAULT_PREFUNDED_ACCOUNT_BALANCE;
Expand Down Expand Up @@ -170,17 +172,21 @@ pub struct EnvironmentOptions {
#[arg(value_parser = ChainId::parse)]
pub chain_id: ChainId,

#[arg(long)]
#[arg(help = "The gas price.")]
pub gas_price: Option<u64>,

#[arg(long)]
#[arg(help = "The maximum number of steps available for the account validation logic.")]
pub validate_max_steps: Option<u32>,

#[arg(long)]
#[arg(help = "The maximum number of steps available for the account execution logic.")]
pub invoke_max_steps: Option<u32>,

#[arg(long = "eth-gas-price")]
#[arg(help = "The L1 ETH gas price.")]
pub l1_eth_gas_price: Option<u128>,

#[arg(long = "strk-gas-price")]
#[arg(help = "The L1 STRK gas price.")]
pub l1_strk_gas_price: Option<u128>,
}

impl KatanaArgs {
Expand Down Expand Up @@ -227,6 +233,11 @@ impl KatanaArgs {
}

pub fn starknet_config(&self) -> StarknetConfig {
let gas_price = GasPrices {
eth: self.starknet.environment.l1_eth_gas_price.unwrap_or(DEFAULT_ETH_L1_GAS_PRICE),
strk: self.starknet.environment.l1_strk_gas_price.unwrap_or(DEFAULT_STRK_L1_GAS_PRICE),
};

let genesis = match self.starknet.genesis.clone() {
Some(genesis) => genesis,
None => {
Expand All @@ -235,7 +246,12 @@ impl KatanaArgs {
.with_balance(DEFAULT_PREFUNDED_ACCOUNT_BALANCE)
.generate();

let mut genesis = Genesis::default();
let mut genesis = Genesis {
gas_prices: gas_price.clone(),
sequencer_address: *DEFAULT_SEQUENCER_ADDRESS,
..Default::default()
};

genesis.extend_allocations(accounts.into_iter().map(|(k, v)| (k, v.into())));
genesis
}
Expand All @@ -247,8 +263,8 @@ impl KatanaArgs {
fork_rpc_url: self.rpc_url.clone(),
fork_block_number: self.fork_block_number,
env: Environment {
gas_price,
chain_id: self.starknet.environment.chain_id,
gas_price: self.starknet.environment.gas_price.unwrap_or(DEFAULT_GAS_PRICE),
invoke_max_steps: self
.starknet
.environment
Expand All @@ -274,15 +290,18 @@ mod test {
fn default_block_context_from_args() {
let args = KatanaArgs::parse_from(["katana"]);
let block_context = args.starknet_config().block_env();
assert_eq!(block_context.l1_gas_prices.eth, DEFAULT_GAS_PRICE);
assert_eq!(block_context.l1_gas_prices.eth, DEFAULT_ETH_L1_GAS_PRICE);
assert_eq!(block_context.l1_gas_prices.strk, DEFAULT_STRK_L1_GAS_PRICE);
}

#[test]
fn custom_block_context_from_args() {
let args = KatanaArgs::parse_from([
"katana",
"--gas-price",
"--eth-gas-price",
"10",
"--strk-gas-price",
"20",
"--chain-id",
"SN_GOERLI",
"--validate-max-steps",
Expand All @@ -294,5 +313,6 @@ mod test {
let block_context = args.starknet_config().block_env();

assert_eq!(block_context.l1_gas_prices.eth, 10);
assert_eq!(block_context.l1_gas_prices.strk, 20);
}
}
2 changes: 1 addition & 1 deletion crates/benches/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub fn parse_calls(calls: Vec<BenchCall>, to: FieldElement) -> Vec<Call> {
.collect()
}

pub async fn estimate_calls(account: &OwnerAccount, calls: Vec<Call>) -> Result<u64> {
pub async fn estimate_calls(account: &OwnerAccount, calls: Vec<Call>) -> Result<FieldElement> {
let fee = account
.execute(calls)
.nonce(cached_nonce(account).await)
Expand Down
8 changes: 4 additions & 4 deletions crates/benches/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub fn estimate_gas_last(
account: &OwnerAccount,
calls: Vec<BenchCall>,
contract: FieldElement,
) -> Result<u64> {
) -> Result<FieldElement> {
let mut calls = parse_calls(calls, contract);
let all = calls.clone();
calls.pop().expect("Empty calls vector"); // remove last call
Expand All @@ -43,7 +43,7 @@ pub fn estimate_gas(
account: &OwnerAccount,
call: BenchCall,
contract: FieldElement,
) -> Result<u64> {
) -> Result<FieldElement> {
let calls = parse_calls(vec![call], contract);
let _rt = RUNTIME.enter();
block_on(async move { estimate_calls(account, calls).await })
Expand All @@ -53,7 +53,7 @@ pub fn estimate_gas_multiple(
account: &OwnerAccount,
calls: Vec<BenchCall>,
contract: FieldElement,
) -> Result<u64> {
) -> Result<FieldElement> {
let calls = parse_calls(calls, contract);
let _rt = RUNTIME.enter();
block_on(async move { estimate_calls(account, calls).await })
Expand All @@ -63,7 +63,7 @@ pub async fn estimate_gas_async(
account: &OwnerAccount,
calls: Vec<BenchCall>,
contract: FieldElement,
) -> Result<u64> {
) -> Result<FieldElement> {
let calls = parse_calls(calls, contract);
estimate_calls(account, calls).await
}
Expand Down
3 changes: 2 additions & 1 deletion crates/dojo-world/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ starknet.workspace = true
thiserror.workspace = true
tracing.workspace = true

cainome = { git = "https://github.com/cartridge-gg/cainome", tag = "v0.2.4", features = ["abigen-rs"] }
cainome = { git = "https://github.com/cartridge-gg/cainome", tag = "v0.2.5", features = [ "abigen-rs" ] }
dojo-types = { path = "../dojo-types", optional = true }
http = { version = "0.2.9", optional = true }
ipfs-api-backend-hyper = { git = "https://github.com/ferristseng/rust-ipfs-api", rev = "af2c17f7b19ef5b9898f458d97a90055c3605633", features = [ "with-hyper-rustls" ], optional = true }
Expand All @@ -36,6 +36,7 @@ url = { version = "2.2.2", optional = true }
assert_fs = "1.0.9"
assert_matches.workspace = true
dojo-test-utils = { path = "../dojo-test-utils" }
similar-asserts.workspace = true
tokio.workspace = true
toml.workspace = true

Expand Down
22 changes: 13 additions & 9 deletions crates/dojo-world/src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,15 +345,19 @@ fn parse_contracts_events(
let class_hash = data.next().expect("qed; missing class hash");
let address = data.next().expect("qed; missing address");

upgrades
.entry(address)
.and_modify(|(current_block, current_class_hash)| {
if *current_block < block_num {
*current_block = block_num;
*current_class_hash = class_hash;
}
})
.or_insert((block_num, class_hash));
// Events that do not have a block number are ignored because we are unable to evaluate
// whether the events happened before or after the latest event that has been processed.
if let Some(num) = block_num {
upgrades
.entry(address)
.and_modify(|(current_block, current_class_hash)| {
if *current_block < num {
*current_block = num;
*current_class_hash = class_hash;
}
})
.or_insert((num, class_hash));
}
});

upgrades.into_iter().map(|(addr, (_, class_hash))| (addr, class_hash)).collect()
Expand Down
100 changes: 96 additions & 4 deletions crates/dojo-world/src/manifest_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,39 +209,131 @@ fn parse_deployed_contracts_events_with_upgrade() {
EmittedEvent {
data: vec![felt!("0x66"), felt!("0x123")],
keys: vec![],
block_number: 2,
block_number: Some(2),
block_hash: Default::default(),
from_address: Default::default(),
transaction_hash: Default::default(),
},
EmittedEvent {
data: vec![felt!("0x69"), felt!("0x123")],
keys: vec![],
block_number: 9,
block_number: Some(9),
block_hash: Default::default(),
from_address: Default::default(),
transaction_hash: Default::default(),
},
EmittedEvent {
data: vec![felt!("0x77"), felt!("0x123")],
keys: vec![],
block_number: 5,
block_number: Some(5),
block_hash: Default::default(),
from_address: Default::default(),
transaction_hash: Default::default(),
},
EmittedEvent {
data: vec![felt!("0x88"), felt!("0x789")],
keys: vec![],
block_number: Some(5),
block_hash: Default::default(),
from_address: Default::default(),
transaction_hash: Default::default(),
},
];

let actual_contracts = parse_contracts_events(deployed_events, upgrade_events);
similar_asserts::assert_eq!(actual_contracts, expected_contracts);
}

#[test]
fn events_without_block_number_arent_parsed() {
let expected_contracts = vec![
Contract {
name: "".into(),
class_hash: felt!("0x66"),
address: Some(felt!("0x123")),
..Default::default()
},
Contract {
name: "".into(),
class_hash: felt!("0x2"),
address: Some(felt!("0x456")),
..Default::default()
},
Contract {
name: "".into(),
class_hash: felt!("0x3"),
address: Some(felt!("0x789")),
..Default::default()
},
];

let deployed_events = vec![
EmittedEvent {
data: vec![felt!("0x0"), felt!("0x1"), felt!("0x123")],
keys: vec![],
block_hash: Default::default(),
from_address: Default::default(),
block_number: Default::default(),
transaction_hash: Default::default(),
},
EmittedEvent {
data: vec![felt!("0x0"), felt!("0x2"), felt!("0x456")],
keys: vec![],
block_hash: Default::default(),
from_address: Default::default(),
block_number: Default::default(),
transaction_hash: Default::default(),
},
EmittedEvent {
data: vec![felt!("0x0"), felt!("0x3"), felt!("0x789")],
keys: vec![],
block_hash: Default::default(),
from_address: Default::default(),
block_number: Default::default(),
transaction_hash: Default::default(),
},
];

// only the first upgrade event has a block number and is parsed
// meaning that the second and third upgrade events are ignored
// and are not evaluated when parsing the remote contracts
let upgrade_events = vec![
EmittedEvent {
data: vec![felt!("0x66"), felt!("0x123")],
keys: vec![],
block_number: Some(2),
block_hash: Default::default(),
from_address: Default::default(),
transaction_hash: Default::default(),
},
EmittedEvent {
data: vec![felt!("0x69"), felt!("0x123")],
keys: vec![],
block_number: None,
block_hash: Default::default(),
from_address: Default::default(),
transaction_hash: Default::default(),
},
EmittedEvent {
data: vec![felt!("0x77"), felt!("0x123")],
keys: vec![],
block_number: None,
block_hash: Default::default(),
from_address: Default::default(),
transaction_hash: Default::default(),
},
EmittedEvent {
data: vec![felt!("0x88"), felt!("0x789")],
keys: vec![],
block_number: None,
block_hash: Default::default(),
from_address: Default::default(),
transaction_hash: Default::default(),
},
];

let actual_contracts = parse_contracts_events(deployed_events, upgrade_events);
assert_eq!(actual_contracts, expected_contracts);
similar_asserts::assert_eq!(actual_contracts, expected_contracts);
}

#[tokio::test(flavor = "multi_thread")]
Expand Down
23 changes: 12 additions & 11 deletions crates/dojo-world/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,9 +323,9 @@ mod tests {
get_default_test_starknet_config, SequencerConfig, TestSequencer,
};
use starknet::core::types::{
ExecutionResources, ExecutionResult, FieldElement, InvokeTransactionReceipt,
ExecutionResources, ExecutionResult, FeePayment, FieldElement, InvokeTransactionReceipt,
MaybePendingTransactionReceipt, PendingInvokeTransactionReceipt, PendingTransactionReceipt,
TransactionFinalityStatus, TransactionReceipt,
PriceUnit, TransactionFinalityStatus, TransactionReceipt,
};
use starknet::providers::jsonrpc::HttpTransport;
use starknet::providers::JsonRpcClient;
Expand All @@ -343,13 +343,14 @@ mod tests {
const EXECUTION_RESOURCES: ExecutionResources = ExecutionResources {
steps: 0,
memory_holes: None,
ec_op_builtin_applications: 0,
ecdsa_builtin_applications: 0,
keccak_builtin_applications: 0,
bitwise_builtin_applications: 0,
pedersen_builtin_applications: 0,
poseidon_builtin_applications: 0,
range_check_builtin_applications: 0,
ec_op_builtin_applications: Some(0),
ecdsa_builtin_applications: Some(0),
keccak_builtin_applications: Some(0),
bitwise_builtin_applications: Some(0),
pedersen_builtin_applications: Some(0),
poseidon_builtin_applications: Some(0),
range_check_builtin_applications: Some(0),
segment_arena_builtin: Some(0),
};

fn mock_receipt(
Expand All @@ -360,7 +361,7 @@ mod tests {
finality_status,
execution_result,
events: Default::default(),
actual_fee: Default::default(),
actual_fee: FeePayment { amount: Default::default(), unit: PriceUnit::Wei },
block_hash: Default::default(),
block_number: Default::default(),
messages_sent: Default::default(),
Expand All @@ -373,7 +374,7 @@ mod tests {
PendingTransactionReceipt::Invoke(PendingInvokeTransactionReceipt {
execution_result,
events: Default::default(),
actual_fee: Default::default(),
actual_fee: FeePayment { amount: Default::default(), unit: PriceUnit::Wei },
messages_sent: Default::default(),
transaction_hash: Default::default(),
execution_resources: EXECUTION_RESOURCES,
Expand Down
Loading

0 comments on commit 23e9234

Please sign in to comment.