Appendix F: Version History

PRE-ALPHA WARNING: This is a pre-alpha version of The Sigma Book. Content may be incomplete, inaccurate, or subject to change. Do not use as a source of truth. For authoritative information, consult the official repositories:

Version history of ErgoScript and the SigmaState interpreter12.

Protocol Versions Overview

Block VersionActivated VersionErgoTree VersionNameRelease
100InitialMainnet launch
211v4.02020
322v5.0 (JIT)2022
433v6.02024/2025

Version Context

const VersionContext = struct {
    activated_version: u8,  // Protocol version on network
    ergo_tree_version: u8,  // Version of currently executing script

    pub const MAX_SUPPORTED_SCRIPT_VERSION: u8 = 3; // Supports 0, 1, 2, 3
    pub const JIT_ACTIVATION_VERSION: u8 = 2;       // v5.0 JIT activation
    pub const V6_SOFT_FORK_VERSION: u8 = 3;         // v6.0 soft-fork

    pub fn isJitActivated(self: VersionContext) bool {
        return self.activated_version >= JIT_ACTIVATION_VERSION;
    }

    pub fn isV6Activated(self: VersionContext) bool {
        return self.activated_version >= V6_SOFT_FORK_VERSION;
    }
};

Version 1 (Initial - v3.x)

ErgoTree Version: 0

Features:

  • Core ErgoScript language
  • Basic types: Boolean, Byte, Short, Int, Long, BigInt, GroupElement, SigmaProp
  • Collection operations: map, filter, fold, exists, forall
  • Sigma protocols: ProveDlog, ProveDHTuple, AND, OR, THRESHOLD
  • Box operations: value, propositionBytes, id, registers R0-R9
  • Context access: INPUTS, OUTPUTS, HEIGHT, SELF

Limitations:

  • AOT (Ahead-of-Time) interpreter only
  • Fixed cost model
  • No constant segregation required

Version 2 (v4.0)

ErgoTree Version: 1 Block Version: 2

New Features:

  • Mandatory constant segregation flag
  • Improved script validation
  • Enhanced soft-fork mechanism
  • Size flag in ErgoTree header

Changes:

  • ErgoTree header now requires size bytes when flag is set
  • Better error handling for malformed scripts

Version 3 (v5.0 - JIT)

ErgoTree Version: 2 Block Version: 3 Activated Version: 2

This was the major interpreter upgrade replacing AOT with JIT costing.

Major Changes

New Interpreter Architecture:

  • JIT (Just-In-Time) costing model
  • Data-driven evaluation via eval() methods
  • Precise cost tracking per operation
  • Profiler support for cost measurement

New Cost Model:

  • FixedCost for constant-time operations
  • PerItemCost for collection operations
  • TypeBasedCost for type-dependent costs
  • DynamicCost for complex operations

Costing Changes:

AOT: Fixed costs estimated at compile time
JIT: Actual costs computed during execution

New Operations:

  • Context.dataInputs - access data inputs
  • Context.headers - access last 10 block headers
  • Context.preHeader - access current block pre-header
  • Header type with full block header access
  • PreHeader type

Soft-Fork Infrastructure:

  • ValidationRules framework
  • Configurable rule status (enabled, disabled, replaced)
  • trySoftForkable pattern for graceful degradation

AOT to JIT Transition

The transition happened at a specific block height. Scripts created before JIT activation continue to work, but new scripts benefit from more accurate costing.

Version 4 (v6.0 - Evolution)

ErgoTree Version: 3 Block Version: 4 Activated Version: 3

This soft-fork adds significant new functionality.

New Types

SUnsignedBigInt (Type code 9):

  • 256-bit unsigned integers
  • Modular arithmetic operations
  • Conversion between signed/unsigned

New Methods

Numeric Types (Byte, Short, Int, Long, BigInt):

  • toBytes: Convert to byte array
  • toBits: Convert to boolean array
  • bitwiseInverse: Bitwise NOT
  • bitwiseOr, bitwiseAnd, bitwiseXor: Bitwise operations
  • shiftLeft, shiftRight: Bit shifting

BigInt:

  • toUnsigned: Convert to UnsignedBigInt
  • toUnsignedMod: Modular conversion

UnsignedBigInt:

  • modInverse: Modular multiplicative inverse
  • plusMod, subtractMod, multiplyMod: Modular arithmetic
  • mod: Modulo operation
  • toSigned: Convert to signed BigInt

GroupElement:

  • expUnsigned: Scalar multiplication with unsigned exponent

Header:

  • checkPow: Verify Proof-of-Work solution

Collection:

  • patch: Replace range with another collection
  • updated: Update single element
  • updateMany: Batch update elements
  • indexOf: Find element index
  • zip: Pair with another collection
  • reverse: Reverse order
  • startsWith, endsWith: Prefix/suffix checks
  • get: Safe element access returning Option

Global:

  • serialize: Serialize any value to bytes
  • fromBigEndianBytes: Decode big-endian bytes
  • encodeNBits, decodeNBits: Difficulty encoding
  • powHit: Autolykos2 PoW verification

Version Checks

fn evaluateWithVersion(ctx: *VersionContext, expr: *const Expr) !Value {
    if (ctx.isV6Activated()) {
        // Use v6 methods and features
        return try evalV6(expr);
    } else if (ctx.isJitActivated()) {
        // Use JIT costing
        return try evalJit(expr);
    } else {
        // Legacy AOT path
        return try evalAot(expr);
    }
}

Backward Compatibility

Script Compatibility

All scripts created for earlier versions continue to work:

  1. Version 0 scripts: Execute with v0 semantics
  2. Version 1 scripts: Execute with v1 semantics
  3. Version 2 scripts: Execute with JIT costing
  4. Version 3 scripts: Full v6 features available

Method Resolution by Version

fn getMethods(ctx: *const VersionContext, type_code: u8) []const SMethod {
    const container = getTypeCompanion(type_code);
    if (ctx.isV6Activated()) {
        return container.all_methods;  // All methods including v6
    }
    return container.v5_methods;  // Pre-v6 methods only
}

Soft-Fork Safety

Unknown opcodes and methods in future versions are handled gracefully:

fn checkOpCode(opcode: u8, ctx: *const VersionContext) ValidationResult {
    if (isKnownOpcode(opcode)) return .validated;
    if (ctx.isSoftForkable(opcode)) return .soft_forkable;
    return .invalid;
}

Migration Guide

For Script Authors

v5 → v6:

  • Use UnsignedBigInt for modular arithmetic (more efficient)
  • Use new collection methods (reverse, zip, etc.)
  • Use Header.checkPow for PoW verification
  • Use Global.serialize for value encoding

For Node Operators

Upgrading to v6:

  1. Update node software before activation height
  2. No action needed for existing scripts
  3. New features available after soft-fork activation

Feature Matrix

Featurev3.xv4.0v5.0v6.0
Basic types
Sigma protocols
JIT costing--
Data inputs--
Headers access--
UnsignedBigInt---
Bitwise ops---
Collection updates---
PoW verification---
Serialization---

Test Coverage

Version-specific behavior is tested in:

  • LanguageSpecificationV5.scala (~9,690 lines)
  • LanguageSpecificationV6.scala (~3,081 lines)

These tests verify:

  • All operations produce expected results
  • Cost calculations are accurate
  • Version-gated features work correctly
  • Backward compatibility is maintained

Previous: Appendix E | Back to Book

2

Rust: ergo_tree.rs (ErgoTreeVersion)