Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
930620a
feat: update documentation for poseidon_hash_1 to reflect value_proof…
nol4lej May 19, 2026
90adc1e
feat: update circuit identifiers and public inputs for value proof op…
nol4lej May 19, 2026
764b068
feat: implement value proof circuit with public signals and proof str…
nol4lej May 19, 2026
f468920
feat: update ZkVerifierPort to replace disclosure proof with value pr…
nol4lej May 19, 2026
a531f41
Refactor shielded pool operations: remove audit and disclosure functi…
nol4lej May 19, 2026
6e82578
feat: update changelog, README, and runtime API for value proof integ…
nol4lej May 19, 2026
42bad8a
feat: implement claim_shielded_fees precompile with ABI decoding and …
nol4lej May 19, 2026
7f6c9a3
feat: add Chain RPC for general chain state queries and integrate wit…
nol4lej May 19, 2026
e5045ec
feat: add Orbinum relay functionality with shielded fees support
nol4lej May 19, 2026
399c239
feat: integrate Chain RPC and Relayer API for enhanced Ethereum compa…
nol4lej May 19, 2026
36d5a5f
feat: remove Orbinum relay RPC implementation and related code
nol4lej May 19, 2026
954926c
chore: update Cargo.lock staging-xcm 17.0.0 -> 17.0.1
nol4lej May 19, 2026
9a13e81
feat: remove unused CommitmentMemos import from benchmarking module
nol4lej May 19, 2026
1df70f6
feat: optimize public signals handling in claim_shielded_fees tests
nol4lej May 19, 2026
c48b886
feat: remove unused mock_evm_address_set function from testing module
nol4lej May 19, 2026
bd5e71b
feat: remove sync-circuit-artifacts.sh and generate-vk-rust.sh scripts
nol4lej May 19, 2026
7a3b12a
feat: update README to clarify value proofs and enhance privacy features
nol4lej May 19, 2026
d7b998b
Implement feature X to enhance user experience and optimize performance
nol4lej May 19, 2026
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
365 changes: 183 additions & 182 deletions Cargo.lock

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Orbinum Network

Orbinum is a privacy-focused blockchain network built on Substrate that enables confidential transactions with selective disclosure capabilities.
Orbinum is a privacy-focused blockchain network built on Substrate that enables confidential transactions with cryptographic value proofs.

## Overview

Orbinum combines the transparency benefits of blockchain technology with advanced cryptographic privacy features, allowing users to control what information they reveal while maintaining verifiable trust.
Orbinum combines the transparency benefits of blockchain technology with advanced cryptographic privacy features, allowing users to transact privately and prove specific note properties without revealing underlying data.

## Key Features

Expand All @@ -13,10 +13,10 @@ Orbinum combines the transparency benefits of blockchain technology with advance
- **Private Transfers**: Send and receive assets without revealing amounts, sender, or recipient
- **Shield/Unshield**: Move assets between transparent and private domains seamlessly

### Selective Disclosure
- **Proof Generation**: Create cryptographic proofs that reveal specific transaction properties without exposing underlying data
- **Compliance Tools**: Selectively disclose transaction details to authorized parties
- **Audit Trail**: Maintain verifiable records while preserving user privacy
### Value Proofs
- **Value Proof Circuit**: Cryptographic proof that a note commitment encodes the declared value and asset, used for relay fee claiming (`claim_shielded_fees`)
- **Proof of Note Ownership**: Any note owner can generate a value proof to demonstrate knowledge of a commitment's preimage without revealing the blinding factor
- **Audit Trail**: Maintain verifiable records for compliance while preserving user privacy

### EVM Compatibility
- **Frontier Integration**: Full Ethereum Virtual Machine compatibility layer
Expand All @@ -33,10 +33,10 @@ Orbinum combines the transparency benefits of blockchain technology with advance

Orbinum is built using Substrate's FRAME framework and implements Clean Architecture principles across all components:

- **Pallets**: Modular runtime components (`pallet-shielded-pool`, `pallet-zk-verifier`)
- **Pallets**: Modular runtime components (`pallet-shielded-pool`, `pallet-zk-verifier`, `pallet-relayer`)
- **Primitives**: Core cryptographic libraries (`zk-core`, `zk-verifier`, `zk-circuits`)
- **Client**: RPC layer and blockchain infrastructure
- **Circuits**: TypeScript/Circom zero-knowledge circuits
- **Circuits**: Circom zero-knowledge circuits (`value_proof`, `transfer`, `unshield`, `private_link`)

## License

Expand Down
63 changes: 50 additions & 13 deletions client/rpc-v2/src/README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
# fc-rpc-v2 — Orbinum Privacy RPC
# fc-rpc-v2 — Orbinum Custom RPC

Read-only JSON-RPC layer for the Orbinum shielded pool. Exposes five endpoints that query `pallet-shielded-pool` storage directly, without going through the Runtime API.
Read-only JSON-RPC layer for Orbinum-specific chain state. Endpoints query pallet storage directly, without going through the Runtime API — no runtime upgrade required to extend this layer.

## Crate layout

```
src/
├── lib.rs — crate root, re-exports public types
└── privacy.rs — all five endpoints, response types, and tests
├── lib.rs — crate root, re-exports public types
├── chain.rs — general chain state endpoints (`chain_*`)
└── privacy.rs — shielded-pool endpoints (`privacy_*`)
```

## Public API

### Server struct
All server structs share the same generic signature:

```rust
pub struct PrivacyRpc<C, B, BE> { ... }

impl<C, B, BE> PrivacyRpc<C, B, BE> {
pub fn new(client: Arc<C>) -> Self
}
pub struct PrivacyRpc<C, B, BE> { pub fn new(client: Arc<C>) -> Self }
pub struct ChainRpc<C, B, BE> { pub fn new(client: Arc<C>) -> Self }
```

Bounds required on the generic parameters:
Required bounds on generic parameters:

| Parameter | Required traits |
|-----------|----------------|
Expand All @@ -33,15 +31,46 @@ Bounds required on the generic parameters:
### Registering with the node

```rust
use fc_rpc_v2::{PrivacyApiServer, PrivacyRpc};
use fc_rpc_v2::{ChainApiServer, ChainRpc, PrivacyApiServer, PrivacyRpc};

io.merge(PrivacyRpc::new(client.clone()).into_rpc())?;
io.merge(ChainRpc::new(client.clone()).into_rpc())?;
```

---

## Endpoints

### `chain_isValidator`

Returns `true` if the given SS58-encoded account is an active Aura block author.

Reads `pallet_aura::Authorities` directly from storage — no runtime API call is made. Intended for UIs that need to gate actions (e.g. relayer registration) on validator eligibility without waiting for an extrinsic to fail.

**Parameters**

| Name | Type | Description |
|------|------|-------------|
| `account` | `String` | SS58-encoded account address |

**Result:** `bool`

```json
// request
{ "jsonrpc": "2.0", "method": "chain_isValidator", "params": ["5GrwvaEF..."], "id": 1 }

// response
{ "jsonrpc": "2.0", "result": true, "id": 1 }
```

**Storage read:** `Twox128("Aura") ++ Twox128("Authorities")` → SCALE `Vec<[u8; 32]>`

**Errors**
- `InvalidParams` — invalid SS58 address
- `InternalError` — storage decode failure

---

### `privacy_getMerkleRoot`

Returns the current Merkle tree root.
Expand Down Expand Up @@ -206,11 +235,19 @@ pub struct PoolStatsResponse {

## Storage access

All endpoints query `pallet-shielded-pool` storage directly using `sc_client_api::StorageProvider`. No Runtime API call is made, which means:
All endpoints query pallet storage directly using `sc_client_api::StorageProvider`. No Runtime API call is made, which means:

- No runtime upgrade required to add or change these endpoints.
- Keys are built with the standard Substrate hasher layout:

### `chain.rs` — `pallet_aura`

| Storage item | Key layout |
|---|---|
| `Authorities` | `Twox128("Aura") ++ Twox128("Authorities")` |

### `privacy.rs` — `pallet_shielded_pool`

| Storage item | Key layout | Hasher |
|---|---|---|
| `PoseidonRoot` | `Twox128("ShieldedPool") ++ Twox128("PoseidonRoot")` | — |
Expand Down
140 changes: 140 additions & 0 deletions client/rpc-v2/src/chain.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
//! Chain RPC — general chain state queries.
//!
//! Endpoints:
//! - `chain_isValidator` — returns `true` if the given SS58 account is an active Aura validator.

use jsonrpsee::{
core::RpcResult,
proc_macros::rpc,
types::error::{ErrorCode, ErrorObject},
};
use sc_client_api::StorageProvider as ScStorageProvider;
use scale_codec::Decode;
use sp_blockchain::HeaderBackend;
use sp_core::{crypto::Ss58Codec, hashing::twox_128, storage::StorageKey};
use sp_runtime::{traits::Block as BlockT, AccountId32};
use std::{marker::PhantomData, sync::Arc};

// ============================================================================
// Storage key helpers
// ============================================================================

/// `twox_128("Aura") ++ twox_128("Authorities")` — `StorageValue` key for `pallet_aura`.
fn aura_authorities_key() -> Vec<u8> {
[twox_128(b"Aura"), twox_128(b"Authorities")].concat()
}

fn read_storage<B: BlockT, C: ScStorageProvider<B, BE>, BE: sc_client_api::Backend<B>>(
client: &C,
hash: B::Hash,
key: Vec<u8>,
) -> RpcResult<Option<Vec<u8>>> {
ScStorageProvider::storage(client, hash, &StorageKey(key))
.map_err(internal_error)
.map(|opt| opt.map(|data| data.0))
}

// ============================================================================
// RPC trait
// ============================================================================

#[rpc(server)]
pub trait ChainApi {
/// Returns `true` if the given SS58-encoded account is an active Aura validator.
///
/// Reads `pallet_aura::Authorities` directly from storage at the best known block.
/// No runtime API call is performed.
#[method(name = "chain_isValidator")]
fn is_validator(&self, account: String) -> RpcResult<bool>;
}

// ============================================================================
// RPC server struct
// ============================================================================

/// Chain RPC server for general Orbinum chain state queries.
pub struct ChainRpc<C, B, BE> {
client: Arc<C>,
_ph: PhantomData<(B, BE)>,
}

impl<C, B, BE> ChainRpc<C, B, BE> {
pub fn new(client: Arc<C>) -> Self {
Self {
client,
_ph: PhantomData,
}
}
}

// ============================================================================
// Error helpers
// ============================================================================

fn internal_error(msg: impl std::fmt::Display) -> ErrorObject<'static> {
ErrorObject::owned(
ErrorCode::InternalError.code(),
format!("Internal error: {msg}"),
None::<()>,
)
}

fn invalid_params(msg: impl std::fmt::Display) -> ErrorObject<'static> {
ErrorObject::owned(
ErrorCode::InvalidParams.code(),
format!("Invalid params: {msg}"),
None::<()>,
)
}

// ============================================================================
// Implementation
// ============================================================================

impl<C, B, BE> ChainApiServer for ChainRpc<C, B, BE>
where
C: HeaderBackend<B> + ScStorageProvider<B, BE> + Send + Sync + 'static,
B: BlockT,
BE: sc_client_api::Backend<B> + Send + Sync + 'static,
{
fn is_validator(&self, account: String) -> RpcResult<bool> {
// Parse SS58 address → 32-byte AccountId32.
let account_id = AccountId32::from_ss58check(&account)
.map_err(|e| invalid_params(format!("invalid SS58 address: {e:?}")))?;
let target: [u8; 32] = *account_id.as_ref();

// Read `Aura::Authorities` from storage at the best known block.
let best = self.client.info().best_hash;
let raw = read_storage(&*self.client, best, aura_authorities_key())?;

let Some(bytes) = raw else {
// Storage item absent → chain has no configured validators.
return Ok(false);
};

// SCALE-decode as `Vec<[u8; 32]>`.
// `AuraId = sr25519::Public`, which serialises as a plain 32-byte array.
let authorities = Vec::<[u8; 32]>::decode(&mut bytes.as_slice())
.map_err(|e| internal_error(format!("failed to decode Aura::Authorities: {e}")))?;

Ok(authorities.iter().any(|auth| auth == &target))
}
}

#[cfg(test)]
mod tests {
use super::aura_authorities_key;
use sp_core::hashing::twox_128;

#[test]
fn aura_authorities_key_is_32_bytes() {
assert_eq!(aura_authorities_key().len(), 32);
}

#[test]
fn aura_authorities_key_uses_correct_hashes() {
let key = aura_authorities_key();
assert_eq!(&key[..16], &twox_128(b"Aura"));
assert_eq!(&key[16..], &twox_128(b"Authorities"));
}
}
2 changes: 2 additions & 0 deletions client/rpc-v2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@
// Orbinum Privacy RPC
// ============================================================================

pub mod chain;
pub mod privacy;

pub use chain::{ChainApiServer, ChainRpc};
pub use privacy::{
AssetBalanceResponse, MerkleProofResponse, NullifierStatusResponse, PoolStatsResponse,
PrivacyApiServer, PrivacyRpc,
Expand Down
1 change: 1 addition & 0 deletions client/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ fp-evm = { workspace = true, features = ["default"] }
fp-rpc = { workspace = true, features = ["default"] }
fp-storage = { workspace = true, features = ["default"] }
pallet-evm = { workspace = true, features = ["default"] }
pallet-relayer-runtime-api = { workspace = true, features = ["std"] }
pallet-shielded-pool-runtime-api = { workspace = true, features = ["std"] }

[dev-dependencies]
Expand Down
Loading
Loading