Skip to content

Commit 2aff9a3

Browse files
committed
Merge bitcoin/bitcoin#30352: policy: Add PayToAnchor(P2A), OP_1 <0x4e73> as a standard output script for spending
75648ce test: add P2A ProduceSignature coverage (Greg Sanders) 7998ce6 Add release note for P2A output feature (Greg Sanders) 71c9b02 test: add P2A coverage for decodescript (Greg Sanders) 1349e9e test: Add anchor mempool acceptance test (Greg Sanders) 9d89209 policy: stop 3rd party wtxid malleability of anchor spend (Greg Sanders) b60aaf8 policy: make anchor spend standard (Greg Sanders) 455fca8 policy: Add OP_1 <0x4e73> as a standard output type (Greg Sanders) Pull request description: This is a sub-feature taken out of the original proposal for ephemeral anchors #30239 This PR makes *spending* of `OP_1 <0x4e73>` (i.e. `bc1pfeessrawgf`) standard. Creation of this output type is already standard. Any future witness output types are considered relay-standard to create, but not to spend. This preserves upgrade hooks, such as a completely new output type for a softfork such as BIP341. It also gives us a bit of room to use a new output type for policy uses. This particular sized witness program has no other known use-cases (https://bitcoin.stackexchange.com/a/110664/17078), s it affords insufficient cryptographic security for a secure commitment to data, such as a script or a public key. This makes this type of output "keyless", or unauthenticated. As a witness program, the `scriptSig` of the input MUST be blank, by BIP141. This helps ensure txid-stability of the spending transaction, which may be required for smart contracting wallets. If we do not use segwit, a miner can simply insert an `OP_NOP` in the `scriptSig` without effecting the result of program execution. An additional relay restriction is to disallow non-empty witness data, which an adversary may use to penalize the "honest" transactor when RBF'ing the transaction due to the incremental fee requirement of RBF rules. The intended use-case for this output type is to "anchor" the transaction with a spending child to bring exogenous CPFP fees into the transaction package, encouraging the inclusion of the package in a block. The minimal size of creation and spending of this output makes it an attractive contrast to outputs like `p2sh(OP_TRUE)` and `p2wsh(OP_TRUE)` which are significantly larger in vbyte terms. Combined with TRUC transactions which limits the size of child transactions significantly, this is an attractive option for presigned transactions that need to be fee-bumped after the fact. ACKs for top commit: sdaftuar: utACK 75648ce theStack: re-ACK 75648ce ismaelsadeeq: re-ACK 75648ce via [diff](https://github.com/bitcoin/bitcoin/compare/e7ce6dc070c0319cbb868d41cadd836b2e6ca9db..75648cea5a9032b3d388cbebacb94d908e08924e) glozow: ACK 75648ce tdb3: ACK 75648ce Tree-SHA512: d529de23d20857e6cdb40fa611d0446b49989eaafed06c28280e8fd1897f1ed8d89a4eabbec1bbf8df3d319910066c3dbbba5a70a87ff0b2967d5205db32ad1e
2 parents ec8b38c + 75648ce commit 2aff9a3

24 files changed

+200
-3
lines changed

doc/release-notes-30352.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
P2P and network changes
2+
-----------------------
3+
4+
- Pay To Anchor(P2A) is a new standard witness output type for spending,
5+
a newly recognised output template. This allows for key-less anchor
6+
outputs, with compact spending conditions for additional efficiencies on
7+
top of an equivalent `sh(OP_TRUE)` output, in addition to the txid stability
8+
of the spending transaction.
9+
N.B. propagation of this output spending on the network will be limited
10+
until a sufficient number of nodes on the network adopt this upgrade.

src/addresstype.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
8787
addressRet = tap;
8888
return true;
8989
}
90+
case TxoutType::ANCHOR: {
91+
addressRet = PayToAnchor();
92+
return true;
93+
}
9094
case TxoutType::WITNESS_UNKNOWN: {
9195
addressRet = WitnessUnknown{vSolutions[0][0], vSolutions[1]};
9296
return true;

src/addresstype.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <pubkey.h>
1010
#include <script/script.h>
1111
#include <uint256.h>
12+
#include <util/check.h>
1213
#include <util/hash_type.h>
1314

1415
#include <algorithm>
@@ -116,6 +117,13 @@ struct WitnessUnknown
116117
}
117118
};
118119

120+
struct PayToAnchor : public WitnessUnknown
121+
{
122+
PayToAnchor() : WitnessUnknown(1, {0x4e, 0x73}) {
123+
Assume(CScript::IsPayToAnchor(1, {0x4e, 0x73}));
124+
};
125+
};
126+
119127
/**
120128
* A txout script categorized into standard templates.
121129
* * CNoDestination: Optionally a script, no corresponding address.
@@ -125,10 +133,11 @@ struct WitnessUnknown
125133
* * WitnessV0ScriptHash: TxoutType::WITNESS_V0_SCRIPTHASH destination (P2WSH address)
126134
* * WitnessV0KeyHash: TxoutType::WITNESS_V0_KEYHASH destination (P2WPKH address)
127135
* * WitnessV1Taproot: TxoutType::WITNESS_V1_TAPROOT destination (P2TR address)
136+
* * PayToAnchor: TxoutType::ANCHOR destination (P2A address)
128137
* * WitnessUnknown: TxoutType::WITNESS_UNKNOWN destination (P2W??? address)
129138
* A CTxDestination is the internal data type encoded in a bitcoin address
130139
*/
131-
using CTxDestination = std::variant<CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown>;
140+
using CTxDestination = std::variant<CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown>;
132141

133142
/** Check whether a CTxDestination corresponds to one with an address. */
134143
bool IsValidDestination(const CTxDestination& dest);

src/key_io.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
181181
return tap;
182182
}
183183

184+
if (CScript::IsPayToAnchor(version, data)) {
185+
return PayToAnchor();
186+
}
187+
184188
if (version > 16) {
185189
error_str = "Invalid Bech32 address witness version";
186190
return CNoDestination();

src/policy/policy.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,11 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
225225
// get the scriptPubKey corresponding to this input:
226226
CScript prevScript = prev.scriptPubKey;
227227

228+
// witness stuffing detected
229+
if (prevScript.IsPayToAnchor()) {
230+
return false;
231+
}
232+
228233
bool p2sh = false;
229234
if (prevScript.IsPayToScriptHash()) {
230235
std::vector <std::vector<unsigned char> > stack;

src/rpc/rawtransaction.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ static RPCHelpMan decodescript()
557557
case TxoutType::SCRIPTHASH:
558558
case TxoutType::WITNESS_UNKNOWN:
559559
case TxoutType::WITNESS_V1_TAPROOT:
560+
case TxoutType::ANCHOR:
560561
// Should not be wrapped
561562
return false;
562563
} // no default case, so the compiler can warn about missing cases
@@ -599,6 +600,7 @@ static RPCHelpMan decodescript()
599600
case TxoutType::WITNESS_V0_KEYHASH:
600601
case TxoutType::WITNESS_V0_SCRIPTHASH:
601602
case TxoutType::WITNESS_V1_TAPROOT:
603+
case TxoutType::ANCHOR:
602604
// Should not be wrapped
603605
return false;
604606
} // no default case, so the compiler can warn about missing cases

src/rpc/util.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,14 @@ class DescribeAddressVisitor
332332
return obj;
333333
}
334334

335+
UniValue operator()(const PayToAnchor& anchor) const
336+
{
337+
UniValue obj(UniValue::VOBJ);
338+
obj.pushKV("isscript", true);
339+
obj.pushKV("iswitness", true);
340+
return obj;
341+
}
342+
335343
UniValue operator()(const WitnessUnknown& id) const
336344
{
337345
UniValue obj(UniValue::VOBJ);

src/script/interpreter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1943,6 +1943,8 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
19431943
}
19441944
return set_success(serror);
19451945
}
1946+
} else if (!is_p2sh && CScript::IsPayToAnchor(witversion, program)) {
1947+
return true;
19461948
} else {
19471949
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) {
19481950
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM);

src/script/script.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,23 @@ unsigned int CScript::GetSigOpCount(const CScript& scriptSig) const
204204
return subscript.GetSigOpCount(true);
205205
}
206206

207+
bool CScript::IsPayToAnchor() const
208+
{
209+
return (this->size() == 4 &&
210+
(*this)[0] == OP_1 &&
211+
(*this)[1] == 0x02 &&
212+
(*this)[2] == 0x4e &&
213+
(*this)[3] == 0x73);
214+
}
215+
216+
bool CScript::IsPayToAnchor(int version, const std::vector<unsigned char>& program)
217+
{
218+
return version == 1 &&
219+
program.size() == 2 &&
220+
program[0] == 0x4e &&
221+
program[1] == 0x73;
222+
}
223+
207224
bool CScript::IsPayToScriptHash() const
208225
{
209226
// Extra-fast test for pay-to-script-hash CScripts:

src/script/script.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,14 @@ class CScript : public CScriptBase
533533
*/
534534
unsigned int GetSigOpCount(const CScript& scriptSig) const;
535535

536+
/*
537+
* OP_1 <0x4e73>
538+
*/
539+
bool IsPayToAnchor() const;
540+
/** Checks if output of IsWitnessProgram comes from a P2A output script
541+
*/
542+
static bool IsPayToAnchor(int version, const std::vector<unsigned char>& program);
543+
536544
bool IsPayToScriptHash() const;
537545
bool IsPayToWitnessScriptHash() const;
538546
bool IsWitnessProgram(int& version, std::vector<unsigned char>& program) const;

0 commit comments

Comments
 (0)