## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

- Auto
- Light
- Dark

# Algorand Specifications

Here we describe the process of adding a new AVM OpCode to `go-algorand` reference implementation, providing the example of a dummy `double` OpCode.

The AVM OpCodes are versioned (`langspec_v`) and can be categorized as:

- Arithmetic and Logic Operations
- Byte Array Manipulation
- Cryptographic Operations
- Pushing Values on Stack/Heap (Constants, Txn / ASA / App / Account / Global Fields)
- Control Flow
- State Access
- Inner Transactions

Most OpCodes logic lives in `data/transactions/logic/eval.go`. Some exceptions are larger families of OpCodes with their own files (e.g., `box.go`).

For the dummy `double` OpCode example, let’s define the _operator_ function in `data/transactions/logic/eval.go` :

```go

func opDouble(cx *EvalContext) error {
    last := len(cx.Stack) - 1
    res, carry := bits.Add64(cx.Stack[last].Uint, cx.Stack[last].Uint, 0)
    if carry > 0 {
        return errors.New("double overflowed")
    }
    cx.Stack[last].Uint = res
    return nil
}
```

OpCodes are included by adding them to `opcodes.go` with a unique byte value.

Let’s add the new `OpSpec` value in the `OpSpecs` array.

The format is `{0x01, "sha256", opSHA256, proto("b:b{32}"), 2, costly(35)}`.

The arguments may be interpreted as follows:

- A `byte` indicating the OpCode number,

- A `string` with the identifier of the OpCode,

- The `eval.go` function that handles OpCode execution (defined above),

- A `proto` structure defined through the `proto()` function. This indicates the actual signature of the new OpCode.
  - The element before `:` indicates the values _to be popped from the top_ of the stack,
  - The element after `:` indicates the values _to be pushed to the stack,_
  - The letter identifies the type of arguments. In case of `byte` arrays the length could be expressed as a number in curly brackets.
- The AVM `version` where the new OpCode is introduced,

- The `cost` of the new OpCode.

For the `double` dummy OpCode:

```go

var OpSpecs = []OpSpec{
    ...
    // Double OpCode
    {0x75, "double", opDouble, proto("i:i"), 42, detDefault()},
    ...
}
```

Run `make` from within the `data/transactions/logic/` directory to generate an updated _language specification_ (`langspec_v`) and TEAL docs.

Run `make` from the root of the `go-algorand` directory to build new `algod` binary.

Tests are organized in the accompanying `data/transactions/logic/eval_test.go` file.

Let’s test the new OpCode locally by generating a netgoal template and running a new Local Network.

> Be sure to set the network’s Consensus Version to `future` if you’re adding an OpCode to a future AVM version.

Estimate the new OpCode budget (e.g., benchmarking against similar ones).
