SegwitAddress: allow instantiation of P2A (pay-to-anchor) address

This commit is contained in:
Johannes Zweng 2024-11-08 18:09:15 +01:00 committed by Andreas Schildbach
parent 25ff2243cd
commit cd922bb839
2 changed files with 23 additions and 2 deletions

View file

@ -50,7 +50,11 @@ public class SegwitAddress implements Address {
public static final int WITNESS_PROGRAM_LENGTH_TR = 32;
public static final int WITNESS_PROGRAM_MIN_LENGTH = 2;
public static final int WITNESS_PROGRAM_MAX_LENGTH = 40;
/**
* <p>P2A (pay-to-anchor) Script</p>
* Defined <a href="https://github.com/bitcoin/bitcoin/blob/455fca86cfada1823aa28615b5683f9dc73dbb9a/src/script/script.cpp#L216-L222">here in Bitcoin Core</a>:
*/
private static final byte[] P2A_SCRIPT = { 0x4e, 0x73 };
/**
* Human-readable part (HRP) of Segwit addresses for standard Bitcoin networks.
@ -166,7 +170,10 @@ public class SegwitAddress implements Address {
// Rationale for still restricting length here: creating anyone-can-spend Taproot addresses is probably
// not that what callers expect.
if (witnessVersion == 1 && witnessProgram.length != WITNESS_PROGRAM_LENGTH_TR)
// (With one exception, the P2A (pay-to-anchor) output scripts are expected to be version 1 but shorter
// than 32 bytes.)
if (witnessVersion == 1 && witnessProgram.length != WITNESS_PROGRAM_LENGTH_TR
&& !isPayToAnchorOutputScript(witnessVersion, witnessProgram))
throw new AddressFormatException.InvalidDataLength(
"Invalid length for address version 1: " + witnessProgram.length);
this.network = normalizeNetwork(Objects.requireNonNull(network));
@ -174,6 +181,15 @@ public class SegwitAddress implements Address {
this.witnessProgram = Objects.requireNonNull(witnessProgram);
}
/**
* Check if this script is a P2A (pay-to-anchor) output script.
*
* @return <code>true</code> if the given wittnessProgram and wittnessVersion represent a Pay-to-anchor output script, <code>false</code> otherwise
*/
private boolean isPayToAnchorOutputScript(int witnessVersion, byte[] witnessProgram) {
return witnessVersion == 1 && Arrays.equals(P2A_SCRIPT, witnessProgram);
}
/**
* Returns the witness version in decoded form. Only versions 0 and 1 are in use right now.
*

View file

@ -20,6 +20,7 @@ import org.bitcoinj.base.BitcoinNetwork;
import static org.bitcoinj.base.BitcoinNetwork.MAINNET;
import static org.bitcoinj.base.BitcoinNetwork.TESTNET;
import static org.bitcoinj.base.BitcoinNetwork.REGTEST;
/**
* AddressData wrapper class with valid and invalid address test vectors.
@ -39,6 +40,10 @@ public class AddressData {
"5120000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433", 1),
new AddressData("bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0", MAINNET,
"512079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", 1),
// P2A (pay-to-anchor) output script address representations (see https://delvingbitcoin.org/t/segwit-ephemeral-anchors/160/2)
new AddressData("bc1pfeessrawgf", MAINNET, "51024e73", 1), // pay-2-anchor (P2A) mainnet address
new AddressData("tb1pfees9rn5nz", TESTNET, "51024e73", 1), // pay-2-anchor (P2A) testnet address
new AddressData("bcrt1pfeesnyr2tx", REGTEST, "51024e73", 1), // pay-2-anchor (P2A) regtest address
};
public static String[] INVALID_ADDRESSES = {
// from BIP173: