Skip to content
Merged
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ More expansive patch notes and explanations may be found in the specific [pathfi
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased

### Changed

- `CANDIDATE` transaction status is deprecated and will never be returned by gateway or pathfinder. Using it as a filter in `subscribeNewTransactions` will fall back to `PRE_CONFIRMED` with a warning.

## [0.22.5] - 2026-06-08

### Added
Expand Down
38 changes: 12 additions & 26 deletions crates/pending-data/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,12 @@ pub struct PreLatestData {
pub state_update: StateUpdate,
}

/// Chain data observed in flight: the pre-confirmed block, an optional
/// pre-latest parent, and any candidate transactions.
/// Chain data observed in flight: the pre-confirmed block and an optional
/// pre-latest parent.
#[derive(Clone, Default, Debug, PartialEq)]
pub struct PendingBlocks {
pub pre_confirmed: PreConfirmedBlock,
pub pre_latest: Option<PreLatestData>,
pub candidate_transactions: Vec<Transaction>,
}

impl PendingBlocks {
Expand Down Expand Up @@ -127,8 +126,7 @@ impl PendingData {
}

/// Converts a pre-confirmed block from the gateway into pending data.
/// Candidate transactions are filtered out; the state update is composed
/// from the per-transaction diffs.
/// State update is composed from the per-transaction diffs.
pub fn try_from_pre_confirmed_block(
block: Box<starknet_gateway_types::reply::PreConfirmedBlock>,
number: BlockNumber,
Expand Down Expand Up @@ -161,13 +159,13 @@ impl PendingData {
.iter()
.map(|(receipt, _)| receipt.transaction_hash)
.collect();
let (pre_confirmed_transactions, candidate_transactions): (Vec<_>, Vec<_>) =
pre_confirmed_block
.transactions
.into_iter()
.partition(|tx| pre_confirmed_transaction_hashes.contains(&tx.hash));

if transaction_receipts.len() != pre_confirmed_transactions.len() {
for tx in &pre_confirmed_block.transactions {
if !pre_confirmed_transaction_hashes.contains(&tx.hash) {
anyhow::bail!("Missing transaction receipt for tx ({})", tx.hash);
}
}
if transaction_receipts.len() != pre_confirmed_block.transactions.len() {
anyhow::bail!("Mismatched transaction and receipt count in pre-confirmed block");
}
Comment thread
sistemd marked this conversation as resolved.

Expand Down Expand Up @@ -203,7 +201,7 @@ impl PendingData {
timestamp: pre_confirmed_block.timestamp,
starknet_version: pre_confirmed_block.starknet_version,
l1_da_mode: pre_confirmed_block.l1_da_mode.into(),
transactions: pre_confirmed_transactions,
transactions: pre_confirmed_block.transactions,
transaction_receipts,
};

Expand Down Expand Up @@ -249,7 +247,6 @@ impl PendingData {
blocks: Arc::new(PendingBlocks {
pre_confirmed: pre_confirmed_block,
pre_latest: pre_latest_data,
candidate_transactions,
}),
state_update: pre_confirmed_state_update,
aggregated_state_update,
Expand Down Expand Up @@ -286,7 +283,6 @@ impl PendingData {
Self {
blocks: Arc::new(PendingBlocks {
pre_confirmed: block,
candidate_transactions: vec![],
pre_latest: None,
}),
state_update: Arc::clone(&state_update),
Expand Down Expand Up @@ -402,10 +398,6 @@ impl PendingData {
self.blocks.pre_latest_tx_receipts_and_events()
}

pub fn candidate_transactions(&self) -> &[Transaction] {
&self.blocks.candidate_transactions
}

/// Look up a contract nonce across the aggregated pending state.
pub fn find_nonce(&self, contract_address: ContractAddress) -> Option<ContractNonce> {
self.aggregated_state_update()
Expand All @@ -422,19 +414,13 @@ impl PendingData {
.storage_value_with_provenance(contract_address, storage_address)
}

/// Look up a transaction by hash across pre-confirmed, candidate, and
/// pre-latest, in that order.
/// Look up a transaction by hash across pre-confirmed and pre-latest, in
/// that order.
pub fn find_transaction(&self, tx_hash: TransactionHash) -> Option<Transaction> {
self.pre_confirmed_transactions()
.iter()
.find(|tx| tx.hash == tx_hash)
.cloned()
.or_else(|| {
self.candidate_transactions()
.iter()
.find(|tx| tx.hash == tx_hash)
.cloned()
})
.or_else(|| {
self.pre_latest_transactions()
.and_then(|pre_latest| pre_latest.iter().find(|tx| tx.hash == tx_hash).cloned())
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

5 changes: 0 additions & 5 deletions crates/rpc/src/dto/receipt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use crate::{dto, RpcVersion};
pub enum TxnStatus {
Received,
Rejected,
Candidate,
PreConfirmed,
AcceptedOnL2,
AcceptedOnL1,
Expand Down Expand Up @@ -43,7 +42,6 @@ struct TxnExecutionStatusWithRevertReason<'a>(pub &'a pathfinder_common::receipt

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum TxnFinalityStatus {
Candidate,
PreConfirmed,
AcceptedOnL2,
AcceptedOnL1,
Expand Down Expand Up @@ -89,7 +87,6 @@ impl SerializeForVersion for TxnStatus {
match self {
TxnStatus::Received => "RECEIVED",
TxnStatus::Rejected => "REJECTED",
TxnStatus::Candidate => "CANDIDATE",
TxnStatus::PreConfirmed => "PRE_CONFIRMED",
TxnStatus::AcceptedOnL2 => "ACCEPTED_ON_L2",
TxnStatus::AcceptedOnL1 => "ACCEPTED_ON_L1",
Expand Down Expand Up @@ -136,7 +133,6 @@ impl SerializeForVersion for TxnExecutionStatusWithRevertReason<'_> {
impl SerializeForVersion for TxnFinalityStatus {
fn serialize(&self, serializer: Serializer) -> Result<crate::dto::Ok, crate::dto::Error> {
match self {
TxnFinalityStatus::Candidate => "CANDIDATE",
TxnFinalityStatus::PreConfirmed => "PRE_CONFIRMED",
TxnFinalityStatus::AcceptedOnL2 => "ACCEPTED_ON_L2",
TxnFinalityStatus::AcceptedOnL1 => "ACCEPTED_ON_L1",
Expand All @@ -149,7 +145,6 @@ impl crate::dto::DeserializeForVersion for TxnFinalityStatus {
fn deserialize(value: crate::dto::Value) -> Result<Self, serde_json::Error> {
let s: String = value.deserialize()?;
match s.as_str() {
"CANDIDATE" => Ok(Self::Candidate),
"ACCEPTED_ON_L1" => Ok(Self::AcceptedOnL1),
"ACCEPTED_ON_L2" => Ok(Self::AcceptedOnL2),
"PRE_CONFIRMED" => Ok(Self::PreConfirmed),
Expand Down
24 changes: 0 additions & 24 deletions crates/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -786,16 +786,6 @@ pub mod test_utils {
},
];

let candidate_transactions = vec![Transaction {
hash: transaction_hash_bytes!(b"candidate tx hash 0"),
variant: TransactionVariant::InvokeV0(InvokeTransactionV0 {
sender_address: contract_address_bytes!(b"candidate contract addr 0"),
entry_point_selector: entry_point_bytes!(b"entry point 0"),
entry_point_type: Some(EntryPointType::External),
..Default::default()
}),
}];

let transaction_receipts = vec![
(
Receipt {
Expand Down Expand Up @@ -907,7 +897,6 @@ pub mod test_utils {
l1_da_mode: L1DataAvailabilityMode::Calldata,
},
pre_latest: None,
candidate_transactions,
};

// The class definitions must be inserted into the database.
Expand Down Expand Up @@ -1142,16 +1131,6 @@ pub mod test_utils {
},
];

let candidate_transactions = vec![Transaction {
hash: transaction_hash_bytes!(b"candidate tx hash 0"),
variant: TransactionVariant::InvokeV0(InvokeTransactionV0 {
sender_address: contract_address_bytes!(b"candidate contract addr 0"),
entry_point_selector: entry_point_bytes!(b"entry point 0"),
entry_point_type: Some(EntryPointType::External),
..Default::default()
}),
}];

let pre_confirmed_tx_receipts = vec![
(
Receipt {
Expand Down Expand Up @@ -1267,7 +1246,6 @@ pub mod test_utils {
block: pre_latest_block,
state_update: pre_latest_state_update.clone(),
}),
candidate_transactions,
};

let aggregated_state_update = pre_latest_state_update
Expand Down Expand Up @@ -1741,7 +1719,5 @@ mod tests {
panic!("{failures:#?} were marked as excluded but are actually present");
}
}


}
}
1 change: 0 additions & 1 deletion crates/rpc/src/method/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,6 @@ mod tests {
l1_da_mode: L1DataAvailabilityMode::Blob.into(),
},
pre_latest: None,
candidate_transactions: vec![],
},
state_update,
aggregated_state_update,
Expand Down
2 changes: 1 addition & 1 deletion crates/rpc/src/method/get_messages_status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ pub async fn get_messages_status(
// transactions; the cases are kept for backwards
// compatibility - more explicit error handling can be
// added if/when they actually happen.
TxStatus::Received | TxStatus::Candidate => (FinalityStatus::Received, None),
TxStatus::Received => (FinalityStatus::Received, None),
TxStatus::Rejected { .. } => (FinalityStatus::Rejected, None),
TxStatus::PreConfirmed(ref exec_status) => {
(FinalityStatus::PreConfirmed, Some(exec_status.clone()))
Expand Down
43 changes: 0 additions & 43 deletions crates/rpc/src/method/get_transaction_by_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,49 +220,6 @@ mod tests {
}
}

#[rstest::rstest]
#[case::v06(RpcVersion::V06)]
#[case::v07(RpcVersion::V07)]
#[case::v08(RpcVersion::V08)]
#[case::v09(RpcVersion::V09)]
#[case::v10(RpcVersion::V10)]
#[tokio::test]
async fn candidate(#[case] version: RpcVersion) {
let context = RpcContext::for_tests_with_pre_confirmed().await;
let tx_hash = transaction_hash_bytes!(b"candidate tx hash 0");
let input = Input {
transaction_hash: tx_hash,
response_flags: TransactionResponseFlags::default(),
};
let result = get_transaction_by_hash(context, input, version).await;

match version {
RpcVersion::PathfinderV01 => unreachable!(),
RpcVersion::V06 | RpcVersion::V07 | RpcVersion::V08 => {
assert_matches::assert_matches!(
result,
Err(GetTransactionByHashError::TxnHashNotFound)
);
}
RpcVersion::V09 => {
let output_json = result.unwrap().serialize(Serializer { version }).unwrap();
let expected_json: serde_json::Value = serde_json::from_str(include_str!(
"../../fixtures/0.9.0/transactions/txn_candidate_hash_0.json"
))
.unwrap();
assert_eq!(output_json, expected_json);
}
RpcVersion::V10 => {
let output_json = result.unwrap().serialize(Serializer { version }).unwrap();
let expected_json: serde_json::Value = serde_json::from_str(include_str!(
"../../fixtures/0.10.0/transactions/txn_candidate_hash_0.json"
))
.unwrap();
assert_eq!(output_json, expected_json);
}
}
}

#[rstest::rstest]
#[case::v06(RpcVersion::V06)]
#[case::v07(RpcVersion::V07)]
Expand Down
Loading
Loading