Skip to content

Conversation

@Roasbeef
Copy link
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

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

return nil, fmt.Errorf("unable to parse address: %v", err)
}

// P2A scripts don't have addresses.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
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
nilAddrErrStr)
}
return payToWitnessTaprootScript(addr.ScriptAddress())
case *btcutil.AddressPayToAnchor:
Copy link
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.

},
{
name: "invalid - wrong version",
script: []byte{OP_0, OP_DATA_2, 0x4e, 0x73},
Copy link
Collaborator

@kcalvinalvin kcalvinalvin Dec 12, 2025

Choose a reason for hiding this comment

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

Just a question: is OP_1 a version? Curious as to the test's name

nvm figured it out


go 1.23.2

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

otherNet = &chaincfg.TestNet3Params
}
if addr.IsForNet(otherNet) {
t.Errorf("IsForNet(other) = true, want false")
Copy link
Collaborator

Choose a reason for hiding this comment

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

What's this testing for? Why do we want to test "othernet-ness"

Copy link
Member Author

Choose a reason for hiding this comment

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

Just that IsForNet properly detects if an address isn't for the target network.

I agree it's a trivial test, tbh I did it just so the test coverage reported is higher.

t.Errorf("IsForNet(other) = true, want false")
}

expectedScript := []byte{0x51, 0x02, 0x4e, 0x73}
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's better if I we declare something like the declaration in txscript/standard.go

var PayToAnchorScript = []byte{OP_1, OP_DATA_2, 0x4e, 0x73}

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah the issue with that again is the module issue I brought up which will be addressed by #1825. This is defined, but the btcutil module wasn't updated (as this was only added in this PR). So I had to add yet another replace to amek things work.

// script bytes: OP_1 <0x4e73>.
func (a *AddressPayToAnchor) ScriptAddress() []byte {
// Return the fixed P2A script bytes.
return []byte{0x51, 0x02, 0x4e, 0x73}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah here too. Would be better if we declared some variable and referred to it

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually this won't work, as it causes an import cycle. We can't import txscript from btcutil. The other changed worked at it was in btcutil_test.

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.
@Roasbeef
Copy link
Member Author

@kcalvinalvin PTAL

@Roasbeef Roasbeef changed the base branch from v3-tx-standard to master December 18, 2025 02:15
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.

5 participants