BSV.Contract behaviour (bsv_sdk v2.0.0)

Copy Markdown View Source

A behaviour and pipeline DSL for building Bitcoin locking and unlocking scripts.

Contracts define locking_script/2 and optionally unlocking_script/2 callbacks that build scripts using a chainable pipeline of opcode and data push helpers.

Example

defmodule MyP2PKH do
  use BSV.Contract

  @impl true
  def locking_script(ctx, %{pubkey_hash: pkh}) do
    ctx
    |> op_dup()
    |> op_hash160()
    |> push(pkh)
    |> op_equalverify()
    |> op_checksig()
  end
end

script = MyP2PKH.lock(1000, %{pubkey_hash: <<...>>}) |> BSV.Contract.to_script()

Using contracts with TxBuilder

Contracts return BSV.Contract.t() structs that carry the module, function, and parameters needed to build scripts lazily.

Summary

Types

Transaction context: {transaction, input_index}

t()

Contract struct

Callbacks

Callback to generate the locking script.

Callback to generate the unlocking script.

Functions

Attach a transaction context to the contract for signature generation.

Push a value (opcode byte, data binary, or integer) onto the contract script.

Return the size in bytes of the compiled script.

Simulate a contract lock/unlock cycle and verify it against the script interpreter.

Compile the contract and return the script as a binary.

Compile the contract and return the built BSV.Script.

Compile the unlocking contract and return a BSV.Transaction.Input.

Compile the locking contract and return a BSV.Transaction.Output.

Types

ctx()

@type ctx() :: {BSV.Transaction.t(), non_neg_integer()}

Transaction context: {transaction, input_index}

t()

@type t() :: %BSV.Contract{
  ctx: ctx() | nil,
  mfa: {module(), atom(), list()},
  opts: keyword(),
  script: BSV.Script.t(),
  subject: non_neg_integer() | map() | nil
}

Contract struct

Callbacks

locking_script(t, map)

@callback locking_script(t(), map()) :: t()

Callback to generate the locking script.

unlocking_script(t, map)

(optional)
@callback unlocking_script(t(), map()) :: t()

Callback to generate the unlocking script.

Functions

put_ctx(contract, arg)

@spec put_ctx(t(), ctx()) :: t()

Attach a transaction context to the contract for signature generation.

script_push(contract, chunk)

@spec script_push(t(), BSV.Script.chunk()) :: t()

Push a value (opcode byte, data binary, or integer) onto the contract script.

script_size(contract)

@spec script_size(t()) :: non_neg_integer()

Return the size in bytes of the compiled script.

simulate(mod, lock_params, unlock_params, opts \\ [])

@spec simulate(module(), map(), map(), keyword()) ::
  {:ok, boolean()} | {:error, term()}

Simulate a contract lock/unlock cycle and verify it against the script interpreter.

Creates a fake locking transaction, then spends it with the unlocking params, and runs the combined script through BSV.Script.Interpreter.

Returns {:ok, true} on success, {:error, reason} on failure.

Example

{:ok, true} = Contract.simulate(
  BSV.Contract.P2PKH,
  %{pubkey_hash: pkh},
  %{signature: sig, pubkey: pubkey}
)

to_binary(contract)

@spec to_binary(t()) :: binary()

Compile the contract and return the script as a binary.

to_script(contract)

@spec to_script(t()) :: BSV.Script.t()

Compile the contract and return the built BSV.Script.

to_txin(contract)

@spec to_txin(t()) :: BSV.Transaction.Input.t()

Compile the unlocking contract and return a BSV.Transaction.Input.

The contract subject must be a map with :source_txid, :source_tx_out_index, and optionally :source_output and :sequence_number.

to_txout(contract)

@spec to_txout(t()) :: BSV.Transaction.Output.t()

Compile the locking contract and return a BSV.Transaction.Output.