Skip to content

Conversation

luke-jr
Copy link
Member

@luke-jr luke-jr commented Jun 30, 2025

Feature requested by @SomberNight for Electrum's Lightning stuff. (Please confirm this does what you need)

Unfortunately WIP because the wtxid merkle root calculation doesn't match and I don't have time to figure out why not yet (maybe after concept ACK? or if anyone else wants to take a look...)

Mostly backward compatible, but a segwit-enabled proof will verify the generation tx in old versions.

@DrahtBot
Copy link
Contributor

DrahtBot commented Jun 30, 2025

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Code Coverage & Benchmarks

For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/32844.

Reviews

See the guideline for information on the review process.

Type Reviewers
Concept ACK Sjors

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #33116 (refactor: Convert uint256 to Txid by marcofleon)
  • #33094 (refactor: unify container presence checks by l0rinc)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

LLM Linter (✨ experimental)

Possible typos and grammar issues:

  • In RPCResult description: "If verify_witness is true and the proof invalid" -> "If verify_witness is true and the proof is invalid" [missing “is” makes the sentence ungrammatical]

No other typos were found.

drahtbot_id_4_m

@SomberNight
Copy link
Contributor

SomberNight commented Jul 1, 2025

Feature requested by @SomberNight for Electrum's Lightning stuff. (Please confirm this does what you need)

Wow, thank you for working on this! I was meaning to open an issue to ask for this, but did not even get to that yet.

The request I would like an electrum server, assuming txindex=1, to be able to serve is:

bc.tx.get_merkle_witness(txid), (so given just a txid,)

return a dict containing:

  • wtxid
  • block_height
  • block_hash
  • pos (index of tx in block)
  • merkle or wmerkle
    • exactly one of the two
    • merkle is the Satoshi-SPV proof, in case there is no witness commitment in the block
    • wmerkle is the witness-SPV proof otherwise
  • cb_tx, the generation/coinbase tx
  • cb_proof, the Satoshi-SPV proof for the generation tx

Obviously the electrum server can act as middleware and transform the response, assuming the necessary fields are available or obtainable.

As far as I can tell, but I haven't tried yet, the RPC response from this PR can be transformed to what I describe above. So the RPC looks to be doing what I need. :)


I think it is non-trivial, so let me detail how an electrum/light client would then use bc.tx.get_merkle_witness(txid):

  • it is assumed client already has a full raw tx, and wants to verify whether it has been mined
  • client also has full header chain, proof-of-work verified
  • client calls bc.tx.get_merkle_witness(txid)
  • client calculates wtxid of full tx it has, compares it with received wtxid
  • using cb_tx, cb_proof, block_height, block_hash
    • client Satoshi-SPVs the received coinbase tx, against block header merkle_root
  • client extracts witness_commitment from cb_tx
    1. if there is no witness_commitment,
      • client Satoshi-SPVs the txid, using merkle, block_height, block_hash, pos, against block header merkle_root
      • now client has an SPV guarantee that block only contains non-segwit txs, and tx in particular is also non-segwit (wtxid==txid) and it was mined in this block
    2. if there is a witness_commitment,
      • client must do witness-SPV, even if tx seems non-segwit (as e.g. malicious electrum server could have stripped away the witness)
      • client does witness-SPV using wmerkle and pos, against witness_commitment
      • client must check that length of wmerkle matches length of cb_proof. This ensures there are the same number of levels in the wtxid merkle tree and in the txid merkle tree. (the two trees should have the same number of leaves, but this seems hard to check as a light client) This is intended as some protection against merkle-tree-construction weaknesses (cf. banning of 64 byte transactions and similar).
  • now client has an SPV guarantee that wtxid was mined in this block
    • or if some check failed, then the client can connect to another server

@Sjors
Copy link
Member

Sjors commented Jul 1, 2025

Concept ACK. @SomberNight it's still useful if you open an issue to track the reason you need this, just in case this implementation PR doesn't make.

Copy link
Member

@Sjors Sjors left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took an initial look at the code, but got a bit confused. Will check again later.

@luke-jr luke-jr force-pushed the rpc_gettxoutproof_segwit branch from 3abfd6d to e826ffd Compare July 9, 2025 03:49
@luke-jr luke-jr marked this pull request as ready for review July 9, 2025 03:49
@luke-jr luke-jr force-pushed the rpc_gettxoutproof_segwit branch 2 times, most recently from e95981b to 4b3a33a Compare July 9, 2025 03:52
@luke-jr
Copy link
Member Author

luke-jr commented Jul 9, 2025

Reworked this to cover @SomberNight 's requirements and address feedback. Test is now passing.

@DrahtBot
Copy link
Contributor

🐙 This pull request conflicts with the target branch and needs rebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants