diff --git a/crates/core/src/backend/storage.rs b/crates/core/src/backend/storage.rs
index 63cb36c0e..6d526058c 100644
--- a/crates/core/src/backend/storage.rs
+++ b/crates/core/src/backend/storage.rs
@@ -141,7 +141,7 @@ impl Blockchain {
// TODO: convert this to block number instead of BlockHashOrNumber so that it is easier to
// check if the requested block is within the supported range or not.
- let database = ForkedProvider::new(db, block_id, provider.clone());
+ let database = ForkedProvider::new(db, block_num, provider.clone());
// initialize parent fork block
//
diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs
index 15866a6ea..708abfb7e 100644
--- a/crates/primitives/src/block.rs
+++ b/crates/primitives/src/block.rs
@@ -52,7 +52,7 @@ pub enum ConfirmedBlockIdOrTag {
L1Accepted,
}
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum BlockHashOrNumber {
Hash(BlockHash),
diff --git a/crates/storage/fork/src/lib.rs b/crates/storage/fork/src/lib.rs
index 97a53c45e..78ee06856 100644
--- a/crates/storage/fork/src/lib.rs
+++ b/crates/storage/fork/src/lib.rs
@@ -14,7 +14,7 @@ use futures::channel::mpsc::{channel as async_channel, Receiver, SendError, Send
use futures::future::BoxFuture;
use futures::stream::Stream;
use futures::{Future, FutureExt};
-use katana_primitives::block::{BlockHashOrNumber, BlockIdOrTag};
+use katana_primitives::block::{BlockIdOrTag, BlockNumber};
use katana_primitives::class::{
ClassHash, CompiledClassHash, ComputeClassHashError, ContractClass,
ContractClassCompilationError,
@@ -68,10 +68,10 @@ struct Request
{
/// Each request consists of a payload and the sender half of a oneshot channel that will be used
/// to send the result back to the backend handle.
enum BackendRequest {
- Nonce(Request),
- Class(Request),
- ClassHash(Request),
- Storage(Request<(ContractAddress, StorageKey)>),
+ Nonce(Request<(ContractAddress, BlockNumber)>),
+ Class(Request<(ClassHash, BlockNumber)>),
+ ClassHash(Request<(ContractAddress, BlockNumber)>),
+ Storage(Request<((ContractAddress, StorageKey), BlockNumber)>),
// Test-only request kind for requesting the backend stats
#[cfg(test)]
Stats(OneshotSender),
@@ -79,30 +79,40 @@ enum BackendRequest {
impl BackendRequest {
/// Create a new request for fetching the nonce of a contract.
- fn nonce(address: ContractAddress) -> (BackendRequest, OneshotReceiver) {
+ fn nonce(
+ address: ContractAddress,
+ block_id: BlockNumber,
+ ) -> (BackendRequest, OneshotReceiver) {
let (sender, receiver) = oneshot();
- (BackendRequest::Nonce(Request { payload: address, sender }), receiver)
+ (BackendRequest::Nonce(Request { payload: (address, block_id), sender }), receiver)
}
/// Create a new request for fetching the class definitions of a contract.
- fn class(hash: ClassHash) -> (BackendRequest, OneshotReceiver) {
+ fn class(
+ hash: ClassHash,
+ block_id: BlockNumber,
+ ) -> (BackendRequest, OneshotReceiver) {
let (sender, receiver) = oneshot();
- (BackendRequest::Class(Request { payload: hash, sender }), receiver)
+ (BackendRequest::Class(Request { payload: (hash, block_id), sender }), receiver)
}
/// Create a new request for fetching the class hash of a contract.
- fn class_hash(address: ContractAddress) -> (BackendRequest, OneshotReceiver) {
+ fn class_hash(
+ address: ContractAddress,
+ block_id: BlockNumber,
+ ) -> (BackendRequest, OneshotReceiver) {
let (sender, receiver) = oneshot();
- (BackendRequest::ClassHash(Request { payload: address, sender }), receiver)
+ (BackendRequest::ClassHash(Request { payload: (address, block_id), sender }), receiver)
}
/// Create a new request for fetching the storage value of a contract.
fn storage(
address: ContractAddress,
key: StorageKey,
+ block_id: BlockNumber,
) -> (BackendRequest, OneshotReceiver) {
let (sender, receiver) = oneshot();
- (BackendRequest::Storage(Request { payload: (address, key), sender }), receiver)
+ (BackendRequest::Storage(Request { payload: ((address, key), block_id), sender }), receiver)
}
#[cfg(test)]
@@ -118,10 +128,10 @@ type BackendRequestFuture = BoxFuture<'static, BackendResponse>;
// This is used for request deduplication.
#[derive(Eq, Hash, PartialEq, Clone, Copy, Debug)]
enum BackendRequestIdentifier {
- Nonce(ContractAddress),
- Class(ClassHash),
- ClassHash(ContractAddress),
- Storage((ContractAddress, StorageKey)),
+ Nonce(ContractAddress, BlockNumber),
+ Class(ClassHash, BlockNumber),
+ ClassHash(ContractAddress, BlockNumber),
+ Storage((ContractAddress, StorageKey), BlockNumber),
}
/// The backend for the forked provider.
@@ -139,8 +149,6 @@ pub struct Backend {
queued_requests: VecDeque,
/// A channel for receiving requests from the [BackendHandle]s.
incoming: Receiver,
- /// Pinned block id for all requests.
- block_id: BlockHashOrNumber,
}
/////////////////////////////////////////////////////////////////
@@ -150,14 +158,11 @@ pub struct Backend {
impl Backend {
// TODO(kariy): create a `.start()` method start running the backend logic and let the users
// choose which thread to running it on instead of spawning the thread ourselves.
- /// Create a new [Backend] with the given provider and block id, and returns a handle to it. The
- /// backend will start processing requests immediately upon creation.
+ /// Create a new [Backend] with the given provider and returns a handle to it. The backend
+ /// will start processing requests immediately upon creation.
#[allow(clippy::new_ret_no_self)]
- pub fn new(
- provider: StarknetClient,
- block_id: BlockHashOrNumber,
- ) -> Result {
- let (handle, backend) = Self::new_inner(provider, block_id);
+ pub fn new(provider: StarknetClient) -> Result {
+ let (handle, backend) = Self::new_inner(provider);
thread::Builder::new()
.name("forking-backend".into())
@@ -175,14 +180,10 @@ impl Backend {
Ok(handle)
}
- fn new_inner(
- provider: StarknetClient,
- block_id: BlockHashOrNumber,
- ) -> (BackendClient, Backend) {
+ fn new_inner(provider: StarknetClient) -> (BackendClient, Backend) {
// Create async channel to receive requests from the handle.
let (tx, rx) = async_channel(100);
let backend = Backend {
- block_id,
incoming: rx,
provider: Arc::new(provider),
request_dedup_map: HashMap::new(),
@@ -196,20 +197,20 @@ impl Backend {
/// This method is responsible for transforming the incoming request
/// sent from a [BackendHandle] into a RPC request to the remote network.
fn handle_requests(&mut self, request: BackendRequest) {
- let block_id = BlockIdOrTag::from(self.block_id);
let provider = self.provider.clone();
// Check if there are similar requests in the queue before sending the request
match request {
- BackendRequest::Nonce(Request { payload, sender }) => {
- let req_key = BackendRequestIdentifier::Nonce(payload);
+ BackendRequest::Nonce(Request { payload: (address, block_id), sender }) => {
+ let req_key = BackendRequestIdentifier::Nonce(address, block_id);
+ let block_id = BlockIdOrTag::from(block_id);
self.dedup_request(
req_key,
sender,
Box::pin(async move {
let res = provider
- .get_nonce(block_id, payload)
+ .get_nonce(block_id, address)
.await
.map_err(|e| BackendError::StarknetProvider(Arc::new(e)));
@@ -218,8 +219,9 @@ impl Backend {
);
}
- BackendRequest::Storage(Request { payload: (addr, key), sender }) => {
- let req_key = BackendRequestIdentifier::Storage((addr, key));
+ BackendRequest::Storage(Request { payload: ((addr, key), block_id), sender }) => {
+ let req_key = BackendRequestIdentifier::Storage((addr, key), block_id);
+ let block_id = BlockIdOrTag::from(block_id);
self.dedup_request(
req_key,
@@ -235,15 +237,16 @@ impl Backend {
);
}
- BackendRequest::ClassHash(Request { payload, sender }) => {
- let req_key = BackendRequestIdentifier::ClassHash(payload);
+ BackendRequest::ClassHash(Request { payload: (address, block_id), sender }) => {
+ let req_key = BackendRequestIdentifier::ClassHash(address, block_id);
+ let block_id = BlockIdOrTag::from(block_id);
self.dedup_request(
req_key,
sender,
Box::pin(async move {
let res = provider
- .get_class_hash_at(block_id, payload)
+ .get_class_hash_at(block_id, address)
.await
.map_err(|e| BackendError::StarknetProvider(Arc::new(e)));
@@ -252,15 +255,16 @@ impl Backend {
);
}
- BackendRequest::Class(Request { payload, sender }) => {
- let req_key = BackendRequestIdentifier::Class(payload);
+ BackendRequest::Class(Request { payload: (hash, block_id), sender }) => {
+ let req_key = BackendRequestIdentifier::Class(hash, block_id);
+ let block_id = BlockIdOrTag::from(block_id);
self.dedup_request(
req_key,
sender,
Box::pin(async move {
let res = provider
- .get_class(block_id, payload)
+ .get_class(block_id, hash)
.await
.map_err(|e| BackendError::StarknetProvider(Arc::new(e)));
@@ -370,7 +374,6 @@ impl Debug for Backend {
.field("pending_requests", &self.pending_requests.len())
.field("queued_requests", &self.queued_requests.len())
.field("incoming", &self.incoming)
- .field("block", &self.block_id)
.finish()
}
}
@@ -417,9 +420,13 @@ impl Clone for BackendClient {
/////////////////////////////////////////////////////////////////
impl BackendClient {
- pub fn get_nonce(&self, address: ContractAddress) -> Result