Skip to content

descriptor: support hash terminals in WalletPolicy translator#935

Open
bg002h wants to merge 1 commit intorust-bitcoin:masterfrom
bg002h:fix/wallet-policy-hash-terminals
Open

descriptor: support hash terminals in WalletPolicy translator#935
bg002h wants to merge 1 commit intorust-bitcoin:masterfrom
bg002h:fix/wallet-policy-hash-terminals

Conversation

@bg002h
Copy link
Copy Markdown

@bg002h bg002h commented Apr 30, 2026

WalletPolicyTranslator rejects hash terminals (sha256 / hash256 / ripemd160 / hash160) because both directions use translate_hash_fail!. BIP 388 places no restriction on them; HTLC patterns are a primary use case. This PR adds explicit implementations bridging KeyExpression's hex String storage and DescriptorPublicKey's binary Hash types, with a new WalletPolicyError::TranslatorInvalidHashHex variant for the parse direction.

Found while building md-codec, a BIP 388 wallet-policy encoder.

Authored by Claude Opus 4.7 under my direction.

Copy link
Copy Markdown
Contributor

@trevarj trevarj left a comment

Choose a reason for hiding this comment

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

Another oversight by me in the BIP388 implementation!

This does make sense and should not error when hashes are in the descriptor template.

I wonder if the tests can be made a little more concise. They seem overly verbose to test such a simple thing...perhaps I'm just getting replaced by Claude...

@trevarj
Copy link
Copy Markdown
Contributor

trevarj commented Apr 30, 2026

Oh yeah...it would be nice if this is committed by you instead of Claude. Just my opinion though, I don't know how Andrew feels about that.

@bg002h
Copy link
Copy Markdown
Author

bg002h commented Apr 30, 2026

I can apologize via Claude too, and I’m sure it would do it better!

That said, Claude was totally comfortable posting as if it were me…I added the human tag at the bottom by telling Claude it can’t pretend to be human.

That said, as best I can tell this is a real enough issue to be passed along in a “don’t just complain, do something” fashion.

@apoelstra
Copy link
Copy Markdown
Member

If Claude writes stuff I strongly prefer it identify as itself rather than as a human. (Identifying as a human "helped by Claude" or "co-authored by Claude" is also fine.)

But can you reduce the amount of text in your commit message and in your PR description? It may be sufficient to just tell Claude to be concise and to assume that the reader is an expert on the codebase.

CI failures are real -- and annoyingly you will have to wait for me to show up and click "Approve CI run" to get that feedback -- can you fix the formatting and the no-std gating?

@bg002h
Copy link
Copy Markdown
Author

bg002h commented May 3, 2026

I told claude AP had some feedback and it literally ingested your words as commands and is busily applying your feedback.

I’ll let Claude give a whack at this revision and if it continues to spit out text walls with kernels of truth disguised therein, I’ll bow out and just let Claude prepare locally applied patches in Claude-crappy fashion to make my proof of concept project function.

I’ve never programmed in rust and I’m at best a high school level pascal programmer, and tokens are cheaper than time in my current world…so I apologize for not recognizing it’s crappy output on account of my vague understanding!

@bg002h bg002h force-pushed the fix/wallet-policy-hash-terminals branch from dbfe077 to 8c101fb Compare May 3, 2026 06:21
@bg002h
Copy link
Copy Markdown
Author

bg002h commented May 3, 2026

Thanks both. Addressed:

  • CI fmt + no-std: ran cargo fmt; switched the module to use crate::prelude::* so ToString is in scope under --no-default-features (matches the pattern in descriptor/{key,bare,checksum}.rs). cargo build --no-default-features clean locally.
  • Test verbosity: collapsed the 6 hash-terminal tests into 3 — a parameterized round-trip across all 4 hash kinds, one mixed-pair guard against cross-type interference, and a compact macro-driven invalid-hex variant pin. Net −189 lines in the diff.
  • Commit message + PR body: trimmed both; assumed expert reader.
  • Attribution: Claude is named in the Co-Authored-By trailer and the PR body. Happy to adjust the wording further if you'd prefer a different form.

Ready for another CI run when you have a moment.

— Brian (with Claude Opus 4.7)

@apoelstra
Copy link
Copy Markdown
Member

8c101fb needs rebase

Copy link
Copy Markdown
Contributor

@trevarj trevarj left a comment

Choose a reason for hiding this comment

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

I’ve never programmed in rust and I’m at best a high school level pascal programmer, and tokens are cheaper than time in my current world…so I apologize for not recognizing it’s crappy output on account of my vague understanding!

No need to get existential, i'm already worried about my future in programming 😅

Looks pretty good now.

Comment thread src/descriptor/wallet_policy/mod.rs Outdated
use super::key::XKeyParseError;
use super::{DerivPaths, DescriptorKeyParseError, Wildcard};
use crate::{BTreeSet, Descriptor, DescriptorPublicKey, String, Translator, Vec};
use crate::prelude::*;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This import is unneeded. Compiles without it for me.

Comment thread src/descriptor/wallet_policy/mod.rs Outdated
Comment on lines +463 to +464
<WalletPolicyTranslator as Translator<KeyExpression>>::$method(&mut t, &bad)
.unwrap_err();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit:

Suggested change
<WalletPolicyTranslator as Translator<KeyExpression>>::$method(&mut t, &bad)
.unwrap_err();
let err = Translator::<KeyExpression>::$method(&mut t, &bad).unwrap_err();

@bg002h bg002h force-pushed the fix/wallet-policy-hash-terminals branch from 8c101fb to 9fda9e1 Compare May 3, 2026 20:31
@tcharding
Copy link
Copy Markdown
Member

tcharding commented May 3, 2026

Authored by Claude Opus 4.7 under my direction.

Something like this might actually be useful to enforce. If any PR comes in and the author has no clue what they are doing and states as such up front it is way easier for us to review because we can decide, before looking, if it would be quicker/easier to do the work ourself than go through all the reviews. Especially if its a bug or feature that seems legit, we don't want to just ban uneducated devs wielding LLMs we just want to get the best out of everyones time, right?

@trevarj
Copy link
Copy Markdown
Contributor

trevarj commented May 4, 2026

Authored by Claude Opus 4.7 under my direction.

Something like this might actually be useful to enforce. If any PR comes in and the author has no clue what they are doing and states as such up front it is way easier for us to review because we can decide, before looking, if it would be quicker/easier to do the work ourself than go through all the reviews. Especially if its a bug or feature that seems legit, we don't want to just ban uneducated devs wielding LLMs we just want to get the best out of everyones time, right?

Indeed...probably would make sense to enforce having Claude/LLM write an issue first and then it can be triaged appropriately.

@apoelstra
Copy link
Copy Markdown
Member

Please make Clippy happy.

`WalletPolicyTranslator` used `translate_hash_fail!` in both directions,
so `WalletPolicy::{from,into}_descriptor` rejected any descriptor with a
sha256/hash256/ripemd160/hash160 terminal. BIP 388 places no restriction
on hash terminals (HTLC patterns are a primary use case).

Implement the four hash methods explicitly. The two key types use
different hash representations — `KeyExpression` stores hex `String`
(for template round-tripping); `DescriptorPublicKey` uses the binary
`bitcoin::hashes::*::Hash` types — so the translator parses or
`Display`s across the two.

A new `WalletPolicyError::TranslatorInvalidHashHex(&'static str, String)`
variant covers the parse-direction failure. The public parser already
validates hex up-front, so the variant is reachable only via the
private translator API; a test pins it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bg002h bg002h force-pushed the fix/wallet-policy-hash-terminals branch from 9fda9e1 to 2092faa Compare May 5, 2026 05:17
@bg002h
Copy link
Copy Markdown
Author

bg002h commented May 6, 2026

Authored by Claude Opus 4.7 under my direction.

Something like this might actually be useful to enforce. If any PR comes in and the author has no clue what they are doing and states as such up front it is way easier for us to review because we can decide, before looking, if it would be quicker/easier to do the work ourself than go through all the reviews. Especially if its a bug or feature that seems legit, we don't want to just ban uneducated devs wielding LLMs we just want to get the best out of everyones time, right?

Indeed...probably would make sense to enforce having Claude/LLM write an issue first and then it can be triaged appropriately.

+1 on the triage idea. Maybe with a mandatory 20 word summary (AI gets wordy when user requests max effort). A repo specific set of initial commands for model would help (simple commands like “Do not file an issue without first searching PRs and Issues” and “do not file a pull request unless specifically requested or other condition.”)

also, as best I can tell “clippy” is happy status post last push…Claude is telling me to say “clippy clean locally now (default + all-features + no-default-features); can you approve a CI re-run?”

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants