Skip to content

Commit 2ee309b

Browse files
committed
rpctest: add new e2e test for new P2A behavior
We make sure it'll be accepted into the mempool, and can be spent without a witness.
1 parent 394e818 commit 2ee309b

File tree

1 file changed

+133
-0
lines changed

1 file changed

+133
-0
lines changed

integration/p2a_test.go

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
//go:build rpctest
2+
// +build rpctest
3+
4+
package integration
5+
6+
import (
7+
"testing"
8+
9+
"github.com/btcsuite/btcd/btcutil"
10+
"github.com/btcsuite/btcd/chaincfg"
11+
"github.com/btcsuite/btcd/integration/rpctest"
12+
"github.com/btcsuite/btcd/txscript"
13+
"github.com/btcsuite/btcd/wire"
14+
)
15+
16+
// TestPayToAnchorSimple tests creating and spending P2A outputs.
17+
func TestPayToAnchorSimple(t *testing.T) {
18+
t.Parallel()
19+
20+
// Integration tests require a full harness setup which is
21+
// resource-intensive.
22+
if testing.Short() {
23+
t.Skip("Skipping P2A integration test in short mode")
24+
}
25+
26+
// Create a btcd instance for testing P2A functionality in a controlled
27+
// environment.
28+
harness, err := rpctest.New(
29+
&chaincfg.SimNetParams, nil, nil, "",
30+
)
31+
if err != nil {
32+
t.Fatalf("unable to create test harness: %v", err)
33+
}
34+
defer harness.TearDown()
35+
36+
// Initialize the test harness with mining enabled to confirm
37+
// transactions.
38+
err = harness.SetUp(true, 25)
39+
if err != nil {
40+
t.Fatalf("unable to setup test harness: %v", err)
41+
}
42+
43+
// Create a P2A output using the helper to get a P2A address. This
44+
// ensures we're using the same P2A script generation logic.
45+
p2aAddr, err := btcutil.NewAddressPayToAnchor(&chaincfg.SimNetParams)
46+
if err != nil {
47+
t.Fatalf("unable to create P2A address: %v", err)
48+
}
49+
50+
// Use the harness to create a transaction that sends to the P2A
51+
// address. This handles all the UTXO selection and signing for us.
52+
amount := btcutil.Amount(10_000)
53+
createP2ATxHash, err := harness.SendOutputs([]*wire.TxOut{
54+
wire.NewTxOut(int64(amount), p2aAddr.ScriptAddress()),
55+
}, 10)
56+
if err != nil {
57+
t.Fatalf("unable to send P2A creation transaction: %v", err)
58+
}
59+
60+
// Mine a block to confirm the P2A creation.
61+
blockHashes, err := harness.Client.Generate(1)
62+
if err != nil {
63+
t.Fatalf("unable to generate block: %v", err)
64+
}
65+
if len(blockHashes) != 1 {
66+
t.Fatalf("expected 1 block hash, got %d", len(blockHashes))
67+
}
68+
69+
// Test spending the P2A output to verify it works as anyone-can-spend.
70+
spendP2ATx := wire.NewMsgTx(wire.TxVersion)
71+
72+
// Reference the P2A output we just created.
73+
p2aOutpoint := wire.NewOutPoint(createP2ATxHash, 0)
74+
p2aInput := wire.NewTxIn(p2aOutpoint, nil, nil)
75+
76+
// P2A outputs are designed to be spent without signatures for CPFP fee
77+
// bumping. The signature script is completely empty for P2A outputs.
78+
p2aInput.SignatureScript = []byte{}
79+
spendP2ATx.AddTxIn(p2aInput)
80+
81+
// Send the P2A funds to a regular address.
82+
spendAddr, err := harness.NewAddress()
83+
if err != nil {
84+
t.Fatalf("unable to get spend address: %v", err)
85+
}
86+
spendScript, err := txscript.PayToAddrScript(spendAddr)
87+
if err != nil {
88+
t.Fatalf("unable to create spend script: %v", err)
89+
}
90+
91+
// Deduct a small fee from the P2A output value.
92+
spendOut := wire.NewTxOut(int64(amount-100), spendScript)
93+
spendP2ATx.AddTxOut(spendOut)
94+
95+
// Broadcast the spend transaction to verify network acceptance. P2A
96+
// outputs are witness programs and are validated through the normal
97+
// transaction validation path in the mempool and consensus.
98+
spendTxHash, err := harness.Client.SendRawTransaction(spendP2ATx, true)
99+
if err != nil {
100+
t.Fatalf("unable to send P2A spend transaction: %v", err)
101+
}
102+
103+
// Mine a block to confirm the spend.
104+
blockHashes, err = harness.Client.Generate(1)
105+
if err != nil {
106+
t.Fatalf("unable to generate block after spend: %v", err)
107+
}
108+
109+
// Ensure the spend transaction was actually mined to prove full P2A
110+
// support.
111+
//
112+
block, err := harness.Client.GetBlock(blockHashes[0])
113+
if err != nil {
114+
t.Fatalf("unable to get block: %v", err)
115+
}
116+
117+
// Confirm the spend transaction exists in the confirmed block.
118+
found := false
119+
for _, tx := range block.Transactions {
120+
txHash := tx.TxHash()
121+
if txHash.IsEqual(spendTxHash) {
122+
found = true
123+
break
124+
}
125+
}
126+
if !found {
127+
t.Errorf("P2A spend transaction not found in block")
128+
}
129+
130+
t.Logf("Successfully created P2A output in tx %v and spent it in tx %v",
131+
createP2ATxHash, spendTxHash)
132+
}
133+

0 commit comments

Comments
 (0)