mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-06-02 23:29:34 +00:00
Merge pull request #499 from logos-blockchain/schouhy/logos-execution-environment-renaming
refactor!: rename nssa crate to lee
This commit is contained in:
commit
f3ab53460a
@ -13,8 +13,7 @@ ignore = [
|
||||
{ id = "RUSTSEC-2025-0055", reason = "`tracing-subscriber` v0.2.25 pulled in by ark-relations v0.4.0 - will be addressed before mainnet" },
|
||||
{ id = "RUSTSEC-2025-0141", reason = "`bincode` is unmaintained but continuing to use it." },
|
||||
{ id = "RUSTSEC-2023-0089", reason = "atomic-polyfill is pulled transitively via risc0-zkvm; waiting on upstream fix (see https://github.com/risc0/risc0/issues/3453)" },
|
||||
{ id = "RUSTSEC-2026-0097", reason = "`rand` v0.8.5 is present transitively from logos crates, modification may break integration" },
|
||||
{ id = "RUSTSEC-2026-0118", reason = "`hickory-proto` v0.25.0-alpha.5 is present transitively from logos crates, modification may break integration" },
|
||||
{ id = "RUSTSEC-2026-0118", reason = "`hickory-proto` v0.25.0-alpha.5 is present transitively from logos crates, modification may break integration" },
|
||||
{ id = "RUSTSEC-2026-0119", reason = "`hickory-proto` v0.25.0-alpha.5 is present transitively from logos crates, modification may break integration" },
|
||||
{ id = "RUSTSEC-2024-0370", reason = "transitive dependency of `logos-blockchain-http-api-common`, can't do anything than wait for upstream fix" },
|
||||
]
|
||||
|
||||
2
.github/workflows/bench-regression.yml
vendored
2
.github/workflows/bench-regression.yml
vendored
@ -3,7 +3,7 @@ on:
|
||||
paths:
|
||||
- "tools/crypto_primitives_bench/**"
|
||||
- "key_protocol/**"
|
||||
- "nssa/core/**"
|
||||
- "lee/core/**"
|
||||
- ".github/workflows/bench-regression.yml"
|
||||
|
||||
permissions:
|
||||
|
||||
@ -27,9 +27,9 @@ Allowed `type` values:
|
||||
- `revert`
|
||||
|
||||
Examples:
|
||||
- `feat(nssa): add private PDA support`
|
||||
- `feat(lee): add private PDA support`
|
||||
- `fix(wallet): correct fee calculation`
|
||||
- `feat(nssa)!: rename AccountId::from((prog, seed)) to AccountId::for_public_pda`
|
||||
- `feat(lee)!: rename AccountId::from((prog, seed)) to AccountId::for_public_pda`
|
||||
|
||||
Breaking changes:
|
||||
- Mark with `!` in the title.
|
||||
|
||||
1426
Cargo.lock
generated
1426
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
12
Cargo.toml
12
Cargo.toml
@ -6,13 +6,13 @@ resolver = "3"
|
||||
members = [
|
||||
"integration_tests",
|
||||
"storage",
|
||||
"key_protocol",
|
||||
"lee/key_protocol",
|
||||
"mempool",
|
||||
"wallet",
|
||||
"wallet-ffi",
|
||||
"common",
|
||||
"nssa",
|
||||
"nssa/core",
|
||||
"lee/state_machine",
|
||||
"lee/state_machine/core",
|
||||
"programs/amm/core",
|
||||
"programs/amm",
|
||||
"programs/clock/core",
|
||||
@ -50,12 +50,12 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.dependencies]
|
||||
nssa = { path = "nssa" }
|
||||
nssa_core = { path = "nssa/core" }
|
||||
lee = { path = "lee/state_machine" }
|
||||
lee_core = { path = "lee/state_machine/core" }
|
||||
common = { path = "common" }
|
||||
mempool = { path = "mempool" }
|
||||
storage = { path = "storage" }
|
||||
key_protocol = { path = "key_protocol" }
|
||||
key_protocol = { path = "lee/key_protocol" }
|
||||
sequencer_core = { path = "sequencer/core" }
|
||||
sequencer_service_protocol = { path = "sequencer/service/protocol" }
|
||||
sequencer_service_rpc = { path = "sequencer/service/rpc" }
|
||||
|
||||
2
Justfile
2
Justfile
@ -63,7 +63,7 @@ run-explorer:
|
||||
[working-directory: 'wallet']
|
||||
run-wallet +args:
|
||||
@echo "🔑 Running wallet"
|
||||
NSSA_WALLET_HOME_DIR=$(pwd)/configs/debug cargo run --release -p wallet -- {{args}}
|
||||
LEE_WALLET_HOME_DIR=$(pwd)/configs/debug cargo run --release -p wallet -- {{args}}
|
||||
|
||||
# Clean runtime data
|
||||
clean:
|
||||
|
||||
@ -80,7 +80,7 @@ For each tag we publish docker images of our services.
|
||||
If you depend on this project you can pin your rust dependency to a git tag like this:
|
||||
|
||||
```toml
|
||||
nssa_core = { git = "https://github.com/logos-blockchain/logos-execution-zone.git", tag = "v0.1.0" }
|
||||
lee_core = { git = "https://github.com/logos-blockchain/logos-execution-zone.git", tag = "v0.1.0" }
|
||||
```
|
||||
|
||||
# Install dependencies
|
||||
@ -134,7 +134,7 @@ RISC0_DEV_MODE=1 cargo test --release
|
||||
### Integration tests
|
||||
|
||||
```bash
|
||||
export NSSA_WALLET_HOME_DIR=$(pwd)/integration_tests/configs/debug/wallet/
|
||||
export LEE_WALLET_HOME_DIR=$(pwd)/integration_tests/configs/debug/wallet/
|
||||
cd integration_tests
|
||||
# RISC0_DEV_MODE=1 skips proof generation; RUST_LOG=info enables runtime logs
|
||||
RUST_LOG=info RISC0_DEV_MODE=1 cargo run $(pwd)/configs/debug all
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -8,8 +8,8 @@ license = { workspace = true }
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
nssa.workspace = true
|
||||
nssa_core.workspace = true
|
||||
lee.workspace = true
|
||||
lee_core.workspace = true
|
||||
authenticated_transfer_core.workspace = true
|
||||
clock_core.workspace = true
|
||||
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
use borsh::{BorshDeserialize, BorshSerialize};
|
||||
use nssa_core::BlockId;
|
||||
pub use nssa_core::Timestamp;
|
||||
use lee_core::BlockId;
|
||||
pub use lee_core::Timestamp;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest as _, Sha256, digest::FixedOutput as _};
|
||||
|
||||
use crate::{HashType, transaction::NSSATransaction};
|
||||
use crate::{HashType, transaction::LeeTransaction};
|
||||
pub type MantleMsgId = [u8; 32];
|
||||
pub type BlockHash = HashType;
|
||||
|
||||
@ -35,12 +35,12 @@ pub struct BlockHeader {
|
||||
pub prev_block_hash: BlockHash,
|
||||
pub hash: BlockHash,
|
||||
pub timestamp: Timestamp,
|
||||
pub signature: nssa::Signature,
|
||||
pub signature: lee::Signature,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)]
|
||||
pub struct BlockBody {
|
||||
pub transactions: Vec<NSSATransaction>,
|
||||
pub transactions: Vec<LeeTransaction>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)]
|
||||
@ -75,14 +75,14 @@ pub struct HashableBlockData {
|
||||
pub block_id: BlockId,
|
||||
pub prev_block_hash: BlockHash,
|
||||
pub timestamp: Timestamp,
|
||||
pub transactions: Vec<NSSATransaction>,
|
||||
pub transactions: Vec<LeeTransaction>,
|
||||
}
|
||||
|
||||
impl HashableBlockData {
|
||||
#[must_use]
|
||||
pub fn into_pending_block(
|
||||
self,
|
||||
signing_key: &nssa::PrivateKey,
|
||||
signing_key: &lee::PrivateKey,
|
||||
bedrock_parent_id: MantleMsgId,
|
||||
) -> Block {
|
||||
const PREFIX: &[u8; 32] = b"/LEE/v0.3/Message/Block/\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
@ -98,7 +98,7 @@ impl HashableBlockData {
|
||||
bytes.extend_from_slice(&data_bytes);
|
||||
|
||||
let hash = OwnHasher::hash(&bytes);
|
||||
let signature = nssa::Signature::new(signing_key, &hash.0);
|
||||
let signature = lee::Signature::new(signing_key, &hash.0);
|
||||
Block {
|
||||
header: BlockHeader {
|
||||
block_id: self.block_id,
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
use nssa::AccountId;
|
||||
use lee::AccountId;
|
||||
|
||||
use crate::{
|
||||
HashType,
|
||||
block::{Block, HashableBlockData},
|
||||
transaction::{NSSATransaction, clock_invocation},
|
||||
transaction::{LeeTransaction, clock_invocation},
|
||||
};
|
||||
|
||||
// Helpers
|
||||
|
||||
#[must_use]
|
||||
pub fn sequencer_sign_key_for_testing() -> nssa::PrivateKey {
|
||||
nssa::PrivateKey::try_new([37; 32]).unwrap()
|
||||
pub fn sequencer_sign_key_for_testing() -> lee::PrivateKey {
|
||||
lee::PrivateKey::try_new([37; 32]).unwrap()
|
||||
}
|
||||
|
||||
// Dummy producers
|
||||
@ -26,9 +26,9 @@ pub fn sequencer_sign_key_for_testing() -> nssa::PrivateKey {
|
||||
pub fn produce_dummy_block(
|
||||
id: u64,
|
||||
prev_hash: Option<HashType>,
|
||||
mut transactions: Vec<NSSATransaction>,
|
||||
mut transactions: Vec<LeeTransaction>,
|
||||
) -> Block {
|
||||
transactions.push(NSSATransaction::Public(clock_invocation(
|
||||
transactions.push(LeeTransaction::Public(clock_invocation(
|
||||
id.saturating_mul(100),
|
||||
)));
|
||||
|
||||
@ -43,23 +43,23 @@ pub fn produce_dummy_block(
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn produce_dummy_empty_transaction() -> NSSATransaction {
|
||||
let program_id = nssa::program::Program::authenticated_transfer_program().id();
|
||||
pub fn produce_dummy_empty_transaction() -> LeeTransaction {
|
||||
let program_id = lee::program::Program::authenticated_transfer_program().id();
|
||||
let account_ids = vec![];
|
||||
let nonces = vec![];
|
||||
let message = nssa::public_transaction::Message::try_new(
|
||||
let message = lee::public_transaction::Message::try_new(
|
||||
program_id,
|
||||
account_ids,
|
||||
nonces,
|
||||
authenticated_transfer_core::Instruction::Initialize,
|
||||
)
|
||||
.unwrap();
|
||||
let private_key = nssa::PrivateKey::try_new([1; 32]).unwrap();
|
||||
let witness_set = nssa::public_transaction::WitnessSet::for_message(&message, &[&private_key]);
|
||||
let private_key = lee::PrivateKey::try_new([1; 32]).unwrap();
|
||||
let witness_set = lee::public_transaction::WitnessSet::for_message(&message, &[&private_key]);
|
||||
|
||||
let nssa_tx = nssa::PublicTransaction::new(message, witness_set);
|
||||
let lee_tx = lee::PublicTransaction::new(message, witness_set);
|
||||
|
||||
NSSATransaction::Public(nssa_tx)
|
||||
LeeTransaction::Public(lee_tx)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
@ -68,12 +68,12 @@ pub fn create_transaction_native_token_transfer(
|
||||
nonce: u128,
|
||||
to: AccountId,
|
||||
balance_to_move: u128,
|
||||
signing_key: &nssa::PrivateKey,
|
||||
) -> NSSATransaction {
|
||||
signing_key: &lee::PrivateKey,
|
||||
) -> LeeTransaction {
|
||||
let account_ids = vec![from, to];
|
||||
let nonces = vec![nonce.into()];
|
||||
let program_id = nssa::program::Program::authenticated_transfer_program().id();
|
||||
let message = nssa::public_transaction::Message::try_new(
|
||||
let program_id = lee::program::Program::authenticated_transfer_program().id();
|
||||
let message = lee::public_transaction::Message::try_new(
|
||||
program_id,
|
||||
account_ids,
|
||||
nonces,
|
||||
@ -82,9 +82,9 @@ pub fn create_transaction_native_token_transfer(
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let witness_set = nssa::public_transaction::WitnessSet::for_message(&message, &[signing_key]);
|
||||
let witness_set = lee::public_transaction::WitnessSet::for_message(&message, &[signing_key]);
|
||||
|
||||
let nssa_tx = nssa::PublicTransaction::new(message, witness_set);
|
||||
let lee_tx = lee::PublicTransaction::new(message, witness_set);
|
||||
|
||||
NSSATransaction::Public(nssa_tx)
|
||||
LeeTransaction::Public(lee_tx)
|
||||
}
|
||||
|
||||
@ -1,31 +1,31 @@
|
||||
use borsh::{BorshDeserialize, BorshSerialize};
|
||||
use lee::{AccountId, V03State, ValidatedStateDiff};
|
||||
use lee_core::{BlockId, Timestamp};
|
||||
use log::warn;
|
||||
use nssa::{AccountId, V03State, ValidatedStateDiff};
|
||||
use nssa_core::{BlockId, Timestamp};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::HashType;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
|
||||
pub enum NSSATransaction {
|
||||
Public(nssa::PublicTransaction),
|
||||
PrivacyPreserving(nssa::PrivacyPreservingTransaction),
|
||||
ProgramDeployment(nssa::ProgramDeploymentTransaction),
|
||||
pub enum LeeTransaction {
|
||||
Public(lee::PublicTransaction),
|
||||
PrivacyPreserving(lee::PrivacyPreservingTransaction),
|
||||
ProgramDeployment(lee::ProgramDeploymentTransaction),
|
||||
}
|
||||
|
||||
impl Serialize for NSSATransaction {
|
||||
impl Serialize for LeeTransaction {
|
||||
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
crate::borsh_base64::serialize(self, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for NSSATransaction {
|
||||
impl<'de> Deserialize<'de> for LeeTransaction {
|
||||
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
crate::borsh_base64::deserialize(deserializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl NSSATransaction {
|
||||
impl LeeTransaction {
|
||||
#[must_use]
|
||||
pub fn hash(&self) -> HashType {
|
||||
HashType(match self {
|
||||
@ -77,7 +77,7 @@ impl NSSATransaction {
|
||||
state: &V03State,
|
||||
block_id: BlockId,
|
||||
timestamp: Timestamp,
|
||||
) -> Result<ValidatedStateDiff, nssa::error::NssaError> {
|
||||
) -> Result<ValidatedStateDiff, lee::error::LeeError> {
|
||||
let diff = match self {
|
||||
Self::Public(tx) => {
|
||||
ValidatedStateDiff::from_public_transaction(tx, state, block_id, timestamp)
|
||||
@ -90,9 +90,9 @@ impl NSSATransaction {
|
||||
}
|
||||
}?;
|
||||
|
||||
let system_accounts = nssa::CLOCK_PROGRAM_ACCOUNT_IDS.iter().copied().chain([
|
||||
nssa::system_faucet_account_id(),
|
||||
nssa::system_bridge_account_id(),
|
||||
let system_accounts = lee::CLOCK_PROGRAM_ACCOUNT_IDS.iter().copied().chain([
|
||||
lee::system_faucet_account_id(),
|
||||
lee::system_bridge_account_id(),
|
||||
]);
|
||||
for account_id in system_accounts {
|
||||
validate_doesnt_modify_account(state, &diff, account_id)?;
|
||||
@ -108,7 +108,7 @@ impl NSSATransaction {
|
||||
state: &mut V03State,
|
||||
block_id: BlockId,
|
||||
timestamp: Timestamp,
|
||||
) -> Result<Self, nssa::error::NssaError> {
|
||||
) -> Result<Self, lee::error::LeeError> {
|
||||
let diff = self
|
||||
.validate_on_state(state, block_id, timestamp)
|
||||
.inspect_err(|err| warn!("Error at transition {err:#?}"))?;
|
||||
@ -117,20 +117,20 @@ impl NSSATransaction {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nssa::PublicTransaction> for NSSATransaction {
|
||||
fn from(value: nssa::PublicTransaction) -> Self {
|
||||
impl From<lee::PublicTransaction> for LeeTransaction {
|
||||
fn from(value: lee::PublicTransaction) -> Self {
|
||||
Self::Public(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nssa::PrivacyPreservingTransaction> for NSSATransaction {
|
||||
fn from(value: nssa::PrivacyPreservingTransaction) -> Self {
|
||||
impl From<lee::PrivacyPreservingTransaction> for LeeTransaction {
|
||||
fn from(value: lee::PrivacyPreservingTransaction) -> Self {
|
||||
Self::PrivacyPreserving(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nssa::ProgramDeploymentTransaction> for NSSATransaction {
|
||||
fn from(value: nssa::ProgramDeploymentTransaction) -> Self {
|
||||
impl From<lee::ProgramDeploymentTransaction> for LeeTransaction {
|
||||
fn from(value: lee::ProgramDeploymentTransaction) -> Self {
|
||||
Self::ProgramDeployment(value)
|
||||
}
|
||||
}
|
||||
@ -157,17 +157,17 @@ pub enum TransactionMalformationError {
|
||||
/// Returns the canonical Clock Program invocation transaction for the given block timestamp.
|
||||
/// Every valid block must end with exactly one occurrence of this transaction.
|
||||
#[must_use]
|
||||
pub fn clock_invocation(timestamp: clock_core::Instruction) -> nssa::PublicTransaction {
|
||||
let message = nssa::public_transaction::Message::try_new(
|
||||
nssa::program::Program::clock().id(),
|
||||
pub fn clock_invocation(timestamp: clock_core::Instruction) -> lee::PublicTransaction {
|
||||
let message = lee::public_transaction::Message::try_new(
|
||||
lee::program::Program::clock().id(),
|
||||
clock_core::CLOCK_PROGRAM_ACCOUNT_IDS.to_vec(),
|
||||
vec![],
|
||||
timestamp,
|
||||
)
|
||||
.expect("Clock invocation message should always be constructable");
|
||||
nssa::PublicTransaction::new(
|
||||
lee::PublicTransaction::new(
|
||||
message,
|
||||
nssa::public_transaction::WitnessSet::from_raw_parts(vec![]),
|
||||
lee::public_transaction::WitnessSet::from_raw_parts(vec![]),
|
||||
)
|
||||
}
|
||||
|
||||
@ -175,13 +175,13 @@ fn validate_doesnt_modify_account(
|
||||
state: &V03State,
|
||||
diff: &ValidatedStateDiff,
|
||||
account_id: AccountId,
|
||||
) -> Result<(), nssa::error::NssaError> {
|
||||
) -> Result<(), lee::error::LeeError> {
|
||||
if diff
|
||||
.public_diff()
|
||||
.get(&account_id)
|
||||
.is_some_and(|post| *post != state.get_account_by_id(account_id))
|
||||
{
|
||||
Err(nssa::error::NssaError::InvalidInput(format!(
|
||||
Err(lee::error::LeeError::InvalidInput(format!(
|
||||
"Transaction modifies restricted system account {account_id}"
|
||||
)))
|
||||
} else {
|
||||
|
||||
@ -9,8 +9,8 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
common.workspace = true
|
||||
nssa.workspace = true
|
||||
nssa_core.workspace = true
|
||||
lee.workspace = true
|
||||
lee_core.workspace = true
|
||||
sequencer_service_rpc = { workspace = true, features = ["client"] }
|
||||
wallet.workspace = true
|
||||
|
||||
|
||||
@ -134,7 +134,7 @@ echo -n SG9sYSBtdW5kbyE= | base64 -d
|
||||
You should see `Hola mundo!`.
|
||||
|
||||
# 5. Understanding the code in `hello_world.rs`.
|
||||
The Hello world example demonstrates the minimal structure of an NSSA program.
|
||||
The Hello world example demonstrates the minimal structure of a LEE program.
|
||||
Its purpose is very simple: append the instruction bytes to the data field of a single account.
|
||||
|
||||
### What this program does in a nutshell
|
||||
@ -145,7 +145,7 @@ Its purpose is very simple: append the instruction bytes to the data field of a
|
||||
2. Checks that there is exactly one input account: this example operates on a single account, so it expects `pre_states` to contain exactly one entry.
|
||||
3. Builds the post-state: It clones the input account and appends the instruction bytes to its data field.
|
||||
4. Handles account claiming logic: If the account is uninitialized (i.e. not yet claimed by any program), its program_owner will equal `DEFAULT_PROGRAM_ID`. In that case, the program issues a claim request, meaning: "This program now owns this account."
|
||||
5. Outputs the proposed state transition: `write_nssa_outputs` emits:
|
||||
5. Outputs the proposed state transition: `write_lee_outputs` emits:
|
||||
- The original instruction data
|
||||
- The original pre-states
|
||||
- The new post-states
|
||||
@ -154,7 +154,7 @@ Its purpose is very simple: append the instruction bytes to the data field of a
|
||||
1. Reading inputs:
|
||||
```rust
|
||||
let (ProgramInput { pre_states, instruction: greeting }, instruction_data)
|
||||
= read_nssa_inputs::<Instruction>();
|
||||
= read_lee_inputs::<Instruction>();
|
||||
```
|
||||
2. Extracting the single account:
|
||||
```rust
|
||||
@ -179,7 +179,7 @@ let post_state = if post_account.program_owner == DEFAULT_PROGRAM_ID {
|
||||
```
|
||||
5. Emmiting the output
|
||||
```rust
|
||||
write_nssa_outputs(instruction_data, vec![pre_state], vec![post_state]);
|
||||
write_lee_outputs(instruction_data, vec![pre_state], vec![post_state]);
|
||||
```
|
||||
|
||||
# 6. Understanding the runner script `run_hello_world.rs`
|
||||
@ -348,7 +348,7 @@ Check the `run_hello_world_private.rs` file to see how it is used.
|
||||
|
||||
# 8. Account authorization mechanism
|
||||
The Hello world example does not enforce any authorization on the input account. This means any user can execute it on any account, regardless of ownership.
|
||||
NSSA provides a mechanism for programs to enforce proper authorization before an execution can succeed. The meaning of authorization differs between public and private accounts:
|
||||
LEE provides a mechanism for programs to enforce proper authorization before an execution can succeed. The meaning of authorization differs between public and private accounts:
|
||||
- Public accounts: authorization requires that the transaction is signed with the account’s signing key.
|
||||
- Private accounts: authorization requires that the circuit verifies knowledge of the account’s nullifier secret key.
|
||||
|
||||
@ -594,7 +594,7 @@ wallet account get --account-id Private/8vzkK7vsdrS2gdPhLk72La8X4FJkgJ5kJLUBRbEV
|
||||
|
||||
## Digression: account authority vs account program ownership
|
||||
|
||||
In NSSA there are two distinct concepts that control who can modify an account:
|
||||
In LEE there are two distinct concepts that control who can modify an account:
|
||||
**Program Ownership:** Each account has a field: `program_owner: ProgramId`.
|
||||
This indicates which program is allowed to update the account’s state during execution.
|
||||
- If a program is the program_owner of an account, it can freely mutate its fields.
|
||||
|
||||
@ -8,7 +8,7 @@ license = { workspace = true }
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
nssa_core.workspace = true
|
||||
lee_core.workspace = true
|
||||
|
||||
hex.workspace = true
|
||||
bytemuck.workspace = true
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use nssa_core::program::{AccountPostState, Claim, ProgramInput, ProgramOutput, read_nssa_inputs};
|
||||
use lee_core::program::{AccountPostState, Claim, ProgramInput, ProgramOutput, read_lee_inputs};
|
||||
|
||||
// Hello-world example program.
|
||||
//
|
||||
@ -25,7 +25,7 @@ fn main() {
|
||||
instruction: greeting,
|
||||
},
|
||||
instruction_data,
|
||||
) = read_nssa_inputs::<Instruction>();
|
||||
) = read_lee_inputs::<Instruction>();
|
||||
|
||||
// Unpack the input account pre state
|
||||
let [pre_state] = pre_states
|
||||
@ -49,7 +49,7 @@ fn main() {
|
||||
|
||||
// The output is a proposed state difference. It will only succeed if the pre states coincide
|
||||
// with the previous values of the accounts, and the transition to the post states conforms
|
||||
// with the NSSA program rules.
|
||||
// with the LEE program rules.
|
||||
// WARNING: constructing a `ProgramOutput` has no effect on its own. `.write()` must be
|
||||
// called to commit the output.
|
||||
ProgramOutput::new(
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use nssa_core::program::{AccountPostState, Claim, ProgramInput, ProgramOutput, read_nssa_inputs};
|
||||
use lee_core::program::{AccountPostState, Claim, ProgramInput, ProgramOutput, read_lee_inputs};
|
||||
|
||||
// Hello-world with authorization example program.
|
||||
//
|
||||
@ -25,7 +25,7 @@ fn main() {
|
||||
instruction: greeting,
|
||||
},
|
||||
instruction_data,
|
||||
) = read_nssa_inputs::<Instruction>();
|
||||
) = read_lee_inputs::<Instruction>();
|
||||
|
||||
// Unpack the input account pre state
|
||||
let [pre_state] = pre_states
|
||||
@ -56,7 +56,7 @@ fn main() {
|
||||
|
||||
// The output is a proposed state difference. It will only succeed if the pre states coincide
|
||||
// with the previous values of the accounts, and the transition to the post states conforms
|
||||
// with the NSSA program rules.
|
||||
// with the LEE program rules.
|
||||
// WARNING: constructing a `ProgramOutput` has no effect on its own. `.write()` must be
|
||||
// called to commit the output.
|
||||
ProgramOutput::new(
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use nssa_core::{
|
||||
use lee_core::{
|
||||
account::{AccountWithMetadata, Data},
|
||||
program::{AccountPostState, Claim, ProgramInput, ProgramOutput, read_nssa_inputs},
|
||||
program::{AccountPostState, Claim, ProgramInput, ProgramOutput, read_lee_inputs},
|
||||
};
|
||||
|
||||
// Hello-world with write + move_data example program.
|
||||
@ -72,7 +72,7 @@ fn main() {
|
||||
instruction: (function_id, data),
|
||||
},
|
||||
instruction_words,
|
||||
) = read_nssa_inputs::<Instruction>();
|
||||
) = read_lee_inputs::<Instruction>();
|
||||
|
||||
let post_states = match (pre_states.as_slice(), function_id, data.len()) {
|
||||
([account_pre], WRITE_FUNCTION_ID, _) => {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use nssa_core::program::{
|
||||
AccountPostState, ChainedCall, ProgramId, ProgramInput, ProgramOutput, read_nssa_inputs,
|
||||
use lee_core::program::{
|
||||
AccountPostState, ChainedCall, ProgramId, ProgramInput, ProgramOutput, read_lee_inputs,
|
||||
};
|
||||
|
||||
// Tail Call example program.
|
||||
@ -33,7 +33,7 @@ fn main() {
|
||||
instruction: (),
|
||||
},
|
||||
instruction_data,
|
||||
) = read_nssa_inputs::<()>();
|
||||
) = read_lee_inputs::<()>();
|
||||
|
||||
// Unpack the input account pre state
|
||||
let [pre_state] = pre_states
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
use nssa_core::program::{
|
||||
AccountPostState, ChainedCall, PdaSeed, ProgramId, ProgramInput, ProgramOutput,
|
||||
read_nssa_inputs,
|
||||
use lee_core::program::{
|
||||
AccountPostState, ChainedCall, PdaSeed, ProgramId, ProgramInput, ProgramOutput, read_lee_inputs,
|
||||
};
|
||||
|
||||
// Tail Call with PDA example program.
|
||||
@ -39,7 +38,7 @@ fn main() {
|
||||
instruction: (),
|
||||
},
|
||||
instruction_data,
|
||||
) = read_nssa_inputs::<()>();
|
||||
) = read_lee_inputs::<()>();
|
||||
|
||||
// Unpack the input account pre state
|
||||
let [pre_state] = pre_states
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use common::transaction::NSSATransaction;
|
||||
use nssa::{
|
||||
use common::transaction::LeeTransaction;
|
||||
use lee::{
|
||||
AccountId, PublicTransaction,
|
||||
program::Program,
|
||||
public_transaction::{Message, WitnessSet},
|
||||
@ -60,7 +60,7 @@ async fn main() {
|
||||
// Submit the transaction
|
||||
let _response = wallet_core
|
||||
.sequencer_client
|
||||
.send_transaction(NSSATransaction::Public(tx))
|
||||
.send_transaction(LeeTransaction::Public(tx))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use nssa::{AccountId, program::Program};
|
||||
use lee::{AccountId, program::Program};
|
||||
use wallet::{AccountIdentity, WalletCore};
|
||||
|
||||
// Before running this example, compile the `hello_world.rs` guest program with:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use common::transaction::NSSATransaction;
|
||||
use nssa::{
|
||||
use common::transaction::LeeTransaction;
|
||||
use lee::{
|
||||
AccountId, PublicTransaction,
|
||||
program::Program,
|
||||
public_transaction::{Message, WitnessSet},
|
||||
@ -56,7 +56,7 @@ async fn main() {
|
||||
// Submit the transaction
|
||||
let _response = wallet_core
|
||||
.sequencer_client
|
||||
.send_transaction(NSSATransaction::Public(tx))
|
||||
.send_transaction(LeeTransaction::Public(tx))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use nssa::{
|
||||
use lee::{
|
||||
AccountId, ProgramId, privacy_preserving_transaction::circuit::ProgramWithDependencies,
|
||||
program::Program,
|
||||
};
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use common::transaction::NSSATransaction;
|
||||
use nssa::{
|
||||
use common::transaction::LeeTransaction;
|
||||
use lee::{
|
||||
AccountId, PublicTransaction,
|
||||
program::Program,
|
||||
public_transaction::{Message, WitnessSet},
|
||||
@ -73,7 +73,7 @@ async fn main() {
|
||||
// Submit the transaction
|
||||
let _response = wallet_core
|
||||
.sequencer_client
|
||||
.send_transaction(NSSATransaction::Public(tx))
|
||||
.send_transaction(LeeTransaction::Public(tx))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@ -3,13 +3,13 @@
|
||||
reason = "This is an example program, it's fine to print to stdout"
|
||||
)]
|
||||
|
||||
use common::transaction::NSSATransaction;
|
||||
use nssa::{
|
||||
use common::transaction::LeeTransaction;
|
||||
use lee::{
|
||||
AccountId, PublicTransaction,
|
||||
program::Program,
|
||||
public_transaction::{Message, WitnessSet},
|
||||
};
|
||||
use nssa_core::program::PdaSeed;
|
||||
use lee_core::program::PdaSeed;
|
||||
use sequencer_service_rpc::RpcClient as _;
|
||||
use wallet::WalletCore;
|
||||
|
||||
@ -58,7 +58,7 @@ async fn main() {
|
||||
// Submit the transaction
|
||||
let _response = wallet_core
|
||||
.sequencer_client
|
||||
.send_transaction(NSSATransaction::Public(tx))
|
||||
.send_transaction(LeeTransaction::Public(tx))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use clap::{Parser, Subcommand};
|
||||
use common::transaction::NSSATransaction;
|
||||
use nssa::{PublicTransaction, program::Program, public_transaction};
|
||||
use common::transaction::LeeTransaction;
|
||||
use lee::{PublicTransaction, program::Program, public_transaction};
|
||||
use sequencer_service_rpc::RpcClient as _;
|
||||
use wallet::{AccountIdentity, WalletCore};
|
||||
|
||||
@ -89,7 +89,7 @@ async fn main() {
|
||||
// Submit the transaction
|
||||
let _response = wallet_core
|
||||
.sequencer_client
|
||||
.send_transaction(NSSATransaction::Public(tx))
|
||||
.send_transaction(LeeTransaction::Public(tx))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
@ -128,7 +128,7 @@ async fn main() {
|
||||
// Submit the transaction
|
||||
let _response = wallet_core
|
||||
.sequencer_client
|
||||
.send_transaction(NSSATransaction::Public(tx))
|
||||
.send_transaction(LeeTransaction::Public(tx))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@ -10,8 +10,8 @@ workspace = true
|
||||
[dependencies]
|
||||
common.workspace = true
|
||||
logos-blockchain-zone-sdk.workspace = true
|
||||
nssa.workspace = true
|
||||
nssa_core.workspace = true
|
||||
lee.workspace = true
|
||||
lee_core.workspace = true
|
||||
storage.workspace = true
|
||||
testnet_initial_state.workspace = true
|
||||
|
||||
|
||||
@ -3,13 +3,13 @@ use std::{path::Path, sync::Arc};
|
||||
use anyhow::{Context as _, Result};
|
||||
use common::{
|
||||
block::{BedrockStatus, Block},
|
||||
transaction::{NSSATransaction, clock_invocation},
|
||||
transaction::{LeeTransaction, clock_invocation},
|
||||
};
|
||||
use lee::{Account, AccountId, V03State};
|
||||
use lee_core::BlockId;
|
||||
use log::info;
|
||||
use logos_blockchain_core::header::HeaderId;
|
||||
use logos_blockchain_zone_sdk::Slot;
|
||||
use nssa::{Account, AccountId, V03State};
|
||||
use nssa_core::BlockId;
|
||||
use storage::indexer::RocksDBIO;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
@ -53,7 +53,7 @@ impl IndexerStore {
|
||||
Ok(self.dbio.get_block_batch(before, limit)?)
|
||||
}
|
||||
|
||||
pub fn get_transaction_by_hash(&self, tx_hash: [u8; 32]) -> Result<Option<NSSATransaction>> {
|
||||
pub fn get_transaction_by_hash(&self, tx_hash: [u8; 32]) -> Result<Option<LeeTransaction>> {
|
||||
let Some(block_id) = self.dbio.get_block_id_by_tx_hash(tx_hash)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
@ -79,7 +79,7 @@ impl IndexerStore {
|
||||
acc_id: [u8; 32],
|
||||
offset: u64,
|
||||
limit: u64,
|
||||
) -> Result<Vec<NSSATransaction>> {
|
||||
) -> Result<Vec<LeeTransaction>> {
|
||||
Ok(self.dbio.get_acc_transactions(acc_id, offset, limit)?)
|
||||
}
|
||||
|
||||
@ -146,7 +146,7 @@ impl IndexerStore {
|
||||
.ok_or_else(|| anyhow::anyhow!("Block has no transactions"))?;
|
||||
|
||||
anyhow::ensure!(
|
||||
*clock_tx == NSSATransaction::Public(clock_invocation(block.header.timestamp)),
|
||||
*clock_tx == LeeTransaction::Public(clock_invocation(block.header.timestamp)),
|
||||
"Last transaction in block must be the clock invocation for the block timestamp"
|
||||
);
|
||||
|
||||
@ -154,9 +154,9 @@ impl IndexerStore {
|
||||
for transaction in user_txs {
|
||||
if is_genesis {
|
||||
let genesis_tx = match transaction {
|
||||
NSSATransaction::Public(public_tx) => public_tx,
|
||||
NSSATransaction::PrivacyPreserving(_)
|
||||
| NSSATransaction::ProgramDeployment(_) => {
|
||||
LeeTransaction::Public(public_tx) => public_tx,
|
||||
LeeTransaction::PrivacyPreserving(_)
|
||||
| LeeTransaction::ProgramDeployment(_) => {
|
||||
anyhow::bail!("Genesis block should contain only public transactions")
|
||||
}
|
||||
};
|
||||
@ -180,7 +180,7 @@ impl IndexerStore {
|
||||
}
|
||||
|
||||
// Apply the clock invocation directly (it is expected to modify clock accounts).
|
||||
let NSSATransaction::Public(clock_public_tx) = clock_tx else {
|
||||
let LeeTransaction::Public(clock_public_tx) = clock_tx else {
|
||||
anyhow::bail!("Clock invocation must be a public transaction");
|
||||
};
|
||||
state_guard.transition_from_public_transaction(
|
||||
@ -231,7 +231,7 @@ mod tests {
|
||||
let sign_key = initial_accounts[0].pub_sign_key.clone();
|
||||
|
||||
// Submit genesis block
|
||||
let clock_tx = NSSATransaction::Public(clock_invocation(0));
|
||||
let clock_tx = LeeTransaction::Public(clock_invocation(0));
|
||||
let genesis_block_data = HashableBlockData {
|
||||
block_id: 1,
|
||||
prev_block_hash: HashType::default(),
|
||||
|
||||
@ -5,7 +5,7 @@ name = "indexer_ffi"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
nssa.workspace = true
|
||||
lee.workspace = true
|
||||
indexer_service.workspace = true
|
||||
indexer_service_rpc = { workspace = true, features = ["client"] }
|
||||
indexer_service_protocol.workspace = true
|
||||
|
||||
@ -194,7 +194,7 @@ typedef struct FfiPublicTransactionBody {
|
||||
} FfiPublicTransactionBody;
|
||||
|
||||
/**
|
||||
* Account data structure - C-compatible version of nssa Account.
|
||||
* Account data structure - C-compatible version of lee Account.
|
||||
*
|
||||
* Note: `balance` and `nonce` are u128 values represented as little-endian
|
||||
* byte arrays since C doesn't have native u128 support.
|
||||
|
||||
@ -184,9 +184,8 @@ pub unsafe extern "C" fn query_account(
|
||||
.map_or_else(
|
||||
|_| PointerResult::from_error(OperationStatus::ClientError),
|
||||
|acc| {
|
||||
let acc_nssa: nssa::Account =
|
||||
acc.try_into().expect("Source is in blocks, must fit");
|
||||
PointerResult::from_value(acc_nssa.into())
|
||||
let acc_lee: lee::Account = acc.try_into().expect("Source is in blocks, must fit");
|
||||
PointerResult::from_value(acc_lee.into())
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ use indexer_service_protocol::ProgramId;
|
||||
|
||||
use crate::api::types::{FfiBytes32, FfiProgramId, FfiU128};
|
||||
|
||||
/// Account data structure - C-compatible version of nssa Account.
|
||||
/// Account data structure - C-compatible version of lee Account.
|
||||
///
|
||||
/// Note: `balance` and `nonce` are u128 values represented as little-endian
|
||||
/// byte arrays since C doesn't have native u128 support.
|
||||
@ -23,15 +23,15 @@ pub struct FfiAccount {
|
||||
|
||||
// Helper functions to convert between Rust and FFI types
|
||||
|
||||
impl From<&nssa::AccountId> for FfiBytes32 {
|
||||
fn from(id: &nssa::AccountId) -> Self {
|
||||
impl From<&lee::AccountId> for FfiBytes32 {
|
||||
fn from(id: &lee::AccountId) -> Self {
|
||||
Self::from_account_id(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nssa::Account> for FfiAccount {
|
||||
fn from(value: nssa::Account) -> Self {
|
||||
let nssa::Account {
|
||||
impl From<lee::Account> for FfiAccount {
|
||||
fn from(value: lee::Account) -> Self {
|
||||
let lee::Account {
|
||||
program_owner,
|
||||
balance,
|
||||
data,
|
||||
|
||||
@ -48,7 +48,7 @@ impl FfiBytes32 {
|
||||
|
||||
/// Create from an `AccountId`.
|
||||
#[must_use]
|
||||
pub const fn from_account_id(id: &nssa::AccountId) -> Self {
|
||||
pub const fn from_account_id(id: &lee::AccountId) -> Self {
|
||||
Self { data: *id.value() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,7 +267,7 @@ impl From<PrivacyPreservingMessage> for FfiPrivacyPreservingMessage {
|
||||
.into(),
|
||||
public_post_states: public_post_states
|
||||
.into_iter()
|
||||
.map(|acc_ind| -> nssa::Account {
|
||||
.map(|acc_ind| -> lee::Account {
|
||||
acc_ind.try_into().expect("Source is in blocks, must fit")
|
||||
})
|
||||
.map(Into::into)
|
||||
|
||||
@ -8,8 +8,8 @@ license = { workspace = true }
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
nssa_core = { workspace = true, optional = true, features = ["host"] }
|
||||
nssa = { workspace = true, optional = true }
|
||||
lee_core = { workspace = true, optional = true, features = ["host"] }
|
||||
lee = { workspace = true, optional = true }
|
||||
common = { workspace = true, optional = true }
|
||||
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
@ -21,5 +21,5 @@ hex.workspace = true
|
||||
anyhow.workspace = true
|
||||
|
||||
[features]
|
||||
# Enable conversion to/from NSSA core types
|
||||
convert = ["dep:nssa_core", "dep:nssa", "dep:common"]
|
||||
# Enable conversion to/from LEE core types
|
||||
convert = ["dep:lee_core", "dep:lee", "dep:common"]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
//! Conversions between `indexer_service_protocol` types and `nssa/nssa_core` types.
|
||||
//! Conversions between `indexer_service_protocol` types and `lee/lee_core` types.
|
||||
|
||||
use nssa_core::account::Nonce;
|
||||
use lee_core::account::Nonce;
|
||||
|
||||
use crate::{
|
||||
Account, AccountId, BedrockStatus, Block, BlockBody, BlockHeader, Ciphertext, Commitment,
|
||||
@ -26,24 +26,24 @@ impl From<ProgramId> for [u32; 8] {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nssa_core::account::AccountId> for AccountId {
|
||||
fn from(value: nssa_core::account::AccountId) -> Self {
|
||||
impl From<lee_core::account::AccountId> for AccountId {
|
||||
fn from(value: lee_core::account::AccountId) -> Self {
|
||||
Self {
|
||||
value: value.into_value(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AccountId> for nssa_core::account::AccountId {
|
||||
impl From<AccountId> for lee_core::account::AccountId {
|
||||
fn from(value: AccountId) -> Self {
|
||||
let AccountId { value } = value;
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nssa_core::account::Account> for Account {
|
||||
fn from(value: nssa_core::account::Account) -> Self {
|
||||
let nssa_core::account::Account {
|
||||
impl From<lee_core::account::Account> for Account {
|
||||
fn from(value: lee_core::account::Account) -> Self {
|
||||
let lee_core::account::Account {
|
||||
program_owner,
|
||||
balance,
|
||||
data,
|
||||
@ -59,8 +59,8 @@ impl From<nssa_core::account::Account> for Account {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Account> for nssa_core::account::Account {
|
||||
type Error = nssa_core::account::data::DataTooBigError;
|
||||
impl TryFrom<Account> for lee_core::account::Account {
|
||||
type Error = lee_core::account::data::DataTooBigError;
|
||||
|
||||
fn try_from(value: Account) -> Result<Self, Self::Error> {
|
||||
let Account {
|
||||
@ -79,14 +79,14 @@ impl TryFrom<Account> for nssa_core::account::Account {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nssa_core::account::Data> for Data {
|
||||
fn from(value: nssa_core::account::Data) -> Self {
|
||||
impl From<lee_core::account::Data> for Data {
|
||||
fn from(value: lee_core::account::Data) -> Self {
|
||||
Self(value.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Data> for nssa_core::account::Data {
|
||||
type Error = nssa_core::account::data::DataTooBigError;
|
||||
impl TryFrom<Data> for lee_core::account::Data {
|
||||
type Error = lee_core::account::data::DataTooBigError;
|
||||
|
||||
fn try_from(value: Data) -> Result<Self, Self::Error> {
|
||||
Self::try_from(value.0)
|
||||
@ -97,37 +97,37 @@ impl TryFrom<Data> for nssa_core::account::Data {
|
||||
// Commitment and Nullifier conversions
|
||||
// ============================================================================
|
||||
|
||||
impl From<nssa_core::Commitment> for Commitment {
|
||||
fn from(value: nssa_core::Commitment) -> Self {
|
||||
impl From<lee_core::Commitment> for Commitment {
|
||||
fn from(value: lee_core::Commitment) -> Self {
|
||||
Self(value.to_byte_array())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Commitment> for nssa_core::Commitment {
|
||||
impl From<Commitment> for lee_core::Commitment {
|
||||
fn from(value: Commitment) -> Self {
|
||||
Self::from_byte_array(value.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nssa_core::Nullifier> for Nullifier {
|
||||
fn from(value: nssa_core::Nullifier) -> Self {
|
||||
impl From<lee_core::Nullifier> for Nullifier {
|
||||
fn from(value: lee_core::Nullifier) -> Self {
|
||||
Self(value.to_byte_array())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Nullifier> for nssa_core::Nullifier {
|
||||
impl From<Nullifier> for lee_core::Nullifier {
|
||||
fn from(value: Nullifier) -> Self {
|
||||
Self::from_byte_array(value.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nssa_core::CommitmentSetDigest> for CommitmentSetDigest {
|
||||
fn from(value: nssa_core::CommitmentSetDigest) -> Self {
|
||||
impl From<lee_core::CommitmentSetDigest> for CommitmentSetDigest {
|
||||
fn from(value: lee_core::CommitmentSetDigest) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CommitmentSetDigest> for nssa_core::CommitmentSetDigest {
|
||||
impl From<CommitmentSetDigest> for lee_core::CommitmentSetDigest {
|
||||
fn from(value: CommitmentSetDigest) -> Self {
|
||||
value.0
|
||||
}
|
||||
@ -137,25 +137,25 @@ impl From<CommitmentSetDigest> for nssa_core::CommitmentSetDigest {
|
||||
// Encryption-related conversions
|
||||
// ============================================================================
|
||||
|
||||
impl From<nssa_core::encryption::Ciphertext> for Ciphertext {
|
||||
fn from(value: nssa_core::encryption::Ciphertext) -> Self {
|
||||
impl From<lee_core::encryption::Ciphertext> for Ciphertext {
|
||||
fn from(value: lee_core::encryption::Ciphertext) -> Self {
|
||||
Self(value.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Ciphertext> for nssa_core::encryption::Ciphertext {
|
||||
impl From<Ciphertext> for lee_core::encryption::Ciphertext {
|
||||
fn from(value: Ciphertext) -> Self {
|
||||
Self::from_inner(value.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nssa_core::encryption::EphemeralPublicKey> for EphemeralPublicKey {
|
||||
fn from(value: nssa_core::encryption::EphemeralPublicKey) -> Self {
|
||||
impl From<lee_core::encryption::EphemeralPublicKey> for EphemeralPublicKey {
|
||||
fn from(value: lee_core::encryption::EphemeralPublicKey) -> Self {
|
||||
Self(value.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EphemeralPublicKey> for nssa_core::encryption::EphemeralPublicKey {
|
||||
impl From<EphemeralPublicKey> for lee_core::encryption::EphemeralPublicKey {
|
||||
fn from(value: EphemeralPublicKey) -> Self {
|
||||
Self(value.0)
|
||||
}
|
||||
@ -165,28 +165,28 @@ impl From<EphemeralPublicKey> for nssa_core::encryption::EphemeralPublicKey {
|
||||
// Signature and PublicKey conversions
|
||||
// ============================================================================
|
||||
|
||||
impl From<nssa::Signature> for Signature {
|
||||
fn from(value: nssa::Signature) -> Self {
|
||||
let nssa::Signature { value } = value;
|
||||
impl From<lee::Signature> for Signature {
|
||||
fn from(value: lee::Signature) -> Self {
|
||||
let lee::Signature { value } = value;
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Signature> for nssa::Signature {
|
||||
impl From<Signature> for lee::Signature {
|
||||
fn from(value: Signature) -> Self {
|
||||
let Signature(sig_value) = value;
|
||||
Self { value: sig_value }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nssa::PublicKey> for PublicKey {
|
||||
fn from(value: nssa::PublicKey) -> Self {
|
||||
impl From<lee::PublicKey> for PublicKey {
|
||||
fn from(value: lee::PublicKey) -> Self {
|
||||
Self(*value.value())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PublicKey> for nssa::PublicKey {
|
||||
type Error = nssa::error::NssaError;
|
||||
impl TryFrom<PublicKey> for lee::PublicKey {
|
||||
type Error = lee::error::LeeError;
|
||||
|
||||
fn try_from(value: PublicKey) -> Result<Self, Self::Error> {
|
||||
Self::try_new(value.0)
|
||||
@ -197,13 +197,13 @@ impl TryFrom<PublicKey> for nssa::PublicKey {
|
||||
// Proof conversions
|
||||
// ============================================================================
|
||||
|
||||
impl From<nssa::privacy_preserving_transaction::circuit::Proof> for Proof {
|
||||
fn from(value: nssa::privacy_preserving_transaction::circuit::Proof) -> Self {
|
||||
impl From<lee::privacy_preserving_transaction::circuit::Proof> for Proof {
|
||||
fn from(value: lee::privacy_preserving_transaction::circuit::Proof) -> Self {
|
||||
Self(value.into_inner())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Proof> for nssa::privacy_preserving_transaction::circuit::Proof {
|
||||
impl From<Proof> for lee::privacy_preserving_transaction::circuit::Proof {
|
||||
fn from(value: Proof) -> Self {
|
||||
Self::from_inner(value.0)
|
||||
}
|
||||
@ -213,10 +213,10 @@ impl From<Proof> for nssa::privacy_preserving_transaction::circuit::Proof {
|
||||
// EncryptedAccountData conversions
|
||||
// ============================================================================
|
||||
|
||||
impl From<nssa::privacy_preserving_transaction::message::EncryptedAccountData>
|
||||
impl From<lee::privacy_preserving_transaction::message::EncryptedAccountData>
|
||||
for EncryptedAccountData
|
||||
{
|
||||
fn from(value: nssa::privacy_preserving_transaction::message::EncryptedAccountData) -> Self {
|
||||
fn from(value: lee::privacy_preserving_transaction::message::EncryptedAccountData) -> Self {
|
||||
Self {
|
||||
ciphertext: value.ciphertext.into(),
|
||||
epk: value.epk.into(),
|
||||
@ -226,7 +226,7 @@ impl From<nssa::privacy_preserving_transaction::message::EncryptedAccountData>
|
||||
}
|
||||
|
||||
impl From<EncryptedAccountData>
|
||||
for nssa::privacy_preserving_transaction::message::EncryptedAccountData
|
||||
for lee::privacy_preserving_transaction::message::EncryptedAccountData
|
||||
{
|
||||
fn from(value: EncryptedAccountData) -> Self {
|
||||
Self {
|
||||
@ -241,9 +241,9 @@ impl From<EncryptedAccountData>
|
||||
// Transaction Message conversions
|
||||
// ============================================================================
|
||||
|
||||
impl From<nssa::public_transaction::Message> for PublicMessage {
|
||||
fn from(value: nssa::public_transaction::Message) -> Self {
|
||||
let nssa::public_transaction::Message {
|
||||
impl From<lee::public_transaction::Message> for PublicMessage {
|
||||
fn from(value: lee::public_transaction::Message) -> Self {
|
||||
let lee::public_transaction::Message {
|
||||
program_id,
|
||||
account_ids,
|
||||
nonces,
|
||||
@ -258,7 +258,7 @@ impl From<nssa::public_transaction::Message> for PublicMessage {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PublicMessage> for nssa::public_transaction::Message {
|
||||
impl From<PublicMessage> for lee::public_transaction::Message {
|
||||
fn from(value: PublicMessage) -> Self {
|
||||
let PublicMessage {
|
||||
program_id,
|
||||
@ -271,16 +271,16 @@ impl From<PublicMessage> for nssa::public_transaction::Message {
|
||||
account_ids.into_iter().map(Into::into).collect(),
|
||||
nonces
|
||||
.iter()
|
||||
.map(|x| nssa_core::account::Nonce(*x))
|
||||
.map(|x| lee_core::account::Nonce(*x))
|
||||
.collect(),
|
||||
instruction_data,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nssa::privacy_preserving_transaction::message::Message> for PrivacyPreservingMessage {
|
||||
fn from(value: nssa::privacy_preserving_transaction::message::Message) -> Self {
|
||||
let nssa::privacy_preserving_transaction::message::Message {
|
||||
impl From<lee::privacy_preserving_transaction::message::Message> for PrivacyPreservingMessage {
|
||||
fn from(value: lee::privacy_preserving_transaction::message::Message) -> Self {
|
||||
let lee::privacy_preserving_transaction::message::Message {
|
||||
public_account_ids,
|
||||
nonces,
|
||||
public_post_states,
|
||||
@ -309,8 +309,8 @@ impl From<nssa::privacy_preserving_transaction::message::Message> for PrivacyPre
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PrivacyPreservingMessage> for nssa::privacy_preserving_transaction::message::Message {
|
||||
type Error = nssa::error::NssaError;
|
||||
impl TryFrom<PrivacyPreservingMessage> for lee::privacy_preserving_transaction::message::Message {
|
||||
type Error = lee::error::LeeError;
|
||||
|
||||
fn try_from(value: PrivacyPreservingMessage) -> Result<Self, Self::Error> {
|
||||
let PrivacyPreservingMessage {
|
||||
@ -327,13 +327,13 @@ impl TryFrom<PrivacyPreservingMessage> for nssa::privacy_preserving_transaction:
|
||||
public_account_ids: public_account_ids.into_iter().map(Into::into).collect(),
|
||||
nonces: nonces
|
||||
.iter()
|
||||
.map(|x| nssa_core::account::Nonce(*x))
|
||||
.map(|x| lee_core::account::Nonce(*x))
|
||||
.collect(),
|
||||
public_post_states: public_post_states
|
||||
.into_iter()
|
||||
.map(TryInto::try_into)
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|e| nssa::error::NssaError::InvalidInput(format!("{e}")))?,
|
||||
.map_err(|e| lee::error::LeeError::InvalidInput(format!("{e}")))?,
|
||||
encrypted_private_post_states: encrypted_private_post_states
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
@ -345,23 +345,23 @@ impl TryFrom<PrivacyPreservingMessage> for nssa::privacy_preserving_transaction:
|
||||
.collect(),
|
||||
block_validity_window: block_validity_window
|
||||
.try_into()
|
||||
.map_err(|e| nssa::error::NssaError::InvalidInput(format!("{e}")))?,
|
||||
.map_err(|e| lee::error::LeeError::InvalidInput(format!("{e}")))?,
|
||||
timestamp_validity_window: timestamp_validity_window
|
||||
.try_into()
|
||||
.map_err(|e| nssa::error::NssaError::InvalidInput(format!("{e}")))?,
|
||||
.map_err(|e| lee::error::LeeError::InvalidInput(format!("{e}")))?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nssa::program_deployment_transaction::Message> for ProgramDeploymentMessage {
|
||||
fn from(value: nssa::program_deployment_transaction::Message) -> Self {
|
||||
impl From<lee::program_deployment_transaction::Message> for ProgramDeploymentMessage {
|
||||
fn from(value: lee::program_deployment_transaction::Message) -> Self {
|
||||
Self {
|
||||
bytecode: value.into_bytecode(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ProgramDeploymentMessage> for nssa::program_deployment_transaction::Message {
|
||||
impl From<ProgramDeploymentMessage> for lee::program_deployment_transaction::Message {
|
||||
fn from(value: ProgramDeploymentMessage) -> Self {
|
||||
let ProgramDeploymentMessage { bytecode } = value;
|
||||
Self::new(bytecode)
|
||||
@ -372,8 +372,8 @@ impl From<ProgramDeploymentMessage> for nssa::program_deployment_transaction::Me
|
||||
// WitnessSet conversions
|
||||
// ============================================================================
|
||||
|
||||
impl From<nssa::public_transaction::WitnessSet> for WitnessSet {
|
||||
fn from(value: nssa::public_transaction::WitnessSet) -> Self {
|
||||
impl From<lee::public_transaction::WitnessSet> for WitnessSet {
|
||||
fn from(value: lee::public_transaction::WitnessSet) -> Self {
|
||||
Self {
|
||||
signatures_and_public_keys: value
|
||||
.signatures_and_public_keys()
|
||||
@ -385,8 +385,8 @@ impl From<nssa::public_transaction::WitnessSet> for WitnessSet {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nssa::privacy_preserving_transaction::witness_set::WitnessSet> for WitnessSet {
|
||||
fn from(value: nssa::privacy_preserving_transaction::witness_set::WitnessSet) -> Self {
|
||||
impl From<lee::privacy_preserving_transaction::witness_set::WitnessSet> for WitnessSet {
|
||||
fn from(value: lee::privacy_preserving_transaction::witness_set::WitnessSet) -> Self {
|
||||
let (sigs_and_pks, proof) = value.into_raw_parts();
|
||||
Self {
|
||||
signatures_and_public_keys: sigs_and_pks
|
||||
@ -398,8 +398,8 @@ impl From<nssa::privacy_preserving_transaction::witness_set::WitnessSet> for Wit
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<WitnessSet> for nssa::privacy_preserving_transaction::witness_set::WitnessSet {
|
||||
type Error = nssa::error::NssaError;
|
||||
impl TryFrom<WitnessSet> for lee::privacy_preserving_transaction::witness_set::WitnessSet {
|
||||
type Error = lee::error::LeeError;
|
||||
|
||||
fn try_from(value: WitnessSet) -> Result<Self, Self::Error> {
|
||||
let WitnessSet {
|
||||
@ -415,7 +415,7 @@ impl TryFrom<WitnessSet> for nssa::privacy_preserving_transaction::witness_set::
|
||||
signatures_and_public_keys,
|
||||
proof
|
||||
.map(Into::into)
|
||||
.ok_or_else(|| nssa::error::NssaError::InvalidInput("Missing proof".to_owned()))?,
|
||||
.ok_or_else(|| lee::error::LeeError::InvalidInput("Missing proof".to_owned()))?,
|
||||
))
|
||||
}
|
||||
}
|
||||
@ -424,10 +424,10 @@ impl TryFrom<WitnessSet> for nssa::privacy_preserving_transaction::witness_set::
|
||||
// Transaction conversions
|
||||
// ============================================================================
|
||||
|
||||
impl From<nssa::PublicTransaction> for PublicTransaction {
|
||||
fn from(value: nssa::PublicTransaction) -> Self {
|
||||
impl From<lee::PublicTransaction> for PublicTransaction {
|
||||
fn from(value: lee::PublicTransaction) -> Self {
|
||||
let hash = HashType(value.hash());
|
||||
let nssa::PublicTransaction {
|
||||
let lee::PublicTransaction {
|
||||
message,
|
||||
witness_set,
|
||||
} = value;
|
||||
@ -440,8 +440,8 @@ impl From<nssa::PublicTransaction> for PublicTransaction {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PublicTransaction> for nssa::PublicTransaction {
|
||||
type Error = nssa::error::NssaError;
|
||||
impl TryFrom<PublicTransaction> for lee::PublicTransaction {
|
||||
type Error = lee::error::LeeError;
|
||||
|
||||
fn try_from(value: PublicTransaction) -> Result<Self, Self::Error> {
|
||||
let PublicTransaction {
|
||||
@ -456,7 +456,7 @@ impl TryFrom<PublicTransaction> for nssa::PublicTransaction {
|
||||
|
||||
Ok(Self::new(
|
||||
message.into(),
|
||||
nssa::public_transaction::WitnessSet::from_raw_parts(
|
||||
lee::public_transaction::WitnessSet::from_raw_parts(
|
||||
signatures_and_public_keys
|
||||
.into_iter()
|
||||
.map(|(sig, pk)| Ok((sig.into(), pk.try_into()?)))
|
||||
@ -466,10 +466,10 @@ impl TryFrom<PublicTransaction> for nssa::PublicTransaction {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nssa::PrivacyPreservingTransaction> for PrivacyPreservingTransaction {
|
||||
fn from(value: nssa::PrivacyPreservingTransaction) -> Self {
|
||||
impl From<lee::PrivacyPreservingTransaction> for PrivacyPreservingTransaction {
|
||||
fn from(value: lee::PrivacyPreservingTransaction) -> Self {
|
||||
let hash = HashType(value.hash());
|
||||
let nssa::PrivacyPreservingTransaction {
|
||||
let lee::PrivacyPreservingTransaction {
|
||||
message,
|
||||
witness_set,
|
||||
} = value;
|
||||
@ -482,8 +482,8 @@ impl From<nssa::PrivacyPreservingTransaction> for PrivacyPreservingTransaction {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PrivacyPreservingTransaction> for nssa::PrivacyPreservingTransaction {
|
||||
type Error = nssa::error::NssaError;
|
||||
impl TryFrom<PrivacyPreservingTransaction> for lee::PrivacyPreservingTransaction {
|
||||
type Error = lee::error::LeeError;
|
||||
|
||||
fn try_from(value: PrivacyPreservingTransaction) -> Result<Self, Self::Error> {
|
||||
let PrivacyPreservingTransaction {
|
||||
@ -496,10 +496,10 @@ impl TryFrom<PrivacyPreservingTransaction> for nssa::PrivacyPreservingTransactio
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nssa::ProgramDeploymentTransaction> for ProgramDeploymentTransaction {
|
||||
fn from(value: nssa::ProgramDeploymentTransaction) -> Self {
|
||||
impl From<lee::ProgramDeploymentTransaction> for ProgramDeploymentTransaction {
|
||||
fn from(value: lee::ProgramDeploymentTransaction) -> Self {
|
||||
let hash = HashType(value.hash());
|
||||
let nssa::ProgramDeploymentTransaction { message } = value;
|
||||
let lee::ProgramDeploymentTransaction { message } = value;
|
||||
|
||||
Self {
|
||||
hash,
|
||||
@ -508,29 +508,29 @@ impl From<nssa::ProgramDeploymentTransaction> for ProgramDeploymentTransaction {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ProgramDeploymentTransaction> for nssa::ProgramDeploymentTransaction {
|
||||
impl From<ProgramDeploymentTransaction> for lee::ProgramDeploymentTransaction {
|
||||
fn from(value: ProgramDeploymentTransaction) -> Self {
|
||||
let ProgramDeploymentTransaction { hash: _, message } = value;
|
||||
Self::new(message.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<common::transaction::NSSATransaction> for Transaction {
|
||||
fn from(value: common::transaction::NSSATransaction) -> Self {
|
||||
impl From<common::transaction::LeeTransaction> for Transaction {
|
||||
fn from(value: common::transaction::LeeTransaction) -> Self {
|
||||
match value {
|
||||
common::transaction::NSSATransaction::Public(tx) => Self::Public(tx.into()),
|
||||
common::transaction::NSSATransaction::PrivacyPreserving(tx) => {
|
||||
common::transaction::LeeTransaction::Public(tx) => Self::Public(tx.into()),
|
||||
common::transaction::LeeTransaction::PrivacyPreserving(tx) => {
|
||||
Self::PrivacyPreserving(tx.into())
|
||||
}
|
||||
common::transaction::NSSATransaction::ProgramDeployment(tx) => {
|
||||
common::transaction::LeeTransaction::ProgramDeployment(tx) => {
|
||||
Self::ProgramDeployment(tx.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Transaction> for common::transaction::NSSATransaction {
|
||||
type Error = nssa::error::NssaError;
|
||||
impl TryFrom<Transaction> for common::transaction::LeeTransaction {
|
||||
type Error = lee::error::LeeError;
|
||||
|
||||
fn try_from(value: Transaction) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
@ -565,7 +565,7 @@ impl From<common::block::BlockHeader> for BlockHeader {
|
||||
}
|
||||
|
||||
impl TryFrom<BlockHeader> for common::block::BlockHeader {
|
||||
type Error = nssa::error::NssaError;
|
||||
type Error = lee::error::LeeError;
|
||||
|
||||
fn try_from(value: BlockHeader) -> Result<Self, Self::Error> {
|
||||
let BlockHeader {
|
||||
@ -592,11 +592,11 @@ impl From<common::block::BlockBody> for BlockBody {
|
||||
let transactions = transactions
|
||||
.into_iter()
|
||||
.map(|tx| match tx {
|
||||
common::transaction::NSSATransaction::Public(tx) => Transaction::Public(tx.into()),
|
||||
common::transaction::NSSATransaction::PrivacyPreserving(tx) => {
|
||||
common::transaction::LeeTransaction::Public(tx) => Transaction::Public(tx.into()),
|
||||
common::transaction::LeeTransaction::PrivacyPreserving(tx) => {
|
||||
Transaction::PrivacyPreserving(tx.into())
|
||||
}
|
||||
common::transaction::NSSATransaction::ProgramDeployment(tx) => {
|
||||
common::transaction::LeeTransaction::ProgramDeployment(tx) => {
|
||||
Transaction::ProgramDeployment(tx.into())
|
||||
}
|
||||
})
|
||||
@ -607,7 +607,7 @@ impl From<common::block::BlockBody> for BlockBody {
|
||||
}
|
||||
|
||||
impl TryFrom<BlockBody> for common::block::BlockBody {
|
||||
type Error = nssa::error::NssaError;
|
||||
type Error = lee::error::LeeError;
|
||||
|
||||
fn try_from(value: BlockBody) -> Result<Self, Self::Error> {
|
||||
let BlockBody { transactions } = value;
|
||||
@ -615,8 +615,8 @@ impl TryFrom<BlockBody> for common::block::BlockBody {
|
||||
let transactions = transactions
|
||||
.into_iter()
|
||||
.map(|tx| {
|
||||
let nssa_tx: common::transaction::NSSATransaction = tx.try_into()?;
|
||||
Ok::<_, nssa::error::NssaError>(nssa_tx)
|
||||
let lee_tx: common::transaction::LeeTransaction = tx.try_into()?;
|
||||
Ok::<_, lee::error::LeeError>(lee_tx)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
@ -643,7 +643,7 @@ impl From<common::block::Block> for Block {
|
||||
}
|
||||
|
||||
impl TryFrom<Block> for common::block::Block {
|
||||
type Error = nssa::error::NssaError;
|
||||
type Error = lee::error::LeeError;
|
||||
|
||||
fn try_from(value: Block) -> Result<Self, Self::Error> {
|
||||
let Block {
|
||||
@ -698,14 +698,14 @@ impl From<HashType> for common::HashType {
|
||||
// ValidityWindow conversions
|
||||
// ============================================================================
|
||||
|
||||
impl From<nssa_core::program::ValidityWindow<u64>> for ValidityWindow {
|
||||
fn from(value: nssa_core::program::ValidityWindow<u64>) -> Self {
|
||||
impl From<lee_core::program::ValidityWindow<u64>> for ValidityWindow {
|
||||
fn from(value: lee_core::program::ValidityWindow<u64>) -> Self {
|
||||
Self((value.start(), value.end()))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ValidityWindow> for nssa_core::program::ValidityWindow<u64> {
|
||||
type Error = nssa_core::program::InvalidWindow;
|
||||
impl TryFrom<ValidityWindow> for lee_core::program::ValidityWindow<u64> {
|
||||
type Error = lee_core::program::InvalidWindow;
|
||||
|
||||
fn try_from(value: ValidityWindow) -> Result<Self, Self::Error> {
|
||||
value.0.try_into()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
//! This crate defines the protocol types used by the indexer service.
|
||||
//!
|
||||
//! Currently it mostly mimics types from `nssa_core`, but it's important to have a separate crate
|
||||
//! Currently it mostly mimics types from `lee_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};
|
||||
|
||||
@ -10,8 +10,8 @@ workspace = true
|
||||
[dependencies]
|
||||
test_fixtures.workspace = true
|
||||
|
||||
nssa_core = { workspace = true, features = ["host"] }
|
||||
nssa.workspace = true
|
||||
lee_core = { workspace = true, features = ["host"] }
|
||||
lee.workspace = true
|
||||
authenticated_transfer_core.workspace = true
|
||||
sequencer_core = { workspace = true, features = ["default", "testnet"] }
|
||||
wallet.workspace = true
|
||||
|
||||
@ -3,4 +3,49 @@
|
||||
//! non-test consumers (e.g. `integration_bench`) can depend on them without
|
||||
//! pulling in the test files.
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context as _, Result};
|
||||
use log::info;
|
||||
pub use test_fixtures::*;
|
||||
|
||||
/// Maximum time to wait for the indexer to catch up to the sequencer.
|
||||
pub const L2_TO_L1_TIMEOUT: Duration = Duration::from_mins(6);
|
||||
|
||||
/// Poll the indexer until its last finalized block id reaches the sequencer's
|
||||
/// current last block id or until [`L2_TO_L1_TIMEOUT`] elapses.
|
||||
/// Returns the last indexer block id observed.
|
||||
pub async fn wait_for_indexer_to_catch_up(ctx: &TestContext) -> Result<u64> {
|
||||
use indexer_service_rpc::RpcClient as _;
|
||||
|
||||
let block_id_to_catch_up =
|
||||
sequencer_service_rpc::RpcClient::get_last_block_id(ctx.sequencer_client()).await?;
|
||||
let mut last_ind: u64 = 1;
|
||||
let inner = async {
|
||||
loop {
|
||||
let ind = ctx
|
||||
.indexer_client()
|
||||
.get_last_finalized_block_id()
|
||||
.await?
|
||||
.unwrap_or(0);
|
||||
last_ind = ind;
|
||||
if ind >= block_id_to_catch_up {
|
||||
let last_seq =
|
||||
sequencer_service_rpc::RpcClient::get_last_block_id(ctx.sequencer_client())
|
||||
.await?;
|
||||
info!(
|
||||
"Indexer caught up. Indexer last block id: {ind}. Current sequencer last block id: {last_seq}"
|
||||
);
|
||||
return Ok(ind);
|
||||
}
|
||||
tokio::time::sleep(Duration::from_secs(2)).await;
|
||||
}
|
||||
};
|
||||
tokio::time::timeout(L2_TO_L1_TIMEOUT, inner)
|
||||
.await
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"Indexer failed to catch up within {L2_TO_L1_TIMEOUT:?}. Last indexer block id observed: {last_ind}, but needed to catch up to at least {block_id_to_catch_up}"
|
||||
)
|
||||
})?
|
||||
}
|
||||
|
||||
@ -6,9 +6,9 @@
|
||||
use anyhow::{Context as _, Result};
|
||||
use integration_tests::{TestContext, private_mention};
|
||||
use key_protocol::key_management::KeyChain;
|
||||
use lee::{Data, program::Program};
|
||||
use lee_core::account::Nonce;
|
||||
use log::info;
|
||||
use nssa::{Data, program::Program};
|
||||
use nssa_core::account::Nonce;
|
||||
use sequencer_service_rpc::RpcClient as _;
|
||||
use tokio::test;
|
||||
use wallet::{
|
||||
@ -127,8 +127,8 @@ async fn new_public_account_without_label() -> Result<()> {
|
||||
async fn import_public_account() -> Result<()> {
|
||||
let mut ctx = TestContext::new().await?;
|
||||
|
||||
let private_key = nssa::PrivateKey::new_os_random();
|
||||
let account_id = nssa::AccountId::from(&nssa::PublicKey::new_from_private_key(&private_key));
|
||||
let private_key = lee::PrivateKey::new_os_random();
|
||||
let account_id = lee::AccountId::from(&lee::PublicKey::new_from_private_key(&private_key));
|
||||
|
||||
let command = Command::Account(AccountSubcommand::Import(ImportSubcommand::Public {
|
||||
private_key,
|
||||
@ -156,8 +156,8 @@ async fn import_private_account() -> Result<()> {
|
||||
let mut ctx = TestContext::new().await?;
|
||||
|
||||
let key_chain = KeyChain::new_os_random();
|
||||
let account_id = nssa::AccountId::from((&key_chain.nullifier_public_key, 0));
|
||||
let account = nssa::Account {
|
||||
let account_id = lee::AccountId::from((&key_chain.nullifier_public_key, 0));
|
||||
let account = lee::Account {
|
||||
program_owner: Program::authenticated_transfer_program().id(),
|
||||
balance: 777,
|
||||
data: Data::default(),
|
||||
@ -213,11 +213,11 @@ async fn import_private_account_second_time_overrides_account_data() -> Result<(
|
||||
let mut ctx = TestContext::new().await?;
|
||||
|
||||
let key_chain = KeyChain::new_os_random();
|
||||
let account_id = nssa::AccountId::from((&key_chain.nullifier_public_key, 0));
|
||||
let account_id = lee::AccountId::from((&key_chain.nullifier_public_key, 0));
|
||||
let key_chain_json =
|
||||
serde_json::to_string(&key_chain).context("Failed to serialize key chain")?;
|
||||
|
||||
let initial_account = nssa::Account {
|
||||
let initial_account = lee::Account {
|
||||
program_owner: Program::authenticated_transfer_program().id(),
|
||||
balance: 100,
|
||||
data: Data::default(),
|
||||
@ -236,7 +236,7 @@ async fn import_private_account_second_time_overrides_account_data() -> Result<(
|
||||
)
|
||||
.await?;
|
||||
|
||||
let updated_account = nssa::Account {
|
||||
let updated_account = lee::Account {
|
||||
program_owner: Program::authenticated_transfer_program().id(),
|
||||
balance: 999,
|
||||
data: Data::default(),
|
||||
|
||||
@ -12,8 +12,8 @@ use integration_tests::{
|
||||
TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, private_mention, public_mention,
|
||||
verify_commitment_is_in_state,
|
||||
};
|
||||
use lee::program::Program;
|
||||
use log::info;
|
||||
use nssa::program::Program;
|
||||
use sequencer_service_rpc::RpcClient as _;
|
||||
use token_core::{TokenDefinition, TokenHolding};
|
||||
use tokio::test;
|
||||
@ -24,7 +24,7 @@ use wallet::cli::{
|
||||
};
|
||||
|
||||
/// Create a public account and return its ID.
|
||||
async fn new_public_account(ctx: &mut TestContext) -> Result<nssa::AccountId> {
|
||||
async fn new_public_account(ctx: &mut TestContext) -> Result<lee::AccountId> {
|
||||
let result = wallet::cli::execute_subcommand(
|
||||
ctx.wallet_mut(),
|
||||
Command::Account(AccountSubcommand::New(NewSubcommand::Public {
|
||||
@ -40,7 +40,7 @@ async fn new_public_account(ctx: &mut TestContext) -> Result<nssa::AccountId> {
|
||||
}
|
||||
|
||||
/// Create a private account and return its ID.
|
||||
async fn new_private_account(ctx: &mut TestContext) -> Result<nssa::AccountId> {
|
||||
async fn new_private_account(ctx: &mut TestContext) -> Result<lee::AccountId> {
|
||||
let result = wallet::cli::execute_subcommand(
|
||||
ctx.wallet_mut(),
|
||||
Command::Account(AccountSubcommand::New(NewSubcommand::Private {
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context as _, Result};
|
||||
use common::transaction::NSSATransaction;
|
||||
use common::transaction::LeeTransaction;
|
||||
use integration_tests::{
|
||||
TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, fetch_privacy_preserving_tx, private_mention,
|
||||
public_mention, verify_commitment_is_in_state,
|
||||
};
|
||||
use log::info;
|
||||
use nssa::{
|
||||
use lee::{
|
||||
AccountId, SharedSecretKey, execute_and_prove,
|
||||
privacy_preserving_transaction::circuit::ProgramWithDependencies, program::Program,
|
||||
};
|
||||
use nssa_core::{
|
||||
use lee_core::{
|
||||
InputAccountIdentity, NullifierPublicKey, account::AccountWithMetadata,
|
||||
encryption::shared_key_derivation::Secp256k1Point,
|
||||
};
|
||||
use log::info;
|
||||
use sequencer_service_rpc::RpcClient as _;
|
||||
use tokio::test;
|
||||
use wallet::{
|
||||
@ -639,20 +639,20 @@ async fn ppt_cant_chain_call_faucet() -> Result<()> {
|
||||
std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../artifacts/test_program_methods/faucet_chain_caller.bin"),
|
||||
)?;
|
||||
let deploy_tx = NSSATransaction::ProgramDeployment(nssa::ProgramDeploymentTransaction::new(
|
||||
nssa::program_deployment_transaction::Message::new(binary.clone()),
|
||||
let deploy_tx = LeeTransaction::ProgramDeployment(lee::ProgramDeploymentTransaction::new(
|
||||
lee::program_deployment_transaction::Message::new(binary.clone()),
|
||||
));
|
||||
ctx.sequencer_client().send_transaction(deploy_tx).await?;
|
||||
|
||||
info!("Waiting for deploy block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
let faucet_account_id = nssa::system_faucet_account_id();
|
||||
let faucet_account_id = lee::system_faucet_account_id();
|
||||
let attacker_id = ctx.existing_public_accounts()[0];
|
||||
let faucet_program_id = Program::faucet().id();
|
||||
let vault_program_id = Program::vault().id();
|
||||
let auth_transfer_program_id = Program::authenticated_transfer_program().id();
|
||||
let nsk: nssa_core::NullifierSecretKey = [3; 32];
|
||||
let nsk: lee_core::NullifierSecretKey = [3; 32];
|
||||
let npk = NullifierPublicKey::from(&nsk);
|
||||
let vpk = Secp256k1Point::from_scalar([4; 32]);
|
||||
let ssk = SharedSecretKey::new([55; 32], &vpk);
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
use std::{path::PathBuf, time::Duration};
|
||||
|
||||
use anyhow::Result;
|
||||
use common::transaction::NSSATransaction;
|
||||
use common::transaction::LeeTransaction;
|
||||
use integration_tests::{TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, public_mention};
|
||||
use lee::{program::Program, public_transaction, system_faucet_account_id};
|
||||
use log::info;
|
||||
use nssa::{program::Program, public_transaction, system_faucet_account_id};
|
||||
use sequencer_service_rpc::RpcClient as _;
|
||||
use tokio::test;
|
||||
use wallet::{
|
||||
@ -368,13 +368,13 @@ async fn cannot_transfer_funds_from_system_faucet_account() -> Result<()> {
|
||||
vec![],
|
||||
authenticated_transfer_core::Instruction::Transfer { amount },
|
||||
)?;
|
||||
let tx = nssa::PublicTransaction::new(
|
||||
let tx = lee::PublicTransaction::new(
|
||||
message,
|
||||
nssa::public_transaction::WitnessSet::from_raw_parts(vec![]),
|
||||
lee::public_transaction::WitnessSet::from_raw_parts(vec![]),
|
||||
);
|
||||
let tx_hash = ctx
|
||||
.sequencer_client()
|
||||
.send_transaction(NSSATransaction::Public(tx))
|
||||
.send_transaction(LeeTransaction::Public(tx))
|
||||
.await?;
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
@ -426,13 +426,13 @@ async fn cannot_execute_faucet_program() -> Result<()> {
|
||||
amount,
|
||||
},
|
||||
)?;
|
||||
let tx = nssa::PublicTransaction::new(
|
||||
let tx = lee::PublicTransaction::new(
|
||||
message,
|
||||
nssa::public_transaction::WitnessSet::from_raw_parts(vec![]),
|
||||
lee::public_transaction::WitnessSet::from_raw_parts(vec![]),
|
||||
);
|
||||
let tx_hash = ctx
|
||||
.sequencer_client()
|
||||
.send_transaction(NSSATransaction::Public(tx))
|
||||
.send_transaction(LeeTransaction::Public(tx))
|
||||
.await?;
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
@ -464,8 +464,8 @@ async fn user_tx_that_chain_calls_faucet_is_dropped() -> Result<()> {
|
||||
.join("../artifacts/test_program_methods/faucet_chain_caller.bin"),
|
||||
)?;
|
||||
let faucet_chain_caller_id = Program::new(binary.clone())?.id();
|
||||
let deploy_tx = NSSATransaction::ProgramDeployment(nssa::ProgramDeploymentTransaction::new(
|
||||
nssa::program_deployment_transaction::Message::new(binary),
|
||||
let deploy_tx = LeeTransaction::ProgramDeployment(lee::ProgramDeploymentTransaction::new(
|
||||
lee::program_deployment_transaction::Message::new(binary),
|
||||
));
|
||||
ctx.sequencer_client().send_transaction(deploy_tx).await?;
|
||||
|
||||
@ -485,9 +485,9 @@ async fn user_tx_that_chain_calls_faucet_is_dropped() -> Result<()> {
|
||||
vec![],
|
||||
(faucet_program_id, vault_program_id, attacker, amount),
|
||||
)?;
|
||||
let attack_tx = NSSATransaction::Public(nssa::PublicTransaction::new(
|
||||
let attack_tx = LeeTransaction::Public(lee::PublicTransaction::new(
|
||||
message,
|
||||
nssa::public_transaction::WitnessSet::from_raw_parts(vec![]),
|
||||
lee::public_transaction::WitnessSet::from_raw_parts(vec![]),
|
||||
));
|
||||
|
||||
let faucet_balance_before = ctx
|
||||
|
||||
@ -8,11 +8,11 @@ use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use bytesize::ByteSize;
|
||||
use common::transaction::NSSATransaction;
|
||||
use common::transaction::LeeTransaction;
|
||||
use integration_tests::{
|
||||
TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, config::SequencerPartialConfig,
|
||||
};
|
||||
use nssa::program::Program;
|
||||
use lee::program::Program;
|
||||
use sequencer_service_rpc::RpcClient as _;
|
||||
use tokio::test;
|
||||
|
||||
@ -33,13 +33,13 @@ async fn reject_oversized_transaction() -> Result<()> {
|
||||
// Create a 1.1 MiB binary to ensure it exceeds the limit
|
||||
let oversized_binary = vec![0_u8; 1100 * 1024]; // 1.1 MiB binary
|
||||
|
||||
let message = nssa::program_deployment_transaction::Message::new(oversized_binary);
|
||||
let tx = nssa::ProgramDeploymentTransaction::new(message);
|
||||
let message = lee::program_deployment_transaction::Message::new(oversized_binary);
|
||||
let tx = lee::ProgramDeploymentTransaction::new(message);
|
||||
|
||||
// Try to submit the transaction and expect an error
|
||||
let result = ctx
|
||||
.sequencer_client()
|
||||
.send_transaction(NSSATransaction::ProgramDeployment(tx))
|
||||
.send_transaction(LeeTransaction::ProgramDeployment(tx))
|
||||
.await;
|
||||
|
||||
assert!(
|
||||
@ -74,13 +74,13 @@ async fn accept_transaction_within_limit() -> Result<()> {
|
||||
// Create a small program deployment that should fit
|
||||
let small_binary = vec![0_u8; 1024]; // 1 KiB binary
|
||||
|
||||
let message = nssa::program_deployment_transaction::Message::new(small_binary);
|
||||
let tx = nssa::ProgramDeploymentTransaction::new(message);
|
||||
let message = lee::program_deployment_transaction::Message::new(small_binary);
|
||||
let tx = lee::ProgramDeploymentTransaction::new(message);
|
||||
|
||||
// This should succeed
|
||||
let result = ctx
|
||||
.sequencer_client()
|
||||
.send_transaction(NSSATransaction::ProgramDeployment(tx))
|
||||
.send_transaction(LeeTransaction::ProgramDeployment(tx))
|
||||
.await;
|
||||
|
||||
assert!(
|
||||
@ -123,17 +123,17 @@ async fn transaction_deferred_to_next_block_when_current_full() -> Result<()> {
|
||||
|
||||
// Submit both program deployments
|
||||
ctx.sequencer_client()
|
||||
.send_transaction(NSSATransaction::ProgramDeployment(
|
||||
nssa::ProgramDeploymentTransaction::new(
|
||||
nssa::program_deployment_transaction::Message::new(burner_bytecode),
|
||||
.send_transaction(LeeTransaction::ProgramDeployment(
|
||||
lee::ProgramDeploymentTransaction::new(
|
||||
lee::program_deployment_transaction::Message::new(burner_bytecode),
|
||||
),
|
||||
))
|
||||
.await?;
|
||||
|
||||
ctx.sequencer_client()
|
||||
.send_transaction(NSSATransaction::ProgramDeployment(
|
||||
nssa::ProgramDeploymentTransaction::new(
|
||||
nssa::program_deployment_transaction::Message::new(chain_caller_bytecode),
|
||||
.send_transaction(LeeTransaction::ProgramDeployment(
|
||||
lee::ProgramDeploymentTransaction::new(
|
||||
lee::program_deployment_transaction::Message::new(chain_caller_bytecode),
|
||||
),
|
||||
))
|
||||
.await?;
|
||||
@ -148,13 +148,13 @@ async fn transaction_deferred_to_next_block_when_current_full() -> Result<()> {
|
||||
.unwrap();
|
||||
|
||||
// Check which program is in block 1
|
||||
let get_program_ids = |block: &common::block::Block| -> Vec<nssa::ProgramId> {
|
||||
let get_program_ids = |block: &common::block::Block| -> Vec<lee::ProgramId> {
|
||||
block
|
||||
.body
|
||||
.transactions
|
||||
.iter()
|
||||
.filter_map(|tx| {
|
||||
if let NSSATransaction::ProgramDeployment(deployment) = tx {
|
||||
if let LeeTransaction::ProgramDeployment(deployment) = tx {
|
||||
let bytecode = deployment.message.clone().into_bytecode();
|
||||
Program::new(bytecode).ok().map(|p| p.id())
|
||||
} else {
|
||||
|
||||
@ -8,8 +8,13 @@ use std::time::Duration;
|
||||
|
||||
use anyhow::Context as _;
|
||||
use borsh::BorshSerialize;
|
||||
use common::transaction::NSSATransaction;
|
||||
use common::transaction::LeeTransaction;
|
||||
use integration_tests::{TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext};
|
||||
use lee::{
|
||||
AccountId, execute_and_prove, privacy_preserving_transaction, program::Program,
|
||||
public_transaction,
|
||||
};
|
||||
use lee_core::{InputAccountIdentity, account::AccountWithMetadata};
|
||||
use log::info;
|
||||
use logos_blockchain_core::mantle::{Value, ledger::Inputs, ops::channel::deposit::DepositOp};
|
||||
use logos_blockchain_http_api_common::bodies::{
|
||||
@ -19,11 +24,6 @@ use logos_blockchain_http_api_common::bodies::{
|
||||
transfer_funds::{WalletTransferFundsRequestBody, WalletTransferFundsResponseBody},
|
||||
},
|
||||
};
|
||||
use nssa::{
|
||||
AccountId, execute_and_prove, privacy_preserving_transaction, program::Program,
|
||||
public_transaction,
|
||||
};
|
||||
use nssa_core::{InputAccountIdentity, account::AccountWithMetadata};
|
||||
use sequencer_service_rpc::RpcClient as _;
|
||||
use tokio::test;
|
||||
|
||||
@ -34,7 +34,7 @@ async fn public_bridge_deposit_invocation_is_dropped() -> anyhow::Result<()> {
|
||||
let ctx = TestContext::new().await?;
|
||||
|
||||
let recipient_id = ctx.existing_public_accounts()[0];
|
||||
let bridge_account_id = nssa::system_bridge_account_id();
|
||||
let bridge_account_id = lee::system_bridge_account_id();
|
||||
let vault_program_id = Program::vault().id();
|
||||
let recipient_vault_id = vault_core::compute_vault_account_id(vault_program_id, recipient_id);
|
||||
|
||||
@ -50,9 +50,9 @@ async fn public_bridge_deposit_invocation_is_dropped() -> anyhow::Result<()> {
|
||||
)
|
||||
.context("Failed to build public bridge deposit transaction")?;
|
||||
|
||||
let attack_tx = NSSATransaction::Public(nssa::PublicTransaction::new(
|
||||
let attack_tx = LeeTransaction::Public(lee::PublicTransaction::new(
|
||||
message,
|
||||
nssa::public_transaction::WitnessSet::from_raw_parts(vec![]),
|
||||
lee::public_transaction::WitnessSet::from_raw_parts(vec![]),
|
||||
));
|
||||
|
||||
let bridge_balance_before = ctx
|
||||
@ -93,7 +93,7 @@ async fn private_bridge_deposit_invocation_is_dropped() -> anyhow::Result<()> {
|
||||
let ctx = TestContext::new().await?;
|
||||
|
||||
let recipient_id = ctx.existing_public_accounts()[0];
|
||||
let bridge_account_id = nssa::system_bridge_account_id();
|
||||
let bridge_account_id = lee::system_bridge_account_id();
|
||||
let vault_program_id = Program::vault().id();
|
||||
let recipient_vault_id = vault_core::compute_vault_account_id(vault_program_id, recipient_id);
|
||||
|
||||
@ -115,7 +115,7 @@ async fn private_bridge_deposit_invocation_is_dropped() -> anyhow::Result<()> {
|
||||
|
||||
// Create program with dependencies
|
||||
let program_with_deps =
|
||||
nssa::privacy_preserving_transaction::circuit::ProgramWithDependencies::new(
|
||||
lee::privacy_preserving_transaction::circuit::ProgramWithDependencies::new(
|
||||
Program::bridge(),
|
||||
[
|
||||
(vault_program_id, Program::vault()),
|
||||
@ -154,7 +154,7 @@ async fn private_bridge_deposit_invocation_is_dropped() -> anyhow::Result<()> {
|
||||
.context("Failed to build privacy-preserving bridge deposit message")?;
|
||||
|
||||
let witness_set = privacy_preserving_transaction::WitnessSet::for_message(&message, proof, &[]);
|
||||
let attack_tx = NSSATransaction::PrivacyPreserving(nssa::PrivacyPreservingTransaction::new(
|
||||
let attack_tx = LeeTransaction::PrivacyPreserving(lee::PrivacyPreservingTransaction::new(
|
||||
message,
|
||||
witness_set,
|
||||
));
|
||||
@ -413,7 +413,7 @@ async fn bedrock_deposit_mints_to_vault_then_claim_succeeds() -> anyhow::Result<
|
||||
|
||||
let claim_witness_set =
|
||||
public_transaction::WitnessSet::for_message(&claim_message, &[signing_key]);
|
||||
let claim_tx = NSSATransaction::Public(nssa::PublicTransaction::new(
|
||||
let claim_tx = LeeTransaction::Public(lee::PublicTransaction::new(
|
||||
claim_message,
|
||||
claim_witness_set,
|
||||
));
|
||||
|
||||
@ -1,278 +0,0 @@
|
||||
#![expect(
|
||||
clippy::shadow_unrelated,
|
||||
clippy::tests_outside_test_module,
|
||||
reason = "We don't care about these in tests"
|
||||
)]
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context as _, Result};
|
||||
use indexer_service_rpc::RpcClient as _;
|
||||
use integration_tests::{
|
||||
TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, private_mention, public_mention,
|
||||
verify_commitment_is_in_state,
|
||||
};
|
||||
use log::info;
|
||||
use nssa::AccountId;
|
||||
use wallet::{
|
||||
account::Label,
|
||||
cli::{CliAccountMention, Command, programs::native_token_transfer::AuthTransferSubcommand},
|
||||
};
|
||||
|
||||
/// Maximum time to wait for the indexer to catch up to the sequencer.
|
||||
const L2_TO_L1_TIMEOUT: Duration = Duration::from_mins(6);
|
||||
|
||||
/// Poll the indexer until its last finalized block id reaches the sequencer's
|
||||
/// current last block id or until [`L2_TO_L1_TIMEOUT_MILLIS`] elapses.
|
||||
/// Returns the last indexer block id observed.
|
||||
async fn wait_for_indexer_to_catch_up(ctx: &TestContext) -> Result<u64> {
|
||||
let block_id_to_catch_up =
|
||||
sequencer_service_rpc::RpcClient::get_last_block_id(ctx.sequencer_client()).await?;
|
||||
let mut last_ind: u64 = 1;
|
||||
let inner = async {
|
||||
loop {
|
||||
let ind = ctx
|
||||
.indexer_client()
|
||||
.get_last_finalized_block_id()
|
||||
.await?
|
||||
.unwrap_or(0);
|
||||
last_ind = ind;
|
||||
if ind >= block_id_to_catch_up {
|
||||
let last_seq =
|
||||
sequencer_service_rpc::RpcClient::get_last_block_id(ctx.sequencer_client())
|
||||
.await?;
|
||||
info!(
|
||||
"Indexer caught up. Indexer last block id: {ind}. Current sequencer last block id: {last_seq}"
|
||||
);
|
||||
return Ok(ind);
|
||||
}
|
||||
tokio::time::sleep(Duration::from_secs(2)).await;
|
||||
}
|
||||
};
|
||||
tokio::time::timeout(L2_TO_L1_TIMEOUT, inner)
|
||||
.await
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"Indexer failed to catch up within {L2_TO_L1_TIMEOUT:?}. Last indexer block id observed: {last_ind}, but needed to catch up to at least {block_id_to_catch_up}"
|
||||
)
|
||||
})?
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn indexer_test_run() -> Result<()> {
|
||||
let ctx = TestContext::new().await?;
|
||||
|
||||
let last_block_indexer = wait_for_indexer_to_catch_up(&ctx).await?;
|
||||
|
||||
let last_block_seq =
|
||||
sequencer_service_rpc::RpcClient::get_last_block_id(ctx.sequencer_client()).await?;
|
||||
|
||||
info!("Last block on seq now is {last_block_seq}");
|
||||
info!("Last block on ind now is {last_block_indexer}");
|
||||
|
||||
assert!(last_block_indexer > 0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn indexer_block_batching() -> Result<()> {
|
||||
let ctx = TestContext::new().await?;
|
||||
|
||||
info!("Waiting for indexer to parse blocks");
|
||||
let last_block_indexer = wait_for_indexer_to_catch_up(&ctx).await?;
|
||||
|
||||
info!("Last block on ind now is {last_block_indexer}");
|
||||
|
||||
assert!(last_block_indexer > 0);
|
||||
|
||||
// Getting wide batch to fit all blocks (from latest backwards)
|
||||
let mut block_batch = ctx.indexer_client().get_blocks(None, 100).await.unwrap();
|
||||
|
||||
// Reverse to check chain consistency from oldest to newest
|
||||
block_batch.reverse();
|
||||
|
||||
// Checking chain consistency
|
||||
let mut prev_block_hash = block_batch.first().unwrap().header.hash;
|
||||
|
||||
for block in &block_batch[1..] {
|
||||
assert_eq!(block.header.prev_block_hash, prev_block_hash);
|
||||
|
||||
info!("Block {} chain-consistent", block.header.block_id);
|
||||
|
||||
prev_block_hash = block.header.hash;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn indexer_state_consistency() -> Result<()> {
|
||||
let mut ctx = TestContext::new().await?;
|
||||
|
||||
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
|
||||
from: public_mention(ctx.existing_public_accounts()[0]),
|
||||
to: Some(public_mention(ctx.existing_public_accounts()[1])),
|
||||
to_npk: None,
|
||||
to_vpk: None,
|
||||
to_identifier: Some(0),
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
info!("Checking correct balance move");
|
||||
let acc_1_balance = sequencer_service_rpc::RpcClient::get_account_balance(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[0],
|
||||
)
|
||||
.await?;
|
||||
let acc_2_balance = sequencer_service_rpc::RpcClient::get_account_balance(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[1],
|
||||
)
|
||||
.await?;
|
||||
|
||||
info!("Balance of sender: {acc_1_balance:#?}");
|
||||
info!("Balance of receiver: {acc_2_balance:#?}");
|
||||
|
||||
assert_eq!(acc_1_balance, 9900);
|
||||
assert_eq!(acc_2_balance, 20100);
|
||||
|
||||
let from: AccountId = ctx.existing_private_accounts()[0];
|
||||
let to: AccountId = ctx.existing_private_accounts()[1];
|
||||
|
||||
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
|
||||
from: private_mention(from),
|
||||
to: Some(private_mention(to)),
|
||||
to_npk: None,
|
||||
to_vpk: None,
|
||||
to_identifier: Some(0),
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
let new_commitment1 = ctx
|
||||
.wallet()
|
||||
.get_private_account_commitment(from)
|
||||
.context("Failed to get private account commitment for sender")?;
|
||||
assert!(verify_commitment_is_in_state(new_commitment1, ctx.sequencer_client()).await);
|
||||
|
||||
let new_commitment2 = ctx
|
||||
.wallet()
|
||||
.get_private_account_commitment(to)
|
||||
.context("Failed to get private account commitment for receiver")?;
|
||||
assert!(verify_commitment_is_in_state(new_commitment2, ctx.sequencer_client()).await);
|
||||
|
||||
info!("Successfully transferred privately to owned account");
|
||||
|
||||
info!("Waiting for indexer to parse blocks");
|
||||
wait_for_indexer_to_catch_up(&ctx).await?;
|
||||
|
||||
let acc1_ind_state = ctx
|
||||
.indexer_client()
|
||||
.get_account(ctx.existing_public_accounts()[0].into())
|
||||
.await
|
||||
.unwrap();
|
||||
let acc2_ind_state = ctx
|
||||
.indexer_client()
|
||||
.get_account(ctx.existing_public_accounts()[1].into())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
info!("Checking correct state transition");
|
||||
let acc1_seq_state = sequencer_service_rpc::RpcClient::get_account(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[0],
|
||||
)
|
||||
.await?;
|
||||
let acc2_seq_state = sequencer_service_rpc::RpcClient::get_account(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[1],
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert_eq!(acc1_ind_state, acc1_seq_state.into());
|
||||
assert_eq!(acc2_ind_state, acc2_seq_state.into());
|
||||
|
||||
// ToDo: Check private state transition
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn indexer_state_consistency_with_labels() -> Result<()> {
|
||||
let mut ctx = TestContext::new().await?;
|
||||
|
||||
// Assign labels to both accounts
|
||||
let from_label = Label::new("idx-sender-label");
|
||||
let to_label = Label::new("idx-receiver-label");
|
||||
|
||||
let label_cmd = Command::Account(wallet::cli::account::AccountSubcommand::Label {
|
||||
account_id: public_mention(ctx.existing_public_accounts()[0]),
|
||||
label: from_label.clone(),
|
||||
});
|
||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), label_cmd).await?;
|
||||
|
||||
let label_cmd = Command::Account(wallet::cli::account::AccountSubcommand::Label {
|
||||
account_id: public_mention(ctx.existing_public_accounts()[1]),
|
||||
label: to_label.clone(),
|
||||
});
|
||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), label_cmd).await?;
|
||||
|
||||
// Send using labels instead of account IDs
|
||||
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
|
||||
from: CliAccountMention::Label(from_label),
|
||||
to: Some(CliAccountMention::Label(to_label)),
|
||||
to_npk: None,
|
||||
to_vpk: None,
|
||||
to_identifier: Some(0),
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
let acc_1_balance = sequencer_service_rpc::RpcClient::get_account_balance(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[0],
|
||||
)
|
||||
.await?;
|
||||
let acc_2_balance = sequencer_service_rpc::RpcClient::get_account_balance(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[1],
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert_eq!(acc_1_balance, 9900);
|
||||
assert_eq!(acc_2_balance, 20100);
|
||||
|
||||
info!("Waiting for indexer to parse blocks");
|
||||
wait_for_indexer_to_catch_up(&ctx).await?;
|
||||
|
||||
let acc1_ind_state = ctx
|
||||
.indexer_client()
|
||||
.get_account(ctx.existing_public_accounts()[0].into())
|
||||
.await
|
||||
.unwrap();
|
||||
let acc1_seq_state = sequencer_service_rpc::RpcClient::get_account(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[0],
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert_eq!(acc1_ind_state, acc1_seq_state.into());
|
||||
|
||||
info!("Indexer state is consistent after label-based transfer");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
40
integration_tests/tests/indexer_block_batching.rs
Normal file
40
integration_tests/tests/indexer_block_batching.rs
Normal file
@ -0,0 +1,40 @@
|
||||
#![expect(
|
||||
clippy::tests_outside_test_module,
|
||||
reason = "We don't care about these in tests"
|
||||
)]
|
||||
|
||||
use anyhow::Result;
|
||||
use indexer_service_rpc::RpcClient as _;
|
||||
use integration_tests::{TestContext, wait_for_indexer_to_catch_up};
|
||||
use log::info;
|
||||
|
||||
#[tokio::test]
|
||||
async fn indexer_block_batching() -> Result<()> {
|
||||
let ctx = TestContext::new().await?;
|
||||
|
||||
info!("Waiting for indexer to parse blocks");
|
||||
let last_block_indexer = wait_for_indexer_to_catch_up(&ctx).await?;
|
||||
|
||||
info!("Last block on ind now is {last_block_indexer}");
|
||||
|
||||
assert!(last_block_indexer > 0);
|
||||
|
||||
// Getting wide batch to fit all blocks (from latest backwards)
|
||||
let mut block_batch = ctx.indexer_client().get_blocks(None, 100).await.unwrap();
|
||||
|
||||
// Reverse to check chain consistency from oldest to newest
|
||||
block_batch.reverse();
|
||||
|
||||
// Checking chain consistency
|
||||
let mut prev_block_hash = block_batch.first().unwrap().header.hash;
|
||||
|
||||
for block in &block_batch[1..] {
|
||||
assert_eq!(block.header.prev_block_hash, prev_block_hash);
|
||||
|
||||
info!("Block {} chain-consistent", block.header.block_id);
|
||||
|
||||
prev_block_hash = block.header.hash;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -1,404 +0,0 @@
|
||||
#![expect(
|
||||
clippy::shadow_unrelated,
|
||||
clippy::tests_outside_test_module,
|
||||
clippy::undocumented_unsafe_blocks,
|
||||
reason = "We don't care about these in tests"
|
||||
)]
|
||||
|
||||
use std::{
|
||||
ffi::{CString, c_char},
|
||||
fs::File,
|
||||
io::Write as _,
|
||||
net::SocketAddr,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use anyhow::{Context as _, Result};
|
||||
use indexer_ffi::{
|
||||
IndexerServiceFFI, OperationStatus, Runtime,
|
||||
api::{
|
||||
PointerResult,
|
||||
lifecycle::InitializedIndexerServiceFFIResult,
|
||||
types::{FfiAccountId, FfiOption, FfiVec, account::FfiAccount, block::FfiBlock},
|
||||
},
|
||||
};
|
||||
use integration_tests::{
|
||||
BlockingTestContext, TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, private_mention,
|
||||
public_mention, verify_commitment_is_in_state,
|
||||
};
|
||||
use log::{debug, info};
|
||||
use nssa::AccountId;
|
||||
use tempfile::TempDir;
|
||||
use wallet::{
|
||||
account::Label,
|
||||
cli::{Command, programs::native_token_transfer::AuthTransferSubcommand},
|
||||
};
|
||||
|
||||
/// Maximum time to wait for the indexer to catch up to the sequencer.
|
||||
const L2_TO_L1_TIMEOUT: Duration = Duration::from_mins(6);
|
||||
|
||||
unsafe extern "C" {
|
||||
unsafe fn query_last_block(
|
||||
runtime: *const Runtime,
|
||||
indexer: *const IndexerServiceFFI,
|
||||
) -> PointerResult<u64, OperationStatus>;
|
||||
|
||||
unsafe fn query_block_vec(
|
||||
runtime: *const Runtime,
|
||||
indexer: *const IndexerServiceFFI,
|
||||
before: FfiOption<u64>,
|
||||
limit: u64,
|
||||
) -> PointerResult<FfiVec<FfiBlock>, OperationStatus>;
|
||||
|
||||
unsafe fn query_account(
|
||||
runtime: *const Runtime,
|
||||
indexer: *const IndexerServiceFFI,
|
||||
account_id: FfiAccountId,
|
||||
) -> PointerResult<FfiAccount, OperationStatus>;
|
||||
|
||||
unsafe fn start_indexer(
|
||||
runtime: *const Runtime,
|
||||
config_path: *const c_char,
|
||||
port: u16,
|
||||
) -> InitializedIndexerServiceFFIResult;
|
||||
}
|
||||
|
||||
fn setup_indexer_ffi(
|
||||
runtime: &Runtime,
|
||||
bedrock_addr: SocketAddr,
|
||||
) -> Result<(IndexerServiceFFI, TempDir)> {
|
||||
let temp_indexer_dir =
|
||||
tempfile::tempdir().context("Failed to create temp dir for indexer home")?;
|
||||
|
||||
debug!(
|
||||
"Using temp indexer home at {}",
|
||||
temp_indexer_dir.path().display()
|
||||
);
|
||||
|
||||
let indexer_config =
|
||||
integration_tests::config::indexer_config(bedrock_addr, temp_indexer_dir.path().to_owned())
|
||||
.context("Failed to create Indexer config")?;
|
||||
|
||||
let config_json = serde_json::to_vec(&indexer_config)?;
|
||||
let config_path = temp_indexer_dir.path().join("indexer_config.json");
|
||||
let mut file = File::create(config_path.as_path())?;
|
||||
file.write_all(&config_json)?;
|
||||
file.flush()?;
|
||||
|
||||
let res =
|
||||
// SAFETY: lib function ensures validity of value.
|
||||
unsafe { start_indexer(std::ptr::from_ref(runtime), CString::new(config_path.to_str().unwrap())?.as_ptr(), 0) };
|
||||
|
||||
if res.error.is_error() {
|
||||
anyhow::bail!("Indexer FFI error {:?}", res.error);
|
||||
}
|
||||
|
||||
Ok((
|
||||
// SAFETY: lib function ensures validity of value.
|
||||
unsafe { std::ptr::read(res.value) },
|
||||
temp_indexer_dir,
|
||||
))
|
||||
}
|
||||
|
||||
/// Prepare setup for tests.
|
||||
fn setup() -> Result<(BlockingTestContext, IndexerServiceFFI, TempDir)> {
|
||||
let ctx = TestContext::builder().disable_indexer().build_blocking()?;
|
||||
// Safety: ctx runtime is valid for the lifetime of the returned Runtime
|
||||
let runtime = unsafe { Runtime::from_borrowed(ctx.runtime()) };
|
||||
let (indexer_ffi, indexer_dir) = setup_indexer_ffi(&runtime, ctx.ctx().bedrock_addr())?;
|
||||
|
||||
Ok((ctx, indexer_ffi, indexer_dir))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn indexer_test_run_ffi() -> Result<()> {
|
||||
let (ctx, indexer_ffi, _indexer_dir) = setup()?;
|
||||
|
||||
// RUN OBSERVATION
|
||||
std::thread::sleep(L2_TO_L1_TIMEOUT);
|
||||
|
||||
// Safety: ctx runtime is valid for the lifetime of the returned Runtime
|
||||
let runtime = unsafe { Runtime::from_borrowed(ctx.runtime()) };
|
||||
let last_block_indexer_ffi_res =
|
||||
unsafe { query_last_block(&raw const runtime, &raw const indexer_ffi) };
|
||||
|
||||
assert!(last_block_indexer_ffi_res.error.is_ok());
|
||||
|
||||
let last_block_indexer_ffi = unsafe { *last_block_indexer_ffi_res.value };
|
||||
|
||||
info!("Last block on indexer FFI now is {last_block_indexer_ffi}");
|
||||
|
||||
assert!(last_block_indexer_ffi > 0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn indexer_ffi_block_batching() -> Result<()> {
|
||||
let (ctx, indexer_ffi, _indexer_dir) = setup()?;
|
||||
|
||||
// WAIT
|
||||
info!("Waiting for indexer to parse blocks");
|
||||
std::thread::sleep(L2_TO_L1_TIMEOUT);
|
||||
|
||||
// Safety: ctx runtime is valid for the lifetime of the returned Runtime
|
||||
let runtime = unsafe { Runtime::from_borrowed(ctx.runtime()) };
|
||||
let last_block_indexer_ffi_res =
|
||||
unsafe { query_last_block(&raw const runtime, &raw const indexer_ffi) };
|
||||
|
||||
assert!(last_block_indexer_ffi_res.error.is_ok());
|
||||
|
||||
let last_block_indexer = unsafe { *last_block_indexer_ffi_res.value };
|
||||
|
||||
info!("Last block on indexer FFI now is {last_block_indexer}");
|
||||
|
||||
assert!(last_block_indexer > 0);
|
||||
|
||||
let before_ffi = FfiOption::<u64>::from_none();
|
||||
let limit = 100;
|
||||
|
||||
let block_batch_ffi_res = unsafe {
|
||||
query_block_vec(
|
||||
&raw const runtime,
|
||||
&raw const indexer_ffi,
|
||||
before_ffi,
|
||||
limit,
|
||||
)
|
||||
};
|
||||
|
||||
assert!(block_batch_ffi_res.error.is_ok());
|
||||
|
||||
let block_batch = unsafe { &*block_batch_ffi_res.value };
|
||||
|
||||
let mut last_block_prev_hash = unsafe { block_batch.get(0) }.header.prev_block_hash.data;
|
||||
|
||||
for i in 1..block_batch.len {
|
||||
let block = unsafe { block_batch.get(i) };
|
||||
|
||||
assert_eq!(last_block_prev_hash, block.header.hash.data);
|
||||
|
||||
info!("Block {} chain-consistent", block.header.block_id);
|
||||
|
||||
last_block_prev_hash = block.header.prev_block_hash.data;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn indexer_ffi_state_consistency() -> Result<()> {
|
||||
let (mut ctx, indexer_ffi, _indexer_dir) = setup()?;
|
||||
|
||||
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
|
||||
from: public_mention(ctx.ctx().existing_public_accounts()[0]),
|
||||
to: Some(public_mention(ctx.ctx().existing_public_accounts()[1])),
|
||||
to_npk: None,
|
||||
to_vpk: None,
|
||||
amount: 100,
|
||||
to_identifier: Some(0),
|
||||
});
|
||||
|
||||
ctx.block_on_mut(|ctx| wallet::cli::execute_subcommand(ctx.wallet_mut(), command))?;
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
std::thread::sleep(std::time::Duration::from_secs(
|
||||
TIME_TO_WAIT_FOR_BLOCK_SECONDS,
|
||||
));
|
||||
|
||||
info!("Checking correct balance move");
|
||||
let acc_1_balance = ctx.block_on(|ctx| {
|
||||
sequencer_service_rpc::RpcClient::get_account_balance(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[0],
|
||||
)
|
||||
})?;
|
||||
let acc_2_balance = ctx.block_on(|ctx| {
|
||||
sequencer_service_rpc::RpcClient::get_account_balance(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[1],
|
||||
)
|
||||
})?;
|
||||
|
||||
info!("Balance of sender: {acc_1_balance:#?}");
|
||||
info!("Balance of receiver: {acc_2_balance:#?}");
|
||||
|
||||
assert_eq!(acc_1_balance, 9900);
|
||||
assert_eq!(acc_2_balance, 20100);
|
||||
|
||||
let from: AccountId = ctx.ctx().existing_private_accounts()[0];
|
||||
let to: AccountId = ctx.ctx().existing_private_accounts()[1];
|
||||
|
||||
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
|
||||
from: private_mention(from),
|
||||
to: Some(private_mention(to)),
|
||||
to_npk: None,
|
||||
to_vpk: None,
|
||||
amount: 100,
|
||||
to_identifier: Some(0),
|
||||
});
|
||||
|
||||
ctx.block_on_mut(|ctx| wallet::cli::execute_subcommand(ctx.wallet_mut(), command))?;
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
std::thread::sleep(std::time::Duration::from_secs(
|
||||
TIME_TO_WAIT_FOR_BLOCK_SECONDS,
|
||||
));
|
||||
|
||||
let new_commitment1 = ctx
|
||||
.ctx()
|
||||
.wallet()
|
||||
.get_private_account_commitment(from)
|
||||
.context("Failed to get private account commitment for sender")?;
|
||||
let commitment_check1 =
|
||||
ctx.block_on(|ctx| verify_commitment_is_in_state(new_commitment1, ctx.sequencer_client()));
|
||||
assert!(commitment_check1);
|
||||
|
||||
let new_commitment2 = ctx
|
||||
.ctx()
|
||||
.wallet()
|
||||
.get_private_account_commitment(to)
|
||||
.context("Failed to get private account commitment for receiver")?;
|
||||
let commitment_check2 =
|
||||
ctx.block_on(|ctx| verify_commitment_is_in_state(new_commitment2, ctx.sequencer_client()));
|
||||
assert!(commitment_check2);
|
||||
|
||||
info!("Successfully transferred privately to owned account");
|
||||
|
||||
// WAIT
|
||||
info!("Waiting for indexer to parse blocks");
|
||||
std::thread::sleep(L2_TO_L1_TIMEOUT);
|
||||
|
||||
// Safety: ctx runtime is valid for the lifetime of the returned Runtime
|
||||
let runtime = unsafe { Runtime::from_borrowed(ctx.runtime()) };
|
||||
let acc1_ind_state_ffi = unsafe {
|
||||
query_account(
|
||||
&raw const runtime,
|
||||
&raw const indexer_ffi,
|
||||
(&ctx.ctx().existing_public_accounts()[0]).into(),
|
||||
)
|
||||
};
|
||||
|
||||
assert!(acc1_ind_state_ffi.error.is_ok());
|
||||
|
||||
let acc1_ind_state_pre = unsafe { &*acc1_ind_state_ffi.value };
|
||||
let acc1_ind_state: indexer_service_protocol::Account = acc1_ind_state_pre.into();
|
||||
|
||||
let acc2_ind_state_ffi = unsafe {
|
||||
query_account(
|
||||
&raw const runtime,
|
||||
&raw const indexer_ffi,
|
||||
(&ctx.ctx().existing_public_accounts()[1]).into(),
|
||||
)
|
||||
};
|
||||
|
||||
assert!(acc2_ind_state_ffi.error.is_ok());
|
||||
|
||||
let acc2_ind_state_pre = unsafe { &*acc2_ind_state_ffi.value };
|
||||
let acc2_ind_state: indexer_service_protocol::Account = acc2_ind_state_pre.into();
|
||||
|
||||
info!("Checking correct state transition");
|
||||
let acc1_seq_state = ctx.block_on(|ctx| {
|
||||
sequencer_service_rpc::RpcClient::get_account(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[0],
|
||||
)
|
||||
})?;
|
||||
let acc2_seq_state = ctx.block_on(|ctx| {
|
||||
sequencer_service_rpc::RpcClient::get_account(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[1],
|
||||
)
|
||||
})?;
|
||||
|
||||
assert_eq!(acc1_ind_state, acc1_seq_state.into());
|
||||
assert_eq!(acc2_ind_state, acc2_seq_state.into());
|
||||
|
||||
// ToDo: Check private state transition
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn indexer_ffi_state_consistency_with_labels() -> Result<()> {
|
||||
let (mut ctx, indexer_ffi, _indexer_dir) = setup()?;
|
||||
|
||||
// Assign labels to both accounts
|
||||
let from_label = Label::new("idx-sender-label");
|
||||
let to_label = Label::new("idx-receiver-label");
|
||||
|
||||
let label_cmd = Command::Account(wallet::cli::account::AccountSubcommand::Label {
|
||||
account_id: public_mention(ctx.ctx().existing_public_accounts()[0]),
|
||||
label: from_label.clone(),
|
||||
});
|
||||
ctx.block_on_mut(|ctx| wallet::cli::execute_subcommand(ctx.wallet_mut(), label_cmd))?;
|
||||
|
||||
let label_cmd = Command::Account(wallet::cli::account::AccountSubcommand::Label {
|
||||
account_id: public_mention(ctx.ctx().existing_public_accounts()[1]),
|
||||
label: to_label.clone(),
|
||||
});
|
||||
ctx.block_on_mut(|ctx| wallet::cli::execute_subcommand(ctx.wallet_mut(), label_cmd))?;
|
||||
|
||||
// Send using labels instead of account IDs
|
||||
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
|
||||
from: from_label.into(),
|
||||
to: Some(to_label.into()),
|
||||
to_npk: None,
|
||||
to_vpk: None,
|
||||
amount: 100,
|
||||
to_identifier: Some(0),
|
||||
});
|
||||
|
||||
ctx.block_on_mut(|ctx| wallet::cli::execute_subcommand(ctx.wallet_mut(), command))?;
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
std::thread::sleep(std::time::Duration::from_secs(
|
||||
TIME_TO_WAIT_FOR_BLOCK_SECONDS,
|
||||
));
|
||||
|
||||
let acc_1_balance = ctx.block_on(|ctx| {
|
||||
sequencer_service_rpc::RpcClient::get_account_balance(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[0],
|
||||
)
|
||||
})?;
|
||||
let acc_2_balance = ctx.block_on(|ctx| {
|
||||
sequencer_service_rpc::RpcClient::get_account_balance(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[1],
|
||||
)
|
||||
})?;
|
||||
|
||||
assert_eq!(acc_1_balance, 9900);
|
||||
assert_eq!(acc_2_balance, 20100);
|
||||
|
||||
info!("Waiting for indexer to parse blocks");
|
||||
std::thread::sleep(L2_TO_L1_TIMEOUT);
|
||||
|
||||
// Safety: ctx runtime is valid for the lifetime of the returned Runtime
|
||||
let runtime = unsafe { Runtime::from_borrowed(ctx.runtime()) };
|
||||
let acc1_ind_state_ffi = unsafe {
|
||||
query_account(
|
||||
&raw const runtime,
|
||||
&raw const indexer_ffi,
|
||||
(&ctx.ctx().existing_public_accounts()[0]).into(),
|
||||
)
|
||||
};
|
||||
|
||||
assert!(acc1_ind_state_ffi.error.is_ok());
|
||||
|
||||
let acc1_ind_state_pre = unsafe { &*acc1_ind_state_ffi.value };
|
||||
let acc1_ind_state: indexer_service_protocol::Account = acc1_ind_state_pre.into();
|
||||
|
||||
let acc1_seq_state = ctx.block_on(|ctx| {
|
||||
sequencer_service_rpc::RpcClient::get_account(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[0],
|
||||
)
|
||||
})?;
|
||||
|
||||
assert_eq!(acc1_ind_state, acc1_seq_state.into());
|
||||
|
||||
info!("Indexer state is consistent after label-based transfer");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
66
integration_tests/tests/indexer_ffi_block_batching.rs
Normal file
66
integration_tests/tests/indexer_ffi_block_batching.rs
Normal file
@ -0,0 +1,66 @@
|
||||
#![expect(
|
||||
clippy::tests_outside_test_module,
|
||||
clippy::undocumented_unsafe_blocks,
|
||||
reason = "We don't care about these in tests"
|
||||
)]
|
||||
|
||||
use anyhow::Result;
|
||||
use indexer_ffi::{Runtime, api::types::FfiOption};
|
||||
use integration_tests::L2_TO_L1_TIMEOUT;
|
||||
use log::info;
|
||||
|
||||
#[path = "indexer_ffi_helpers/mod.rs"]
|
||||
mod indexer_ffi_helpers;
|
||||
|
||||
#[test]
|
||||
fn indexer_ffi_block_batching() -> Result<()> {
|
||||
let (ctx, indexer_ffi, _indexer_dir) = indexer_ffi_helpers::setup()?;
|
||||
|
||||
// WAIT
|
||||
info!("Waiting for indexer to parse blocks");
|
||||
std::thread::sleep(L2_TO_L1_TIMEOUT);
|
||||
|
||||
// Safety: ctx runtime is valid for the lifetime of the returned Runtime
|
||||
let runtime = unsafe { Runtime::from_borrowed(ctx.runtime()) };
|
||||
let last_block_indexer_ffi_res = unsafe {
|
||||
indexer_ffi_helpers::query_last_block(&raw const runtime, &raw const indexer_ffi)
|
||||
};
|
||||
|
||||
assert!(last_block_indexer_ffi_res.error.is_ok());
|
||||
|
||||
let last_block_indexer = unsafe { *last_block_indexer_ffi_res.value };
|
||||
|
||||
info!("Last block on indexer FFI now is {last_block_indexer}");
|
||||
|
||||
assert!(last_block_indexer > 0);
|
||||
|
||||
let before_ffi = FfiOption::<u64>::from_none();
|
||||
let limit = 100;
|
||||
|
||||
let block_batch_ffi_res = unsafe {
|
||||
indexer_ffi_helpers::query_block_vec(
|
||||
&raw const runtime,
|
||||
&raw const indexer_ffi,
|
||||
before_ffi,
|
||||
limit,
|
||||
)
|
||||
};
|
||||
|
||||
assert!(block_batch_ffi_res.error.is_ok());
|
||||
|
||||
let block_batch = unsafe { &*block_batch_ffi_res.value };
|
||||
|
||||
let mut last_block_prev_hash = unsafe { block_batch.get(0) }.header.prev_block_hash.data;
|
||||
|
||||
for i in 1..block_batch.len {
|
||||
let block = unsafe { block_batch.get(i) };
|
||||
|
||||
assert_eq!(last_block_prev_hash, block.header.hash.data);
|
||||
|
||||
info!("Block {} chain-consistent", block.header.block_id);
|
||||
|
||||
last_block_prev_hash = block.header.prev_block_hash.data;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
91
integration_tests/tests/indexer_ffi_helpers/mod.rs
Normal file
91
integration_tests/tests/indexer_ffi_helpers/mod.rs
Normal file
@ -0,0 +1,91 @@
|
||||
#![allow(dead_code, reason = "helper module used only by FFI test binaries")]
|
||||
|
||||
use std::{
|
||||
ffi::{CString, c_char},
|
||||
fs::File,
|
||||
io::Write as _,
|
||||
net::SocketAddr,
|
||||
};
|
||||
|
||||
use anyhow::{Context as _, Result};
|
||||
use indexer_ffi::{
|
||||
IndexerServiceFFI, OperationStatus, Runtime,
|
||||
api::{
|
||||
PointerResult,
|
||||
lifecycle::InitializedIndexerServiceFFIResult,
|
||||
types::{FfiAccountId, FfiOption, FfiVec, account::FfiAccount, block::FfiBlock},
|
||||
},
|
||||
};
|
||||
use integration_tests::{BlockingTestContext, TestContext};
|
||||
use tempfile::TempDir;
|
||||
|
||||
unsafe extern "C" {
|
||||
pub unsafe fn query_last_block(
|
||||
runtime: *const Runtime,
|
||||
indexer: *const IndexerServiceFFI,
|
||||
) -> PointerResult<u64, OperationStatus>;
|
||||
|
||||
pub unsafe fn query_block_vec(
|
||||
runtime: *const Runtime,
|
||||
indexer: *const IndexerServiceFFI,
|
||||
before: FfiOption<u64>,
|
||||
limit: u64,
|
||||
) -> PointerResult<FfiVec<FfiBlock>, OperationStatus>;
|
||||
|
||||
pub unsafe fn query_account(
|
||||
runtime: *const Runtime,
|
||||
indexer: *const IndexerServiceFFI,
|
||||
account_id: FfiAccountId,
|
||||
) -> PointerResult<FfiAccount, OperationStatus>;
|
||||
|
||||
pub unsafe fn start_indexer(
|
||||
runtime: *const Runtime,
|
||||
config_path: *const c_char,
|
||||
port: u16,
|
||||
) -> InitializedIndexerServiceFFIResult;
|
||||
}
|
||||
|
||||
pub fn setup_indexer_ffi(
|
||||
runtime: &Runtime,
|
||||
bedrock_addr: SocketAddr,
|
||||
) -> Result<(IndexerServiceFFI, TempDir)> {
|
||||
let temp_indexer_dir =
|
||||
tempfile::tempdir().context("Failed to create temp dir for indexer home")?;
|
||||
|
||||
log::debug!(
|
||||
"Using temp indexer home at {}",
|
||||
temp_indexer_dir.path().display()
|
||||
);
|
||||
|
||||
let indexer_config =
|
||||
integration_tests::config::indexer_config(bedrock_addr, temp_indexer_dir.path().to_owned())
|
||||
.context("Failed to create Indexer config")?;
|
||||
|
||||
let config_json = serde_json::to_vec(&indexer_config)?;
|
||||
let config_path = temp_indexer_dir.path().join("indexer_config.json");
|
||||
let mut file = File::create(config_path.as_path())?;
|
||||
file.write_all(&config_json)?;
|
||||
file.flush()?;
|
||||
|
||||
let res =
|
||||
// SAFETY: lib function ensures validity of value.
|
||||
unsafe { start_indexer(std::ptr::from_ref(runtime), CString::new(config_path.to_str().unwrap())?.as_ptr(), 0) };
|
||||
|
||||
if res.error.is_error() {
|
||||
anyhow::bail!("Indexer FFI error {:?}", res.error);
|
||||
}
|
||||
|
||||
Ok((
|
||||
// SAFETY: lib function ensures validity of value.
|
||||
unsafe { std::ptr::read(res.value) },
|
||||
temp_indexer_dir,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn setup() -> Result<(BlockingTestContext, IndexerServiceFFI, TempDir)> {
|
||||
let ctx = TestContext::builder().disable_indexer().build_blocking()?;
|
||||
// Safety: ctx runtime is valid for the lifetime of the returned Runtime
|
||||
let runtime = unsafe { Runtime::from_borrowed(ctx.runtime()) };
|
||||
let (indexer_ffi, indexer_dir) = setup_indexer_ffi(&runtime, ctx.ctx().bedrock_addr())?;
|
||||
Ok((ctx, indexer_ffi, indexer_dir))
|
||||
}
|
||||
151
integration_tests/tests/indexer_ffi_state_consistency.rs
Normal file
151
integration_tests/tests/indexer_ffi_state_consistency.rs
Normal file
@ -0,0 +1,151 @@
|
||||
#![expect(
|
||||
clippy::shadow_unrelated,
|
||||
clippy::tests_outside_test_module,
|
||||
clippy::undocumented_unsafe_blocks,
|
||||
reason = "We don't care about these in tests"
|
||||
)]
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context as _, Result};
|
||||
use indexer_ffi::Runtime;
|
||||
use indexer_service_protocol::Account;
|
||||
use integration_tests::{
|
||||
L2_TO_L1_TIMEOUT, TIME_TO_WAIT_FOR_BLOCK_SECONDS, private_mention, public_mention,
|
||||
verify_commitment_is_in_state,
|
||||
};
|
||||
use lee::AccountId;
|
||||
use log::info;
|
||||
use wallet::cli::{Command, programs::native_token_transfer::AuthTransferSubcommand};
|
||||
|
||||
#[path = "indexer_ffi_helpers/mod.rs"]
|
||||
mod indexer_ffi_helpers;
|
||||
|
||||
#[test]
|
||||
fn indexer_ffi_state_consistency() -> Result<()> {
|
||||
let (mut ctx, indexer_ffi, _indexer_dir) = indexer_ffi_helpers::setup()?;
|
||||
|
||||
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
|
||||
from: public_mention(ctx.ctx().existing_public_accounts()[0]),
|
||||
to: Some(public_mention(ctx.ctx().existing_public_accounts()[1])),
|
||||
to_npk: None,
|
||||
to_vpk: None,
|
||||
amount: 100,
|
||||
to_identifier: Some(0),
|
||||
});
|
||||
|
||||
ctx.block_on_mut(|ctx| wallet::cli::execute_subcommand(ctx.wallet_mut(), command))?;
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
std::thread::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS));
|
||||
|
||||
info!("Checking correct balance move");
|
||||
let acc_1_balance = ctx.block_on(|ctx| {
|
||||
sequencer_service_rpc::RpcClient::get_account_balance(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[0],
|
||||
)
|
||||
})?;
|
||||
let acc_2_balance = ctx.block_on(|ctx| {
|
||||
sequencer_service_rpc::RpcClient::get_account_balance(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[1],
|
||||
)
|
||||
})?;
|
||||
|
||||
info!("Balance of sender: {acc_1_balance:#?}");
|
||||
info!("Balance of receiver: {acc_2_balance:#?}");
|
||||
|
||||
assert_eq!(acc_1_balance, 9900);
|
||||
assert_eq!(acc_2_balance, 20100);
|
||||
|
||||
let from: AccountId = ctx.ctx().existing_private_accounts()[0];
|
||||
let to: AccountId = ctx.ctx().existing_private_accounts()[1];
|
||||
|
||||
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
|
||||
from: private_mention(from),
|
||||
to: Some(private_mention(to)),
|
||||
to_npk: None,
|
||||
to_vpk: None,
|
||||
amount: 100,
|
||||
to_identifier: Some(0),
|
||||
});
|
||||
|
||||
ctx.block_on_mut(|ctx| wallet::cli::execute_subcommand(ctx.wallet_mut(), command))?;
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
std::thread::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS));
|
||||
|
||||
let new_commitment1 = ctx
|
||||
.ctx()
|
||||
.wallet()
|
||||
.get_private_account_commitment(from)
|
||||
.context("Failed to get private account commitment for sender")?;
|
||||
let commitment_check1 =
|
||||
ctx.block_on(|ctx| verify_commitment_is_in_state(new_commitment1, ctx.sequencer_client()));
|
||||
assert!(commitment_check1);
|
||||
|
||||
let new_commitment2 = ctx
|
||||
.ctx()
|
||||
.wallet()
|
||||
.get_private_account_commitment(to)
|
||||
.context("Failed to get private account commitment for receiver")?;
|
||||
let commitment_check2 =
|
||||
ctx.block_on(|ctx| verify_commitment_is_in_state(new_commitment2, ctx.sequencer_client()));
|
||||
assert!(commitment_check2);
|
||||
|
||||
info!("Successfully transferred privately to owned account");
|
||||
|
||||
// WAIT
|
||||
info!("Waiting for indexer to parse blocks");
|
||||
std::thread::sleep(L2_TO_L1_TIMEOUT);
|
||||
|
||||
// Safety: ctx runtime is valid for the lifetime of the returned Runtime
|
||||
let runtime = unsafe { Runtime::from_borrowed(ctx.runtime()) };
|
||||
let acc1_ind_state_ffi = unsafe {
|
||||
indexer_ffi_helpers::query_account(
|
||||
&raw const runtime,
|
||||
&raw const indexer_ffi,
|
||||
(&ctx.ctx().existing_public_accounts()[0]).into(),
|
||||
)
|
||||
};
|
||||
|
||||
assert!(acc1_ind_state_ffi.error.is_ok());
|
||||
|
||||
let acc1_ind_state_pre = unsafe { &*acc1_ind_state_ffi.value };
|
||||
let acc1_ind_state: Account = acc1_ind_state_pre.into();
|
||||
|
||||
let acc2_ind_state_ffi = unsafe {
|
||||
indexer_ffi_helpers::query_account(
|
||||
&raw const runtime,
|
||||
&raw const indexer_ffi,
|
||||
(&ctx.ctx().existing_public_accounts()[1]).into(),
|
||||
)
|
||||
};
|
||||
|
||||
assert!(acc2_ind_state_ffi.error.is_ok());
|
||||
|
||||
let acc2_ind_state_pre = unsafe { &*acc2_ind_state_ffi.value };
|
||||
let acc2_ind_state: Account = acc2_ind_state_pre.into();
|
||||
|
||||
info!("Checking correct state transition");
|
||||
let acc1_seq_state = ctx.block_on(|ctx| {
|
||||
sequencer_service_rpc::RpcClient::get_account(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[0],
|
||||
)
|
||||
})?;
|
||||
let acc2_seq_state = ctx.block_on(|ctx| {
|
||||
sequencer_service_rpc::RpcClient::get_account(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[1],
|
||||
)
|
||||
})?;
|
||||
|
||||
assert_eq!(acc1_ind_state, acc1_seq_state.into());
|
||||
assert_eq!(acc2_ind_state, acc2_seq_state.into());
|
||||
|
||||
// ToDo: Check private state transition
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
#![expect(
|
||||
clippy::shadow_unrelated,
|
||||
clippy::tests_outside_test_module,
|
||||
clippy::undocumented_unsafe_blocks,
|
||||
reason = "We don't care about these in tests"
|
||||
)]
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use indexer_ffi::Runtime;
|
||||
use indexer_service_protocol::Account;
|
||||
use integration_tests::{L2_TO_L1_TIMEOUT, TIME_TO_WAIT_FOR_BLOCK_SECONDS, public_mention};
|
||||
use log::info;
|
||||
use wallet::{
|
||||
account::Label,
|
||||
cli::{Command, programs::native_token_transfer::AuthTransferSubcommand},
|
||||
};
|
||||
|
||||
#[path = "indexer_ffi_helpers/mod.rs"]
|
||||
mod indexer_ffi_helpers;
|
||||
|
||||
#[test]
|
||||
fn indexer_ffi_state_consistency_with_labels() -> Result<()> {
|
||||
let (mut ctx, indexer_ffi, _indexer_dir) = indexer_ffi_helpers::setup()?;
|
||||
|
||||
// Assign labels to both accounts
|
||||
let from_label = Label::new("idx-sender-label");
|
||||
let to_label = Label::new("idx-receiver-label");
|
||||
|
||||
let label_cmd = Command::Account(wallet::cli::account::AccountSubcommand::Label {
|
||||
account_id: public_mention(ctx.ctx().existing_public_accounts()[0]),
|
||||
label: from_label.clone(),
|
||||
});
|
||||
ctx.block_on_mut(|ctx| wallet::cli::execute_subcommand(ctx.wallet_mut(), label_cmd))?;
|
||||
|
||||
let label_cmd = Command::Account(wallet::cli::account::AccountSubcommand::Label {
|
||||
account_id: public_mention(ctx.ctx().existing_public_accounts()[1]),
|
||||
label: to_label.clone(),
|
||||
});
|
||||
ctx.block_on_mut(|ctx| wallet::cli::execute_subcommand(ctx.wallet_mut(), label_cmd))?;
|
||||
|
||||
// Send using labels instead of account IDs
|
||||
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
|
||||
from: from_label.into(),
|
||||
to: Some(to_label.into()),
|
||||
to_npk: None,
|
||||
to_vpk: None,
|
||||
amount: 100,
|
||||
to_identifier: Some(0),
|
||||
});
|
||||
|
||||
ctx.block_on_mut(|ctx| wallet::cli::execute_subcommand(ctx.wallet_mut(), command))?;
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
std::thread::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS));
|
||||
|
||||
let acc_1_balance = ctx.block_on(|ctx| {
|
||||
sequencer_service_rpc::RpcClient::get_account_balance(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[0],
|
||||
)
|
||||
})?;
|
||||
let acc_2_balance = ctx.block_on(|ctx| {
|
||||
sequencer_service_rpc::RpcClient::get_account_balance(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[1],
|
||||
)
|
||||
})?;
|
||||
|
||||
assert_eq!(acc_1_balance, 9900);
|
||||
assert_eq!(acc_2_balance, 20100);
|
||||
|
||||
info!("Waiting for indexer to parse blocks");
|
||||
std::thread::sleep(L2_TO_L1_TIMEOUT);
|
||||
|
||||
// Safety: ctx runtime is valid for the lifetime of the returned Runtime
|
||||
let runtime = unsafe { Runtime::from_borrowed(ctx.runtime()) };
|
||||
let acc1_ind_state_ffi = unsafe {
|
||||
indexer_ffi_helpers::query_account(
|
||||
&raw const runtime,
|
||||
&raw const indexer_ffi,
|
||||
(&ctx.ctx().existing_public_accounts()[0]).into(),
|
||||
)
|
||||
};
|
||||
|
||||
assert!(acc1_ind_state_ffi.error.is_ok());
|
||||
|
||||
let acc1_ind_state_pre = unsafe { &*acc1_ind_state_ffi.value };
|
||||
let acc1_ind_state: Account = acc1_ind_state_pre.into();
|
||||
|
||||
let acc1_seq_state = ctx.block_on(|ctx| {
|
||||
sequencer_service_rpc::RpcClient::get_account(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[0],
|
||||
)
|
||||
})?;
|
||||
|
||||
assert_eq!(acc1_ind_state, acc1_seq_state.into());
|
||||
|
||||
info!("Indexer state is consistent after label-based transfer");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
118
integration_tests/tests/indexer_state_consistency.rs
Normal file
118
integration_tests/tests/indexer_state_consistency.rs
Normal file
@ -0,0 +1,118 @@
|
||||
#![expect(
|
||||
clippy::shadow_unrelated,
|
||||
clippy::tests_outside_test_module,
|
||||
reason = "We don't care about these in tests"
|
||||
)]
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context as _, Result};
|
||||
use indexer_service_rpc::RpcClient as _;
|
||||
use integration_tests::{
|
||||
TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, private_mention, public_mention,
|
||||
verify_commitment_is_in_state, wait_for_indexer_to_catch_up,
|
||||
};
|
||||
use lee::AccountId;
|
||||
use log::info;
|
||||
use wallet::cli::{Command, programs::native_token_transfer::AuthTransferSubcommand};
|
||||
|
||||
#[tokio::test]
|
||||
async fn indexer_state_consistency() -> Result<()> {
|
||||
let mut ctx = TestContext::new().await?;
|
||||
|
||||
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
|
||||
from: public_mention(ctx.existing_public_accounts()[0]),
|
||||
to: Some(public_mention(ctx.existing_public_accounts()[1])),
|
||||
to_npk: None,
|
||||
to_vpk: None,
|
||||
to_identifier: Some(0),
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
info!("Checking correct balance move");
|
||||
let acc_1_balance = sequencer_service_rpc::RpcClient::get_account_balance(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[0],
|
||||
)
|
||||
.await?;
|
||||
let acc_2_balance = sequencer_service_rpc::RpcClient::get_account_balance(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[1],
|
||||
)
|
||||
.await?;
|
||||
|
||||
info!("Balance of sender: {acc_1_balance:#?}");
|
||||
info!("Balance of receiver: {acc_2_balance:#?}");
|
||||
|
||||
assert_eq!(acc_1_balance, 9900);
|
||||
assert_eq!(acc_2_balance, 20100);
|
||||
|
||||
let from: AccountId = ctx.existing_private_accounts()[0];
|
||||
let to: AccountId = ctx.existing_private_accounts()[1];
|
||||
|
||||
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
|
||||
from: private_mention(from),
|
||||
to: Some(private_mention(to)),
|
||||
to_npk: None,
|
||||
to_vpk: None,
|
||||
to_identifier: Some(0),
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
let new_commitment1 = ctx
|
||||
.wallet()
|
||||
.get_private_account_commitment(from)
|
||||
.context("Failed to get private account commitment for sender")?;
|
||||
assert!(verify_commitment_is_in_state(new_commitment1, ctx.sequencer_client()).await);
|
||||
|
||||
let new_commitment2 = ctx
|
||||
.wallet()
|
||||
.get_private_account_commitment(to)
|
||||
.context("Failed to get private account commitment for receiver")?;
|
||||
assert!(verify_commitment_is_in_state(new_commitment2, ctx.sequencer_client()).await);
|
||||
|
||||
info!("Successfully transferred privately to owned account");
|
||||
|
||||
info!("Waiting for indexer to parse blocks");
|
||||
wait_for_indexer_to_catch_up(&ctx).await?;
|
||||
|
||||
let acc1_ind_state = ctx
|
||||
.indexer_client()
|
||||
.get_account(ctx.existing_public_accounts()[0].into())
|
||||
.await
|
||||
.unwrap();
|
||||
let acc2_ind_state = ctx
|
||||
.indexer_client()
|
||||
.get_account(ctx.existing_public_accounts()[1].into())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
info!("Checking correct state transition");
|
||||
let acc1_seq_state = sequencer_service_rpc::RpcClient::get_account(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[0],
|
||||
)
|
||||
.await?;
|
||||
let acc2_seq_state = sequencer_service_rpc::RpcClient::get_account(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[1],
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert_eq!(acc1_ind_state, acc1_seq_state.into());
|
||||
assert_eq!(acc2_ind_state, acc2_seq_state.into());
|
||||
|
||||
// ToDo: Check private state transition
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
#![expect(
|
||||
clippy::shadow_unrelated,
|
||||
clippy::tests_outside_test_module,
|
||||
reason = "We don't care about these in tests"
|
||||
)]
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use indexer_service_rpc::RpcClient as _;
|
||||
use integration_tests::{
|
||||
TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, public_mention, wait_for_indexer_to_catch_up,
|
||||
};
|
||||
use log::info;
|
||||
use wallet::{
|
||||
account::Label,
|
||||
cli::{CliAccountMention, Command, programs::native_token_transfer::AuthTransferSubcommand},
|
||||
};
|
||||
|
||||
#[tokio::test]
|
||||
async fn indexer_state_consistency_with_labels() -> Result<()> {
|
||||
let mut ctx = TestContext::new().await?;
|
||||
|
||||
// Assign labels to both accounts
|
||||
let from_label = Label::new("idx-sender-label");
|
||||
let to_label = Label::new("idx-receiver-label");
|
||||
|
||||
let label_cmd = Command::Account(wallet::cli::account::AccountSubcommand::Label {
|
||||
account_id: public_mention(ctx.existing_public_accounts()[0]),
|
||||
label: from_label.clone(),
|
||||
});
|
||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), label_cmd).await?;
|
||||
|
||||
let label_cmd = Command::Account(wallet::cli::account::AccountSubcommand::Label {
|
||||
account_id: public_mention(ctx.existing_public_accounts()[1]),
|
||||
label: to_label.clone(),
|
||||
});
|
||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), label_cmd).await?;
|
||||
|
||||
// Send using labels instead of account IDs
|
||||
let command = Command::AuthTransfer(AuthTransferSubcommand::Send {
|
||||
from: CliAccountMention::Label(from_label),
|
||||
to: Some(CliAccountMention::Label(to_label)),
|
||||
to_npk: None,
|
||||
to_vpk: None,
|
||||
to_identifier: Some(0),
|
||||
amount: 100,
|
||||
});
|
||||
|
||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
let acc_1_balance = sequencer_service_rpc::RpcClient::get_account_balance(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[0],
|
||||
)
|
||||
.await?;
|
||||
let acc_2_balance = sequencer_service_rpc::RpcClient::get_account_balance(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[1],
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert_eq!(acc_1_balance, 9900);
|
||||
assert_eq!(acc_2_balance, 20100);
|
||||
|
||||
info!("Waiting for indexer to parse blocks");
|
||||
wait_for_indexer_to_catch_up(&ctx).await?;
|
||||
|
||||
let acc1_ind_state = ctx
|
||||
.indexer_client()
|
||||
.get_account(ctx.existing_public_accounts()[0].into())
|
||||
.await
|
||||
.unwrap();
|
||||
let acc1_seq_state = sequencer_service_rpc::RpcClient::get_account(
|
||||
ctx.sequencer_client(),
|
||||
ctx.existing_public_accounts()[0],
|
||||
)
|
||||
.await?;
|
||||
|
||||
assert_eq!(acc1_ind_state, acc1_seq_state.into());
|
||||
|
||||
info!("Indexer state is consistent after label-based transfer");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
25
integration_tests/tests/indexer_test_run.rs
Normal file
25
integration_tests/tests/indexer_test_run.rs
Normal file
@ -0,0 +1,25 @@
|
||||
#![expect(
|
||||
clippy::tests_outside_test_module,
|
||||
reason = "We don't care about these in tests"
|
||||
)]
|
||||
|
||||
use anyhow::Result;
|
||||
use integration_tests::{TestContext, wait_for_indexer_to_catch_up};
|
||||
use log::info;
|
||||
|
||||
#[tokio::test]
|
||||
async fn indexer_test_run() -> Result<()> {
|
||||
let ctx = TestContext::new().await?;
|
||||
|
||||
let last_block_indexer = wait_for_indexer_to_catch_up(&ctx).await?;
|
||||
|
||||
let last_block_seq =
|
||||
sequencer_service_rpc::RpcClient::get_last_block_id(ctx.sequencer_client()).await?;
|
||||
|
||||
info!("Last block on seq now is {last_block_seq}");
|
||||
info!("Last block on ind now is {last_block_indexer}");
|
||||
|
||||
assert!(last_block_indexer > 0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
37
integration_tests/tests/indexer_test_run_ffi.rs
Normal file
37
integration_tests/tests/indexer_test_run_ffi.rs
Normal file
@ -0,0 +1,37 @@
|
||||
#![expect(
|
||||
clippy::tests_outside_test_module,
|
||||
clippy::undocumented_unsafe_blocks,
|
||||
reason = "We don't care about these in tests"
|
||||
)]
|
||||
|
||||
use anyhow::Result;
|
||||
use indexer_ffi::Runtime;
|
||||
use integration_tests::L2_TO_L1_TIMEOUT;
|
||||
use log::info;
|
||||
|
||||
#[path = "indexer_ffi_helpers/mod.rs"]
|
||||
mod indexer_ffi_helpers;
|
||||
|
||||
#[test]
|
||||
fn indexer_test_run_ffi() -> Result<()> {
|
||||
let (ctx, indexer_ffi, _indexer_dir) = indexer_ffi_helpers::setup()?;
|
||||
|
||||
// RUN OBSERVATION
|
||||
std::thread::sleep(L2_TO_L1_TIMEOUT);
|
||||
|
||||
// Safety: ctx runtime is valid for the lifetime of the returned Runtime
|
||||
let runtime = unsafe { Runtime::from_borrowed(ctx.runtime()) };
|
||||
let last_block_indexer_ffi_res = unsafe {
|
||||
indexer_ffi_helpers::query_last_block(&raw const runtime, &raw const indexer_ffi)
|
||||
};
|
||||
|
||||
assert!(last_block_indexer_ffi_res.error.is_ok());
|
||||
|
||||
let last_block_indexer_ffi = unsafe { *last_block_indexer_ffi_res.value };
|
||||
|
||||
info!("Last block on indexer FFI now is {last_block_indexer_ffi}");
|
||||
|
||||
assert!(last_block_indexer_ffi > 0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -12,8 +12,8 @@ use integration_tests::{
|
||||
public_mention, verify_commitment_is_in_state,
|
||||
};
|
||||
use key_protocol::key_management::key_tree::chain_index::ChainIndex;
|
||||
use lee::{AccountId, program::Program};
|
||||
use log::info;
|
||||
use nssa::{AccountId, program::Program};
|
||||
use sequencer_service_rpc::RpcClient as _;
|
||||
use tokio::test;
|
||||
use wallet::cli::{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user