From 24271b398e993dae459f3169b4f280c088f181af Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Wed, 25 Feb 2026 17:13:48 +0200 Subject: [PATCH] fix: possibly fixed tx accounts --- Cargo.lock | 2 + bedrock/docker-compose.yml | 2 +- explorer_service/Cargo.toml | 3 + .../src/components/transaction_preview.rs | 14 ++-- .../src/pages/transaction_page.rs | 44 +++++++++-- indexer/service/protocol/Cargo.toml | 1 + indexer/service/protocol/src/lib.rs | 78 ++++++++++++++++++- indexer/service/rpc/Cargo.toml | 2 +- 8 files changed, 129 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5543243a..7d240a64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2721,6 +2721,7 @@ dependencies = [ "env_logger", "indexer_service_protocol", "indexer_service_rpc", + "itertools 0.14.0", "jsonrpsee", "leptos", "leptos_axum", @@ -3769,6 +3770,7 @@ dependencies = [ "schemars 1.2.1", "serde", "serde_with", + "sha2", ] [[package]] diff --git a/bedrock/docker-compose.yml b/bedrock/docker-compose.yml index cb93a624..93f5d485 100644 --- a/bedrock/docker-compose.yml +++ b/bedrock/docker-compose.yml @@ -11,7 +11,7 @@ services: image: ghcr.io/logos-blockchain/logos-blockchain@sha256:000982e751dfd346ca5346b8025c685fc3abc585079c59cde3bde7fd63100657 ports: # Map 0 port so that multiple instances can run on the same host - - "0:18080/tcp" + - "8080:18080/tcp" volumes: - ./scripts:/etc/logos-blockchain/scripts - ./kzgrs_test_params:/kzgrs_test_params:z diff --git a/explorer_service/Cargo.toml b/explorer_service/Cargo.toml index 219f2bc0..1dc989d0 100644 --- a/explorer_service/Cargo.toml +++ b/explorer_service/Cargo.toml @@ -50,6 +50,9 @@ clap = { workspace = true, features = ["derive"], optional = true } url = { workspace = true, optional = true } env_logger = { workspace = true, optional = true } +# Mandatory server side dependencies +itertools.workspace = true + [features] hydrate = ["leptos/hydrate"] ssr = [ diff --git a/explorer_service/src/components/transaction_preview.rs b/explorer_service/src/components/transaction_preview.rs index 68c1e86e..7fc98e77 100644 --- a/explorer_service/src/components/transaction_preview.rs +++ b/explorer_service/src/components/transaction_preview.rs @@ -19,14 +19,12 @@ pub fn TransactionPreview(transaction: Transaction) -> impl IntoView { let (type_name, type_class) = transaction_type_info(&transaction); // Get additional metadata based on transaction type + let affected_pub_account_ids = transaction + .affected_public_account_ids(); + let metadata = match &transaction { - Transaction::Public(tx) => { - let indexer_service_protocol::PublicTransaction { - hash: _, - message, - witness_set: _, - } = tx; - format!("{} accounts involved", message.account_ids.len()) + Transaction::Public(_) => { + format!("{} accounts involved", affected_pub_account_ids.len()) } Transaction::PrivacyPreserving(tx) => { let indexer_service_protocol::PrivacyPreservingTransaction { @@ -36,7 +34,7 @@ pub fn TransactionPreview(transaction: Transaction) -> impl IntoView { } = tx; format!( "{} public accounts, {} commitments", - message.public_account_ids.len(), + affected_pub_account_ids.len(), message.new_commitments.len() ) } diff --git a/explorer_service/src/pages/transaction_page.rs b/explorer_service/src/pages/transaction_page.rs index d0f1b4da..8ab33ff9 100644 --- a/explorer_service/src/pages/transaction_page.rs +++ b/explorer_service/src/pages/transaction_page.rs @@ -4,6 +4,7 @@ use indexer_service_protocol::{ HashType, PrivacyPreservingMessage, PrivacyPreservingTransaction, ProgramDeploymentMessage, ProgramDeploymentTransaction, PublicMessage, PublicTransaction, Transaction, WitnessSet, }; +use itertools::{EitherOrBoth, Itertools}; use leptos::prelude::*; use leptos_router::{components::A, hooks::use_params_map}; @@ -65,7 +66,9 @@ pub fn TransactionPage() -> impl IntoView { - {match tx { + { + let affected_pub_acc_ids = tx.affected_public_account_ids(); + match tx { Transaction::Public(ptx) => { let PublicTransaction { hash: _, @@ -74,7 +77,7 @@ pub fn TransactionPage() -> impl IntoView { } = ptx; let PublicMessage { program_id, - account_ids, + account_ids: _, nonces, instruction_data, } = message; @@ -113,11 +116,13 @@ pub fn TransactionPage() -> impl IntoView {

"Accounts"

- {account_ids + {affected_pub_acc_ids .into_iter() - .zip(nonces.into_iter()) - .map(|(account_id, nonce)| { - let account_id_str = account_id.to_string(); + .zip_longest(nonces.into_iter()) + .map(|maybe_pair| { + match maybe_pair { + EitherOrBoth::Both(account_id, nonce) => { + let account_id_str = account_id.to_string(); view! { } + } + EitherOrBoth::Left(account_id) => { + let account_id_str = account_id.to_string(); + view! { + + } + } + EitherOrBoth::Right(_) => { + view! { + + } + } + } }) .collect::>()}
diff --git a/indexer/service/protocol/Cargo.toml b/indexer/service/protocol/Cargo.toml index f9a3c2ad..2f787d2d 100644 --- a/indexer/service/protocol/Cargo.toml +++ b/indexer/service/protocol/Cargo.toml @@ -16,6 +16,7 @@ base64.workspace = true base58.workspace = true hex.workspace = true anyhow.workspace = true +sha2.workspace = true [features] # Enable conversion to/from NSSA core types diff --git a/indexer/service/protocol/src/lib.rs b/indexer/service/protocol/src/lib.rs index 8fdd3289..f13a51c5 100644 --- a/indexer/service/protocol/src/lib.rs +++ b/indexer/service/protocol/src/lib.rs @@ -3,13 +3,14 @@ //! Currently it mostly mimics types from `nssa_core`, but it's important to have a separate crate //! to define a stable interface for the indexer service RPCs which evolves in its own way. -use std::{fmt::Display, str::FromStr}; +use std::{collections::HashSet, fmt::Display, str::FromStr}; use anyhow::anyhow; use base58::{FromBase58 as _, ToBase58 as _}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_with::{DeserializeFromStr, SerializeDisplay}; +use sha2::{Digest, Sha256}; #[cfg(feature = "convert")] mod convert; @@ -53,6 +54,18 @@ pub struct AccountId { pub value: [u8; 32], } +impl From<&PublicKey> for AccountId { + fn from(key: &PublicKey) -> Self { + const PUBLIC_ACCOUNT_ID_PREFIX: &[u8; 32] = + b"/LEE/v0.3/AccountId/Public/\x00\x00\x00\x00\x00"; + + let mut hasher = Sha256::new(); + hasher.update(PUBLIC_ACCOUNT_ID_PREFIX); + hasher.update(key.0); + Self{ value: hasher.finalize().into()} + } +} + impl Display for AccountId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.value.to_base58()) @@ -148,6 +161,15 @@ impl Transaction { Transaction::ProgramDeployment(tx) => &tx.hash, } } + + /// Get affected public account ids + pub fn affected_public_account_ids(&self) -> Vec { + match self { + Transaction::Public(tx) => tx.affected_public_account_ids(), + Transaction::PrivacyPreserving(tx) => tx.affected_public_account_ids(), + Transaction::ProgramDeployment(tx) => tx.affected_public_account_ids(), + } + } } #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] @@ -157,6 +179,28 @@ pub struct PublicTransaction { pub witness_set: WitnessSet, } +impl PublicTransaction { + + + pub(crate) fn signer_account_ids(&self) -> Vec { + self.witness_set + .signatures_and_public_keys() + .iter() + .map(|(_, public_key)| AccountId::from(public_key)) + .collect() + } + + pub fn affected_public_account_ids(&self) -> Vec { + let mut acc_set = self + .signer_account_ids() + .into_iter() + .collect::>(); + acc_set.extend(&self.message.account_ids); + + acc_set.into_iter().collect() + } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] pub struct PrivacyPreservingTransaction { pub hash: HashType, @@ -164,6 +208,26 @@ pub struct PrivacyPreservingTransaction { pub witness_set: WitnessSet, } +impl PrivacyPreservingTransaction { + pub(crate) fn signer_account_ids(&self) -> Vec { + self.witness_set + .signatures_and_public_keys() + .iter() + .map(|(_, public_key)| AccountId::from(public_key)) + .collect() + } + + pub fn affected_public_account_ids(&self) -> Vec { + let mut acc_set = self + .signer_account_ids() + .into_iter() + .collect::>(); + acc_set.extend(&self.message.public_account_ids); + + acc_set.into_iter().collect() + } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] pub struct PublicMessage { pub program_id: ProgramId, @@ -190,6 +254,12 @@ pub struct WitnessSet { pub proof: Proof, } +impl WitnessSet { + pub fn signatures_and_public_keys(&self) -> &[(Signature, PublicKey)] { + &self.signatures_and_public_keys + } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] pub struct Proof( #[serde(with = "base64")] @@ -210,6 +280,12 @@ pub struct ProgramDeploymentTransaction { pub message: ProgramDeploymentMessage, } +impl ProgramDeploymentTransaction { + pub fn affected_public_account_ids(&self) -> Vec { + vec![] + } +} + pub type ViewTag = u8; #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] diff --git a/indexer/service/rpc/Cargo.toml b/indexer/service/rpc/Cargo.toml index 2bed63ae..b2194882 100644 --- a/indexer/service/rpc/Cargo.toml +++ b/indexer/service/rpc/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" license = { workspace = true } [dependencies] -indexer_service_protocol = { workspace = true } +indexer_service_protocol = { workspace = true, features = ["convert"] } jsonrpsee = { workspace = true, features = ["macros"] } serde_json.workspace = true