Skip to content

Comments

feat: add BIP353 DNS payment instructions#236

Open
sdmg15 wants to merge 1 commit intobitcoindevkit:masterfrom
sdmg15:feat/bip353-payment-instructions
Open

feat: add BIP353 DNS payment instructions#236
sdmg15 wants to merge 1 commit intobitcoindevkit:masterfrom
sdmg15:feat/bip353-payment-instructions

Conversation

@sdmg15
Copy link

@sdmg15 sdmg15 commented Jan 7, 2026

Description

This PR adds support for BIP353 payment instructions.
The following notable changes are done:

  • Adding of an option resolve_dns_recipient which receives a Human Readable Name (HRN) and returns the associated address
  • Modify the create_tx for it to support user specifying recipients as HRN.

Notes to the reviewers

Here is a list of HRN that could be used to test the implementation:

  • pay@dunxen.dev: Supports BOLT 12 Payment method only
  • send.some@satsto.me: Supports BOLT 12 payment and On Chain
  • Testing resolving: bdk-cli -n bitcoin resolve_dns_recipient send.some@satsto.me
  • Testing create tx: bdk-cli -n bitcoin wallet -w regtest_default_wallet create_tx --to "bcrt1qe497k549sgw9trzym50tdlegq3xx4apjqynjqm:1000" --to_dns "send.some@satsto.me:5000"

Changelog notice

  • Add top level command resolve_dns_recipient to resolve the DNS payment instructions
  • Add option --to_dns to create_tx command to allow sending to a Human Readable Name (HRN)

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature
  • I've updated CHANGELOG.md

@sdmg15 sdmg15 force-pushed the feat/bip353-payment-instructions branch from ba3c713 to a0f3e9d Compare January 8, 2026 18:13
@sdmg15 sdmg15 marked this pull request as ready for review January 9, 2026 08:39
@va-an
Copy link
Contributor

va-an commented Feb 7, 2026

@sdmg15 Hi! Could you make it compile?

@sdmg15 sdmg15 force-pushed the feat/bip353-payment-instructions branch 2 times, most recently from 49154f3 to baf349b Compare February 9, 2026 08:51
@coveralls
Copy link

Pull Request Test Coverage Report for Build 21818410493

Details

  • 0 of 120 (0.0%) changed or added relevant lines in 3 files are covered.
  • 1 unchanged line in 1 file lost coverage.
  • Overall coverage decreased (-0.5%) to 10.237%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/utils.rs 0 15 0.0%
src/handlers.rs 0 36 0.0%
src/dns_payment_instructions.rs 0 69 0.0%
Files with Coverage Reduction New Missed Lines %
src/handlers.rs 1 12.57%
Totals Coverage Status
Change from base Build 21153868360: -0.5%
Covered Lines: 268
Relevant Lines: 2618

💛 - Coveralls

@sdmg15 sdmg15 force-pushed the feat/bip353-payment-instructions branch from baf349b to 0e9756e Compare February 11, 2026 04:52
@sdmg15
Copy link
Author

sdmg15 commented Feb 11, 2026

@va-an Thanks for taking a look. I think it should be resolved now.

Copy link
Contributor

@va-an va-an left a comment

Choose a reason for hiding this comment

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

Thanks for working on this @sdmg15!
I have left a few suggestions, please have a look.

@sdmg15 sdmg15 force-pushed the feat/bip353-payment-instructions branch from 0e9756e to 6724be5 Compare February 13, 2026 09:21
@sdmg15
Copy link
Author

sdmg15 commented Feb 13, 2026

@va-an Applied some reviews and recommendation on 6724be5

I've also updated the PR description.

@sdmg15 sdmg15 force-pushed the feat/bip353-payment-instructions branch from 6724be5 to 20ef094 Compare February 13, 2026 11:46
Copy link
Contributor

@va-an va-an left a comment

Choose a reason for hiding this comment

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

@sdmg15 thanks for update and for the detailed description!
Please take a look at the comments.

@sdmg15 sdmg15 force-pushed the feat/bip353-payment-instructions branch from 20ef094 to 977534a Compare February 17, 2026 20:05
Copy link
Contributor

@va-an va-an left a comment

Choose a reason for hiding this comment

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

@sdmg15 thanks for update!
I've added some suggestions, pls have a look.


#[cfg(feature = "dns_payment")]
/// Parse dns recipients in the form "test@me.com:10000" from cli input
pub(crate) fn parse_dns_recipients(s: &str) -> Result<(String, u64), String> {
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be better to rename it to parse_dns_recipient, because the function parses one recipient at a time.

Comment on lines +25 to +27
pub fn display(&self, pretty: bool) -> Result<String, Error> {
let mut methods: Vec<String> = Vec::new();
self.payment_methods.iter().for_each(|pm| match pm {
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like you forgot to run cargo fmt 🙂 , please do so.

Comment on lines +134 to +136
#[cfg(feature = "dns_payment")]
/// Resolves the given hrn payment instructions
ResolveDnsRecipient { hrn: String , resolver: Option<String>},
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
#[cfg(feature = "dns_payment")]
/// Resolves the given hrn payment instructions
ResolveDnsRecipient { hrn: String , resolver: Option<String>},
#[cfg(feature = "dns_payment")]
/// Resolves BIP-353 DNS payment instructions for a human-readable name.
ResolveDnsRecipient {
/// Human-readable name (e.g. user@domain.com)
hrn: String,
/// DNS resolver address
#[arg(long, default_value = "8.8.8.8")]
resolver: String,
},

This will make --help more useful:

-> % cargo run --all-features -- -n bitcoin resolve_dns_recipient --help
Resolves BIP-353 DNS payment instructions for a human-readable name

Usage: bdk-cli resolve_dns_recipient [OPTIONS] <HRN>

Arguments:
  <HRN>  Human-readable name (e.g. user@domain.com)

Options:
      --resolver <RESOLVER>  DNS resolver address [default: 8.8.8.8]
      --pretty               Output results in pretty format (instead of JSON)
  -h, --help                 Print help

Please note that the type for the resolver has changed.
See the suggested changes in the function itself.

Comment on lines +109 to +113

let mut ip_address = "8.8.8.8:53".to_string();
if let Some(res_addr) = resolver_ip {
ip_address = res_addr;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
let mut ip_address = "8.8.8.8:53".to_string();
if let Some(res_addr) = resolver_ip {
ip_address = res_addr;
}
let ip_address = if resolver_ip.contains(':') {
resolver_ip
} else {
format!("{resolver_ip}:53")
};

Please note that resolver_ip should be passed to this function as a String (not Option<String>), because we added a default_value in commands.rs, as proposed here.

Also, in this suggestion I slightly changed the semantics — the user can provide an IP without a port (port 53 will be used), or with a port (the user-specified port will be used). In the vast majority of cases, a DNS server uses the standard port, so we can simplify this a bit for the user.

The error message when creating DNSHrnResolver needs to be updated, since the user may provide an invalid value and receive a confusing "Should not fail" error.

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

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

3 participants