pub struct Client { /* private fields */ }Expand description
Client for the Autonomi decentralized network.
Provides high-level APIs for storing and retrieving chunks and files on the network.
Implementations§
Source§impl Client
impl Client
Sourcepub async fn prepare_chunk_payment(
&self,
content: Bytes,
) -> Result<Option<PreparedChunk>>
pub async fn prepare_chunk_payment( &self, content: Bytes, ) -> Result<Option<PreparedChunk>>
Prepare a single chunk for batch payment.
Collects quotes and uses node-reported prices without making any
on-chain transaction. Returns Ok(None) if the chunk is already
stored on the network.
§Errors
Returns an error if quote collection or payment construction fails.
Sourcepub async fn batch_pay(
&self,
prepared: Vec<PreparedChunk>,
) -> Result<(Vec<PaidChunk>, String, u128)>
pub async fn batch_pay( &self, prepared: Vec<PreparedChunk>, ) -> Result<(Vec<PaidChunk>, String, u128)>
Pay for multiple chunks in a single EVM transaction.
Flattens all quote payments from the prepared chunks into one
wallet.pay_for_quotes() call, then maps transaction hashes
back to per-chunk PaymentProof bytes.
§Errors
Returns an error if the wallet is not configured or the on-chain
payment fails.
Returns (paid_chunks, storage_cost_atto, gas_cost_wei).
Sourcepub async fn batch_upload_chunks(
&self,
chunks: Vec<Bytes>,
) -> Result<(Vec<XorName>, String, u128)>
pub async fn batch_upload_chunks( &self, chunks: Vec<Bytes>, ) -> Result<(Vec<XorName>, String, u128)>
Upload chunks in waves with pipelined EVM payments.
Processes chunks in waves of PAYMENT_WAVE_SIZE (64). Within each wave:
- Prepare: collect quotes for all chunks concurrently
- Pay: single EVM transaction for the whole wave
- Store: concurrent chunk replication to close group
Stores from wave N overlap with quote collection for wave N+1
via tokio::join!.
§Errors
Returns an error if any payment or store operation fails.
Returns (addresses, total_storage_cost_atto, total_gas_cost_wei).
Sourcepub async fn batch_upload_chunks_with_events(
&self,
chunks: Vec<Bytes>,
progress: Option<&Sender<UploadEvent>>,
stored_offset: usize,
file_total: usize,
resume_key: Option<&str>,
) -> Result<(Vec<XorName>, String, u128, WaveAggregateStats)>
pub async fn batch_upload_chunks_with_events( &self, chunks: Vec<Bytes>, progress: Option<&Sender<UploadEvent>>, stored_offset: usize, file_total: usize, resume_key: Option<&str>, ) -> Result<(Vec<XorName>, String, u128, WaveAggregateStats)>
Same as Client::batch_upload_chunks but sends UploadEvent::ChunkStored
events as each chunk is stored, enabling per-chunk progress bars.
stored_offset is the number of chunks already stored in previous waves
(so events report cumulative progress). file_total is the total chunk
count across ALL waves (for the total field in events).
When resume_key is Some, per-wave payment proofs are persisted
to <data_dir>/payments/single/<ts>_<hash(resume_key)> via
crate::data::client::cached_single so that a partial-upload
failure can be resumed on the next attempt without paying twice.
The caller is responsible for deleting the cache entry on full
success (typically upload_with_options in file.rs).
Source§impl Client
impl Client
Sourcepub async fn chunk_put(&self, content: Bytes) -> Result<XorName>
pub async fn chunk_put(&self, content: Bytes) -> Result<XorName>
Store a chunk on the Autonomi network with payment.
Checks if the chunk already exists before paying. If it does,
returns the address immediately without incurring on-chain costs.
Otherwise collects quotes, pays on-chain, then stores with proof
to CLOSE_GROUP_MAJORITY peers.
§Errors
Returns an error if payment or the network operation fails.
Sourcepub async fn chunk_put_with_proof(
&self,
content: Bytes,
proof: Vec<u8>,
target_peer: &PeerId,
peer_addrs: &[MultiAddr],
) -> Result<XorName>
pub async fn chunk_put_with_proof( &self, content: Bytes, proof: Vec<u8>, target_peer: &PeerId, peer_addrs: &[MultiAddr], ) -> Result<XorName>
Store a chunk on the Autonomi network with a pre-built payment proof.
Sends to a single peer. Callers that need replication across the
close group should use chunk_put_to_close_group instead.
§Errors
Returns an error if the network operation fails.
Sourcepub async fn chunk_get(&self, address: &XorName) -> Result<Option<DataChunk>>
pub async fn chunk_get(&self, address: &XorName) -> Result<Option<DataChunk>>
Retrieve a chunk from the Autonomi network.
Queries all peers in the close group for the chunk address, returning the first successful response. This handles the case where the storing peer differs from the first peer returned by DHT routing.
§Adaptive controller feedback
Each per-peer GET attempt is fed individually to the adaptive
fetch limiter via controller().fetch.observe(...). This is
deliberately finer-grained than wrapping the outer chunk_get
with observe_op: when a chunk takes 6 peer tries to land,
5 of them are real capacity signals (timeouts / network errors)
that should pull the cap down even if the chunk eventually
succeeds. The outer Ok(_) would mask all five as a single
Outcome::Success. See adaptive::Outcome for the per-attempt
classification rules used below.
Callers should therefore NOT wrap chunk_get in observe_op.
§Errors
Returns an error if the network operation fails.
Sourcepub async fn chunk_get_from_closest_peers(
&self,
address: &XorName,
peer_count: usize,
) -> Result<Option<DataChunk>>
pub async fn chunk_get_from_closest_peers( &self, address: &XorName, peer_count: usize, ) -> Result<Option<DataChunk>>
Retrieve a chunk from the requested number of closest peers.
Queries peers in XOR-distance order for the chunk address, returning the first successful response. This handles the case where the storing peer differs from the first peer returned by DHT routing.
§Errors
Returns an error if the network operation fails.
Sourcepub async fn chunk_get_from_close_group(
&self,
address: &XorName,
) -> Result<Vec<ChunkPeerGetResult>>
pub async fn chunk_get_from_close_group( &self, address: &XorName, ) -> Result<Vec<ChunkPeerGetResult>>
Retrieve a chunk from every peer in the close group.
Unlike Client::chunk_get, this method does not return early
after the first successful response. It returns one result per
close-group peer, sorted from closest XOR distance to furthest.
§Errors
Returns an error if the close-group lookup fails.
Sourcepub async fn chunk_get_from_closest_peer_group(
&self,
address: &XorName,
peer_count: usize,
) -> Result<Vec<ChunkPeerGetResult>>
pub async fn chunk_get_from_closest_peer_group( &self, address: &XorName, peer_count: usize, ) -> Result<Vec<ChunkPeerGetResult>>
Retrieve a chunk from the requested number of closest peers.
Unlike Client::chunk_get_from_closest_peers, this method does
not return early after the first successful response. It returns
one result per queried peer, sorted from closest XOR distance to
furthest.
§Errors
Returns an error if the DHT lookup fails.
Sourcepub async fn chunk_exists(&self, address: &XorName) -> Result<bool>
pub async fn chunk_exists(&self, address: &XorName) -> Result<bool>
Sourcepub async fn finalize_chunk(
&self,
prepared: PreparedChunk,
tx_hash_map: &HashMap<QuoteHash, TxHash>,
) -> Result<XorName>
pub async fn finalize_chunk( &self, prepared: PreparedChunk, tx_hash_map: &HashMap<QuoteHash, TxHash>, ) -> Result<XorName>
Finalize a single-chunk publish after an external signer has paid.
Single-chunk analogue of Client::finalize_upload. Takes a
PreparedChunk (from Client::prepare_chunk_payment) and a
quote_hash -> tx_hash map containing receipts for every non-zero
quote in the chunk’s payment. Builds the PaymentProof and stores
the chunk on CLOSE_GROUP_MAJORITY peers, returning its address.
Wave-batch payment shape only. Single-chunk publishes don’t need Merkle batching: one chunk’s worth of quotes is well below the wave-batch threshold.
§Errors
Returns an error if the proof construction fails (e.g. missing
tx_hash for a non-zero quote) or if fewer than
CLOSE_GROUP_MAJORITY peers accept the chunk.
Source§impl Client
impl Client
Sourcepub async fn data_upload(&self, content: Bytes) -> Result<DataUploadResult>
pub async fn data_upload(&self, content: Bytes) -> Result<DataUploadResult>
Upload in-memory data to the network using self-encryption.
The content is encrypted and split into chunks, each stored
as a content-addressed chunk on the network. Returns a DataMap
that can be used to retrieve and decrypt the data.
§Errors
Returns an error if encryption fails or any chunk cannot be stored.
Sourcepub async fn data_upload_with_mode(
&self,
content: Bytes,
mode: PaymentMode,
) -> Result<DataUploadResult>
pub async fn data_upload_with_mode( &self, content: Bytes, mode: PaymentMode, ) -> Result<DataUploadResult>
Upload in-memory data with a specific payment mode.
When mode is Auto and the chunk count >= threshold, or when mode
is Merkle, this buffers all chunks and pays via a single merkle
batch transaction. Otherwise falls back to per-chunk payment.
§Errors
Returns an error if encryption fails or any chunk cannot be stored.
Sourcepub async fn data_prepare_upload(
&self,
content: Bytes,
) -> Result<PreparedUpload>
pub async fn data_prepare_upload( &self, content: Bytes, ) -> Result<PreparedUpload>
Phase 1 of external-signer data upload: encrypt and collect quotes.
Equivalent to Client::data_prepare_upload_with_visibility with
Visibility::Private — see that method for details.
Sourcepub async fn data_prepare_upload_with_visibility(
&self,
content: Bytes,
visibility: Visibility,
) -> Result<PreparedUpload>
pub async fn data_prepare_upload_with_visibility( &self, content: Bytes, visibility: Visibility, ) -> Result<PreparedUpload>
Phase 1 of external-signer data upload with explicit Visibility control.
Encrypts in-memory data via self-encryption, then collects storage
quotes for each chunk without making any on-chain payment. Returns
a PreparedUpload containing the data map and a PaymentIntent
with the payment details for external signing.
When visibility is Visibility::Public, the serialized DataMap
is bundled into the payment batch as an additional chunk and its
address is recorded on the returned PreparedUpload. After
Client::finalize_upload succeeds, that address is surfaced via
crate::data::client::file::FileUploadResult::data_map_address so
the uploader can share a single address from which anyone can retrieve
the data.
Wave-batch payment only — the in-memory data path does not currently
support merkle batching. Use Client::file_prepare_upload_with_visibility
for merkle-eligible public uploads.
After the caller signs and submits the payment transaction, call
Client::finalize_upload with the tx hashes to complete storage.
§Errors
Returns an error if encryption fails, DataMap serialization fails (public only), or quote collection fails.
Sourcepub async fn data_map_store(&self, data_map: &DataMap) -> Result<[u8; 32]>
pub async fn data_map_store(&self, data_map: &DataMap) -> Result<[u8; 32]>
Store a DataMap on the network as a public chunk.
The serialized DataMap is stored as a regular content-addressed chunk.
Anyone who knows the returned address can retrieve and use the DataMap
to download the original data.
§Errors
Returns an error if serialization or the chunk store fails.
Sourcepub async fn data_map_fetch(&self, address: &[u8; 32]) -> Result<DataMap>
pub async fn data_map_fetch(&self, address: &[u8; 32]) -> Result<DataMap>
Fetch a DataMap from the network by its chunk address.
Retrieves the chunk at address and deserializes it as a DataMap.
§Errors
Returns Error::NotFound if no chunk exists at address; other
errors if retrieval or deserialization fails.
Sourcepub async fn data_map_fetch_from_closest_peers(
&self,
address: &[u8; 32],
peer_count: NonZeroUsize,
) -> Result<DataMap>
pub async fn data_map_fetch_from_closest_peers( &self, address: &[u8; 32], peer_count: NonZeroUsize, ) -> Result<DataMap>
Fetch a DataMap from the network by trying the requested number
of closest peers for the DataMap chunk.
§Errors
Returns Error::NotFound if no chunk exists at address; other
errors if retrieval or deserialization fails.
Sourcepub async fn data_download(&self, data_map: &DataMap) -> Result<Bytes>
pub async fn data_download(&self, data_map: &DataMap) -> Result<Bytes>
Download and decrypt data from the network using its DataMap.
Retrieves all chunks referenced by the data map, then decrypts
and reassembles the original content. Fetches chunks concurrently;
the fan-out is sized by the adaptive controller’s fetch channel
and ramps up under healthy conditions.
Large uploads produce a shrunk (child) DataMap whose infos()
reference wrapper chunks rather than the root content chunks. Such a
map is resolved back to its root form before download, keeping this
primitive symmetric with data_upload.
Resolving a shrunk map bridges self-encryption’s synchronous fetcher
onto the async network via block_in_place, so it requires a
multi-threaded Tokio runtime; on a current-thread runtime it returns
Error::Config instead of panicking. Flat maps (the common case)
take neither path, so this requirement never applies to them.
§Errors
Returns an error if any chunk cannot be retrieved (a chunk absent from
every queried peer surfaces as Error::NotFound), if decryption
fails, or if a shrunk map must be resolved on a current-thread runtime.
Source§impl Client
impl Client
Sourcepub async fn file_upload(&self, path: &Path) -> Result<FileUploadResult>
pub async fn file_upload(&self, path: &Path) -> Result<FileUploadResult>
Upload a file to the network using streaming self-encryption.
Automatically selects merkle batch payment for files that produce 64+ chunks (saves gas). Encrypted chunks are spilled to a temp directory so peak memory stays at ~256 MB regardless of file size.
§Errors
Returns an error if the file cannot be read, encryption fails, or any chunk cannot be stored.
Sourcepub async fn estimate_upload_cost(
&self,
path: &Path,
mode: PaymentMode,
progress: Option<Sender<UploadEvent>>,
) -> Result<UploadCostEstimate>
pub async fn estimate_upload_cost( &self, path: &Path, mode: PaymentMode, progress: Option<Sender<UploadEvent>>, ) -> Result<UploadCostEstimate>
Estimate the cost of uploading a file without actually uploading.
Encrypts the file to determine chunk count and sizes, then requests a single quote from the network for a representative chunk. The per-chunk price is extrapolated to the total chunk count.
The estimate is fast (~2-5s) and does not require a wallet. Spilled chunks are cleaned up automatically when the function returns.
Gas cost is an advisory heuristic, not a live gas-oracle query. It is
derived from realistic per-transaction budgets (GAS_PER_WAVE_TX,
GAS_PER_MERKLE_TX) priced at ARBITRUM_GAS_PRICE_WEI. Real gas
varies with network conditions.
Sampled chunk addresses are spread across the whole file (not the first
N) so a shared leading prefix doesn’t bias the sample. When a sample
returns a live quote the per-chunk price is extrapolated and the result
is tagged CostEstimateConfidence::PricedSample.
When every sampled chunk is already stored the result is still Ok
with storage_cost_atto: "0", tagged either
CostEstimateConfidence::VerifiedAllAlreadyStored when the whole file
was sampled (exactly free) or
CostEstimateConfidence::AllSamplesAlreadyStoredIncomplete when the
tail was unsampled (a best-effort guess that payment reconciles).
§Errors
Returns an error if the file cannot be read, encryption fails, or the network cannot provide a quote.
Sourcepub async fn file_prepare_upload(&self, path: &Path) -> Result<PreparedUpload>
pub async fn file_prepare_upload(&self, path: &Path) -> Result<PreparedUpload>
Phase 1 of external-signer upload: encrypt file and prepare chunks.
Equivalent to Client::file_prepare_upload_with_visibility with
Visibility::Private — see that method for details.
Sourcepub async fn file_prepare_upload_with_visibility(
&self,
path: &Path,
visibility: Visibility,
) -> Result<PreparedUpload>
pub async fn file_prepare_upload_with_visibility( &self, path: &Path, visibility: Visibility, ) -> Result<PreparedUpload>
Phase 1 of external-signer upload with explicit Visibility control.
Equivalent to Client::file_prepare_upload_with_progress with
progress: None — see that method for details.
Sourcepub async fn file_prepare_upload_with_progress(
&self,
path: &Path,
visibility: Visibility,
progress: Option<Sender<UploadEvent>>,
) -> Result<PreparedUpload>
pub async fn file_prepare_upload_with_progress( &self, path: &Path, visibility: Visibility, progress: Option<Sender<UploadEvent>>, ) -> Result<PreparedUpload>
Phase 1 of external-signer upload with progress events.
Equivalent to Client::file_prepare_upload_with_mode with
PaymentMode::Auto — see that method for details.
Sourcepub async fn file_prepare_upload_with_mode(
&self,
path: &Path,
visibility: Visibility,
mode: PaymentMode,
progress: Option<Sender<UploadEvent>>,
) -> Result<PreparedUpload>
pub async fn file_prepare_upload_with_mode( &self, path: &Path, visibility: Visibility, mode: PaymentMode, progress: Option<Sender<UploadEvent>>, ) -> Result<PreparedUpload>
Phase 1 of external-signer upload with an explicit PaymentMode.
Requires an EVM network (for contract price queries) but NOT a wallet.
Returns a PreparedUpload containing the data map and either a
PaymentIntent (wave-batch) or prepared merkle sub-batches that
the external signer uses to construct and submit the on-chain payment
transaction(s) — one per sub-batch (ADR-0003).
mode mirrors the wallet path’s Client::file_upload_with_mode:
PaymentMode::Auto picks merkle at the chunk threshold,
PaymentMode::Merkle forces merkle for ≥ 2 upload chunks (this is
how tests exercise the external merkle flow with small files), and
PaymentMode::Single forces wave-batch.
When visibility is Visibility::Public, the serialized DataMap
is bundled into the payment batch as an additional chunk and its
address is recorded on the returned PreparedUpload. After
Client::finalize_upload (or _merkle) succeeds, that address is
surfaced via FileUploadResult::data_map_address so the uploader
can share a single address from which anyone can retrieve the file.
When progress is Some, UploadEvents are emitted on the channel
during encryption (UploadEvent::Encrypting / UploadEvent::Encrypted)
and per-chunk quoting (UploadEvent::ChunkQuoted). Storage events are
emitted later by Client::finalize_upload_with_progress /
Client::finalize_upload_merkle_with_progress.
Memory note: on the merkle path, chunk bodies stay in the on-disk
encryption spill inside the returned PreparedUpload and are read
back ≤ store-cap at a time during finalize, so peak RAM stays bounded
(~256 MB) regardless of file size (ADR-0003). The spill directory
lives as long as the PreparedUpload does. The wave-batch path —
below the merkle threshold, so < ~64 × 4 MiB of chunks (unless
PaymentMode::Single forces it for a larger file) — still holds
its chunk bodies resident.
§Errors
Returns an error if there is insufficient disk space, the file cannot be read, encryption fails, or quote collection fails.
Sourcepub async fn finalize_upload(
&self,
prepared: PreparedUpload,
tx_hash_map: &HashMap<QuoteHash, TxHash>,
) -> Result<FileUploadResult>
pub async fn finalize_upload( &self, prepared: PreparedUpload, tx_hash_map: &HashMap<QuoteHash, TxHash>, ) -> Result<FileUploadResult>
Phase 2 of external-signer upload (wave-batch): finalize with externally-signed tx hashes.
Takes a PreparedUpload that used wave-batch payment and a map
of quote_hash -> tx_hash provided by the external signer after on-chain
payment. Builds payment proofs and stores chunks on the network.
§Errors
Returns an error if the prepared upload used merkle payment (use
Client::finalize_upload_merkle instead), proof construction fails,
or any chunk cannot be stored.
Sourcepub async fn finalize_upload_with_progress(
&self,
prepared: PreparedUpload,
tx_hash_map: &HashMap<QuoteHash, TxHash>,
progress: Option<Sender<UploadEvent>>,
) -> Result<FileUploadResult>
pub async fn finalize_upload_with_progress( &self, prepared: PreparedUpload, tx_hash_map: &HashMap<QuoteHash, TxHash>, progress: Option<Sender<UploadEvent>>, ) -> Result<FileUploadResult>
Phase 2 of external-signer upload (wave-batch) with progress events.
Same as Client::finalize_upload but emits UploadEvent::ChunkStored
on the provided channel as each chunk is successfully stored.
§Errors
Same as Client::finalize_upload.
Sourcepub async fn finalize_upload_merkle(
&self,
prepared: PreparedUpload,
winner_pool_hash: [u8; 32],
) -> Result<FileUploadResult>
pub async fn finalize_upload_merkle( &self, prepared: PreparedUpload, winner_pool_hash: [u8; 32], ) -> Result<FileUploadResult>
Phase 2 of external-signer upload (merkle): finalize with winner pool hash.
The single-batch special case of
Client::finalize_upload_merkle_multi: valid only for uploads that
prepared as exactly one merkle sub-batch (any fresh upload below
MAX_LEAVES chunks). Generates proofs and stores chunks on the
network.
§Errors
Returns an error if the prepared upload used wave-batch payment (use
Client::finalize_upload instead), was prepared as more than one
sub-batch (use Client::finalize_upload_merkle_multi), or proof
generation fails. Chunks still short of quorum after all retries
surface as Error::PartialUpload carrying the stored and failed
addresses — the same contract as Client::finalize_upload.
Re-preparing the same file skips chunks that are already stored.
Sourcepub async fn finalize_upload_merkle_with_progress(
&self,
prepared: PreparedUpload,
winner_pool_hash: [u8; 32],
progress: Option<Sender<UploadEvent>>,
) -> Result<FileUploadResult>
pub async fn finalize_upload_merkle_with_progress( &self, prepared: PreparedUpload, winner_pool_hash: [u8; 32], progress: Option<Sender<UploadEvent>>, ) -> Result<FileUploadResult>
Phase 2 of external-signer upload (merkle) with progress events.
Same as Client::finalize_upload_merkle but emits UploadEvent::ChunkStored
on the provided channel as each chunk is successfully stored.
§Errors
Same as Client::finalize_upload_merkle.
Sourcepub async fn finalize_upload_merkle_multi(
&self,
prepared: PreparedUpload,
winner_pool_hashes: Vec<Option<[u8; 32]>>,
) -> Result<FileUploadResult>
pub async fn finalize_upload_merkle_multi( &self, prepared: PreparedUpload, winner_pool_hashes: Vec<Option<[u8; 32]>>, ) -> Result<FileUploadResult>
Phase 2 of external-signer upload (merkle): finalize with one winner pool hash per prepared sub-batch.
winner_pool_hashes aligns with
ExternalPaymentInfo::Merkle::prepared_batches: entry i is the
MerklePaymentMade winner hash of batch i’s on-chain payment, or
None if the signer never paid that batch (e.g. the user abandoned
the flow midway). Paid batches make forward progress: their proofs
are folded — mirroring the wallet path’s multi-batch fold — and their
chunks stored from the on-disk spill in a bounded fan-out; chunks of
unpaid batches are reported through Error::PartialUpload
(ADR-0003).
§Errors
Returns an error if the prepared upload used wave-batch payment, the
hash count does not match the batch count, every entry is None, or
proof generation fails. Chunks short of quorum after all retries —
and all chunks of unpaid batches — surface as
Error::PartialUpload carrying the stored and failed addresses.
Re-preparing the same file skips chunks that are already stored.
Sourcepub async fn finalize_upload_merkle_multi_with_progress(
&self,
prepared: PreparedUpload,
winner_pool_hashes: Vec<Option<[u8; 32]>>,
progress: Option<Sender<UploadEvent>>,
) -> Result<FileUploadResult>
pub async fn finalize_upload_merkle_multi_with_progress( &self, prepared: PreparedUpload, winner_pool_hashes: Vec<Option<[u8; 32]>>, progress: Option<Sender<UploadEvent>>, ) -> Result<FileUploadResult>
Same as Client::finalize_upload_merkle_multi but emits
UploadEvent::ChunkStored on the provided channel as each chunk is
successfully stored.
§Errors
Same as Client::finalize_upload_merkle_multi.
Sourcepub async fn finalize_upload_merkle_multi_resumable(
&self,
prepared: PreparedUpload,
winner_pool_hashes: Vec<Option<[u8; 32]>>,
) -> Result<FinalizeOutcome>
pub async fn finalize_upload_merkle_multi_resumable( &self, prepared: PreparedUpload, winner_pool_hashes: Vec<Option<[u8; 32]>>, ) -> Result<FinalizeOutcome>
Finalize an external-signer merkle upload, returning a resume handle if some chunks remain unstored after retries.
Behaves like Client::finalize_upload_merkle_multi, but instead of
surfacing a quorum shortfall as Error::PartialUpload it returns
FinalizeOutcome::Partial, carrying a MerkleFinalizeResume (inside
FinalizeResume::Merkle) that owns the on-disk chunk spill and the
already-signed payment proofs. The caller can hand that handle to
Client::finalize_resume to store only the still-unstored chunks
against the same on-chain payment — no re-quoting, no second
signature, no double payment (#140).
Unlike the non-resumable method, every sub-batch must be paid
(winner_pool_hashes all Some). A resume handle cannot acquire proofs
for unpaid chunks, so a partially-paid finalize could never drain to
FinalizeOutcome::Complete; partial payment is rejected up front. To
finalize a partial payment, use Client::finalize_upload_merkle_multi,
which reports the unpaid chunks through Error::PartialUpload.
§Errors
Returns an error if any sub-batch is unpaid, the winner-hash count does
not match the prepared batches, the payment info is wave-batch rather
than merkle, or payment finalization fails. Store failures are not
errors here: a quorum shortfall — and a fatal store abort, which keeps
its progress the same way — comes back as FinalizeOutcome::Partial.
Sourcepub async fn finalize_upload_merkle_multi_resumable_with_progress(
&self,
prepared: PreparedUpload,
winner_pool_hashes: Vec<Option<[u8; 32]>>,
progress: Option<Sender<UploadEvent>>,
) -> Result<FinalizeOutcome>
pub async fn finalize_upload_merkle_multi_resumable_with_progress( &self, prepared: PreparedUpload, winner_pool_hashes: Vec<Option<[u8; 32]>>, progress: Option<Sender<UploadEvent>>, ) -> Result<FinalizeOutcome>
Same as Client::finalize_upload_merkle_multi_resumable but emits
UploadEvent::ChunkStored on the provided channel as each chunk is
stored.
§Errors
Sourcepub async fn finalize_upload_resumable(
&self,
prepared: PreparedUpload,
tx_hash_map: &HashMap<QuoteHash, TxHash>,
) -> Result<FinalizeOutcome>
pub async fn finalize_upload_resumable( &self, prepared: PreparedUpload, tx_hash_map: &HashMap<QuoteHash, TxHash>, ) -> Result<FinalizeOutcome>
Finalize an external-signer wave-batch upload, returning a resume handle if some chunks remain unstored after retries.
Behaves like Client::finalize_upload, but instead of surfacing a
storage failure as Error::PartialUpload it returns
FinalizeOutcome::Partial, carrying a WaveFinalizeResume (inside
FinalizeResume::Wave) that owns the already-paid chunks still needing
storage. The caller can hand that handle to Client::finalize_resume
to re-store only those chunks against the same on-chain payment — no
re-quoting, no second signature, no double payment (#140).
§Errors
Returns an error if a tx_hash is missing for a quote, the payment info
is merkle rather than wave-batch, or payment finalization fails. A plain
storage shortfall is not an error — it comes back as
FinalizeOutcome::Partial.
Sourcepub async fn finalize_upload_resumable_with_progress(
&self,
prepared: PreparedUpload,
tx_hash_map: &HashMap<QuoteHash, TxHash>,
progress: Option<Sender<UploadEvent>>,
) -> Result<FinalizeOutcome>
pub async fn finalize_upload_resumable_with_progress( &self, prepared: PreparedUpload, tx_hash_map: &HashMap<QuoteHash, TxHash>, progress: Option<Sender<UploadEvent>>, ) -> Result<FinalizeOutcome>
Same as Client::finalize_upload_resumable but emits
UploadEvent::ChunkStored on the provided channel as each chunk is
stored.
§Errors
Same as Client::finalize_upload_resumable.
Sourcepub async fn finalize_resume(
&self,
resume: FinalizeResume,
) -> Result<FinalizeOutcome>
pub async fn finalize_resume( &self, resume: FinalizeResume, ) -> Result<FinalizeOutcome>
Resume an external-signer finalize that returned
FinalizeOutcome::Partial, storing only the still-unstored chunks
against the already-signed payment carried by the FinalizeResume
handle.
No re-quoting and no new signature: the handle owns the retained chunk
bodies (wave path) or the spill + merkle proofs (merkle path). Every
chunk in the handle has its payment material, so the upload always
can complete once the network cooperates. Safe to call repeatedly —
each call stores what it can and either completes the upload
(FinalizeOutcome::Complete) or hands back the remainder, so a
caller can loop until it drains or gives up (#140).
Bound that loop. Store failures — including persistent ones, such
as a chunk whose close group stays unreachable — surface as
FinalizeOutcome::Partial on every call, never as Err, so an
unbounded while let Partial loop will spin for as long as the
failure persists. Cap the attempts (or apply backoff between them) and
treat a handle that stops shrinking as stuck.
§Errors
Store failures are not errors — every store-side outcome, fatal aborts
included, comes back as FinalizeOutcome::Partial with the payment
material retained for retry. Err is reserved for failures outside
the chunk store itself.
Sourcepub async fn finalize_resume_with_progress(
&self,
resume: FinalizeResume,
progress: Option<Sender<UploadEvent>>,
) -> Result<FinalizeOutcome>
pub async fn finalize_resume_with_progress( &self, resume: FinalizeResume, progress: Option<Sender<UploadEvent>>, ) -> Result<FinalizeOutcome>
Same as Client::finalize_resume but emits UploadEvent::ChunkStored
as each remaining chunk is stored.
§Errors
Same as Client::finalize_resume.
Sourcepub async fn file_upload_with_mode(
&self,
path: &Path,
mode: PaymentMode,
) -> Result<FileUploadResult>
pub async fn file_upload_with_mode( &self, path: &Path, mode: PaymentMode, ) -> Result<FileUploadResult>
Upload a file with a specific payment mode.
Before encryption, checks that the temp directory has enough free disk space for the spilled chunks (~1.1× source file size).
Encrypted chunks are spilled to a temp directory during encryption so that only their 32-byte addresses stay in memory. At upload time, chunks are read back one wave at a time (~64 × 4 MB ≈ 256 MB peak).
§Errors
Returns an error if there is insufficient disk space, the file cannot be read, encryption fails, or any chunk cannot be stored.
Sourcepub async fn file_upload_public_with_mode(
&self,
path: &Path,
mode: PaymentMode,
) -> Result<FileUploadResult>
pub async fn file_upload_public_with_mode( &self, path: &Path, mode: PaymentMode, ) -> Result<FileUploadResult>
Upload a file publicly, storing the serialized DataMap as part of
the same upload payment batch.
The returned FileUploadResult::data_map_address can be shared for
public downloads via Client::data_map_fetch.
Sourcepub async fn file_upload_with_progress(
&self,
path: &Path,
mode: PaymentMode,
progress: Option<Sender<UploadEvent>>,
) -> Result<FileUploadResult>
pub async fn file_upload_with_progress( &self, path: &Path, mode: PaymentMode, progress: Option<Sender<UploadEvent>>, ) -> Result<FileUploadResult>
Upload a file with progress events sent to the given channel.
Same as Client::file_upload_with_mode but sends UploadEvents to the
provided channel for UI progress feedback.
Sourcepub async fn file_upload_public_with_progress(
&self,
path: &Path,
mode: PaymentMode,
progress: Option<Sender<UploadEvent>>,
) -> Result<FileUploadResult>
pub async fn file_upload_public_with_progress( &self, path: &Path, mode: PaymentMode, progress: Option<Sender<UploadEvent>>, ) -> Result<FileUploadResult>
Public file upload with progress events.
Same as Client::file_upload_public_with_mode but sends
UploadEvents to the provided channel for UI progress feedback.
Sourcepub async fn file_download(
&self,
data_map: &DataMap,
output: &Path,
) -> Result<u64>
pub async fn file_download( &self, data_map: &DataMap, output: &Path, ) -> Result<u64>
Download and decrypt a file from the network, writing it to disk.
Uses streaming_decrypt so that only one batch of chunks lives in
memory at a time, avoiding OOM on large files. Chunks are fetched
concurrently within each batch, then decrypted data is written to
disk incrementally.
Returns the number of bytes written.
§Panics
Requires a multi-threaded Tokio runtime (flavor = "multi_thread").
Will panic if called from a current_thread runtime because
streaming_decrypt takes a synchronous callback that must bridge
back to async via block_in_place.
§Errors
Returns an error if any chunk cannot be retrieved, decryption fails, or the file cannot be written.
Sourcepub async fn file_download_from_closest_peers(
&self,
data_map: &DataMap,
output: &Path,
peer_count: NonZeroUsize,
) -> Result<u64>
pub async fn file_download_from_closest_peers( &self, data_map: &DataMap, output: &Path, peer_count: NonZeroUsize, ) -> Result<u64>
Download and decrypt a file, trying the requested number of closest peers for every chunk fetch.
Returns the number of bytes written.
§Errors
Returns an error if any chunk cannot be retrieved, decryption fails, or the file cannot be written.
Sourcepub async fn file_download_with_progress_from_closest_peers(
&self,
data_map: &DataMap,
output: &Path,
progress: Option<Sender<DownloadEvent>>,
peer_count: NonZeroUsize,
) -> Result<u64>
pub async fn file_download_with_progress_from_closest_peers( &self, data_map: &DataMap, output: &Path, progress: Option<Sender<DownloadEvent>>, peer_count: NonZeroUsize, ) -> Result<u64>
Download and decrypt a file with progress events, trying the requested number of closest peers for every chunk fetch.
Same as Client::file_download_from_closest_peers but sends
DownloadEvents for UI feedback.
§Errors
Returns an error if any chunk cannot be retrieved, decryption fails, or the file cannot be written.
Sourcepub async fn file_download_with_progress_and_diagnostics_from_closest_peers(
&self,
data_map: &DataMap,
output: &Path,
progress: Option<Sender<DownloadEvent>>,
peer_count: NonZeroUsize,
diagnostics: Option<DownloadDiagnosticsSender>,
) -> Result<u64>
pub async fn file_download_with_progress_and_diagnostics_from_closest_peers( &self, data_map: &DataMap, output: &Path, progress: Option<Sender<DownloadEvent>>, peer_count: NonZeroUsize, diagnostics: Option<DownloadDiagnosticsSender>, ) -> Result<u64>
Download a file with progress and optional per-attempt JSONL diagnostics.
Passing None preserves the standard path without diagnostic records.
Sourcepub async fn file_download_with_peer_report_from_closest_peers(
&self,
data_map: &DataMap,
output: &Path,
progress: Option<Sender<DownloadEvent>>,
peer_count: NonZeroUsize,
) -> Result<FileDownloadWithPeerReport>
pub async fn file_download_with_peer_report_from_closest_peers( &self, data_map: &DataMap, output: &Path, progress: Option<Sender<DownloadEvent>>, peer_count: NonZeroUsize, ) -> Result<FileDownloadWithPeerReport>
Download and decrypt a file with peer-health diagnostics.
Each file chunk is fetched by querying every selected closest peer, not by returning after the first successful peer. The returned report records which peers had each chunk and which did not. DataMap resolution still uses the normal early-return fetch path; diagnostics are for file chunks only.
§Errors
Returns an error if any chunk cannot be retrieved, decryption fails, or the file cannot be written.
Sourcepub async fn file_download_with_progress(
&self,
data_map: &DataMap,
output: &Path,
progress: Option<Sender<DownloadEvent>>,
) -> Result<u64>
pub async fn file_download_with_progress( &self, data_map: &DataMap, output: &Path, progress: Option<Sender<DownloadEvent>>, ) -> Result<u64>
Download and decrypt a file to disk, with optional progress events.
Same as Client::file_download but sends DownloadEvents for UI
feedback. Streams to a temp file (one decrypt batch resident at a time)
and renames atomically on success. A TempDownload guard removes the
staging file on any error path, including a panic.
Sourcepub async fn file_download_to_sender(
&self,
data_map: &DataMap,
sink: Sender<Result<Bytes, Error>>,
progress: Option<Sender<DownloadEvent>>,
) -> Result<u64>
pub async fn file_download_to_sender( &self, data_map: &DataMap, sink: Sender<Result<Bytes, Error>>, progress: Option<Sender<DownloadEvent>>, ) -> Result<u64>
Download and decrypt a file, streaming the plaintext to sink instead
of writing to disk.
Constant memory (one decrypt batch resident at a time); the caller
receives bytes progressively as each batch decrypts, suitable for
forwarding to an HTTP chunked body or a gRPC response stream. The
bounded sink applies backpressure. If the receiver is dropped (e.g.
the client disconnected) the download stops early and returns
Error::Cancelled.
The channel item type is Result<Bytes, Error>, so the caller sets up:
let (tx, rx) = tokio::sync::mpsc::channel::<Result<Bytes, Error>>(8);Typically the caller tokio::spawns this and converts the matching
Receiver into its response stream. Requires a multi-threaded Tokio
runtime (the decrypt iterator uses block_in_place).
Source§impl Client
impl Client
Sourcepub fn should_use_merkle(&self, chunk_count: usize, mode: PaymentMode) -> bool
pub fn should_use_merkle(&self, chunk_count: usize, mode: PaymentMode) -> bool
Determine whether to use merkle payments for a given batch size.
Sourcepub async fn pay_for_merkle_batch(
&self,
addresses: &[[u8; 32]],
data_type: u32,
data_size: u64,
) -> Result<MerkleBatchPaymentResult>
pub async fn pay_for_merkle_batch( &self, addresses: &[[u8; 32]], data_type: u32, data_size: u64, ) -> Result<MerkleBatchPaymentResult>
Pay for a batch of chunks using merkle batch payment.
Builds a merkle tree, collects candidate pools, pays on-chain in one tx,
and returns per-chunk proofs. Anything longer than MAX_LEAVES is split
by merkle_batch_sizes and paid one transaction per sub-batch.
This low-level helper assumes the caller has already selected the addresses that need payment. User-facing upload paths first run the merkle upload planner to skip chunks already stored on the network.
§Errors
Returns an error if the batch is too small, candidate collection fails, on-chain payment fails, or proof generation fails.
Sourcepub async fn prepare_merkle_batches_external(
&self,
addresses: &[[u8; 32]],
data_type: u32,
data_size: u64,
cap: usize,
) -> Result<Vec<PreparedMerkleBatch>>
pub async fn prepare_merkle_batches_external( &self, addresses: &[[u8; 32]], data_type: u32, data_size: u64, cap: usize, ) -> Result<Vec<PreparedMerkleBatch>>
Phase 1 of external-signer merkle payment for an address set of any
size: partition into MerkleTree-sized sub-batches and prepare each.
The partition follows merkle_batch_partitions_with_cap (≤ cap
leaves per batch, singleton-remainder rebalanced), so the external
signer pays one transaction per returned batch — the same shape the
wallet path’s pay_for_merkle_multi_batch signs internally
(ADR-0003). Batch order matches address order; the caller’s finalize
supplies one winner hash per batch in the same order.
cap is clamped to 3..=MAX_LEAVES (see
merkle_batch_sizes_with_cap for why 3 is the floor); production
callers pass MAX_LEAVES, tests pass small caps to get real
multi-batch flows from kilobyte files.
§Errors
Returns an error if any sub-batch’s candidate collection fails. Nothing is spent in either case — payment happens externally after this returns.
Sourcepub async fn prepare_merkle_batch_external(
&self,
addresses: &[[u8; 32]],
data_type: u32,
data_size: u64,
) -> Result<PreparedMerkleBatch>
pub async fn prepare_merkle_batch_external( &self, addresses: &[[u8; 32]], data_type: u32, data_size: u64, ) -> Result<PreparedMerkleBatch>
Phase 1 of external-signer merkle payment: prepare batch without paying.
Builds the merkle tree, collects candidate pools from the network,
and returns the data needed for the on-chain payment call.
Requires EvmNetwork but NOT a wallet.
§Errors
Returns Error::MerkleBatchTooLarge if addresses holds more than
MAX_LEAVES entries. One prepared batch is one signature and one
payment, so an oversized set has no valid external-signing form; the
wallet path splits it across transactions instead
(Client::prepare_merkle_batches_external is the partitioned
equivalent for external signing). The check runs before any candidate
collection, so nothing is spent.
Source§impl Client
impl Client
Sourcepub async fn pay_for_storage(
&self,
address: &[u8; 32],
data_size: u64,
data_type: u32,
) -> Result<(Vec<u8>, Vec<(PeerId, Vec<MultiAddr>)>)>
pub async fn pay_for_storage( &self, address: &[u8; 32], data_size: u64, data_type: u32, ) -> Result<(Vec<u8>, Vec<(PeerId, Vec<MultiAddr>)>)>
Pay for storage and return the serialized payment proof bytes.
This orchestrates the full payment flow:
- Collect at least one witnessed quote plus ordered PUT targets
- Build single-node payment using node-reported prices (median 3x, others 0)
- Pay on-chain via the wallet
- Serialize
PaymentProofwith transaction hashes
§Errors
Returns an error if the wallet is not set, quotes cannot be collected,
on-chain payment fails, or serialization fails.
Returns (proof_bytes, put_targets). The peer list is the ordered PUT
target set from quote planning: it starts with peers expected to accept
the paid proof and can include non-quoted fallback peers beyond the
quoted close group.
Sourcepub async fn approve_token_spend(&self) -> Result<()>
pub async fn approve_token_spend(&self) -> Result<()>
Approve the wallet to spend tokens on the payment vault contract.
This must be called once before any payments can be made.
Approves U256::MAX (unlimited) spending.
§Errors
Returns an error if the wallet is not set or the approval transaction fails.
Source§impl Client
impl Client
Sourcepub async fn get_store_quotes(
&self,
address: &[u8; 32],
data_size: u64,
data_type: u32,
) -> Result<Vec<(PeerId, Vec<MultiAddr>, PaymentQuote, Amount, Option<Vec<u8>>)>>
pub async fn get_store_quotes( &self, address: &[u8; 32], data_size: u64, data_type: u32, ) -> Result<Vec<(PeerId, Vec<MultiAddr>, PaymentQuote, Amount, Option<Vec<u8>>)>>
Get storage quotes from the closest peers for a given address.
Builds a quorum-witnessed candidate set, still attempts to collect the close-group quote count, and returns the largest supported successful quote set. The single-node path now only requires one valid quote to proceed, but still pays the median quote from the selected set when more quotes were successfully fetched.
Returns Error::AlreadyStored early if CLOSE_GROUP_MAJORITY peers
report the chunk is already stored.
§Errors
Returns an error if insufficient quotes can be collected.
Source§impl Client
impl Client
Sourcepub fn from_node(node: Arc<P2PNode>, config: ClientConfig) -> Self
pub fn from_node(node: Arc<P2PNode>, config: ClientConfig) -> Self
Create a client connected to the given P2P node.
Sourcepub fn from_node_with_peer_cache(
node: Arc<P2PNode>,
config: ClientConfig,
peer_cache_path: Option<PathBuf>,
) -> Self
pub fn from_node_with_peer_cache( node: Arc<P2PNode>, config: ClientConfig, peer_cache_path: Option<PathBuf>, ) -> Self
Create a client connected to the given P2P node and attach an optional persistent peer cache path.
Sourcepub async fn connect(
bootstrap_peers: &[SocketAddr],
config: ClientConfig,
) -> Result<Self>
pub async fn connect( bootstrap_peers: &[SocketAddr], config: ClientConfig, ) -> Result<Self>
Create a client connected to bootstrap peers.
Threads config.allow_loopback and config.ipv6 through to
Network::new, which controls the saorsa-transport local and
ipv6 flags on the underlying CoreNodeConfig. See
ClientConfig::allow_loopback and ClientConfig::ipv6 for details.
§Errors
Returns an error if the P2P node cannot be created or bootstrapping fails.
Sourcepub fn with_wallet(self, wallet: Wallet) -> Self
pub fn with_wallet(self, wallet: Wallet) -> Self
Set the wallet for payment operations.
Also populates the EVM network from the wallet so that
token approvals work without a separate with_evm_network call.
Sourcepub fn with_evm_network(self, network: Network) -> Self
pub fn with_evm_network(self, network: Network) -> Self
Set the EVM network without requiring a wallet.
This enables token approval and contract interactions for external-signer flows where the private key lives outside Rust.
Sourcepub fn config(&self) -> &ClientConfig
pub fn config(&self) -> &ClientConfig
Get the client configuration.
Sourcepub fn config_mut(&mut self) -> &mut ClientConfig
pub fn config_mut(&mut self) -> &mut ClientConfig
Get a mutable reference to the client configuration.
Sourcepub async fn network_health(&self) -> NetworkHealth
pub async fn network_health(&self) -> NetworkHealth
Compute the live network-participation snapshot.
Convenience pass-through to Network::health — the single
write-readiness implementation shared by all embedded-client
consumers (antd, ant-gui, ant-ffi, ant-tui).
Sourcepub fn chunk_cache(&self) -> &ChunkCache
pub fn chunk_cache(&self) -> &ChunkCache
Get a reference to the chunk cache.
Sourcepub fn controller(&self) -> &AdaptiveController
pub fn controller(&self) -> &AdaptiveController
Adaptive concurrency controller. Hot loops read
controller().<channel>.current() to size their fan-out and
call .observe(...) on each completion.
Sourcepub fn save_adaptive_snapshot(&self)
pub fn save_adaptive_snapshot(&self)
Persist the current adaptive snapshot to disk so the next
Client::connect warm-starts at the learned values instead of
cold defaults. Best effort — failures log and are discarded.
Idempotent. Safe to call from a Drop impl or an explicit
shutdown hook.
Sourcepub async fn save_peer_cache(&self)
pub async fn save_peer_cache(&self)
Persist currently connected peers that have Direct-tagged addresses in the DHT. Best effort; failures are logged and do not affect the client operation that just completed.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for Client
impl !RefUnwindSafe for Client
impl !UnwindSafe for Client
impl Send for Client
impl Sync for Client
impl Unpin for Client
impl UnsafeUnpin for Client
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more