Dedupe NFT mint URI fetches across editions - #866
Open
judeallred wants to merge 5 commits into
Open
Conversation
judeallred
commented
Sep 9, 2026
Author
|
This version decreases the time to mine 50 NFTs from 2:17 to 1:24 in my testbed. Trying to optimize further... |
Cache the fetched content hash per URI list instead of the full Data blob, so repeated editions sharing data/metadata/license URIs skip the network fetch without cloning the raw bytes on every cache hit. info.nft_data remains the single place the blob is stored.
fetch_minter_hash walks parent coin spends looking for the minting singleton, sleeping 1s between failed hops as a backoff against a full node not having caught up yet. But for a freshly-minted NFT, most of that ancestor chain is part of the very same transaction being submitted and is already resolvable from the local pending-spend cache, so the sleep just adds dead time for data we already have. Only back off when the previous hop actually required a real network round-trip. Benchmarked with a 50-NFT bulk mint against the test PeerSimulator: submit time drops from 67.6s to 13.8s. Also pins current minter_hash behavior with a regression test, since nothing previously asserted on it.
judeallred
force-pushed
the
worktree-nft-mint-url-fetch-dedupe
branch
from
September 10, 2026 03:38
0e3628a to
eb3085c
Compare
uri_cache and info were always created together and passed together through convert_nft_mint and both of its call sites. Since they share the same per-transaction lifetime, keep them as one struct instead of two parallel mutable parameters.
It doesn't protect the sleep-skip fix: is_pending only gates the backoff sleep and never affects which branch runs or what fetch_minter_hash returns, so this assertion would pass identically regardless of whether is_pending were computed correctly. It was written for a different, unshipped approach (skipping the network fetch entirely for self-minted NFTs), where getting that logic wrong really could have changed the result.
judeallred
marked this pull request as ready for review
September 10, 2026 03:59
Author
|
@Rigidity for your consideration tl;dr: minting 50 NFTs 2:17s -> 35s |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Vec<String>->Bytes32) instead of caching the fullDatablob, so cache hits don't clone the raw bytes/thumbnail.ConfirmationInfo::nft_dataremains the single place the fetched blob is stored.fetch_minter_hash's parent-walking loop when the next hop is already known locally (i.e. it's part of the same pending transaction being submitted), instead of unconditionally sleeping after every failed parse attempt. This was the dominant cost in the "submitting" phase of a bulk mint, since most of a freshly-minted NFT's ancestor chain (launcher → intermediate coin → DID re-spend) is part of the transaction being submitted and needs no propagation-delay backoff.uri_cacheintoConfirmationInfo(uri_hashesfield) instead of threading it as a second parallel mutable parameter next toinfothroughconvert_nft_mintand both of its call sites — they share the same per-transaction lifetime, so they're now one struct instead of two.Profiling
Real-world test (50 NFT mints):
Isolated benchmarks for each change against the test
PeerSimulator/a local mock HTTP server:Both changes are independent and additive — one targets the mint/build phase (redundant network fetches of NFT content), the other targets the submit phase (wasted backoff sleeps while walking coin ancestry).
Test plan
cargo check -p sagecargo clippy -p sage --all-targetscargo test -p sage-wallet(48 tests)