lib/bsv/contract/p2pkh.ex

defmodule BSV.Contract.P2PKH do
  @moduledoc """
  Pay to Public Key Hash contract.

  P2PKH scripts are used to lock Bitcoin to an [`address`](`t:BSV.Address.t/0`).
  The Bitcoin can later be unlocked using the private key corresponding to the
  address.

  ## Lock parameters

  * `:address` - A `t:BSV.Address.t/0` struct.

  ## Unlock parameters

  * `:keypair` - A `t:BSV.KeyPair.t/0` struct.

  ## Examples

      iex> contract = P2PKH.lock(1000, %{address: Address.from_pubkey(@keypair.pubkey)})
      iex> Contract.to_script(contract)
      %Script{chunks: [
        :OP_DUP,
        :OP_HASH160,
        <<83, 143, 209, 121, 200, 190, 15, 40, 156, 115, 14, 51, 181, 246, 163, 84, 27, 233, 102, 143>>,
        :OP_EQUALVERIFY,
        :OP_CHECKSIG
      ]}

      iex> contract = P2PKH.unlock(%UTXO{}, %{keypair: @keypair})
      iex> Contract.to_script(contract)
      %Script{chunks: [
        <<0::568>>, # signatures are zero'd out until the transaction context is attached
        <<3, 248, 31, 140, 139, 144, 245, 236, 6, 238, 66, 69, 234, 177, 102, 232, 175, 144, 63, 199, 58, 109, 215, 54, 54, 104, 126, 240, 39, 135, 10, 190, 57>>
      ]}
  """
  use BSV.Contract
  alias BSV.PubKey

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

  @impl true
  def unlocking_script(ctx, %{keypair: keypair}) do
    ctx
    |> sig(keypair.privkey)
    |> push(PubKey.to_binary(keypair.pubkey))
  end

end