defmodule BitcoinLib.Script.Opcodes.Stack.TwoSwap do
@moduledoc """
Based on https://en.bitcoin.it/wiki/Script
Word OP_2SWAP
Opcode 114
Hex 0x72
Input x1 x2 x3 x4
Output x3 x4 x1 x2
Swaps the top two pairs of items.
"""
@behaviour BitcoinLib.Script.Opcode
defstruct []
alias BitcoinLib.Script.Opcodes.Stack.TwoSwap
@type t :: TwoSwap
@value 0x72
@doc """
Returns 0x72
## Examples
iex> BitcoinLib.Script.Opcodes.Stack.TwoSwap.v()
0x72
"""
@spec v() :: 0x72
def v do
@value
end
@doc """
Returns <<0x72>>
## Examples
iex> BitcoinLib.Script.Opcodes.Stack.TwoSwap.encode()
<<0x72>>
"""
def encode() do
<<@value::8>>
end
@doc """
Swaps the top two pairs of items.
## Examples
iex> stack = [1, 2, 3, 4, 5]
...> %BitcoinLib.Script.Opcodes.Stack.TwoSwap{}
...> |> BitcoinLib.Script.Opcodes.Stack.TwoSwap.execute(stack)
{:ok, [3, 4, 1, 2, 5]}
"""
@spec execute(TwoSwap.t(), list()) :: {:ok, list()} | {:error, binary()}
def execute(_opcode, []), do: {:error, "trying to execute OP_2SWAP on an empty stack"}
def execute(_opcode, [_]), do: {:error, "trying to execute OP_2SWAP on a 1 element stack"}
def execute(_opcode, [_, _]), do: {:error, "trying to execute OP_2SWAP on a 2 elements stack"}
def execute(_opcode, [_, _, _]),
do: {:error, "trying to execute OP_2SWAP on a 3 elements stack"}
def execute(_opcode, [x1, x2, x3, x4] ++ rest) do
{:ok, [x3, x4, x1, x2] ++ rest}
end
end