Using P2SH
How to use P2SH in OP_NET
P2SH addresses in OP_NET are primarily used for legacy contract interactions and compatibility with older Bitcoin infrastructure. The LegacyCalldataGenerator class creates redeem scripts that encode contract calldata into a P2SH-compatible format.
P2SH has a 520-byte script size limit. For larger calldata payloads, consider using P2WSH which supports scripts up to 10,000 bytes.
Generating a Redeem Script
The following example demonstrates how to generate a P2SH redeem script for OP_NET contract interactions. The generateRedeemScript function creates a redeem script from calldata and returns the P2SH address along with the script components.
import bitcoin, { Network } from '@btc-vision/bitcoin';
import { Address, BinaryWriter, LegacyCalldataGenerator } from '@btc-vision/transaction';
export interface RedeemScript {
address: string;
p2shOutputScript: Buffer;
redeemScript: Buffer;
}
// Create calldata with a function selector and parameters
const calldata = new BinaryWriter();
calldata.writeSelector(1);
calldata.writeBytes(Buffer.alloc(300));
export function generateRedeemScript(address: Address, network: Network): RedeemScript {
const senderPubKey = address.originalPublicKeyBuffer();
const calldataGenerator = new LegacyCalldataGenerator(senderPubKey, network);
const redeemScript = calldataGenerator.compile(
Buffer.from(calldata.getBuffer()),
senderPubKey,
Buffer.alloc(0),
0n,
[],
);
const p2sh = bitcoin.payments.p2sh({
redeem: { output: redeemScript },
network,
});
const outputRedeem: Buffer | undefined = p2sh.redeem?.output;
if (!outputRedeem) {
throw new Error('Output redeem is required');
}
console.log('P2SH Address:', p2sh.address);
console.log('P2SH Redeem Script (hex):', outputRedeem.toString('hex'));
if (!p2sh.address) {
throw new Error('P2SH address is required');
}
const p2shOutputScript: Buffer | undefined = p2sh?.redeem?.output;
if (!p2shOutputScript) {
throw new Error('No redeem output');
}
return {
address: p2sh.address,
p2shOutputScript,
redeemScript: redeemScript,
};
}Understanding the Components
BinaryWriter
The BinaryWriter class is used to construct the calldata that will be encoded into the redeem script. The writeSelector() method writes a function selector (identifying which contract function to call), and writeBytes() writes the function parameters.
LegacyCalldataGenerator
The LegacyCalldataGenerator takes the sender's public key and network configuration. The compile() method generates the redeem script from the calldata, including:
- The calldata buffer containing the function selector and parameters.
- The sender's public key for authentication.
- An optional interaction script (empty buffer in this example).
- The transaction value as a bigint.
- Additional parameters as an array.
bitcoin.payments.p2sh
The bitcoin.payments.p2sh() function from the @btc-vision/bitcoin library constructs the P2SH payment object. It takes the compiled redeem script and generates the corresponding P2SH address and output scripts.
Validating P2SH Addresses
Use the AddressVerificator class to validate P2SH addresses before use.
import { AddressVerificator } from '@btc-vision/transaction';
import { networks } from '@btc-vision/bitcoin';
const isValid = AddressVerificator.isP2SHAddress(p2shAddress, networks.bitcoin);
console.log('P2SH valid:', isValid); // true