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

Update JSON-RPC to v0.8.0 #630

Draft
wants to merge 50 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
9d8eea5
Add spec files for 0.8.0 [skip ci]
FabijanC Sep 24, 2024
47610ea
Introduce websocket support (#619)
FabijanC Oct 2, 2024
db9055b
Add starknet_getMessagesStatus (#621)
FabijanC Oct 11, 2024
fb8a645
Merge branch 'main' into json-rpc-v0.8.0
FabijanC Oct 15, 2024
9e5bc95
RPC 0.8.0: restructure errors (#627)
FabijanC Oct 21, 2024
fe92aeb
merge main into json-rpc-v0.8.0-main
marioiordanov Oct 23, 2024
17ff9f2
resolve compilation errors
marioiordanov Oct 23, 2024
c871374
fix integration tests
marioiordanov Oct 23, 2024
47bbdba
clippy
marioiordanov Oct 23, 2024
6e8a299
removed let [skip ci]
marioiordanov Oct 24, 2024
e4253e4
removed duplicated method [skip ci]
marioiordanov Oct 24, 2024
20cc809
remove duplicated test [skip ci]
marioiordanov Oct 24, 2024
5c8fdff
clippy
marioiordanov Oct 24, 2024
ca68187
clippy [skip ci]
marioiordanov Oct 24, 2024
fd01e81
Merge main into json-rpc-v0.8.0 (#632)
marioiordanov Oct 25, 2024
a4300a7
Merge branch 'json-rpc-v0.8.0' into json-rpc-merge
marioiordanov Oct 25, 2024
c61e183
starknet_getCompiledCasm (#633)
marioiordanov Oct 28, 2024
7fcbad5
Merge branch 'main' into json-rpc-v0.8.0
FabijanC Oct 29, 2024
6f86cf2
Merge branch 'main' into json-rpc-v0.8.0
FabijanC Oct 31, 2024
c5e3a61
Add WebSocket RPC methods: subscribeNewHeads, unsubscribe (#634)
FabijanC Nov 8, 2024
9f82187
Skip no-notification assertion in periodic block generation test [ski…
FabijanC Nov 8, 2024
c096337
Change RPC_SPEC_VERSION constant to 0.8.0-rc.0
FabijanC Nov 8, 2024
1cecb99
Revert "Change RPC_SPEC_VERSION constant to 0.8.0-rc.0"
FabijanC Nov 8, 2024
ca7741d
Fix param name in block subscription: block_id -> block
FabijanC Nov 8, 2024
bcf0944
Merge branch 'main' into json-rpc-v0.8.0
FabijanC Nov 11, 2024
0130117
Merge branch 'main' into json-rpc-v0.8.0
marioiordanov Nov 13, 2024
248d5e8
Merge branch 'main' into json-rpc-v0.8.0
marioiordanov Nov 13, 2024
a598805
Support subscribing to transaction status via ws (#646)
FabijanC Nov 15, 2024
ee3fdf2
Merge branch 'main' into json-rpc-v0.8.0
FabijanC Nov 21, 2024
d5eac77
Merge branch 'main' into json-rpc-v0.8.0
FabijanC Nov 21, 2024
0da16ff
Merge branch 'main' into json-rpc-v0.8.0
FabijanC Nov 21, 2024
979a986
Support pending transactions subscription (#647)
FabijanC Nov 22, 2024
55fe695
Support subscribing to events via ws (#652)
FabijanC Nov 27, 2024
6a07b69
Support reorg subscription (#653)
FabijanC Nov 28, 2024
74114a7
Apply v0.8.0-rc1 changes (#654)
FabijanC Nov 29, 2024
9241822
Merge branch 'main' into json-rpc-v0.8.0
FabijanC Dec 6, 2024
36e19d3
Reduce repetition in requires_notifying - leftover from merging main
FabijanC Dec 6, 2024
dd2e612
Use u64 for Subscription ID (#656)
FabijanC Dec 10, 2024
31b11ac
Add dummy `starknet_getStorageProof`, remove unused `Serialize` (#659)
FabijanC Dec 10, 2024
69f3342
Merge branch 'main' into json-rpc-v0.8.0 [skip ci]
FabijanC Dec 11, 2024
187bd7b
Introduce a socket collection abstraction (#661)
FabijanC Dec 11, 2024
f49f59b
Merge branch 'main' into json-rpc-v0.8.0
FabijanC Dec 11, 2024
cbf2798
Fix test: test_fork_if_origin_dies
FabijanC Dec 11, 2024
9ec4665
Merge branch 'main' into json-rpc-v0.8.0
FabijanC Dec 16, 2024
b102b6d
Merge branch 'main' into json-rpc-v0.8.0 [skip ci]
FabijanC Jan 2, 2025
1890781
Merge branch 'main' into json-rpc-v0.8.0
FabijanC Jan 2, 2025
f919e17
Merge branch 'main' into json-rpc-v0.8.0
FabijanC Jan 3, 2025
5f8f83b
Merge branch 'main' into json-rpc-v0.8.0
FabijanC Jan 8, 2025
6e16b77
Fix failing tests
FabijanC Jan 8, 2025
dd55971
Merge branch 'main' into json-rpc-v0.8.0
FabijanC Jan 10, 2025
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,414 changes: 899 additions & 515 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ keywords = ["starknet", "cairo", "testnet", "local", "server"]
[workspace.dependencies]

# axum
axum = { version = "0.7" }
axum = { version = "0.7", features = ["ws"] }
http-body-util = { version = "0.1" }
tower-http = { version = "0.5", features = ["full"] }

Expand Down Expand Up @@ -107,6 +107,7 @@ unsafe-libyaml = "0.2.10"
h2 = "0.4"

ethers = { version = "2.0.11" }
cargo-platform = "=0.1.8" # 0.1.9 is incompatible with rustc 1.76.0

openssl = { version = "0.10", features = ["vendored"] }

Expand All @@ -116,6 +117,7 @@ parking_lot = "0.12.3"
serial_test = "3.1.1"
hex = "0.4.3"
lazy_static = { version = "1.4.0" }
tokio-tungstenite = { version = "0.21.0" }
listeners = "0.2.1"

# https://github.com/paritytech/parity-scale-codec/issues/656
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Compiled using cairo 2.2.0
Compiled using cairo 2.8.0
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
use core::starknet::ContractAddress;

#[starknet::interface]
trait IPanickingContract<TContractState> {
fn create_panic(self: @TContractState, panic_reason: felt252);
fn create_panic_in_another_contract(self: @TContractState, address: ContractAddress, panic_reason: felt252);
}

#[starknet::contract]
mod PanickingContract {
use core::starknet::{ContractAddress, call_contract_syscall};

#[storage]
struct Storage {}

#[external(v0)]
#[abi(embed_v0)]
impl PanickingContract of super::IPanickingContract<ContractState> {
fn create_panic(self: @ContractState, panic_reason: felt252) {
panic_with_felt252(panic_reason);
}

fn create_panic_in_another_contract(self: @ContractState, address: ContractAddress, panic_reason: felt252) {
call_contract_syscall(
address,
selector!("create_panic"),
array![panic_reason].span()
).unwrap();
}
}
}

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion crates/starknet-devnet-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ description = "Starknet core logic for devnet"
[dependencies]
blockifier = { workspace = true, features = ["testing"] }
cairo-lang-starknet-classes = { workspace = true }
cairo-vm = { workspace = true }
clap = { workspace = true }
ethers = { workspace = true }
starknet_api = { workspace = true, features = ["testing"] }
Expand All @@ -28,7 +29,6 @@ tracing = { workspace = true }
indexmap = { workspace = true }
url = { workspace = true }
nonzero_ext = { workspace = true }
usc = { workspace = true }
parking_lot = { workspace = true }

# necessary for installing reqwest in Docker
Expand Down
8 changes: 8 additions & 0 deletions crates/starknet-devnet-core/src/blocks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,14 @@ impl StarknetBlock {
}
}

pub fn create_empty_accepted() -> Self {
Self {
header: BlockHeader::default(),
transaction_hashes: vec![],
status: BlockStatus::AcceptedOnL2,
}
}

pub(crate) fn set_block_number(&mut self, block_number: u64) {
self.header.block_number = BlockNumber(block_number)
}
Expand Down
22 changes: 11 additions & 11 deletions crates/starknet-devnet-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use starknet_types::contract_address::ContractAddress;
use starknet_types::contract_storage_key::ContractStorageKey;
use thiserror::Error;

use crate::stack_trace::{gen_tx_execution_error_trace, ErrorStack};

#[derive(Error, Debug)]
pub enum Error {
#[error(transparent)]
Expand All @@ -16,12 +18,10 @@ pub enum Error {
StateError(#[from] StateError),
#[error(transparent)]
BlockifierStateError(#[from] blockifier::state::errors::StateError),
#[error(transparent)]
BlockifierTransactionError(TransactionExecutionError),
#[error(transparent)]
BlockifierExecutionError(#[from] blockifier::execution::errors::EntryPointExecutionError),
#[error("{execution_error}")]
ExecutionError { execution_error: String, index: usize },
#[error("{0:?}")]
ContractExecutionError(ErrorStack),
#[error("Execution error in simulating transaction no. {failure_index}: {error_stack:?}")]
ContractExecutionErrorInSimulation { failure_index: usize, error_stack: ErrorStack },
#[error("Types error: {0}")]
TypesError(#[from] starknet_types::error::Error),
#[error("I/O error: {0}")]
Expand Down Expand Up @@ -96,8 +96,8 @@ pub enum StateError {

#[derive(Debug, Error)]
pub enum TransactionValidationError {
#[error("Provided max fee is not enough to cover the transaction cost.")]
InsufficientMaxFee,
#[error("The transaction's resources don't cover validation or the minimal transaction fee.")]
InsufficientResourcesForValidate,
#[error("Account transaction nonce is invalid.")]
InvalidTransactionNonce,
#[error("Account balance is not enough to cover the transaction cost.")]
Expand All @@ -123,7 +123,7 @@ impl From<TransactionExecutionError> for Error {
err @ TransactionExecutionError::DeclareTransactionError { .. } => {
Error::ClassAlreadyDeclared { msg: err.to_string() }
}
other => Self::BlockifierTransactionError(other),
other => Self::ContractExecutionError(gen_tx_execution_error_trace(&other)),
}
}
}
Expand All @@ -132,7 +132,7 @@ impl From<FeeCheckError> for Error {
fn from(value: FeeCheckError) -> Self {
match value {
FeeCheckError::MaxL1GasAmountExceeded { .. } | FeeCheckError::MaxFeeExceeded { .. } => {
TransactionValidationError::InsufficientMaxFee.into()
TransactionValidationError::InsufficientResourcesForValidate.into()
}
FeeCheckError::InsufficientFeeTokenBalance { .. } => {
TransactionValidationError::InsufficientAccountBalance.into()
Expand All @@ -148,7 +148,7 @@ impl From<TransactionFeeError> for Error {
| TransactionFeeError::MaxFeeTooLow { .. }
| TransactionFeeError::MaxL1GasPriceTooLow { .. }
| TransactionFeeError::MaxL1GasAmountTooLow { .. } => {
TransactionValidationError::InsufficientMaxFee.into()
TransactionValidationError::InsufficientResourcesForValidate.into()
}
TransactionFeeError::MaxFeeExceedsBalance { .. }
| TransactionFeeError::L1GasBoundsExceedBalance { .. } => {
Expand Down
2 changes: 2 additions & 0 deletions crates/starknet-devnet-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod error;
pub mod messaging;
mod predeployed_accounts;
pub mod raw_execution;
pub mod stack_trace;
pub mod starknet;
mod state;
mod system_contract;
Expand All @@ -18,3 +19,4 @@ mod utils;
pub mod utils;

pub use blocks::StarknetBlock;
pub use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass;
5 changes: 4 additions & 1 deletion crates/starknet-devnet-core/src/messaging/ethereum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use ethers::prelude::*;
use ethers::providers::{Http, Provider, ProviderError};
use ethers::types::{Address, BlockNumber, Log};
use k256::ecdsa::SigningKey;
use starknet_rs_core::types::Felt;
use starknet_rs_core::types::{Felt, Hash256};
use starknet_types::felt::felt_from_prefixed_hex;
use starknet_types::rpc::contract_address::ContractAddress;
use starknet_types::rpc::messaging::{MessageToL1, MessageToL2};
Expand Down Expand Up @@ -302,6 +302,7 @@ impl EthereumMessaging {
///
/// * `log` - The log to be converted.
pub fn message_to_l2_from_log(log: Log) -> DevnetResult<MessageToL2> {
let l1_transaction_hash = log.transaction_hash.map(|h| Hash256::from_bytes(h.to_fixed_bytes()));
let parsed_log = <LogMessageToL2 as EthLogDecode>::decode_log(&log.into()).map_err(|e| {
Error::MessagingError(MessagingError::EthersError(format!("Log parsing failed {}", e)))
})?;
Expand All @@ -318,6 +319,7 @@ pub fn message_to_l2_from_log(log: Log) -> DevnetResult<MessageToL2> {
}

Ok(MessageToL2 {
l1_transaction_hash,
l2_contract_address: contract_address,
entry_point_selector,
l1_contract_address: ContractAddress::new(from_address)?,
Expand Down Expand Up @@ -405,6 +407,7 @@ mod tests {
};

let expected_message = MessageToL2 {
l1_transaction_hash: None,
l1_contract_address: ContractAddress::new(
felt_from_prefixed_hex(from_address).unwrap(),
)
Expand Down
19 changes: 9 additions & 10 deletions crates/starknet-devnet-core/src/messaging/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
//! contract (`mockSendMessageFromL2` entrypoint).
use std::collections::HashMap;

use starknet_rs_core::types::{BlockId, ExecutionResult, Hash256};
use ethers::types::H256;
use starknet_rs_core::types::{BlockId, ExecutionResult, Felt, Hash256};
use starknet_types::rpc::messaging::{MessageToL1, MessageToL2};

use crate::error::{DevnetResult, Error, MessagingError};
Expand All @@ -54,13 +55,11 @@ pub struct MessagingBroker {
/// For each time a message is supposed to be sent to L1, it is stored in this
/// queue. The user may consume those messages using `consume_message_from_l2`
/// to actually test `MessageToL1` emitted without running L1 node.
///
/// Note:
/// `Hash256` is not directly supported as a HashMap key due to missing trait.
/// Using `String` instead.
pub l2_to_l1_messages_hashes: HashMap<String, u64>,
pub l2_to_l1_messages_hashes: HashMap<H256, u64>,
/// This list of messages that will be sent to L1 node at the next `postman/flush`.
pub l2_to_l1_messages_to_flush: Vec<MessageToL1>,
/// Mapping of L1 transaction hash to a chronological sequence of generated L2 transactions.
pub l1_to_l2_tx_hashes: HashMap<H256, Vec<Felt>>,
}

impl MessagingBroker {
Expand Down Expand Up @@ -142,7 +141,7 @@ impl Starknet {
}

for message in &messages {
let hash = format!("{}", message.hash());
let hash = H256(*message.hash().as_bytes());
let count = self.messaging.l2_to_l1_messages_hashes.entry(hash).or_insert(0);
*count += 1;
}
Expand Down Expand Up @@ -188,14 +187,14 @@ impl Starknet {
// Ensure latest messages are collected before consuming the message.
self.collect_messages_to_l1().await?;

let hash = format!("{}", message.hash());
let count = self.messaging.l2_to_l1_messages_hashes.entry(hash.clone()).or_insert(0);
let hash = H256(*message.hash().as_bytes());
let count = self.messaging.l2_to_l1_messages_hashes.entry(hash).or_insert(0);

if *count > 0 {
*count -= 1;
Ok(message.hash())
} else {
Err(Error::MessagingError(MessagingError::MessageToL1NotPresent(hash)))
Err(Error::MessagingError(MessagingError::MessageToL1NotPresent(hash.to_string())))
}
}

Expand Down
Loading