Repository navigation
docs(testnet): tooling directory index, sweep-signer usage notes, and two tooling specs - #753
Merged
phertyameen merged 1 commit intoSep 27, 2026
Conversation
… two tooling specs Adds testnet/tooling/README.md as the index the directory was missing, plus three documents alongside the two specs already there. testnet/tooling/ decision-log.md already referred to "testnet/tooling/README.md" as the index for this directory and nonce-inspector-spec.md already referred to "the contract-ID lookup tool spec" as if it existed, so this closes two live dangling references. testnet/tooling/README.md The index, whose stated job is to stop a future contributor mistaking this directory for where deploy scripts belong. The distinction is drawn once and cross-linked rather than re-argued: scripts/ holds the repository's own build and CI entrypoints, which run in the repo and are versioned in lockstep with the code they build, while testnet/tooling/ describes tools that consume the already-deployed contracts from outside it. The directory contains no tools, which looks like a bug and invites three reasonable-but-wrong reactions. A prominent status line handles the reader who lands here first and does not read the decision log, and the three reactions are tabled with a pointer to decision-log.md for the reasoning. Also carries forward the sandbox caveat from decision-log.md: several of these specs assume there is no local Soroban sandbox, and adding one would make them substantially less useful, so they should be re-evaluated against a sandbox before being built. It also makes explicit that tools/sweep-signer is a real working CLI in a separate top-level directory, not part of this one. Index entries follow security/README.md's Document | Scope | Read it when shape, with each trigger written as a condition - "Your sweep signature is being rejected with no error code" - rather than a category. testnet/tooling/sweep-signer-integration-notes.md Usage notes only; the tool is not modified. It closes the gap the issue names: .env.example shows only the pubkey subcommand in a commented example line, so an integrator who needs to actually sign has no usage note for sign. Documents both subcommands, the sign flags (--contract-id, --destination, --nonce, and exactly one of --signer-seed-hex or --signer-secret, a group that is required = true and multiple = false, so providing both or neither is an error), the env-var form of each signer option, the 32-byte seed requirement, and the exact three-part output including the nonce warning. The environment-variable form is recommended over flags because it keeps keys out of shell history and process listings. Two findings worth surfacing: - The tool's own "Provide either --signer-seed-hex or --signer-secret" message is unreachable dead code, because clap's required group rejects first. Documented as such rather than presented as guidance. - Its soroban-sdk = "22.0.0" pin is a correctness requirement, not hygiene. The pin exists so Address::to_xdr() serialises identically to what the deployed contract expects. A divergence between the signer's XDR encoding and the contract's produces a signature that does not verify, with no diagnostic - which is why docs/SIGNATURE_FORMAT.md warns about hand-rolled XDR encoders at length. This document deliberately does not open with the spec-only line, because the tool it documents is implemented. Describing tools/sweep-signer 0.1.0's actual behaviour is the point. testnet/tooling/contract-id-lookup-spec.md Design only. Opens with the house spec-only line and links decision-log.md. The central design constraint is that there is no single trustworthy source of contract IDs today: contract-status.md says all four are undeployed with IDs "TBD", last-verified.json carries timestamps but is a staleness mechanism rather than evidence of liveness, and deployments/testnet.json does contain concrete IDs the registry does not reflect. A lookup tool that reads a stale file and returns a confident answer is worse than no tool at all, so the output is provenance-first - source file, field, file age, verified state, and the registry's contradicting statement - and refusing to answer is a first-class outcome rather than an error condition. Six exit codes split resolved-verified, resolved-unverified/stale, unknown name, conflicting sources, unreadable data, and probe unreachable, following nonce-inspector-spec.md's reasoning that CI must be able to tell "retry" from "network down". Caching is a named non-goal, because a cached ID is the failure being fixed. testnet/tooling/event-tail-spec.md Design only. Same spec-only opening. Grounded in testnet/registry/event-topics.md, with a check on the design's hardest problem: a wrong topic symbol silently matches nothing, which for a tailer is indistinguishable from "nothing is happening". The tool must therefore distinguish "no matching events" from "wrong filter" from "not actually connected", and say which one it is. Cursor handling is specified in detail - ledger sequence is the only safe cursor on Stellar, why that rules out timestamps, duplicate suppression across a reconnect, and behaviour when the start ledger predates RPC retention. It is a better ergonomics layer over the primitives the tree already documents rather than a different mechanism. Read-only and provably so, per the shared-deployment reasoning in security/README.md: someone else's activity is a real condition, and a tailer that could mutate the shared deployment would itself be a new abuse surface. The opening states the sharpest honesty problem for this tool specifically: it exists to watch a live deployment, and nothing is deployed, so it cannot currently be exercised. Closes bridgelet-org#643 Closes bridgelet-org#644 Closes bridgelet-org#645 Closes bridgelet-org#646
|
@Ogunmepon Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
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
Adds
testnet/tooling/README.md— the index the directory was missing — plus three documents alongside the two specs already there. This closes two live dangling references:decision-log.mdalready callstestnet/tooling/README.md"the index for this directory", andnonce-inspector-spec.mdalready refers to "the contract-ID lookup tool spec" as though it existed.testnet/tooling/README.mdtestnet/tooling/sweep-signer-integration-notes.mdtestnet/tooling/contract-id-lookup-spec.mdtestnet/tooling/event-tail-spec.mddecision-log.md,faucet-helper-spec.mdandnonce-inspector-spec.mdare unmodified.README.md— stopping the directory being misunderstoodThe directory contains no tools, which looks like a bug and invites three reasonable-but-wrong reactions ("add the scripts", "move
scripts/in here", "it's complete"). A prominent status line catches the reader who lands here first and never opens the decision log; the three reactions are tabled with a pointer for the reasoning rather than re-argued.The distinction is drawn once and cross-linked:
scripts/holds the repository's own build and CI entrypoints (build.sh,deploy-testnet.sh,test.sh), which run in the repo and are versioned in lockstep with the code they build.testnet/tooling/describes tools that consume the already-deployed contracts from outside it.It also makes explicit that
tools/sweep-signeris a real, working CLI in a separate top-level directory — not part of this one — and carries forward the sandbox caveat fromdecision-log.md: several specs assume no local Soroban sandbox exists, and adding one would make them substantially less useful, so they should be re-evaluated before being built.Index entries follow
security/README.md's Document | Scope | Read it when shape, with each trigger written as a condition ("Your sweep signature is being rejected with no error code") rather than a category.sweep-signer-integration-notes.md— the gap.env.exampleleavesUsage notes only; the tool is not modified.
.env.exampleshows only thepubkeysubcommand in a commented example line, so an integrator who actually needs to sign has had no usage note at all.Documents both subcommands, the
signflags —--contract-id,--destination,--nonce, and exactly one of--signer-seed-hexor--signer-secret(a clap group that isrequired = true, multiple = false, so both-or-neither is an error) — the env-var form of each signer option, the 32-byte seed requirement, and the exact three-part output including the nonce warning. The env-var form is recommended over flags because it keeps keys out of shell history and process listings.Two findings:
"Provide either --signer-seed-hex or --signer-secret"message is unreachable dead code, because clap's required group rejects first. Documented as such rather than presented as guidance someone should follow.soroban-sdk = "22.0.0"pin is a correctness requirement, not hygiene. It exists soAddress::to_xdr()serialises identically to what the deployed contract expects. A divergence produces a signature that does not verify, with no diagnostic — which is whydocs/SIGNATURE_FORMAT.mdwarns about hand-rolled XDR encoders at length.This document deliberately does not open with the spec-only line, because the tool it documents is implemented. Describing 0.1.0's actual behaviour is the point.
contract-id-lookup-spec.md— spec onlyThe central design constraint is that there is no single trustworthy source of contract IDs today:
contract-status.mdsays all four are undeployed with IDs "TBD";last-verified.jsoncarries timestamps but is a staleness mechanism, not evidence of liveness; anddeployments/testnet.jsondoes contain concrete IDs the registry does not reflect.So the output is provenance-first — source file, field, file age, verified state, and the registry's contradicting statement — and refusing to answer is a first-class outcome, not an error condition. Six exit codes split resolved-verified, resolved-unverified/stale, unknown name, conflicting sources, unreadable data, and probe unreachable, following
nonce-inspector-spec.md's reasoning that CI must distinguish "retry" from "network down". Caching is a named non-goal, because a cached ID is the failure being fixed.event-tail-spec.md— spec onlyGrounded in
testnet/registry/event-topics.md, and built around the design's hardest problem: a wrong topic symbol silently matches nothing, which for a tailer is indistinguishable from "nothing is happening". The tool must therefore distinguish "no matching events" from "wrong filter" from "not actually connected" — and say which one it is.Cursor handling is specified in detail: ledger sequence is the only safe cursor on Stellar and why that rules out timestamps, duplicate suppression across a reconnect, and behaviour when the start ledger predates RPC retention. It is positioned as a better ergonomics layer over primitives the tree already documents, not a different mechanism.
Read-only and provably so, per the shared-deployment reasoning in
security/README.md: someone else's activity is a real condition, and a tailer that could mutate the shared deployment would itself be a new abuse surface.The opening states the sharpest honesty problem for this tool specifically — it exists to watch a live deployment, and nothing is deployed, so it cannot currently be exercised.
Repository defects found, documented rather than papered over
testnet/registry/event-topics.mdis wrong aboutReserveContractevent symbols. It documentsinitializedandbase_reserve_updated;contracts/reserve_contract/src/events.rspublishesinitandreserve.testnet/monitoring/event-watchlist.mdalready noticed this ("Some existing registry prose predates those symbols") but the registry was never corrected. The spec uses the source as authority and flags the divergence inline.event-topics.mdhas theAccountExpiredfield wrong — it saystotal_amount; the source field isamount_returned. Again,event-watchlist.mddocuments this correctly.testnet/registry/README.mdcallscontract-status.mdcanonical;testnet/config/README.mdcallsdeployments/testnet.json+contract-ids.txtthe source of truth. This single undecided question would collapse most of the lookup spec's difficulty, so it is left as the first open question rather than picked.Error::SignatureVerificationFailed = 9is unreachable.verify_sweep_authcallsenv.crypto().ed25519_verify(...)then returnsOk(())unconditionally — a bad signature traps the host function rather than returning the error.InvalidNonce = 11appears dead too. The enum documents an interface the code does not implement, andtestnet/runbooks/failed-sweep-signature.mddescribes Create API Reference Documentation #9 as the primary symptom an integrator will never see. Flagged in the troubleshooting table.tools/sweep-signer/testnet/config/staleness.mdis a stray issue body committed insidetools/— a GitHub issue title and body, not documentation, describing atestnet/config/staleness-check.mdthat does not exist.sweep_controllerhas noevents.rs. Its three event helpers (sweep,dest_auth,dest_upd) are inline inlib.rs, unlike the other two contracts.testnet/runbooks/failed-sweep-signature.mdandtestnet/config/nonce-tracking.mdboth referencetools/sweep-signer/config.toml, which does not exist. The tool takes flags and env vars only, so anything following those two diagnostics verbatim fails at that step.Verification
git statusshows exactly these four files;git diffis empty — the three pre-existingtestnet/tooling/files are untouched.scripts/andtools/untouched.ls-verified.S[A-Z2-7]{40,}, 64-char hex, and 32+-char hex all return clean — relevant because this batch documents a key-accepting tool. The.env.exampleexample seed is referenced, labelled a documentation artefact, and explicitly marked not-for-use. The onlyC...string is the public XLM SAC address.Closes #643
Closes #644
Closes #645
Closes #646