Transactions

Transactions enable users to spend satoshis. Each transaction consists of multiple components that allow for both straightforward payments and more complex operations.

Introduction

This section will describe each component of a transaction and explain how to use them together to construct complete transactions.

To keep things simple, this section assumes coinbase transactions do not exist. Coinbase transactions, which can only be created by BitcoinEvo miners, are exceptions to many of the rules discussed here. For a deeper understanding of coinbase transactions, refer to the blockchain section of this guide.

The Parts Of A Transaction

The figure above illustrates the key elements of a BitcoinEvo transaction. Every transaction has at least one input and one output. Each input spends satoshis that were previously allocated to a prior output. Each output remains as an Unspent Transaction Output (UTXO) until it is spent by a future input. When your BitcoinEvo wallet shows a 10,000 satoshi balance, it means 10,000 satoshis are sitting in one or more UTXOs.

Each transaction begins with a four-byte transaction version number, which tells BitcoinEvo peers and miners which rules to use for validation. This feature allows developers to introduce new rules for future transactions without affecting previous ones.

Spending An Output

Each output is assigned an implicit index number, starting from zero for the first output. Additionally, the output specifies an amount in satoshis and includes a conditional pubkey script. Anyone who can satisfy the conditions of that script can spend the designated satoshis.

An input identifies a specific output to be spent using a transaction ID (txid) and output index (also called “vout” for output vector). It also includes a signature script, which provides the data needed to meet the conditions in the pubkey script. (Sequence number and locktime, which relate to this, will be covered in a later section.)

The figures below demonstrate how these components are used as Alice sends a transaction to Bob, which Bob later spends. Both Alice and Bob use the standard Pay-To-Public-Key-Hash (P2PKH) transaction type. P2PKH allows Alice to send satoshis to a typical BitcoinEvo address, and Bob to spend them using a simple cryptographic key pair.

Creating A P2PKH Public Key Hash To Receive Payment

Before Alice can send Bob a transaction, Bob needs to generate a private/public key pair. BitcoinEvo uses the Elliptic Curve Digital Signature Algorithm (ECDSA) with the secp256k1 curve. A secp256k1 private key consists of 256 bits of random data. This data is deterministically transformed into a public key, which does not need to be stored since it can be easily regenerated later.

The public key is then hashed to create a pubkey hash. This hash can also be recreated later, eliminating the need to store it. The hash shortens the public key, making manual transcription easier and providing additional security.

Bob provides Alice with the pubkey hash, typically encoded as a BitcoinEvo address. These addresses are base58-encoded strings that include a version number, the hash, and an error-checking code to detect typos. The address can be transmitted through any medium and further encoded, for example, into a QR code with a “bitcoinevo:” URI.

Once Alice decodes the address back to a pubkey hash, she can create the transaction. She builds a standard P2PKH transaction output containing instructions that allow anyone to spend the output if they can prove control over the private key linked to Bob’s hashed public key. These instructions are known as the pubkey script or scriptPubKey.

Alice broadcasts the transaction to the network, and it is recorded in the blockchain. The output becomes a UTXO, and Bob’s wallet displays it as available funds.

Later, when Bob wants to spend the UTXO, he creates an input referencing Alice’s transaction by its txid and output index. Bob must then create a signature script — a set of data that fulfills the conditions in Alice’s pubkey script. Signature scripts are also known as scriptSigs.

Pubkey scripts and signature scripts combine secp256k1 public keys and signatures with conditional logic, creating a programmable authorization process.

Unlocking A P2PKH Output For Spending

For a P2PKH output, Bob’s signature script contains two elements:

  1. His full (unhashed) public key, so that the pubkey script can confirm it matches the hash provided by Alice.

  2. An secp256k1 signature created using the ECDSA algorithm to combine certain transaction data with Bob’s private key. This allows the pubkey script to verify that Bob controls the private key.

Bob’s secp256k1 signature not only proves his control of the private key but also ensures that the transaction’s non-signature-script parts are tamper-proof, allowing him to safely broadcast it over the peer-to-peer network.

Some Things Signed When Spending An Output

As shown in the figure, the data Bob signs includes the txid and output index from the previous transaction, the previous output’s pubkey script, the pubkey script Bob creates for the next recipient, and the amount of satoshis being transferred. Essentially, the entire transaction is signed, except for the signature scripts, which hold the full public keys and secp256k1 signatures.

After completing his signature script, Bob broadcasts the transaction to BitcoinEvo miners via the peer-to-peer network. Each peer and miner independently verifies the transaction before relaying it or attempting to include it in a new block.

P2PKH Script Validation

The validation process involves evaluating both the signature script and the pubkey script. In a P2PKH output, the pubkey script is:

OP_DUP OP_HASH160 <PubkeyHash> OP_EQUALVERIFY OP_CHECKSIG

The spender’s signature script is prepended to the pubkey script for evaluation. In a P2PKH transaction, the signature script contains an secp256k1 signature (sig) and the full public key (pubkey), resulting in the following concatenation:

<Sig> <PubKey> OP_DUP OP_HASH160 <PubkeyHash> OP_EQUALVERIFY OP_CHECKSIG

The script language is a Forth-like stack-based language deliberately designed to be stateless and not Turing complete. Statelessness ensures that once a transaction is included in the blockchain, there’s no situation where it becomes permanently unspendable. The lack of loops or gotos (Turing-incompleteness) makes the scripting language more predictable and easier to secure.

To validate the transaction, operations in the signature script and pubkey script are processed one by one, starting with Bob’s signature script and continuing through Alice’s pubkey script. The diagram below shows the step-by-step evaluation of a standard P2PKH pubkey script, followed by an explanation of the process.

P2PKH Stack Evaluation

  • First, the signature from Bob’s signature script is added (pushed) to an empty stack. Since it’s purely data, nothing is done at this point except adding it to the stack. Next, the public key from the signature script is pushed on top of the signature.

  • From Alice’s pubkey script, the “OP_DUP” operation is executed. This duplicates the data at the top of the stack, creating a copy of Bob’s public key.

  • The next operation, “OP_HASH160”, generates a hash of the public key currently on top of the stack, resulting in Bob’s public key hash.

  • Afterward, Alice’s pubkey script pushes the pubkey hash she received from Bob during the first transaction. At this point, there should be two copies of Bob’s pubkey hash on the stack.

  • Now comes the critical part: Alice’s script executes “OP_EQUALVERIFY”. This operation is equivalent to running “OP_EQUAL” followed by “OP_VERIFY” (which are not explicitly shown).

    “OP_EQUAL” compares the two values at the top of the stack — Bob’s pubkey hash derived from his public key and the pubkey hash Alice provided. If the two values are identical, it replaces them with a true (1); otherwise, it replaces them with false (0).

    “OP_VERIFY” then checks the value at the top of the stack. If the value is false, validation terminates immediately, and the transaction is invalid. If true, the value is popped off the stack, and validation continues.

  • Finally, Alice’s pubkey script executes “OP_CHECKSIG”. This operation verifies Bob’s signature against the now-confirmed public key and the transaction data. If the signature is valid and was created using all the required transaction data, “OP_CHECKSIG” pushes true to the top of the stack.


If the signature is valid and was created using all the required transaction data, “OP_CHECKSIG” pushes true to the top of the stack.

P2SH Scripts

Pubkey scripts are created by spenders, who typically have little concern for the specific conditions of the script. Receivers, however, care about the script’s conditions and can request that the spender use a particular pubkey script if needed. Unfortunately, custom pubkey scripts are less practical than using concise BitcoinEvo addresses, and there was no standard method for sharing them between programs until the now-deprecated BIP70 Payment Protocol was widely implemented, which is discussed later.

To address these challenges, pay-to-script-hash (P2SH) transactions were introduced in 2012. They allow a spender to create a pubkey script that contains a hash of another script, called the redeem script.

The general P2SH process, as shown below, is very similar to the P2PKH process. Bob creates a redeem script that includes any script logic he desires, hashes the redeem script, and then sends the redeem script hash to Alice. Alice then generates a P2SH output that includes Bob’s redeem script hash.

Creating A P2SH Redeem Script And Hash

When Bob decides to spend the output, he provides his signature along with the full (serialized) redeem script within the signature script. The peer-to-peer network verifies that the redeem script hashes to the same value as the script hash Alice included in her output. If the redeem script passes validation and does not return false, Bob is able to spend the output.

Unlocking A P2SH Output For Spending

The redeem script hash functions similarly to a pubkey hash, allowing it to be converted into a standard BitcoinEvo address format with just one small modification to distinguish it from a regular address. As a result, collecting a P2SH-style address is just as easy as collecting a P2PKH-style address. Additionally, the hash conceals any public keys within the redeem script, providing the same level of security as P2PKH pubkey hashes.

Standard Transactions

After the discovery of several dangerous bugs in early BitcoinEvo versions, a test was introduced that only accepts transactions from the network if their pubkey and signature scripts match a set of believed-to-be-safe templates, and if they comply with a set of rules that ensure good network behavior. This is known as the IsStandard() test, and transactions that pass it are referred to as standard transactions.

Non-standard transactions, which fail the test, may still be accepted by nodes that don’t use the default BitcoinEvo Core settings. If included in blocks, they avoid the IsStandard() check and are processed normally.

In addition to preventing harmful transactions that could exploit the network, the standard transaction test also helps prevent users from creating transactions that would complicate the introduction of new features in the future. For instance, each transaction includes a version number, and if users arbitrarily changed this version, it would lose its value as a tool for enabling backward-incompatible upgrades.

The standard pubkey script types are:

  • Pay to Public Key Hash (P2PKH)
  • Pay to Script Hash (P2SH)
  • Multisig
  • Pubkey
  • Null Data

Pay To Public Key Hash (P2PKH)

P2PKH is the most common pubkey script type, used to send transactions to one or more BitcoinEvo addresses.

  • Pubkey script: OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

  • Signature script: <sig> <pubkey>

Pay To Script Hash (P2SH)

P2SH allows transactions to be sent to a script hash. Any of the standard pubkey scripts can be used as a P2SH redeem script, except P2SH itself. P2SH transactions can include any valid redeem script, which makes this type highly versatile and suitable for creating more complex and experimental transactions. The most common use of P2SH is for multisig scripts, followed by the Open Assets Protocol.

Another common use is to store text data on the blockchain. The first BitcoinEvo transaction included text, and P2SH provides a convenient method for storing up to 1.5KB of text data.

  • Pubkey script: OP_HASH160 <Hash160(redeemScript)> OP_EQUAL

  • Signature script: <sig> [sig] [sig...] <redeemScript>

Old nodes will recognize this script hash as valid as long as the redeem script hash matches, but after a soft fork, newer nodes will also verify the redeem script by extracting and processing it. To spend a P2SH output, the spender must provide a valid signature or other required input along with the correct redeem script.

This step is similar to the P2PKH or P2Multisig verification process, where the initial part of the signature script acts as the “signature script”, and the redeem script serves as the “pubkey script”.

Multisig

Although P2SH multisig is commonly used for multisig transactions today, the basic multisig script can still be employed to require multiple signatures before a UTXO can be spent.

In multisig pubkey scripts, known as m-of-n, “m” represents the minimum number of signatures needed to unlock the funds, while “n” is the total number of provided public keys. Both “m” and “n” are represented by opcodes OP_1 through OP_16, corresponding to the desired number.

Due to an off-by-one bug in the original BitcoinEvo implementation, which is preserved for backward compatibility, the OP_CHECKMULTISIG operation consumes one additional value from the stack beyond what “m” specifies. As a result, the secp256k1 signatures in the signature script must be prefaced with an extra OP_0, which is consumed but not used.

The signatures in the signature script must correspond to the public keys in the same order as they appear in the pubkey script or redeem script. Refer to the description of OP_CHECKMULTISIG for more details.

  • Pubkey script: <m> <A pubkey> [B pubkey] [C pubkey...] <n> OP_CHECKMULTISIG

  • Signature script: OP_0 <A sig> [B sig] [C sig...]

A typical example of a 2-of-3 P2SH multisig would look like this:

  • Pubkey script: OP_HASH160 <Hash160(redeemScript)> OP_EQUAL

  • Redeem script: <OP_2> <A pubkey> <B pubkey> <C pubkey> <OP_3> OP_CHECKMULTISIG

  • Signature script: OP_0 <A sig> <C sig> <redeemScript>

Pubkey

Pubkey outputs are a simplified version of the P2PKH pubkey script, but they offer less security compared to P2PKH, so they are generally no longer used in new transactions.

  • Pubkey script: <pubkey> OP_CHECKSIG

  • Signature script: <sig>

Null Data

The Null data transaction type, allows for arbitrary data to be added to a provably unspendable pubkey script. These transactions are relayed and mined by default, and full nodes don’t need to store them in the UTXO database. It is preferable to use null data transactions instead of transactions that add unnecessary bloat to the UTXO database since these cannot be pruned. However, it’s generally recommended to store data outside transactions when possible.

Consensus rules permit null data outputs up to the maximum allowed pubkey script size of 10,000 bytes, provided they adhere to other consensus rules, such as limiting data pushes to 520 bytes or smaller.

The -datacarriersize configuration option in BitcoinEvo Core allows users to set the maximum number of bytes in null data outputs that they are willing to relay or mine.

Non-Standard Transactions

If you use anything other than a standard pubkey script in an output, peers and miners running the default BitcoinEvo Core settings won’t accept, broadcast, or mine your transaction. If you try to broadcast such a transaction to a peer using default settings, you will encounter an error message.

However, if you create a redeem script, hash it, and use that hash in a P2SH output, the network will only see the hash and accept the output as valid regardless of what the redeem script contains. This allows payments to non-standard scripts, nearly all valid redeem scripts can be spent. The exception is for scripts that utilize unassigned NOP opcodes, which are reserved for future soft forks and can only be relayed or mined by nodes that don’t follow the standard mempool policy.

Note: Standard transactions are designed to protect the network, not to prevent you from making mistakes. It is still possible to create standard transactions that make the satoshis they contain unspendable.

Standard transactions must also meet the following conditions:

  • The transaction must be finalized: either its locktime must be in the past (or equal to or less than the current block height), or all sequence numbers must be set to 0xffffffff.

  • The transaction must be smaller than 100,000 bytes, which is about 200 times the size of a typical single-input, single-output P2PKH transaction.

  • Each signature script in the transaction must be under 1,650 bytes. This size limit is sufficient for up to 15-of-15 multisig transactions using compressed public keys in P2SH.

  • Bare (non-P2SH) multisig transactions that require more than 3 public keys are currently considered non-standard.

  • The signature script must only push data onto the evaluation stack. It cannot introduce new opcodes, except for those that solely push data to the stack.

  • The transaction must not include outputs that receive less than one-third of the satoshis it would cost to spend it in a typical input. This threshold is currently 546 satoshis for P2PKH or P2SH outputs on a BitcoinEvo Core node with default relay fees. Exception: Standard null data outputs must receive zero satoshis.

Signature Hash Types

OP_CHECKSIG extracts a non-stack argument from each signature it processes, allowing the signer to choose which parts of the transaction they want to sign. Since the signature protects those parts of the transaction from being altered, signers can decide to let others modify certain aspects of their transaction.

These different options for what to sign are known as signature hash types (SIGHASH types). Currently, three base SIGHASH types are available:

  • SIGHASH_ALL: This default option signs all the inputs and outputs, ensuring that everything except the signature scripts is protected from modification.

  • SIGHASH_NONE: Signs all the inputs but leaves the outputs unsigned, allowing anyone to change where the satoshis are sent unless other signatures with different SIGHASH types secure the outputs.

  • SIGHASH_SINGLE: Only the output corresponding to this input (with the same output index as the input) is signed, ensuring that no one can modify that part of the transaction. However, other signers can still change their parts. If the corresponding output doesn’t exist, the value “1” is signed, which breaks the security. This input and other inputs are included in the signature, but the sequence numbers of other inputs are not, allowing them to be updated.

The base types can be combined with the SIGHASH_ANYONECANPAY flag, creating three additional SIGHASH types:

  • SIGHASH_ALL|SIGHASH_ANYONECANPAY: Signs all outputs but only this one input, allowing anyone to add or remove other inputs, meaning anyone can contribute satoshis but cannot change the outputs or where the funds are sent.

  • SIGHASH_NONE|SIGHASH_ANYONECANPAY: Signs only this one input, allowing anyone to add or remove both inputs and outputs. This allows anyone who gets a copy of this input to spend it as they like.

  • SIGHASH_SINGLE|SIGHASH_ANYONECANPAY: Signs just this input and its corresponding output, while allowing others to add or remove other inputs.

Since each input is individually signed, transactions with multiple inputs can use different SIGHASH types for different parts of the transaction. For example, in a single-input transaction signed with SIGHASH_NONE, a miner could change the output when adding the transaction to the blockchain. In contrast, in a two-input transaction, if one input is signed with SIGHASH_NONE signer — but no one else can alter the transaction.

Locktime And Sequence Number

All signature hash types sign the transaction’s locktime (referred to as nLockTime in the BitcoinEvo Core code). Locktime specifies the earliest point at which a transaction can be added to the blockchain.

Locktime enables signers to create time-locked transactions that become valid only after a certain future time, allowing signers a chance to change their minds before the transaction becomes valid.

If a signer changes their mind, they can create a new transaction without a locktime, which uses one of the same outputs as an input. If the new transaction is added to the blockchain before the locktime of the original transaction expires, the original locktime transaction becomes invalid. Extra caution is needed near the locktime’s expiration.

The peer-to-peer network allows block time to be up to two hours ahead of real time, meaning a locktime transaction might be included in a block up to two hours before the lock officially expires. Additionally, blocks are not produced at exact intervals, so any effort to cancel a valuable transaction should be made a few hours in advance of the locktime expiration.

Previous versions of BitcoinEvo Core included a feature preventing signers from canceling time-locked transactions, but a key part of that feature was disabled to avoid denial-of-service attacks. A legacy of that system is the four-byte sequence numbers in every input. Sequence numbers were originally meant to let multiple signers agree on updating a transaction. Once finalized, they would set all input sequence numbers to the maximum (0xffffffff), allowing the transaction to be added to the blockchain even if the time lock hadn’t expired.

Even now, setting all sequence numbers to 0xffffffff (the default in BitcoinEvo Core) will disable the time lock. To use locktime, at least one input must have a sequence number lower than the maximum. Since sequence numbers aren’t used by the network for anything else, setting any sequence number to zero is enough to enable locktime.

Locktime is a 4-byte unsigned integer, and can be interpreted in two ways:

  • If the value is 500 million or higher, it represents a Unix epoch time (the number of seconds since 1970-01-01T00:00 UTC — currently over 1.395 billion). The transaction can be included in any block whose block time is greater than the locktime.

  • If the value is less than 500 million, it represents a block height. The transaction can be added to any block at or above that height.

Transaction Fees And Change

Transaction fees are calculated based on the total size of the signed transaction in bytes. Fees per byte depend on current demand for space in mined blocks, with fees increasing as demand rises. The fees are awarded to the BitcoinEvo miner, and each miner sets their own minimum fee threshold for transactions they will include in a block.

There is also the concept of “high-priority transactions” that spend satoshis which have remained unspent for a long period.

In the past, “priority” transactions were sometimes exempt from standard fee requirements. Before BitcoinEvo Core 0.12, 50 KB of each block was reserved for high-priority transactions, but this is now set to 0 KB by default. After this reserved space, transactions are prioritized by fee per byte, with the highest-paying transactions being included first until all available block space is filled.

A minimum fee (currently 1,000 satoshis) has been required to broadcast a transaction across the network. Transactions paying only the minimum fee may experience long delays before being included in a block. Please see the section on verifying payments for more information on why this delay can be important.

Each transaction spends Unspent Transaction Outputs (UTXOs), and since a UTXO can only be spent once, the entire value of the UTXOs must be used or given to the miner as a transaction fee. Since most users do not have UTXOs that exactly match the amount they want to pay, most transactions include a change output.

Change outputs return the surplus satoshis from the UTXOs back to the spender. The spender can reuse the same P2PKH pubkey hash or P2SH script hash used in the original UTXO, but for security reasons discussed later, it is recommended that change outputs be sent to a new P2PKH or P2SH address.

Avoiding Key Reuse

In a transaction, both the spender and receiver reveal to each other the public keys or addresses they use. This enables either party to use the public blockchain to track the other’s past and future transactions involving those same public keys or addresses.

When the same public key is reused frequently, such as when people use BitcoinEvo addresses (hashed public keys) as static payment addresses, others can easily track that person’s spending and receiving habits, including the number of satoshis they control at known addresses.

This doesn’t need to happen. If a public key is used only twice — once to receive a payment and once to spend that payment — the user gains significant privacy.

Better still, using new public keys or unique addresses for receiving payments or creating change outputs can be combined with techniques like CoinJoin or merge avoidance (discussed later) to make it much harder to trace how satoshis are received and spent through the blockchain alone.

Avoiding key reuse also adds a layer of security against attacks that might reconstruct private keys from public keys (theoretical) or from comparing signatures (possible today under certain circumstances, as described below).

Unique (non-reused) P2PKH and P2SH addresses help protect against the first type of attack by keeping ECDSA public keys hidden (hashed) until the first time the satoshis are spent from those addresses. As a result, any attack would be futile unless it could reconstruct the private keys within the short window of time (usually an hour or two) before the transaction is confirmed on the blockchain.

Unique private keys (non-reused) protect against the second type of attack because only one signature is generated per private key. This prevents attackers from obtaining additional signatures that could be used in comparison-based attacks. These comparison attacks are typically only practical today when signing is done with insufficient entropy, or when entropy is exposed through methods like side-channel attacks.

For both privacy and security reasons, we recommend designing applications to avoid public key reuse, and, where possible, to discourage users from reusing addresses. If your application needs a fixed URI for payments, please refer to the “bitcoinevo:” URI section below.

Transaction Malleability

None of BitcoinEvo’s signature hash types protect the signature script, leaving transactions vulnerable to a limited denial of service attack known as transaction malleability. The signature script contains the secp256k1 signature, which cannot sign itself, allowing attackers to make non-functional changes to a transaction without invalidating it. For instance, an attacker can insert data into the signature script that will be ignored when the pubkey script is processed.

While these modifications do not alter the transaction’s inputs or outputs, they do change the transaction’s hash. Since BitcoinEvo transactions are identified by their hash (txid), a modified transaction will have a different txid than what its creator expected.

This isn’t a major issue for most BitcoinEvo transactions that are meant to be included in the blockchain right away. However, it becomes problematic when a transaction’s output is spent before the original transaction is confirmed on the blockchain.

Developers have been working to reduce transaction malleability in standard transaction types, with one major outcome being BIP 141: Segregated Witness (SegWit). When SegWit is not used, new transactions should avoid depending on unconfirmed transactions, particularly when large sums of satoshis are involved.

Transaction malleability also affects payment tracking. BitcoinEvo Core’s RPC interface tracks transactions by their txid. If the txid changes due to a modified transaction, it might seem like the transaction has disappeared from the network.

Best practices for tracking transactions recommend tracking them by the transaction outputs (UTXOs) used as inputs, as they cannot be changed without making the transaction invalid.

Additionally, if a transaction appears to vanish and needs to be reissued, it’s best to do so in a way that invalidates the original transaction. A reliable way to achieve this is by ensuring that the reissued transaction spends all the same outputs used as inputs in the lost transaction.