mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-05-18 05:59:33 +00:00
Merge branch 'schouhy/compress-proofs' into Pravdyvy/indexer-explorer-integration-fixes
This commit is contained in:
commit
fe5db24620
41
flake.nix
41
flake.nix
@ -45,6 +45,44 @@
|
|||||||
rustToolchain = pkgs.rust-bin.stable.latest.default;
|
rustToolchain = pkgs.rust-bin.stable.latest.default;
|
||||||
craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain;
|
craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain;
|
||||||
src = ./.;
|
src = ./.;
|
||||||
|
cargoLock = builtins.fromTOML (builtins.readFile ./Cargo.lock);
|
||||||
|
|
||||||
|
# Parse Cargo.lock at eval time to find the locked risc0-circuit-recursion
|
||||||
|
# version and its crates.io checksum — no hardcoding required.
|
||||||
|
risc0CircuitRecursion = builtins.head (
|
||||||
|
builtins.filter (p: p.name == "risc0-circuit-recursion") cargoLock.package
|
||||||
|
);
|
||||||
|
|
||||||
|
# Download the crate tarball from crates.io; the checksum from Cargo.lock
|
||||||
|
# is the sha256 of the .crate file, so this is a verified fixed-output fetch.
|
||||||
|
risc0CircuitRecursionCrate = pkgs.fetchurl {
|
||||||
|
url = "https://crates.io/api/v1/crates/risc0-circuit-recursion/${risc0CircuitRecursion.version}/download";
|
||||||
|
sha256 = risc0CircuitRecursion.checksum;
|
||||||
|
name = "risc0-circuit-recursion-${risc0CircuitRecursion.version}.crate";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Extract the zkr artifact hash from build.rs inside the crate (IFD).
|
||||||
|
# This hash is both the S3 filename and the sha256 of the zip content.
|
||||||
|
recursionZkrHash =
|
||||||
|
let
|
||||||
|
hashFile = pkgs.runCommand "extract-risc0-recursion-zkr-hash"
|
||||||
|
{ nativeBuildInputs = [ pkgs.gnutar ]; }
|
||||||
|
''
|
||||||
|
tmp=$(mktemp -d)
|
||||||
|
tar xf ${risc0CircuitRecursionCrate} -C "$tmp"
|
||||||
|
hash=$(grep -o '"[0-9a-f]\{64\}"' \
|
||||||
|
"$tmp/risc0-circuit-recursion-${risc0CircuitRecursion.version}/build.rs" \
|
||||||
|
| head -1 | tr -d '"')
|
||||||
|
printf '%s' "$hash" > $out
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
builtins.replaceStrings [ "\n" " " ] [ "" "" ] (builtins.readFile hashFile);
|
||||||
|
|
||||||
|
# Pre-fetch the zkr zip so the sandboxed Rust build can't be blocked.
|
||||||
|
recursionZkr = pkgs.fetchurl {
|
||||||
|
url = "https://risc0-artifacts.s3.us-west-2.amazonaws.com/zkr/${recursionZkrHash}.zip";
|
||||||
|
sha256 = recursionZkrHash;
|
||||||
|
};
|
||||||
|
|
||||||
commonArgs = {
|
commonArgs = {
|
||||||
inherit src;
|
inherit src;
|
||||||
@ -55,6 +93,9 @@
|
|||||||
pkgs.llvmPackages.libclang.lib
|
pkgs.llvmPackages.libclang.lib
|
||||||
];
|
];
|
||||||
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
|
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
|
||||||
|
# Point the risc0-circuit-recursion build script to the pre-fetched zip
|
||||||
|
# so it doesn't try to download it inside the sandbox.
|
||||||
|
RECURSION_SRC_PATH = "${recursionZkr}";
|
||||||
};
|
};
|
||||||
|
|
||||||
walletFfiPackage = craneLib.buildPackage (
|
walletFfiPackage = craneLib.buildPackage (
|
||||||
|
|||||||
@ -7,7 +7,7 @@ use nssa_core::{
|
|||||||
account::AccountWithMetadata,
|
account::AccountWithMetadata,
|
||||||
program::{ChainedCall, InstructionData, ProgramId, ProgramOutput},
|
program::{ChainedCall, InstructionData, ProgramId, ProgramOutput},
|
||||||
};
|
};
|
||||||
use risc0_zkvm::{ExecutorEnv, InnerReceipt, Receipt, default_prover};
|
use risc0_zkvm::{ExecutorEnv, InnerReceipt, ProverOpts, Receipt, default_prover};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::NssaError,
|
error::NssaError,
|
||||||
@ -126,8 +126,9 @@ pub fn execute_and_prove(
|
|||||||
env_builder.write(&circuit_input).unwrap();
|
env_builder.write(&circuit_input).unwrap();
|
||||||
let env = env_builder.build().unwrap();
|
let env = env_builder.build().unwrap();
|
||||||
let prover = default_prover();
|
let prover = default_prover();
|
||||||
|
let opts = ProverOpts::succinct();
|
||||||
let prove_info = prover
|
let prove_info = prover
|
||||||
.prove(env, PRIVACY_PRESERVING_CIRCUIT_ELF)
|
.prove_with_opts(env, PRIVACY_PRESERVING_CIRCUIT_ELF, &opts)
|
||||||
.map_err(|e| NssaError::CircuitProvingError(e.to_string()))?;
|
.map_err(|e| NssaError::CircuitProvingError(e.to_string()))?;
|
||||||
|
|
||||||
let proof = Proof(borsh::to_vec(&prove_info.receipt.inner)?);
|
let proof = Proof(borsh::to_vec(&prove_info.receipt.inner)?);
|
||||||
|
|||||||
@ -21,5 +21,5 @@ cbindgen = "0.29"
|
|||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = ["prove"]
|
||||||
prove = ["nssa/prove"]
|
prove = ["nssa/prove"]
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
pub mod account;
|
pub mod account;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod keys;
|
pub mod keys;
|
||||||
|
pub mod pinata;
|
||||||
pub mod sync;
|
pub mod sync;
|
||||||
pub mod transfer;
|
pub mod transfer;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|||||||
308
wallet-ffi/src/pinata.rs
Normal file
308
wallet-ffi/src/pinata.rs
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
//! Pinata program interaction functions.
|
||||||
|
|
||||||
|
use std::{ffi::CString, ptr, slice};
|
||||||
|
|
||||||
|
use common::error::ExecutionFailureKind;
|
||||||
|
use nssa::AccountId;
|
||||||
|
use nssa_core::MembershipProof;
|
||||||
|
use wallet::program_facades::pinata::Pinata;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
block_on,
|
||||||
|
error::{print_error, WalletFfiError},
|
||||||
|
types::{FfiBytes32, FfiTransferResult, WalletHandle},
|
||||||
|
wallet::get_wallet,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Claim a pinata reward using a public transaction.
|
||||||
|
///
|
||||||
|
/// Sends a public claim transaction to the pinata program.
|
||||||
|
///
|
||||||
|
/// # Parameters
|
||||||
|
/// - `handle`: Valid wallet handle
|
||||||
|
/// - `pinata_account_id`: The pinata program account ID
|
||||||
|
/// - `winner_account_id`: The recipient account ID
|
||||||
|
/// - `solution`: The solution value as little-endian [u8; 16]
|
||||||
|
/// - `out_result`: Output pointer for the transaction result
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
/// - `Success` if the claim transaction was submitted successfully
|
||||||
|
/// - Error code on failure
|
||||||
|
///
|
||||||
|
/// # Memory
|
||||||
|
/// The result must be freed with `wallet_ffi_free_transfer_result()`.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
|
||||||
|
/// - `pinata_account_id` must be a valid pointer to a `FfiBytes32` struct
|
||||||
|
/// - `winner_account_id` must be a valid pointer to a `FfiBytes32` struct
|
||||||
|
/// - `solution` must be a valid pointer to a `[u8; 16]` array
|
||||||
|
/// - `out_result` must be a valid pointer to a `FfiTransferResult` struct
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wallet_ffi_claim_pinata(
|
||||||
|
handle: *mut WalletHandle,
|
||||||
|
pinata_account_id: *const FfiBytes32,
|
||||||
|
winner_account_id: *const FfiBytes32,
|
||||||
|
solution: *const [u8; 16],
|
||||||
|
out_result: *mut FfiTransferResult,
|
||||||
|
) -> WalletFfiError {
|
||||||
|
let wrapper = match get_wallet(handle) {
|
||||||
|
Ok(w) => w,
|
||||||
|
Err(e) => return e,
|
||||||
|
};
|
||||||
|
|
||||||
|
if pinata_account_id.is_null()
|
||||||
|
|| winner_account_id.is_null()
|
||||||
|
|| solution.is_null()
|
||||||
|
|| out_result.is_null()
|
||||||
|
{
|
||||||
|
print_error("Null pointer argument");
|
||||||
|
return WalletFfiError::NullPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wallet = match wrapper.core.lock() {
|
||||||
|
Ok(w) => w,
|
||||||
|
Err(e) => {
|
||||||
|
print_error(format!("Failed to lock wallet: {}", e));
|
||||||
|
return WalletFfiError::InternalError;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let pinata_id = AccountId::new(unsafe { (*pinata_account_id).data });
|
||||||
|
let winner_id = AccountId::new(unsafe { (*winner_account_id).data });
|
||||||
|
let solution = u128::from_le_bytes(unsafe { *solution });
|
||||||
|
|
||||||
|
let pinata = Pinata(&wallet);
|
||||||
|
|
||||||
|
match block_on(pinata.claim(pinata_id, winner_id, solution)) {
|
||||||
|
Ok(Ok(response)) => {
|
||||||
|
let tx_hash = CString::new(response.tx_hash.to_string())
|
||||||
|
.map(|s| s.into_raw())
|
||||||
|
.unwrap_or(ptr::null_mut());
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
(*out_result).tx_hash = tx_hash;
|
||||||
|
(*out_result).success = true;
|
||||||
|
}
|
||||||
|
WalletFfiError::Success
|
||||||
|
}
|
||||||
|
Ok(Err(e)) => {
|
||||||
|
print_error(format!("Pinata claim failed: {:?}", e));
|
||||||
|
unsafe {
|
||||||
|
(*out_result).tx_hash = ptr::null_mut();
|
||||||
|
(*out_result).success = false;
|
||||||
|
}
|
||||||
|
map_execution_error(e)
|
||||||
|
}
|
||||||
|
Err(e) => e,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Claim a pinata reward using a private transaction for an already-initialized owned account.
|
||||||
|
///
|
||||||
|
/// Sends a privacy-preserving claim transaction for a winner account that already has
|
||||||
|
/// an on-chain commitment (i.e. was previously initialized).
|
||||||
|
///
|
||||||
|
/// # Parameters
|
||||||
|
/// - `handle`: Valid wallet handle
|
||||||
|
/// - `pinata_account_id`: The pinata program account ID
|
||||||
|
/// - `winner_account_id`: The recipient private account ID (must be owned by this wallet)
|
||||||
|
/// - `solution`: The solution value as little-endian [u8; 16]
|
||||||
|
/// - `winner_proof_index`: Leaf index in the commitment tree for the membership proof
|
||||||
|
/// - `winner_proof_siblings`: Pointer to an array of 32-byte sibling hashes
|
||||||
|
/// - `winner_proof_siblings_len`: Number of sibling hashes in the array
|
||||||
|
/// - `out_result`: Output pointer for the transaction result
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
/// - `Success` if the claim transaction was submitted successfully
|
||||||
|
/// - Error code on failure
|
||||||
|
///
|
||||||
|
/// # Memory
|
||||||
|
/// The result must be freed with `wallet_ffi_free_transfer_result()`.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
|
||||||
|
/// - `pinata_account_id` must be a valid pointer to a `FfiBytes32` struct
|
||||||
|
/// - `winner_account_id` must be a valid pointer to a `FfiBytes32` struct
|
||||||
|
/// - `solution` must be a valid pointer to a `[u8; 16]` array
|
||||||
|
/// - `winner_proof_siblings` must be a valid pointer to an array of `winner_proof_siblings_len`
|
||||||
|
/// elements of `[u8; 32]`, or null if `winner_proof_siblings_len` is 0
|
||||||
|
/// - `out_result` must be a valid pointer to a `FfiTransferResult` struct
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wallet_ffi_claim_pinata_private_owned_already_initialized(
|
||||||
|
handle: *mut WalletHandle,
|
||||||
|
pinata_account_id: *const FfiBytes32,
|
||||||
|
winner_account_id: *const FfiBytes32,
|
||||||
|
solution: *const [u8; 16],
|
||||||
|
winner_proof_index: usize,
|
||||||
|
winner_proof_siblings: *const [u8; 32],
|
||||||
|
winner_proof_siblings_len: usize,
|
||||||
|
out_result: *mut FfiTransferResult,
|
||||||
|
) -> WalletFfiError {
|
||||||
|
let wrapper = match get_wallet(handle) {
|
||||||
|
Ok(w) => w,
|
||||||
|
Err(e) => return e,
|
||||||
|
};
|
||||||
|
|
||||||
|
if pinata_account_id.is_null()
|
||||||
|
|| winner_account_id.is_null()
|
||||||
|
|| solution.is_null()
|
||||||
|
|| out_result.is_null()
|
||||||
|
{
|
||||||
|
print_error("Null pointer argument");
|
||||||
|
return WalletFfiError::NullPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if winner_proof_siblings_len > 0 && winner_proof_siblings.is_null() {
|
||||||
|
print_error("Null proof siblings pointer with non-zero length");
|
||||||
|
return WalletFfiError::NullPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wallet = match wrapper.core.lock() {
|
||||||
|
Ok(w) => w,
|
||||||
|
Err(e) => {
|
||||||
|
print_error(format!("Failed to lock wallet: {}", e));
|
||||||
|
return WalletFfiError::InternalError;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let pinata_id = AccountId::new(unsafe { (*pinata_account_id).data });
|
||||||
|
let winner_id = AccountId::new(unsafe { (*winner_account_id).data });
|
||||||
|
let solution = u128::from_le_bytes(unsafe { *solution });
|
||||||
|
|
||||||
|
let siblings = if winner_proof_siblings_len > 0 {
|
||||||
|
unsafe { slice::from_raw_parts(winner_proof_siblings, winner_proof_siblings_len).to_vec() }
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
let proof: MembershipProof = (winner_proof_index, siblings);
|
||||||
|
|
||||||
|
let pinata = Pinata(&wallet);
|
||||||
|
|
||||||
|
match block_on(
|
||||||
|
pinata
|
||||||
|
.claim_private_owned_account_already_initialized(pinata_id, winner_id, solution, proof),
|
||||||
|
) {
|
||||||
|
Ok(Ok((response, _shared_key))) => {
|
||||||
|
let tx_hash = CString::new(response.tx_hash.to_string())
|
||||||
|
.map(|s| s.into_raw())
|
||||||
|
.unwrap_or(ptr::null_mut());
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
(*out_result).tx_hash = tx_hash;
|
||||||
|
(*out_result).success = true;
|
||||||
|
}
|
||||||
|
WalletFfiError::Success
|
||||||
|
}
|
||||||
|
Ok(Err(e)) => {
|
||||||
|
print_error(format!(
|
||||||
|
"Pinata private claim (already initialized) failed: {:?}",
|
||||||
|
e
|
||||||
|
));
|
||||||
|
unsafe {
|
||||||
|
(*out_result).tx_hash = ptr::null_mut();
|
||||||
|
(*out_result).success = false;
|
||||||
|
}
|
||||||
|
map_execution_error(e)
|
||||||
|
}
|
||||||
|
Err(e) => e,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Claim a pinata reward using a private transaction for a not-yet-initialized owned account.
|
||||||
|
///
|
||||||
|
/// Sends a privacy-preserving claim transaction for a winner account that has not yet
|
||||||
|
/// been committed on-chain (i.e. is being initialized as part of this claim).
|
||||||
|
///
|
||||||
|
/// # Parameters
|
||||||
|
/// - `handle`: Valid wallet handle
|
||||||
|
/// - `pinata_account_id`: The pinata program account ID
|
||||||
|
/// - `winner_account_id`: The recipient private account ID (must be owned by this wallet)
|
||||||
|
/// - `solution`: The solution value as little-endian [u8; 16]
|
||||||
|
/// - `out_result`: Output pointer for the transaction result
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
/// - `Success` if the claim transaction was submitted successfully
|
||||||
|
/// - Error code on failure
|
||||||
|
///
|
||||||
|
/// # Memory
|
||||||
|
/// The result must be freed with `wallet_ffi_free_transfer_result()`.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
|
||||||
|
/// - `pinata_account_id` must be a valid pointer to a `FfiBytes32` struct
|
||||||
|
/// - `winner_account_id` must be a valid pointer to a `FfiBytes32` struct
|
||||||
|
/// - `solution` must be a valid pointer to a `[u8; 16]` array
|
||||||
|
/// - `out_result` must be a valid pointer to a `FfiTransferResult` struct
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wallet_ffi_claim_pinata_private_owned_not_initialized(
|
||||||
|
handle: *mut WalletHandle,
|
||||||
|
pinata_account_id: *const FfiBytes32,
|
||||||
|
winner_account_id: *const FfiBytes32,
|
||||||
|
solution: *const [u8; 16],
|
||||||
|
out_result: *mut FfiTransferResult,
|
||||||
|
) -> WalletFfiError {
|
||||||
|
let wrapper = match get_wallet(handle) {
|
||||||
|
Ok(w) => w,
|
||||||
|
Err(e) => return e,
|
||||||
|
};
|
||||||
|
|
||||||
|
if pinata_account_id.is_null()
|
||||||
|
|| winner_account_id.is_null()
|
||||||
|
|| solution.is_null()
|
||||||
|
|| out_result.is_null()
|
||||||
|
{
|
||||||
|
print_error("Null pointer argument");
|
||||||
|
return WalletFfiError::NullPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wallet = match wrapper.core.lock() {
|
||||||
|
Ok(w) => w,
|
||||||
|
Err(e) => {
|
||||||
|
print_error(format!("Failed to lock wallet: {}", e));
|
||||||
|
return WalletFfiError::InternalError;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let pinata_id = AccountId::new(unsafe { (*pinata_account_id).data });
|
||||||
|
let winner_id = AccountId::new(unsafe { (*winner_account_id).data });
|
||||||
|
let solution = u128::from_le_bytes(unsafe { *solution });
|
||||||
|
|
||||||
|
let pinata = Pinata(&wallet);
|
||||||
|
|
||||||
|
match block_on(pinata.claim_private_owned_account(pinata_id, winner_id, solution)) {
|
||||||
|
Ok(Ok((response, _shared_key))) => {
|
||||||
|
let tx_hash = CString::new(response.tx_hash.to_string())
|
||||||
|
.map(|s| s.into_raw())
|
||||||
|
.unwrap_or(ptr::null_mut());
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
(*out_result).tx_hash = tx_hash;
|
||||||
|
(*out_result).success = true;
|
||||||
|
}
|
||||||
|
WalletFfiError::Success
|
||||||
|
}
|
||||||
|
Ok(Err(e)) => {
|
||||||
|
print_error(format!(
|
||||||
|
"Pinata private claim (not initialized) failed: {:?}",
|
||||||
|
e
|
||||||
|
));
|
||||||
|
unsafe {
|
||||||
|
(*out_result).tx_hash = ptr::null_mut();
|
||||||
|
(*out_result).success = false;
|
||||||
|
}
|
||||||
|
map_execution_error(e)
|
||||||
|
}
|
||||||
|
Err(e) => e,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_execution_error(e: ExecutionFailureKind) -> WalletFfiError {
|
||||||
|
match e {
|
||||||
|
ExecutionFailureKind::InsufficientFundsError => WalletFfiError::InsufficientFunds,
|
||||||
|
ExecutionFailureKind::KeyNotFoundError => WalletFfiError::KeyNotFound,
|
||||||
|
ExecutionFailureKind::SequencerError => WalletFfiError::NetworkError,
|
||||||
|
ExecutionFailureKind::SequencerClientError(_) => WalletFfiError::NetworkError,
|
||||||
|
_ => WalletFfiError::InternalError,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -475,6 +475,112 @@ char *wallet_ffi_account_id_to_base58(const struct FfiBytes32 *account_id);
|
|||||||
enum WalletFfiError wallet_ffi_account_id_from_base58(const char *base58_str,
|
enum WalletFfiError wallet_ffi_account_id_from_base58(const char *base58_str,
|
||||||
struct FfiBytes32 *out_account_id);
|
struct FfiBytes32 *out_account_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Claim a pinata reward using a public transaction.
|
||||||
|
*
|
||||||
|
* Sends a public claim transaction to the pinata program.
|
||||||
|
*
|
||||||
|
* # Parameters
|
||||||
|
* - `handle`: Valid wallet handle
|
||||||
|
* - `pinata_account_id`: The pinata program account ID
|
||||||
|
* - `winner_account_id`: The recipient account ID
|
||||||
|
* - `solution`: The solution value as little-endian [u8; 16]
|
||||||
|
* - `out_result`: Output pointer for the transaction result
|
||||||
|
*
|
||||||
|
* # Returns
|
||||||
|
* - `Success` if the claim transaction was submitted successfully
|
||||||
|
* - Error code on failure
|
||||||
|
*
|
||||||
|
* # Memory
|
||||||
|
* The result must be freed with `wallet_ffi_free_transfer_result()`.
|
||||||
|
*
|
||||||
|
* # Safety
|
||||||
|
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
|
||||||
|
* - `pinata_account_id` must be a valid pointer to a `FfiBytes32` struct
|
||||||
|
* - `winner_account_id` must be a valid pointer to a `FfiBytes32` struct
|
||||||
|
* - `solution` must be a valid pointer to a `[u8; 16]` array
|
||||||
|
* - `out_result` must be a valid pointer to a `FfiTransferResult` struct
|
||||||
|
*/
|
||||||
|
enum WalletFfiError wallet_ffi_claim_pinata(struct WalletHandle *handle,
|
||||||
|
const struct FfiBytes32 *pinata_account_id,
|
||||||
|
const struct FfiBytes32 *winner_account_id,
|
||||||
|
const uint8_t (*solution)[16],
|
||||||
|
struct FfiTransferResult *out_result);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Claim a pinata reward using a private transaction for an already-initialized owned account.
|
||||||
|
*
|
||||||
|
* Sends a privacy-preserving claim transaction for a winner account that already has
|
||||||
|
* an on-chain commitment (i.e. was previously initialized).
|
||||||
|
*
|
||||||
|
* # Parameters
|
||||||
|
* - `handle`: Valid wallet handle
|
||||||
|
* - `pinata_account_id`: The pinata program account ID
|
||||||
|
* - `winner_account_id`: The recipient private account ID (must be owned by this wallet)
|
||||||
|
* - `solution`: The solution value as little-endian [u8; 16]
|
||||||
|
* - `winner_proof_index`: Leaf index in the commitment tree for the membership proof
|
||||||
|
* - `winner_proof_siblings`: Pointer to an array of 32-byte sibling hashes
|
||||||
|
* - `winner_proof_siblings_len`: Number of sibling hashes in the array
|
||||||
|
* - `out_result`: Output pointer for the transaction result
|
||||||
|
*
|
||||||
|
* # Returns
|
||||||
|
* - `Success` if the claim transaction was submitted successfully
|
||||||
|
* - Error code on failure
|
||||||
|
*
|
||||||
|
* # Memory
|
||||||
|
* The result must be freed with `wallet_ffi_free_transfer_result()`.
|
||||||
|
*
|
||||||
|
* # Safety
|
||||||
|
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
|
||||||
|
* - `pinata_account_id` must be a valid pointer to a `FfiBytes32` struct
|
||||||
|
* - `winner_account_id` must be a valid pointer to a `FfiBytes32` struct
|
||||||
|
* - `solution` must be a valid pointer to a `[u8; 16]` array
|
||||||
|
* - `winner_proof_siblings` must be a valid pointer to an array of `winner_proof_siblings_len`
|
||||||
|
* elements of `[u8; 32]`, or null if `winner_proof_siblings_len` is 0
|
||||||
|
* - `out_result` must be a valid pointer to a `FfiTransferResult` struct
|
||||||
|
*/
|
||||||
|
enum WalletFfiError wallet_ffi_claim_pinata_private_owned_already_initialized(struct WalletHandle *handle,
|
||||||
|
const struct FfiBytes32 *pinata_account_id,
|
||||||
|
const struct FfiBytes32 *winner_account_id,
|
||||||
|
const uint8_t (*solution)[16],
|
||||||
|
uintptr_t winner_proof_index,
|
||||||
|
const uint8_t (*winner_proof_siblings)[32],
|
||||||
|
uintptr_t winner_proof_siblings_len,
|
||||||
|
struct FfiTransferResult *out_result);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Claim a pinata reward using a private transaction for a not-yet-initialized owned account.
|
||||||
|
*
|
||||||
|
* Sends a privacy-preserving claim transaction for a winner account that has not yet
|
||||||
|
* been committed on-chain (i.e. is being initialized as part of this claim).
|
||||||
|
*
|
||||||
|
* # Parameters
|
||||||
|
* - `handle`: Valid wallet handle
|
||||||
|
* - `pinata_account_id`: The pinata program account ID
|
||||||
|
* - `winner_account_id`: The recipient private account ID (must be owned by this wallet)
|
||||||
|
* - `solution`: The solution value as little-endian [u8; 16]
|
||||||
|
* - `out_result`: Output pointer for the transaction result
|
||||||
|
*
|
||||||
|
* # Returns
|
||||||
|
* - `Success` if the claim transaction was submitted successfully
|
||||||
|
* - Error code on failure
|
||||||
|
*
|
||||||
|
* # Memory
|
||||||
|
* The result must be freed with `wallet_ffi_free_transfer_result()`.
|
||||||
|
*
|
||||||
|
* # Safety
|
||||||
|
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
|
||||||
|
* - `pinata_account_id` must be a valid pointer to a `FfiBytes32` struct
|
||||||
|
* - `winner_account_id` must be a valid pointer to a `FfiBytes32` struct
|
||||||
|
* - `solution` must be a valid pointer to a `[u8; 16]` array
|
||||||
|
* - `out_result` must be a valid pointer to a `FfiTransferResult` struct
|
||||||
|
*/
|
||||||
|
enum WalletFfiError wallet_ffi_claim_pinata_private_owned_not_initialized(struct WalletHandle *handle,
|
||||||
|
const struct FfiBytes32 *pinata_account_id,
|
||||||
|
const struct FfiBytes32 *winner_account_id,
|
||||||
|
const uint8_t (*solution)[16],
|
||||||
|
struct FfiTransferResult *out_result);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronize private accounts to a specific block.
|
* Synchronize private accounts to a specific block.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -126,7 +126,7 @@ impl WalletCore {
|
|||||||
&produce_random_nonces(1),
|
&produce_random_nonces(1),
|
||||||
&[(winner_npk.clone(), shared_secret_winner.clone())],
|
&[(winner_npk.clone(), shared_secret_winner.clone())],
|
||||||
&[],
|
&[],
|
||||||
&[]
|
&[],
|
||||||
&program.into(),
|
&program.into(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use common::{error::ExecutionFailureKind, rpc_primitives::requests::SendTxResponse};
|
use common::{error::ExecutionFailureKind, rpc_primitives::requests::SendTxResponse};
|
||||||
use nssa::AccountId;
|
use nssa::AccountId;
|
||||||
use nssa_core::SharedSecretKey;
|
use nssa_core::{MembershipProof, SharedSecretKey};
|
||||||
|
|
||||||
use crate::{PrivacyPreservingAccount, WalletCore};
|
use crate::{PrivacyPreservingAccount, WalletCore};
|
||||||
|
|
||||||
@ -25,6 +25,22 @@ impl Pinata<'_> {
|
|||||||
Ok(self.0.sequencer_client.send_tx_public(tx).await?)
|
Ok(self.0.sequencer_client.send_tx_public(tx).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Claim a pinata reward using a privacy-preserving transaction for an already-initialized
|
||||||
|
/// owned private account.
|
||||||
|
///
|
||||||
|
/// The `winner_proof` parameter is accepted for API completeness; the wallet currently fetches
|
||||||
|
/// the membership proof automatically from the chain.
|
||||||
|
pub async fn claim_private_owned_account_already_initialized(
|
||||||
|
&self,
|
||||||
|
pinata_account_id: AccountId,
|
||||||
|
winner_account_id: AccountId,
|
||||||
|
solution: u128,
|
||||||
|
_winner_proof: MembershipProof,
|
||||||
|
) -> Result<(SendTxResponse, SharedSecretKey), ExecutionFailureKind> {
|
||||||
|
self.claim_private_owned_account(pinata_account_id, winner_account_id, solution)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn claim_private_owned_account(
|
pub async fn claim_private_owned_account(
|
||||||
&self,
|
&self,
|
||||||
pinata_account_id: AccountId,
|
pinata_account_id: AccountId,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user