Skip to content

Add support for pay to anchor outputs#4111

Merged
apoelstra merged 1 commit intorust-bitcoin:masterfrom
ErikDeSmedt:erikdesmedt/p2a
Feb 28, 2025
Merged

Add support for pay to anchor outputs#4111
apoelstra merged 1 commit intorust-bitcoin:masterfrom
ErikDeSmedt:erikdesmedt/p2a

Conversation

@ErikDeSmedt
Copy link
Copy Markdown
Contributor

Add support for the newly created Pay2Anchor output-type which was introduced in bitcoin 28.0

See bitcoin/bitcoin#30352

@github-actions github-actions bot added the C-bitcoin PRs modifying the bitcoin crate label Feb 24, 2025
@coveralls
Copy link
Copy Markdown

coveralls commented Feb 24, 2025

Pull Request Test Coverage Report for Build 13561507629

Details

  • 21 of 25 (84.0%) changed or added relevant lines in 3 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.009%) to 82.734%

Changes Missing Coverage Covered Lines Changed/Added Lines %
bitcoin/src/address/mod.rs 16 17 94.12%
bitcoin/src/blockdata/script/witness_program.rs 3 6 50.0%
Totals Coverage Status
Change from base Build 13554993820: 0.009%
Covered Lines: 21218
Relevant Lines: 25646

💛 - Coveralls

Copy link
Copy Markdown
Collaborator

@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

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

Concept ACK, the code looks good too except for one issue.

Comment thread bitcoin/src/address/script_pubkey.rs Outdated
// In SegWit v0, the program must be either 2, 20 or 32 bytes long
debug_assert!(
version != WitnessVersion::V0 ||
program.len() == 2 || program.len() == 20 || program.len() == 32);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I believe this is incorrect. P2A is WitnessVersion::V1.

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.

Correct, I think we need a separate assertion for Segwit v1 witness programs ( P2TR, P2A)
Something like this:

// In SegWit v0, the program must be either 20 or 32 bytes long (P2WPKH/P2WSH)
debug_assert!(version != WitnessVersion::V0 || program.len() == 20 || program.len() == 32);
// In SegWit v1, the program must be either 2 bytes (P2A) or 32 bytes (P2TR)
debug_assert!(version != WitnessVersion::V1 || program.len() == 2 || program.len() == 32);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Yes, that makes sense.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks, this is a great catch. I've adapted the PR

Kixunil
Kixunil previously approved these changes Feb 25, 2025
Copy link
Copy Markdown
Collaborator

@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

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

ACK 34cce11

If you're in the mood you could also check if this can be backported backwards-compatibly. I have an application in mind that could use it.

}

/// Constructs a new pay to anchor address
pub fn p2a() -> Self {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it might be possible to make it const but that might require some modifications to ArrayVec, so I'm not requiring it. Similarly, we could have a const on Script, but that's just extra, so not required.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This was easier as expected. Apprantly ArrayVec::from_slice is already const.

// Verify that the address is considered standard
// and that the output type is P2a
assert!(address.is_spend_standard());
assert_eq!(address.address_type(), Some(AddressType::P2a));
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Testing address.to_string() would be nice too.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've added a comparision for address.to_string()

@ErikDeSmedt ErikDeSmedt force-pushed the erikdesmedt/p2a branch 2 times, most recently from ab0eaeb to 83d7ebb Compare February 25, 2025 13:09
Copy link
Copy Markdown
Collaborator

@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

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

ACK 83d7ebb

tcharding
tcharding previously approved these changes Feb 25, 2025
Copy link
Copy Markdown
Member

@tcharding tcharding left a comment

Choose a reason for hiding this comment

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

ACK 83d7ebb

@tcharding
Copy link
Copy Markdown
Member

Thanks for the contribution!

I created a follow up issue to this PR: #4124. I did so intentionally instead of asking for changes so as not to slow down this PR. We appreciate the effort you went to. You are most welcome to attack the follow up but do not feel obliged.

Thanks again!

Copy link
Copy Markdown
Collaborator

@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

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

Some thoughts crossed my mind and I did some more digging. Unfortunately, this is not right.

pub const MAX_SIZE: usize = 40;

/// The P2A program which is given by 0x4e73
pub const P2A_PROGRAM: [u8;2] = [78, 115];
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Oh, I have now noticed this is public. I don't think it's very helpful and adds noise to docs. I'd prefer to keep it private until there's a use case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I use the P2A_PROGRAM in another module. I have modified to pub(crate)

Comment thread bitcoin/src/address/script_pubkey.rs Outdated
// In SegWit v0, the program must be either 20 (P2WPKH) bytes or 32 (P2WSH) bytes long
debug_assert!(version != WitnessVersion::V0 || program.len() == 20 || program.len() == 32);
// In SegWit v1, the program must be either 2 bytes (P2A) or 32 bytes (P2TR)
debug_assert!(version != WitnessVersion::V1 || program.len() == 2 || program.len() == 32);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I've just realized this entire check is bogus and should be deleted. For witness versions > 0 receiving is standard to ensure future compatibility but this check (even if in debug) undermines that compatibility. It's also the reason it wasn't here in the first place. (And perhaps a reason to write a comment "other versions intentionally not checked" to avoid this mistake again.) The check only makes sense for v0 because that one makes different lengths unspendable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I have removed the check

apoelstra
apoelstra previously approved these changes Feb 26, 2025
Copy link
Copy Markdown
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK 83d7ebb; successfully ran local tests

Add support for the newly created Pay2Anchor output-type.

See bitcoin/bitcoin#30352
Copy link
Copy Markdown
Collaborator

@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

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

ACK f7ea6e5

Copy link
Copy Markdown
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK f7ea6e5; successfully ran local tests

@apoelstra apoelstra merged commit 6518125 into rust-bitcoin:master Feb 28, 2025
tcharding added a commit to tcharding/rust-bitcoin that referenced this pull request Jul 8, 2025
Manually backport PR rust-bitcoin#4111. Of note, here we put `new_p2a` on
`ScriptBuf` instead of on the `script::Builder` because that seems to
be where all the other `new_foo` methods are in this release. 
    
From the original patch:

    Add support for the newly created Pay2Anchor output-type.
    
    See bitcoin/bitcoin#30352
tcharding added a commit to tcharding/rust-bitcoin that referenced this pull request Jul 10, 2025
Manually backport PR rust-bitcoin#4111. Of note, here we put `new_p2a` on
`ScriptBuf` instead of on the `script::Builder` because that seems to
be where all the other `new_foo` methods are in this release. 

Note the `WitnessProgram::p2a` is conditionally const on Rust `v1.61`
because MSRV is only `v1.56.1`.
    
From the original patch:

    Add support for the newly created Pay2Anchor output-type.
    
    See bitcoin/bitcoin#30352
tcharding added a commit to tcharding/rust-bitcoin that referenced this pull request Jul 16, 2025
Manually backport PR rust-bitcoin#4111. Of note, here we put `new_p2a` on
`ScriptBuf` instead of on the `script::Builder` because that seems to
be where all the other `new_foo` methods are in this release. 

Note the `WitnessProgram::p2a` is conditionally const on Rust `v1.61`
because MSRV is only `v1.56.1`.
    
From the original patch:

    Add support for the newly created Pay2Anchor output-type.
    
    See bitcoin/bitcoin#30352
apoelstra added a commit that referenced this pull request Jul 16, 2025
c2481e4 backport: Add support for pay to anchor outputs (Tobin C. Harding)

Pull request description:

  Manually backport PR #4111. Of note, here we put `new_p2a` on `ScriptBuf` instead of on the `script::Builder` because that seems to be where all the other `new_foo` methods are in this release. 
      
  From the original patch:
  
      Add support for the newly created Pay2Anchor output-type.
      
      See bitcoin/bitcoin#30352


ACKs for top commit:
  apoelstra:
    ACK c2481e4; successfully ran local tests


Tree-SHA512: 016919914750adf6f8226acb4e6b36c0dcd8ce230df8cca13f19bcc97709caf07a076be367c76f9519a421fc93fdf73caa078ee65a85a750af7a9d9e6c757e75
yancyribbens pushed a commit to yancyribbens/rust-bitcoin that referenced this pull request Dec 3, 2025
Manually backport PR rust-bitcoin#4111. Of note, here we put `new_p2a` on
`ScriptBuf` instead of on the `script::Builder` because that seems to
be where all the other `new_foo` methods are in this release. 

Note the `WitnessProgram::p2a` is conditionally const on Rust `v1.61`
because MSRV is only `v1.56.1`.
    
From the original patch:

    Add support for the newly created Pay2Anchor output-type.
    
    See bitcoin/bitcoin#30352
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-bitcoin PRs modifying the bitcoin crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants