feat(simulators): Merkle proofs, XDR inspector, storage model, reorg & finality (#1159, #1161, #1162, #1163) - #1217
Open
ayinde38 wants to merge 1 commit into
Conversation
…finality Closes StellarDevHub#1159, StellarDevHub#1161, StellarDevHub#1162, StellarDevHub#1163. Four interactive simulators, each a pure lib plus a page, so the teaching logic is testable without rendering. StellarDevHub#1159 - lib/merkle-sha256.ts + /merkle-simulator. Deliberately not built on the existing merkle-tree-builder: that hashes with stableHash (FNV-1a, 32-bit, non-cryptographic), which is fine for the airdrop demo it backs but wrong for a tool teaching cryptographic immutability - a student could find a collision by hand. Uses real SHA-256 with 0x00/0x01 domain separation for leaves and nodes, so exported proofs are valid contract test vectors. Unpaired nodes are promoted rather than duplicated, avoiding CVE-2012-2459. Shows the audit path, step-by-step root reconstruction, and the tamper cascade. StellarDevHub#1161 - lib/xdr-inspector.ts + /xdr-inspector. Builds Payment, CreateAccount, ManageData and InvokeHostFunction operations, converts between the JSON view and Base64 XDR, decodes envelopes back, and simulates before submitting to testnet. The decoded panel parses the envelope rather than echoing form state, so the two views cannot silently disagree. Surfaces that the transaction hash is network-specific, which is what prevents cross-network replay. StellarDevHub#1162 - lib/soroban-storage-model.ts + /storage-model. Models the distinction students actually get wrong: Temporary and Persistent are not short and long, they differ in what expiry does - deletion versus archival. Live TTL countdowns, a rent calculator, and extend_ttl/restore that refuse the operations the protocol refuses, including restoring a deleted temporary entry. StellarDevHub#1163 - lib/consensus-simulator.ts + /consensus-simulator. Distinct from the existing /chain-reorg animation: models branches concretely, so a reorg names the transactions it reverted rather than just declaring a winner. Implements PoW fork choice by cumulative work, the Nakamoto gambler's-ruin reversal probability, a 51% double-spend, and the SCP contrast where a closed ledger is final and an attacker can only halt progress. Includes a timeline scrubber that replays history through the same fork-choice code.
|
@ayinde38 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! 🚀 |
|
@ayinde38 is attempting to deploy a commit to the Ayomide Adeniran's projects Team on Vercel. A member of the Team first needs to authorize it. |
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.
Closes #1159
Closes #1161
Closes #1162
Closes #1163
Four simulators. Each is a pure library plus a page, so the teaching logic is testable without rendering — and in three of the four the library is where the actual lesson lives.
/merkle-simulatorlib/merkle-sha256.ts/xdr-inspectorlib/xdr-inspector.ts/storage-modellib/soroban-storage-model.ts/consensus-simulatorlib/consensus-simulator.ts#1159 — Merkle visualiser
Not built on the existing
merkle-tree-builder.ts, deliberately. That module hashes withstableHash, which is FNV-1a: a 32-bit, non-cryptographic hash. It is fine for the airdrop demo it backs, where the hash is only an identifier. It is the wrong primitive for a tool whose entire lesson is cryptographic immutability — a student could find an FNV collision by hand, and the tamper demo would be teaching that Merkle roots are forgeable. The existing/merkle-treeroute is untouched.lib/merkle-sha256.tsuses real SHA-256 via Web Crypto, with two properties worth calling out:SHA256(0x00 ‖ value)and nodesSHA256(0x01 ‖ left ‖ right). Without it, an internal node's preimage is 64 bytes and could be presented as a leaf in a tree built over 64-byte leaves — the standard second-preimage attack. RFC 6962 uses the same construction.The page does what the issue asks: student-supplied leaves, audit path with siblings highlighted separately from the path itself, step-by-step reconstruction showing the exact bytes hashed at each level, tamper simulation with the cascade highlighted, and JSON export. The exported bundle records
algorithm,leafPrefixandnodePrefix— a vector that omits the scheme is not reproducible by a contract.#1161 — Transaction builder & XDR inspector
Builds Payment, CreateAccount, ManageData and InvokeHostFunction (Soroban), converts between the structured view and Base64 XDR, and decodes envelopes back.
The decoded panel parses the envelope rather than echoing form state. That is the whole claim of the page — the JSON and the XDR are one object in two spellings — and
verifyRoundTripasserts it on every edit, so a disagreement is visible rather than hidden.Three things the tool surfaces that are easy to get wrong:
manageDatawith no value deletes the entry, which is not the same as storing an empty string.Submission funds the account via Friendbot, re-reads the live sequence (the form's sequence is for teaching; the network wants exactly next), simulates via Soroban RPC first, and only then submits — so authorization and precondition failures cost nothing. Submission is restricted to testnet.
#1162 — Storage model visualiser
The distinction students get wrong is that Temporary and Persistent sound like "short" and "long". They are not — both expire. They differ in what expiry does:
restore, at a cost.So "use Temporary to save money" is only safe for data you can recompute. The page makes this concrete: advance past the TTL, press
restoreon the temporary cache entry and it refuses; press it on the persistent balance at the same moment and it succeeds.Also modelled: Instance storage shares one TTL across every key,
extend_ttlmeasures from the current ledger (repeated calls do not stack) and never shortens a TTL, and neitherextend_ttlnorrestorecan revive a deleted entry. Rent calculator shows all three tiers side by side with the expiry behaviour in the same row, because price alone makes Temporary look like the obvious choice.The fee rates are network parameters, not constants — they are exported and overridable, and the page says so rather than presenting a projection as a quote.
#1163 — Reorg & finality simulator
Distinct from the existing
/chain-reorg, which animates two racing chains with random hashes and declares a winner. This models branches concretely, so a reorg names the transactions it reverted — not "reorgs can happen" but "this payment unhappened, and the goods already shipped".(q/p)^depth, which returns 1 at ≥50% — no confirmation count is safe, which is what "51% attack" actually means.A transaction present on both branches is correctly not counted as reverted.
Verification
npm installdoes not produce a workingnode_modulesfor this repo in my environment, so I could not run vitest. Instead I exercised each library directly with Node's native TypeScript stripping, against independent references where one exists — 147 assertions, all passing:merkle-sha256node:cryptoSHA-256 computed independently — leaf/node hashes, roots, and the promotion-vs-duplication root all cross-checkedsoroban-storage-modelconsensus-simulator(q/p)^depthclosed form, SCP invariantsxdr-inspector@stellar/stellar-sdkv14 — installed separately to confirm the API surface and round-trip actual envelopesThe four vitest files mirror those assertions and are written in the repo's existing convention (
vitest,src/lib/__tests__/), but have not been executed here — worth a CI run.The pages themselves are not type-checked, for the same missing-toolchain reason. I verified the SDK method names I depend on (
Operation.invokeContractFunction,StrKey.encodeContract, etc.) against the installed v14 package rather than assuming them.