Skip to content

Conversation

ErikDeSmedt
Copy link
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

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
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.

// 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
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
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
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
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
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.

@@ -105,6 +108,11 @@ impl WitnessProgram {
WitnessProgram::new_p2tr(pubkey)
}

/// Constructs a new pay to anchor address
pub fn p2a() -> Self {
Copy link
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
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
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
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
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
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
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
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.

@@ -25,6 +25,9 @@ pub const MIN_SIZE: usize = 2;
/// The maximum byte size of a segregated witness program.
pub const MAX_SIZE: usize = 40;

/// The P2A program which is given by 0x4e73
pub const P2A_PROGRAM: [u8;2] = [78, 115];
Copy link
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
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)

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
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
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
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
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
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
24 checks passed
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
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