Skip to content

multi: recognize new standard P2A output type #2433

Open
Roasbeef wants to merge 8 commits intobtcsuite:masterfrom
Roasbeef:p2a
Open

multi: recognize new standard P2A output type #2433
Roasbeef wants to merge 8 commits intobtcsuite:masterfrom
Roasbeef:p2a

Conversation

@Roasbeef
Copy link
Copy Markdown
Member

In this PR, we add initial recognition of the new P2A output type. It actually overloads the existing Taproot witness version, but with a distinct witness program. We adopt the proposed standardness rules to make only spends without any witness data standard. Utilities to parse the script, make addresses, etc - have also been added.

Note that this doesn't include the logic to support "ephemeral dust", which enables zero fee and zero value outputs under certain conditions.

A replace dir is used as we modified btcutil in this PR.

@coveralls
Copy link
Copy Markdown

coveralls commented Sep 27, 2025

Pull Request Test Coverage Report for Build 20117557279

Details

  • 101 of 111 (90.99%) changed or added relevant lines in 6 files are covered.
  • 127 unchanged lines in 8 files lost coverage.
  • Overall coverage increased (+0.4%) to 55.171%

Changes Missing Coverage Covered Lines Changed/Added Lines %
txscript/pkscript.go 1 2 50.0%
txscript/sign.go 0 1 0.0%
mempool/policy.go 28 30 93.33%
txscript/standard.go 24 30 80.0%
Files with Coverage Reduction New Missed Lines %
btcutil/bech32/bech32.go 1 99.61%
btcutil/bloom/filter.go 2 96.84%
btcutil/gcs/gcs.go 2 81.25%
txscript/taproot.go 2 97.74%
database/ffldb/blockio.go 4 88.81%
peer/peer.go 15 71.1%
rpcclient/infrastructure.go 38 47.99%
btcec/schnorr/musig2/context.go 63 80.17%
Totals Coverage Status
Change from base Build 20117517710: 0.4%
Covered Lines: 31296
Relevant Lines: 56725

💛 - Coveralls

Copy link
Copy Markdown
Collaborator

@sputn1ck sputn1ck left a comment

Choose a reason for hiding this comment

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

LGTM!

Comment thread txscript/pkscript.go Outdated
return nil, fmt.Errorf("unable to parse address: %v", err)
}

// P2A scripts don't have addresses.
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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Looks like a stray line, but ExtractPkScriptAddrs should handle that. Will add a test for this.

@Roasbeef Roasbeef requested a review from yyforyongyu October 27, 2025 23:06
@Roasbeef Roasbeef changed the base branch from master to v3-tx-standard December 11, 2025 00:18
Comment thread txscript/standard.go
nilAddrErrStr)
}
return payToWitnessTaprootScript(addr.ScriptAddress())
case *btcutil.AddressPayToAnchor:
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.

nit

btcutil.AddressPayToAnchor isn't introduced until commit 3f99cfe0a9b0ed9a33e0c11136127e8b6e2906ea.

So this commit doesn't build.

Comment thread txscript/p2a_test.go
Comment thread go.mod

go 1.23.2

replace github.com/btcsuite/btcd/btcutil => ./btcutil
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.

Are we ok with this or is this temporary?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is temp. It's needed as we ref the newly added addr type in txscript/standard.go.

#1825 will resolve this circualr dep module issue. After this is merged, I'll be ale to update the module dep, then remove this.

Comment thread btcutil/p2a_address_test.go Outdated
Comment thread btcutil/p2a_address_test.go Outdated
Comment thread btcutil/p2a_address_test.go Outdated
Comment thread btcutil/p2a_address_test.go Outdated
Comment thread btcutil/address.go Outdated
@Roasbeef
Copy link
Copy Markdown
Member Author

@kcalvinalvin PTAL

@Roasbeef Roasbeef changed the base branch from v3-tx-standard to master December 18, 2025 02:15
Comment thread btcutil/address.go
Comment thread btcutil/p2a_address_test.go
Comment thread txscript/standard.go Outdated
Comment thread txscript/p2a_test.go Outdated
Comment thread txscript/p2a_test.go
Comment thread mempool/policy_test.go
@kcalvinalvin
Copy link
Copy Markdown
Collaborator

Most things look good. But ExtractPkScriptAddrs not returning an address for P2A should be fixed before this gets merged.

Things done:

  1. Went through each of the commits again to sanity check the changes.
  2. Checked that the implementation here aligns with BIP-433.
  3. Checked that the tests make sense in each of the commits.

Comment thread go.mod
Comment thread mempool/policy.go
// of the relay fee. This optimization avoids the more complex
// calculation below.
if txscript.IsPayToAnchorScript(txOut.PkScript) {
return txOut.Value < 240
Copy link
Copy Markdown
Collaborator

@yyforyongyu yyforyongyu Apr 27, 2026

Choose a reason for hiding this comment

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

This hard-codes P2A dust at 240 sats regardless of minRelayTxFee. That matches the default P2A dust threshold because the existing witness dust formula already evaluates to 240 sats at the default rate, but it changes configured relay policy: with a zero relay fee, 239-sat P2A is still dust, and with a high relay fee, 240-sat P2A is still non-dust. Bitcoin Core still derives the threshold from the supplied dust relay feerate, so I think this should use the existing fee-sensitive dust calculation rather than special-casing IsDust.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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.

Then what if people decide to increase/decrease it? Also just realized in btcd we are missing the config -dustrelayfee, similar to what bitcoind has https://github.com/bitcoin/bitcoin/blob/859215218667ca9f35d5adae0289e4a125798087/src/policy/policy.h#L63-L68

Comment thread btcutil/address.go
Comment thread txscript/standard.go
Comment thread integration/p2a_test.go
Comment thread btcutil/address.go
Comment thread txscript/standard.go
Comment thread integration/p2a_test.go
Comment thread mempool/policy.go
// of the relay fee. This optimization avoids the more complex
// calculation below.
if txscript.IsPayToAnchorScript(txOut.PkScript) {
return txOut.Value < 240
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.

Then what if people decide to increase/decrease it? Also just realized in btcd we are missing the config -dustrelayfee, similar to what bitcoind has https://github.com/bitcoin/bitcoin/blob/859215218667ca9f35d5adae0289e4a125798087/src/policy/policy.h#L63-L68

Comment thread btcutil/address.go
witnessProg, []byte{0x4e, 0x73},
) {
return &AddressPayToAnchor{
hrp: hrp,
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.

This stores the HRP directly from the input prefix, unlike the other segwit address constructors that normalize decoded HRPs to lowercase. A valid all-uppercase P2A address such as BC1PFEESSRAWGF will decode, and EncodeAddress() will re-emit lowercase, but IsForNet(&chaincfg.MainNetParams) returns false because the stored HRP is BC instead of bc.

Can we normalize the HRP here, or use the lowercase HRP returned by bech32 decoding, and add uppercase decode coverage?

In this commit, we modify the execution logic, such that the P2A witness
program doesn't appear as a unknown witness program version. For
execution, we just make sure the script passes.
P2A is standard if the witness and the sigscript is empty. We make a
smol refactor to be able to write a unit test for the input
standardness.
We make sure it'll be accepted into the mempool, and can be spent
without a witness.
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.

6 participants