Skip to content

P2PK

Pay-to-public-key locks an Output to a Public Key itself, rather than to its hash. The Locking Script is <pubkey> OP_CHECKSIG, and the Unlocking Script is a single Signature. It is smaller to spend than P2PKH, but the recipient has to give us a Public Key instead of an Address. The standard script templates page in the Developer Guide walks through its execution.

The examples use the setup from the Transaction builder.

// We pay to Alice's Public Key directly, with <pubkey> OP_CHECKSIG.
Transaction tx = new TransactionBuilder()
.spendFromTransaction(new TransactionSigner(SIGHASH, alice), fundingTx, 0,
TransactionInput.MAX_SEQ_NUMBER, new P2PKHUnlockBuilder(alice.getPublicKey()))
.spendTo(new P2PKLockBuilder(alice.getPublicKey()), BigInteger.valueOf(50_000))
.sendChangeTo(aliceAddress)
.build(true);

new P2PKLockBuilder(script) parses an existing P2PK Locking Script.

A P2PKUnlockBuilder made without a Signature waits for one. We hand it to the builder along with a signer, and the signer’s Signature becomes the whole of the Unlocking Script.

Transaction fundingTx = Fixtures.fundingTransaction(new P2PKLockBuilder(alice.getPublicKey()), 100_000);
TransactionOutput utxo = fundingTx.getOutputs().get(0);
// An empty P2PKUnlockBuilder takes the Signature that the signer makes.
Transaction tx = new TransactionBuilder()
.spendFromTransaction(new TransactionSigner(SIGHASH, alice), fundingTx, 0,
TransactionInput.MAX_SEQ_NUMBER, new P2PKUnlockBuilder())
.spendTo(new P2PKHLockBuilder(bobAddress), BigInteger.valueOf(50_000))
.sendChangeTo(aliceAddress)
.build(true);

When we already hold the Signature, e.g. one made on another machine, new P2PKUnlockBuilder(signature) takes it directly.