§ 05 · Transactions
Outputs
An amount and a lock
On this page 7 sections
An outputOutput: The part of a transaction that creates a new chunk of PRL: an amount in grains and a lock saying who can spend it. Pearl allows only three kinds: Taproot, P2MR and OP_RETURN. is a coin: an amount, and a lock that says what it takes to spend it.
The amount is a whole number of grainsGrain: The smallest amount of PRL: one hundred-millionth of a coin (0.00000001 PRL). Every amount inside a transaction is counted in grains., the smallest unit of PRL. The lock is a short locking scriptLocking script: The script inside an output that says what is needed to spend it. On Pearl it is always one of three short patterns: Taproot, P2MR or OP_RETURN., usually the address of whoever is being paid, unwrapped into bytes. Once a transaction is in a block, each of its outputs sits in the ledger until a later transaction spends it.
Try it
Pick the payment and hover its two outputs.
What’s in an output?
| Field | Size | Type | Description |
|---|---|---|---|
| amount | 8 | int64 LE | Value in grains. 1 PRL = 100,000,000 grains. |
| script length | 1+ | CompactSize | Length of the locking script: 22 (34) for Taproot and P2MR. |
| locking script | var | script | The lock. On Pearl: 5120…, 5220… or 6a…. |
Here is the first output of the real payment from block 130,825:
| Field | Bytes | Value |
|---|---|---|
| Version version | 4 @0 | 1 int32 little-endian. Pearl wallets and pearld coinbases use version 1; relay policy accepts 1-2. |
| Marker marker | 1 @4 | 0x00 Segwit marker (BIP-144): says witness data follows the outputs. |
| Flag flag | 1 @5 | 0x01 Witness flag; 0x01 is the only value Pearl accepts. |
| Input count vin.length | 1 @6 | 1 CompactSize number of inputs. |
| Previous txid vin[0].txid | 32 @7 | 33218153e215d1a1e80941850a696af178fc83bd6cf266be92e7ba9170553959 The transaction being spent, stored byte-reversed (internal order); shown here in normal display order. |
| Output index vin[0].vout | 4 @39 | 683 Which output of that transaction is spent (uint32 LE). |
| scriptSig length vin[0].scriptSig.length | 1 @43 | 0 Always 0 for non-coinbase inputs in Pearl: every spend uses the witness instead. |
| Sequence vin[0].sequence | 4 @44 | 0xffffffff Final (0xffffffff): no RBF signal, no relative locktime, and locktime is ignored for this input. Pearl wallets use this. |
| Output count vout.length | 1 @48 | 2 CompactSize number of outputs. |
| Amount vout[0].value | 8 @49 | 295,646,640 grains (2.95646640 PRL) int64 little-endian, in grains (1 PRL = 100,000,000 grains). |
| Script length vout[0].scriptPubKey.length | 1 @57 | 34 CompactSize length of the locking script. |
| Locking script vout[0].scriptPubKey | 34 @58 | prl1p674s9jt2xs4amk6aq7ul867kcp8qwll5zsvpzzu6revewsu5z6eqv9d5z4 OP_1 OP_PUSHBYTES_32 <output key Q>: a Taproot output. |
| Amount vout[1].value | 8 @92 | 200,000,000 grains (2.00000000 PRL) int64 little-endian, in grains (1 PRL = 100,000,000 grains). |
| Script length vout[1].scriptPubKey.length | 1 @100 | 34 CompactSize length of the locking script. |
| Locking script vout[1].scriptPubKey | 34 @101 | prl1pvt5a5d5z42egswfv7uscht7rv2rj3z4m8n3qp3w35592ydq88v4seuhn70 OP_1 OP_PUSHBYTES_32 <output key Q>: a Taproot output. |
| Witness items witness[0].length | 1 @135 | 1 Number of witness stack items for input 0. |
| Schnorr signature length witness[0][0].length | 1 @136 | 64 CompactSize length of this witness item. |
| Schnorr signature witness[0][0] | 64 @137 | 4686c7014749649b25555874c7772ecb7a44e85454893ed5888db11ebcdc82a22d74ce1a1671d02810f5ba1dca3277409e95a653ba9644099f7da26be7a86ba2 64-byte BIP-340 signature (R.x ‖ s) with SIGHASH_DEFAULT: a Taproot key-path spend. |
| Locktime locktime | 4 @201 | 0 0: no time lock. |
Amount
- Size
- 8 bytes
- Type
- Signed integer (grains)
- Format
- Little-endian
- Range
- 0 to 21 billion PRL
b0359f1100000000, read smallest byte first, is 0x119f35b0 = 295,646,640 grains, or 2.95646640 PRL. The second output’s 00c2eb0b00000000 is 200,000,000 grains: exactly 2 PRL.
The consensus cap on an amount (and on the total of a transaction’s outputs) is 21 billion PRL, ten times the real supply limit of 2.1 billion. It’s a sanity check, not the supply rule.
Locking script
- Size
- 34 bytes for Taproot and P2MR
- Type
- Script
- Format
- Length-prefixed
22 says 34 bytes follow: 51 (OP_1, witness version 1), 20 (push 32 bytes) and the 32-byte tweaked key d7ab02c9…9416b2. That is the address prl1p674s9jt2…v9d5z4 in raw form; the address page shows the conversion.
How does a wallet write an output?
From an address and an amount, in four mechanical steps. Here is the payment’s second output, 2 PRL to prl1pvt5a5d5…euhn70:
-
Amount to grains
2 PRL × 100,000,000 = 200,000,000 grains = 0x0bebc200. -
Grains to 8 bytes, smallest first
00 c2 eb 0b 00 00 00 00. -
Address to locking script
Decode the bech32m address: version 1, program62e9da36…073b2b. Write51(OP_1),20(push 32), then the program. -
Prefix the length
34 bytes, so22. The output is 8 + 1 + 34 = 43 bytes.
Every Taproot and P2MR output is exactly 43 bytes this way, which is what lets wallets predict a transaction’s size before signing it.
Which locking scripts are allowed?
Exactly three shapes. Pearl’s consensus code checks every output of every transaction, the coinbase included:
| Type | Bytes | Address | Spent by |
|---|---|---|---|
| Taproot (P2TR)P2TR (Pay-to-Taproot): The standard Pearl output: witness version 1, with addresses starting prl1p. It can be spent with one Schnorr signature, or through a hidden tree of scripts. | 51 20 ‖ 32-byte key |
prl1p… |
a signature, or a script path |
| P2MRP2MR (Pay-to-Merkle-Root): An output locked only by a tree of scripts, with no public key in it: witness version 2, addresses starting prl1z. Valid on Pearl from the start; still a draft proposal for Bitcoin. | 52 20 ‖ 32-byte root |
prl1z… |
a script path only |
| OP_RETURNOP_RETURN: An output that starts with OP_RETURN. It can carry data but can never be spent, so it never joins the set of unspent outputs. | 6a ‖ anything |
none | nobody, ever |
for i, txOut := range msgTx.TxOut {
scriptClass := txscript.GetScriptClass(txOut.PkScript)
if scriptClass != txscript.WitnessV1TaprootTy &&
scriptClass != txscript.WitnessV2MerkleRootTy &&
scriptClass != txscript.NullDataTy {
str := fmt.Sprintf("transaction output %d has "+
"unsupported script type %v", i, scriptClass)
return ruleError(ErrScriptMalformed, str)
} Anything else makes the whole transaction invalid. These were all tested against Pearl’s own validation code:
| Output script | On Pearl |
|---|---|
P2PKH 76a914…88ac |
invalid: “unsupported script type nonstandard” |
P2SH a914…87 |
invalid |
segwit v0 0014…, 0020… |
invalid |
witness v3 5320… |
invalid |
witness v1 with a 20-byte program 5114… |
invalid |
pay-to-anchor 51024e73 |
invalid |
bare multisig 51 21… 51 ae |
invalid |
| empty script | invalid |
6a alone, 6a + 1,000 bytes, 6a ac |
valid |
What’s the smallest output?
As far as consensus goes, 0 grains. But nodes won’t relay a transaction that creates a Taproot or P2MR output below the dustDust: An output so small that spending it would eat a large share of its value in fees. Pearl nodes won't pass on transactions that create Taproot or P2MR outputs below 333 grains. limit, 333 grains, because such an output is worth so little that spending it would eat a large share of its value in fees.
The number comes from a formula: three times the cost, at the minimum relay fee of 1 grain per vbyte, of the output plus a typical input that would later spend it.
A 332-grain Taproot output is rejected by the mempool (“payment is dust: 332”); 333 passes. OP_RETURN outputs are exempt. Dust is policyStandardness: A node's own extra rules for which unconfirmed transactions it will relay, like the dust limit or one OP_RETURN per transaction. Breaking policy keeps a transaction out of the mempool; breaking consensus makes a block invalid.: a miner could still put a 1-grain output in a block.
Which output is the change?
Nothing in the bytes says. ChangeChange: The leftover a transaction sends back to its sender. Outputs are spent whole, so if they hold more than you're paying, the rest comes back to you as a new output. is just another output, locked to an address the sender’s wallet controls.
Pearl’s wallet picks the change position at random, so it isn’t always last. In the payment above, the round 2 PRL output (second) is almost certainly the payment, and the first output, 2.95646640 PRL, the change. Observers use guesses like that; the protocol doesn’t care.
What happens to an output next?
- Taproot and P2MR outputs join the UTXO setUTXO: An output that has not been spent yet: a chunk of PRL waiting to be used. Your balance is the total of the UTXOs your keys can unlock. under the name
txid:index, hered919e02a…:0andd919e02a…:1, until an input spends them. - OP_RETURN outputs never enter the UTXO set. Nodes can forget them at once, which is why they’re the place for data.