Merge branch 'main' into schouhy/add-block-context

This commit is contained in:
Sergio Chouhy
2026-03-20 09:52:16 -03:00
126 changed files with 2226 additions and 3575 deletions
-1
View File
@@ -21,7 +21,6 @@ log.workspace = true
jsonrpsee.workspace = true
serde_json.workspace = true
futures.workspace = true
async-trait = "0.1.89"
arc-swap = "1.8.1"
[features]
+65 -65
View File
@@ -11,50 +11,50 @@
"channel_id": "0101010101010101010101010101010101010101010101010101010101010101",
"initial_accounts": [
{
"account_id": "6iArKUXxhUJqS7kCaPNhwMWt3ro71PDyBj7jwAyE2VQV",
"account_id": "CbgR6tj5kWx5oziiFptM7jMvrQeYY3Mzaao6ciuhSr2r",
"balance": 10000
},
{
"account_id": "7wHg9sbJwc6h3NP1S9bekfAzB8CHifEcxKswCKUt3YQo",
"account_id": "2RHZhw9h534Zr3eq2RGhQete2Hh667foECzXPmSkGni2",
"balance": 20000
}
],
"initial_commitments": [
{
"npk":[
177,
64,
1,
"npk": [
139,
19,
158,
11,
87,
38,
254,
159,
155,
231,
165,
1,
94,
64,
137,
243,
76,
249,
101,
251,
129,
33,
101,
189,
30,
42,
11,
191,
34,
103,
186,
227,
230
] ,
85,
206,
132,
228,
220,
114,
145,
89,
113,
156,
238,
142,
242,
74,
182,
91,
43,
100,
6,
190,
31,
15,
31,
88,
96,
204
],
"account": {
"program_owner": [
0,
@@ -73,38 +73,38 @@
},
{
"npk": [
32,
67,
72,
164,
106,
53,
66,
239,
141,
15,
52,
230,
136,
177,
2,
236,
207,
243,
173,
134,
135,
210,
143,
87,
232,
33,
223,
54,
226,
10,
71,
215,
128,
194,
120,
113,
224,
4,
165
254,
143,
172,
24,
244,
243,
208,
65,
112,
118,
70,
217,
240,
69,
100,
129,
3,
121,
25,
213,
132,
42,
45
],
"account": {
"program_owner": [
@@ -157,4 +157,4 @@
37,
37
]
}
}
+15 -16
View File
@@ -363,12 +363,16 @@ impl From<ProgramDeploymentMessage> for nssa::program_deployment_transaction::Me
// WitnessSet conversions
// ============================================================================
impl TryFrom<nssa::public_transaction::WitnessSet> for WitnessSet {
type Error = ();
fn try_from(_value: nssa::public_transaction::WitnessSet) -> Result<Self, Self::Error> {
// Public transaction witness sets don't have proofs, so we can't convert them directly
Err(())
impl From<nssa::public_transaction::WitnessSet> for WitnessSet {
fn from(value: nssa::public_transaction::WitnessSet) -> Self {
Self {
signatures_and_public_keys: value
.signatures_and_public_keys()
.iter()
.map(|(sig, pk)| (sig.clone().into(), pk.clone().into()))
.collect(),
proof: None,
}
}
}
@@ -380,7 +384,7 @@ impl From<nssa::privacy_preserving_transaction::witness_set::WitnessSet> for Wit
.into_iter()
.map(|(sig, pk)| (sig.into(), pk.into()))
.collect(),
proof: proof.into(),
proof: Some(proof.into()),
}
}
}
@@ -400,7 +404,9 @@ impl TryFrom<WitnessSet> for nssa::privacy_preserving_transaction::witness_set::
Ok(Self::from_raw_parts(
signatures_and_public_keys,
proof.into(),
proof
.map(Into::into)
.ok_or_else(|| nssa::error::NssaError::InvalidInput("Missing proof".to_owned()))?,
))
}
}
@@ -420,14 +426,7 @@ impl From<nssa::PublicTransaction> for PublicTransaction {
Self {
hash,
message: message.into(),
witness_set: WitnessSet {
signatures_and_public_keys: witness_set
.signatures_and_public_keys()
.iter()
.map(|(sig, pk)| (sig.clone().into(), pk.clone().into()))
.collect(),
proof: Proof(vec![]), // Public transactions don't have proofs
},
witness_set: witness_set.into(),
}
}
}
+1 -1
View File
@@ -241,7 +241,7 @@ pub struct PrivacyPreservingMessage {
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
pub struct WitnessSet {
pub signatures_and_public_keys: Vec<(Signature, PublicKey)>,
pub proof: Proof,
pub proof: Option<Proof>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
+9 -3
View File
@@ -30,16 +30,22 @@ pub trait Rpc {
async fn get_last_finalized_block_id(&self) -> Result<BlockId, ErrorObjectOwned>;
#[method(name = "getBlockById")]
async fn get_block_by_id(&self, block_id: BlockId) -> Result<Block, ErrorObjectOwned>;
async fn get_block_by_id(&self, block_id: BlockId) -> Result<Option<Block>, ErrorObjectOwned>;
#[method(name = "getBlockByHash")]
async fn get_block_by_hash(&self, block_hash: HashType) -> Result<Block, ErrorObjectOwned>;
async fn get_block_by_hash(
&self,
block_hash: HashType,
) -> Result<Option<Block>, ErrorObjectOwned>;
#[method(name = "getAccount")]
async fn get_account(&self, account_id: AccountId) -> Result<Account, ErrorObjectOwned>;
#[method(name = "getTransaction")]
async fn get_transaction(&self, tx_hash: HashType) -> Result<Transaction, ErrorObjectOwned>;
async fn get_transaction(
&self,
tx_hash: HashType,
) -> Result<Option<Transaction>, ErrorObjectOwned>;
#[method(name = "getBlocks")]
async fn get_blocks(
+7 -9
View File
@@ -3,7 +3,7 @@ use std::net::SocketAddr;
use anyhow::{Context as _, Result};
pub use indexer_core::config::*;
use indexer_service_rpc::RpcServer as _;
use jsonrpsee::server::Server;
use jsonrpsee::server::{Server, ServerHandle};
use log::{error, info};
pub mod service;
@@ -13,10 +13,11 @@ pub mod mock_service;
pub struct IndexerHandle {
addr: SocketAddr,
server_handle: Option<jsonrpsee::server::ServerHandle>,
/// Option because of `Drop` which forbids to simply move out of `self` in `stopped()`.
server_handle: Option<ServerHandle>,
}
impl IndexerHandle {
const fn new(addr: SocketAddr, server_handle: jsonrpsee::server::ServerHandle) -> Self {
const fn new(addr: SocketAddr, server_handle: ServerHandle) -> Self {
Self {
addr,
server_handle: Some(server_handle),
@@ -28,6 +29,7 @@ impl IndexerHandle {
self.addr
}
/// Wait for all Indexer tasks to stop.
pub async fn stopped(mut self) {
let handle = self
.server_handle
@@ -37,15 +39,11 @@ impl IndexerHandle {
handle.stopped().await;
}
#[expect(
clippy::redundant_closure_for_method_calls,
reason = "Clippy suggested path jsonrpsee::jsonrpsee_server::ServerHandle is not accessible"
)]
#[must_use]
pub fn is_stopped(&self) -> bool {
pub fn is_healthy(&self) -> bool {
self.server_handle
.as_ref()
.is_none_or(|handle| handle.is_stopped())
.is_some_and(|handle| !handle.is_stopped())
}
}
+23 -23
View File
@@ -15,7 +15,10 @@ use indexer_service_protocol::{
ProgramDeploymentTransaction, ProgramId, PublicMessage, PublicTransaction, Signature,
Transaction, ValidityWindow, WitnessSet,
};
use jsonrpsee::{core::SubscriptionResult, types::ErrorObjectOwned};
use jsonrpsee::{
core::{SubscriptionResult, async_trait},
types::ErrorObjectOwned,
};
/// A mock implementation of the `IndexerService` RPC for testing purposes.
pub struct MockIndexerService {
@@ -92,7 +95,7 @@ impl MockIndexerService {
},
witness_set: WitnessSet {
signatures_and_public_keys: vec![],
proof: indexer_service_protocol::Proof(vec![0; 32]),
proof: None,
},
}),
// PrivacyPreserving transactions
@@ -125,7 +128,7 @@ impl MockIndexerService {
},
witness_set: WitnessSet {
signatures_and_public_keys: vec![],
proof: indexer_service_protocol::Proof(vec![0; 32]),
proof: Some(indexer_service_protocol::Proof(vec![0; 32])),
},
}),
// ProgramDeployment transactions (rare)
@@ -172,7 +175,7 @@ impl MockIndexerService {
}
}
#[async_trait::async_trait]
#[async_trait]
impl indexer_service_rpc::RpcServer for MockIndexerService {
async fn subscribe_to_finalized_blocks(
&self,
@@ -199,26 +202,23 @@ impl indexer_service_rpc::RpcServer for MockIndexerService {
})
}
async fn get_block_by_id(&self, block_id: BlockId) -> Result<Block, ErrorObjectOwned> {
self.blocks
async fn get_block_by_id(&self, block_id: BlockId) -> Result<Option<Block>, ErrorObjectOwned> {
Ok(self
.blocks
.iter()
.find(|b| b.header.block_id == block_id)
.cloned()
.ok_or_else(|| {
ErrorObjectOwned::owned(
-32001,
format!("Block with ID {block_id} not found"),
None::<()>,
)
})
.cloned())
}
async fn get_block_by_hash(&self, block_hash: HashType) -> Result<Block, ErrorObjectOwned> {
self.blocks
async fn get_block_by_hash(
&self,
block_hash: HashType,
) -> Result<Option<Block>, ErrorObjectOwned> {
Ok(self
.blocks
.iter()
.find(|b| b.header.hash == block_hash)
.cloned()
.ok_or_else(|| ErrorObjectOwned::owned(-32001, "Block with hash not found", None::<()>))
.cloned())
}
async fn get_account(&self, account_id: AccountId) -> Result<Account, ErrorObjectOwned> {
@@ -228,11 +228,11 @@ impl indexer_service_rpc::RpcServer for MockIndexerService {
.ok_or_else(|| ErrorObjectOwned::owned(-32001, "Account not found", None::<()>))
}
async fn get_transaction(&self, tx_hash: HashType) -> Result<Transaction, ErrorObjectOwned> {
self.transactions
.get(&tx_hash)
.map(|(tx, _)| tx.clone())
.ok_or_else(|| ErrorObjectOwned::owned(-32001, "Transaction not found", None::<()>))
async fn get_transaction(
&self,
tx_hash: HashType,
) -> Result<Option<Transaction>, ErrorObjectOwned> {
Ok(self.transactions.get(&tx_hash).map(|(tx, _)| tx.clone()))
}
async fn get_blocks(
+14 -8
View File
@@ -7,7 +7,7 @@ use indexer_core::{IndexerCore, config::IndexerConfig};
use indexer_service_protocol::{Account, AccountId, Block, BlockId, HashType, Transaction};
use jsonrpsee::{
SubscriptionSink,
core::{Serialize, SubscriptionResult},
core::{Serialize, SubscriptionResult, async_trait},
types::{ErrorCode, ErrorObject, ErrorObjectOwned},
};
use log::{debug, error, info, warn};
@@ -30,7 +30,7 @@ impl IndexerService {
}
}
#[async_trait::async_trait]
#[async_trait]
impl indexer_service_rpc::RpcServer for IndexerService {
async fn subscribe_to_finalized_blocks(
&self,
@@ -52,22 +52,25 @@ impl indexer_service_rpc::RpcServer for IndexerService {
self.indexer.store.get_last_block_id().map_err(db_error)
}
async fn get_block_by_id(&self, block_id: BlockId) -> Result<Block, ErrorObjectOwned> {
async fn get_block_by_id(&self, block_id: BlockId) -> Result<Option<Block>, ErrorObjectOwned> {
Ok(self
.indexer
.store
.get_block_at_id(block_id)
.map_err(db_error)?
.into())
.map(Into::into))
}
async fn get_block_by_hash(&self, block_hash: HashType) -> Result<Block, ErrorObjectOwned> {
async fn get_block_by_hash(
&self,
block_hash: HashType,
) -> Result<Option<Block>, ErrorObjectOwned> {
Ok(self
.indexer
.store
.get_block_by_hash(block_hash.0)
.map_err(db_error)?
.into())
.map(Into::into))
}
async fn get_account(&self, account_id: AccountId) -> Result<Account, ErrorObjectOwned> {
@@ -80,13 +83,16 @@ impl indexer_service_rpc::RpcServer for IndexerService {
.into())
}
async fn get_transaction(&self, tx_hash: HashType) -> Result<Transaction, ErrorObjectOwned> {
async fn get_transaction(
&self,
tx_hash: HashType,
) -> Result<Option<Transaction>, ErrorObjectOwned> {
Ok(self
.indexer
.store
.get_transaction_by_hash(tx_hash.0)
.map_err(db_error)?
.into())
.map(Into::into))
}
async fn get_blocks(