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