New OpCodes - Algorand Specifications

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

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:

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 :


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:

For the double dummy OpCode:


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).