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:
- sigmastate-interpreter — Reference Scala implementation
- sigma-rust — Rust implementation
- ergo — Ergo node
Version history of ErgoScript and the SigmaState interpreter12.
Protocol Versions Overview
| Block Version | Activated Version | ErgoTree Version | Name | Release |
|---|---|---|---|---|
| 1 | 0 | 0 | Initial | Mainnet launch |
| 2 | 1 | 1 | v4.0 | 2020 |
| 3 | 2 | 2 | v5.0 (JIT) | 2022 |
| 4 | 3 | 3 | v6.0 | 2024/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:
FixedCostfor constant-time operationsPerItemCostfor collection operationsTypeBasedCostfor type-dependent costsDynamicCostfor complex operations
Costing Changes:
AOT: Fixed costs estimated at compile time
JIT: Actual costs computed during execution
New Operations:
Context.dataInputs- access data inputsContext.headers- access last 10 block headersContext.preHeader- access current block pre-headerHeadertype with full block header accessPreHeadertype
Soft-Fork Infrastructure:
ValidationRulesframework- Configurable rule status (enabled, disabled, replaced)
trySoftForkablepattern 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 arraytoBits: Convert to boolean arraybitwiseInverse: Bitwise NOTbitwiseOr,bitwiseAnd,bitwiseXor: Bitwise operationsshiftLeft,shiftRight: Bit shifting
BigInt:
toUnsigned: Convert to UnsignedBigInttoUnsignedMod: Modular conversion
UnsignedBigInt:
modInverse: Modular multiplicative inverseplusMod,subtractMod,multiplyMod: Modular arithmeticmod: Modulo operationtoSigned: Convert to signed BigInt
GroupElement:
expUnsigned: Scalar multiplication with unsigned exponent
Header:
checkPow: Verify Proof-of-Work solution
Collection:
patch: Replace range with another collectionupdated: Update single elementupdateMany: Batch update elementsindexOf: Find element indexzip: Pair with another collectionreverse: Reverse orderstartsWith,endsWith: Prefix/suffix checksget: Safe element access returning Option
Global:
serialize: Serialize any value to bytesfromBigEndianBytes: Decode big-endian bytesencodeNBits,decodeNBits: Difficulty encodingpowHit: 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:
- Version 0 scripts: Execute with v0 semantics
- Version 1 scripts: Execute with v1 semantics
- Version 2 scripts: Execute with JIT costing
- 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
UnsignedBigIntfor modular arithmetic (more efficient) - Use new collection methods (
reverse,zip, etc.) - Use
Header.checkPowfor PoW verification - Use
Global.serializefor value encoding
For Node Operators
Upgrading to v6:
- Update node software before activation height
- No action needed for existing scripts
- New features available after soft-fork activation
Feature Matrix
| Feature | v3.x | v4.0 | v5.0 | v6.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
Scala: VersionContext.scala
Rust: ergo_tree.rs (ErgoTreeVersion)