store: parent edges for pruned explorer links - #683
Open
rearden-grok[bot] wants to merge 9 commits into
Open
rearden-grok[bot] wants to merge 9 commits into
rearden-grok[bot] wants to merge 9 commits into
Conversation
| let Some(edges) = query.store().input_edges(tx_fk)? else { | ||
| return Ok(None); | ||
| }; | ||
| let mut vin = Vec::with_capacity(edges.len()); |
| q.set_pruneheight(Some(Height(0))).unwrap(); | ||
| let mut spend_txid = [0u8; 32]; | ||
| spend_txid[31] = 0xee; | ||
| let h1_hash = rbitcoin_store::block_header_hash(1, &merkle, &spend_txid, 2, 0x207fffff, 0); |
| assert_eq!(v["pruned"], true); | ||
| assert!(v.get("vin").is_none(), "pruned JSON omits vin: {v}"); | ||
| assert_eq!(v["vin"][0]["is_coinbase"], true); | ||
| assert!(v["vin"][0].get("witness").is_none(), "{v}"); |
| assert!(v.get("vin").is_none(), "pruned JSON omits vin: {v}"); | ||
| assert_eq!(v["vin"][0]["is_coinbase"], true); | ||
| assert!(v["vin"][0].get("witness").is_none(), "{v}"); | ||
| assert!(v["vin"][0].get("scriptsig").is_none(), "{v}"); |
| assert!(v["vin"][0].get("witness").is_none(), "{v}"); | ||
| assert!(v["vin"][0].get("scriptsig").is_none(), "{v}"); | ||
| let sv = build_tx_json(&q, spend_fk, Network::Regtest).unwrap(); | ||
| assert_eq!(sv["pruned"], true, "{sv}"); |
| assert_eq!(sv["vin"][0]["txid"], block_hash_hex(&txid)); | ||
| assert_eq!(sv["vin"][0]["vout"], 0); | ||
| assert_eq!(sv["vin"][0]["is_coinbase"], false); | ||
| assert!(sv["vin"][0].get("witness").is_none(), "{sv}"); |
| let raw = build_tx_json(&q, fk, Network::Regtest).unwrap(); | ||
| assert_eq!(raw["pruned"], true); | ||
| assert!(raw.get("vin").is_none(), "{raw}"); | ||
| assert_eq!(raw["vin"][0]["is_coinbase"], true, "{raw}"); |
inputs.loc stores n_in and inputs.body stores one 8-byte parent create_fk plus vout per input, in vin order. Class A append writes that edge with txstat. A coinbase is a null parent. n_in remains in the txstat cell until the cell is narrowed.
The 8-byte econ cell is fee, base size, and witness extra. Input count for getblockstats, txout overlay, and the multi-input coinbase hint comes from the parent-edge locator. A row that used to overflow because of the n_in byte now fits; a wide fee and size still tails.
A pruned transaction JSON lists each input's parent txid and vout, and the parent output value and script from txout. scriptSig, witness, and sequence stay absent.
Sequence, scriptSig, and witness stay in seqsigwit. Open renames a leftover inwit stem in place. txstat and inputs live in the same directory as that stem, including under --datadir-cold.
A datadir that already has creates but no inputs.loc recovers parent links by walking seqsigwit prevouts once. The locator probe runs after that fill, so a missing stem is not NotFound. Four-field txstat cells from the unreleased experiment stay a resync.
rearden-grok
Bot
force-pushed
the
store/txfixed
branch
from
September 22, 2026 16:10
5770f06 to
512fe02
Compare
rearden-grok
Bot
force-pushed
the
store/inputs-edge
branch
from
September 22, 2026 16:10
9b8e8d8 to
f2b85b0
Compare
Inputs::append_unstamped scored CRAP 132 with no caller in tests, which failed the coverage job above 30. The test walks a zero count, a window checkpoint, and a later real edge.
New records are sequence, scriptSig, and witness. Flag bit 4 marks that the parent edge lives on inputs.body, and loads stamp it back onto the in-memory input. A record without that bit is still the legacy inline prevout, so a 0.7 datadir can backfill.
The other Class A stems are singular. inputs.loc, inputs.off, and inputs.body become input.*. Kind ids 22 and 23 stay. Open renames a leftover inputs.* stem.
decode_prevout_at scored CRAP 38.5 after the parent edge left the record. The sequence, script, and witness skip is its own functions.
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
Stacked on #659 (
store/txfixed). Amends unreleased schema 25. Do not merge #659 until this series is in the same ship, so master never shipsn_ininsidetxstat.body. No bump to 26.inputs.locisn_inas u16 per create (0= unstamped).n_in > u16::MAXis Corrupt.inputs.bodyis 8 bytes per input in vin order: parentcreate_fk(u40,0= coinbase) and parent vout (u24). The spending vin is the record index (spent.bodyalready stores it).inputs.offcheckpoints every 1024 creates. Confirm appends the edge with Class A. Skew truncate drops it with the other stems.txstat.bodystays 8 bytes: three ULEBs (fee_sat,base,wit_extra). Ordinary large-fee or large-witness rows no longer overflow. A still-too-wide fee plus size still tails (txstat.ovf/txstat.blk). All-zero is unstamped.n_in(the earlier unreleased 25 experiment) is not detected and is not rewritten. Resync that datadir.getblockstatsinsand the range-load coinbase hint readn_infrominputs.locwhen the txout meta count is 0.vinis the parent txid, vout, and prevout value/script. scriptSig, witness, and sequence stay omitted. Child links stay onspent.body.inwitis renamed toseqsigwit(sequence, scriptSig, witness). Table kind id stays 16. Open renames existinginwit.*files in place (same bytes).txstat.*andinputs.*live next toseqsigwit, on the cold datadir when--datadir-coldis set. A split store that still has those stems only on the hot dir is a layout error.inputsandtxstatare not pruned. The 288-height window applies only toseqsigwit.inputs.loc, and a matchingseqsigwitcount backfills the parent edges fromseqsigwitprevouts (decode_prevout_at). A null parent becomes the coinbase edge (vout 0).Test plan
cargo test -p rbitcoin-store --lib reopen_backfills_inputs_from_seqsigwitcargo test -p rbitcoin-store --lib inputs_n_in_scans_both_prevoutscargo clippy -p rbitcoin-store --lib -- -D warningsDo not merge unless asked.