defmodule BitcoinLib.Script.Opcodes.Stack.Rot do
@moduledoc """
Based on https://en.bitcoin.it/wiki/Script
Word OP_ROT
Opcode 123
Hex 0x7b
Input x1 x2 x3
Output x2 x3 x1
The 3rd item down the stack is moved to the top.
"""
@behaviour BitcoinLib.Script.Opcode
defstruct []
alias BitcoinLib.Script.Opcodes.Stack.Rot
@type t :: Rot
@value 0x7B
@doc """
Returns 0x7b
## Examples
iex> BitcoinLib.Script.Opcodes.Stack.Rot.v()
0x7b
"""
@spec v() :: 0x7B
def v do
@value
end
@doc """
Returns <<0x7b>>
## Examples
iex> BitcoinLib.Script.Opcodes.Stack.Rot.encode()
<<0x7b>>
"""
def encode() do
<<@value::8>>
end
@doc """
The 3rd item down the stack is moved to the top.
## Examples
iex> stack = [4, 3, 6, 1, 2]
...> %BitcoinLib.Script.Opcodes.Stack.Rot{}
...> |> BitcoinLib.Script.Opcodes.Stack.Rot.execute(stack)
{:ok, [6, 4, 3, 1, 2]}
"""
@spec execute(Rot.t(), list()) :: {:ok, list()} | {:error, binary()}
def execute(_opcode, []), do: {:error, "trying to execute OP_ROT on an empty stack"}
def execute(_opcode, [_]), do: {:error, "trying to execute OP_ROT on a one element stack"}
def execute(_opcode, [_, _]), do: {:error, "trying to execute OP_ROT on a two element stack"}
def execute(_opcode, [x1 | [x2 | [x3 | remaining]]]) do
{:ok, [x3 | [x1 | [x2 | remaining]]]}
end
end