BSV.Contract.PushTxHelpers (BSV v2.1.0) View Source

Helper module for implementing the technique known as OP_PUSH_TX in BSV.Contract modules.

OP_PUSH_TX is a technique that enables true "smart contracts" to be deployed on Bitcoin. The technique can be defined as:

  • Push the transaction preimage into an unlocking script
  • In the locking script we can verify it is the correct preimage by using Script to create a signature and verifying it with OP_CHECKSIG
  • From there we can extract any data from the preimage and use it in our smart contracts.

The technique allows for storing and tracking state across Bitcoin transactions, defining spending conditions in locking scripts, and much more.

Usage

To use these helpers, import this module into your contract module.

defmodule MyContract do
  use BSV.Contract
  import BSV.Contract.PushTxHelpers

  def locking_script(ctx, _params) do
    check_tx(ctx)
  end

  def unlocking_script(ctx, _params) do
    push_tx(ctx)
  end
end

Link to this section Summary

Functions

Assuming the top stack item is a Tx Preimage, creates and verifies a signature with OP_CHECKSIG.

As check_tx/1 but verifies the signature with OP_CHECKSIGVERIFY.

Assuming the top stack item is a Tx Preimage, creates and verifies a signature with OP_CHECKSIG.

As check_tx_opt/1 but verifies the signature with OP_CHECKSIGVERIFY.

Assuming the top stack item is a Tx Preimage, gets the tx locktime number and places it on the stack on top of the preimage.

Assuming the top stack item is a Tx Preimage, gets the 36 byte outpoint and places it on the stack on top of the preimage.

Assuming the top stack item is a Tx Preimage, gets the 32 byte outputs hash and places it on the stack on top of the preimage.

Assuming the top stack item is a Tx Preimage, gets the 32 byte prevouts hash and places it on the stack on top of the preimage.

Assuming the top stack item is a Tx Preimage, gets the input satoshis number and places it on the stack on top of the preimage.

Assuming the top stack item is a Tx Preimage, gets the locking script and places it on the stack on top of the preimage.

Assuming the top stack item is a Tx Preimage, gets the input sequence number and places it on the stack on top of the preimage.

Assuming the top stack item is a Tx Preimage, gets the 32 byte sequence hash and places it on the stack on top of the preimage.

Assuming the top stack item is a Tx Preimage, gets the preimage sighash type and places it on the stack on top of the preimage.

Assuming the top stack item is a Tx Preimage, gets the tx version number and places it on the stack on top of the preimage.

Pushes the corrent Tx Preimage onto the stack. If no context is available in the contract or if this is called in a locking script, then 181 bytes of zeros are pushed onto the script instead.

Link to this section Functions

Specs

check_tx(BSV.Contract.t()) :: BSV.Contract.t()

Assuming the top stack item is a Tx Preimage, creates and verifies a signature with OP_CHECKSIG.

The Tx Preimage is removed from the stack and replaced with the result from OP_CHECKSIG.

Specs

check_tx!(BSV.Contract.t()) :: BSV.Contract.t()

As check_tx/1 but verifies the signature with OP_CHECKSIGVERIFY.

Specs

check_tx_opt(BSV.Contract.t()) :: BSV.Contract.t()

Assuming the top stack item is a Tx Preimage, creates and verifies a signature with OP_CHECKSIG.

This uses the optimal OP_PUSH_TX approach which compiles to 87 bytes (compared to 438 as per check_tx/1).

However, due to the Low-S Constraint the most significant byte of the sighash must be less than a theshold of 0x7E. There is a roughly 50% chance the signature being invalid. Therefore, when using this technique it is necessary to check the preimage and if necessary keep maleating the transaction until it is valid.

Specs

check_tx_opt!(BSV.Contract.t()) :: BSV.Contract.t()

As check_tx_opt/1 but verifies the signature with OP_CHECKSIGVERIFY.

Specs

get_lock_time(BSV.Contract.t()) :: BSV.Contract.t()

Assuming the top stack item is a Tx Preimage, gets the tx locktime number and places it on the stack on top of the preimage.

Specs

get_outpoint(BSV.Contract.t()) :: BSV.Contract.t()

Assuming the top stack item is a Tx Preimage, gets the 36 byte outpoint and places it on the stack on top of the preimage.

Link to this function

get_outputs_hash(contract)

View Source

Specs

get_outputs_hash(BSV.Contract.t()) :: BSV.Contract.t()

Assuming the top stack item is a Tx Preimage, gets the 32 byte outputs hash and places it on the stack on top of the preimage.

Link to this function

get_prevouts_hash(contract)

View Source

Specs

get_prevouts_hash(BSV.Contract.t()) :: BSV.Contract.t()

Assuming the top stack item is a Tx Preimage, gets the 32 byte prevouts hash and places it on the stack on top of the preimage.

Specs

get_satoshis(BSV.Contract.t()) :: BSV.Contract.t()

Assuming the top stack item is a Tx Preimage, gets the input satoshis number and places it on the stack on top of the preimage.

Specs

get_script(BSV.Contract.t()) :: BSV.Contract.t()

Assuming the top stack item is a Tx Preimage, gets the locking script and places it on the stack on top of the preimage.

State can be placed in the locking script and so this becomes an invaluable method for extracting and using that state.

Specs

get_sequence(BSV.Contract.t()) :: BSV.Contract.t()

Assuming the top stack item is a Tx Preimage, gets the input sequence number and places it on the stack on top of the preimage.

Link to this function

get_sequence_hash(contract)

View Source

Specs

get_sequence_hash(BSV.Contract.t()) :: BSV.Contract.t()

Assuming the top stack item is a Tx Preimage, gets the 32 byte sequence hash and places it on the stack on top of the preimage.

Link to this function

get_sighash_type(contract)

View Source

Specs

get_sighash_type(BSV.Contract.t()) :: BSV.Contract.t()

Assuming the top stack item is a Tx Preimage, gets the preimage sighash type and places it on the stack on top of the preimage.

Specs

get_version(BSV.Contract.t()) :: BSV.Contract.t()

Assuming the top stack item is a Tx Preimage, gets the tx version number and places it on the stack on top of the preimage.

Specs

push_tx(BSV.Contract.t()) :: BSV.Contract.t()

Pushes the corrent Tx Preimage onto the stack. If no context is available in the contract or if this is called in a locking script, then 181 bytes of zeros are pushed onto the script instead.