Skip to content

plutigo

An implementation of Plutus in pure Go.

This package aims to only support Untyped Plutus Core because that is all that is needed for a full node. The other stuff like Typed Plutus Core and Plutus IR is for Plinth.

Features

  • Complete Plutus Support: Implements Untyped Plutus Core (UPLC) evaluation
  • Multi-Version Support: Compatible with Plutus V1, V2, V3, and initial Plutus V4 support
  • Cost Model Integration: Automatic cost model selection based on Plutus version (the Plutus V4 cost model is provisional; only multiIndexArray still uses a placeholder cost)
  • High Performance: Optimized CEK machine implementation in pure Go
  • Cryptographic Operations: Full BLS12-381 support using gnark-crypto
  • Comprehensive Testing: 49.9% test coverage with fuzz testing and property-based testing

Supported CIPs

plutigo implements the following Cardano Improvement Proposals (CIPs) related to Plutus Core:

  • CIP-0042: serialiseData builtin for CBOR serialization of Plutus Data
  • CIP-0049: ECDSA and Schnorr signature verification builtins
  • CIP-0058: Bitwise primitives for integers
  • CIP-0085: Sums-of-products (constructor and case expressions)
  • CIP-0091: Optimized builtin evaluation (no forced evaluation for saturated calls)
  • CIP-0101: keccak_256 hash function
  • CIP-0109: expModInteger for modular exponentiation
  • CIP-0121: Integer to ByteString conversions
  • CIP-0122: Logical operations on ByteString
  • CIP-0123: Bitwise operations on ByteString
  • CIP-0127: ripemd_160 hash function
  • CIP-0132: dropList builtin
  • CIP-0133: BLS12-381 multi-scalar multiplication
  • CIP-0138: Array type and operations (lengthOfArray, listToArray, indexArray)
  • CIP-0153: Mary-era Value builtins (insertCoin, lookupCoin, scaleValue, unionValue, valueContains)
  • CIP-0156: multiIndexArray builtin for batch array indexing
  • CIP-0381: BLS12-381 pairing operations

Testing and Conformance

All implemented CIPs include comprehensive conformance tests ensuring correct behavior and cost modeling.

Mainnet parity corpora can be executed with plutigo-replay; see the replay corpus guide for the normalized transaction format and reporting workflow.

Performance

plutigo is optimized for high-performance Plutus script evaluation:

Cryptographic Operations (Go 1.26, ARM64)

  • SHA256: 100 ns/op
  • Blake2b-256: 325 ns/op
  • Keccak-256: 814 ns/op
  • Ed25519 Verify: 204 μs/op
  • ECDSA Verify: 365 μs/op
  • BLS12-381 G1 Add: 3.4 μs/op
  • BLS12-381 Pairing: 3.4 ms/op

Plutus Script Evaluation (Go 1.26, ARM64)

Evaluates complex smart contracts in milliseconds with accurate cost modeling. Go 1.26 delivers ~10% faster full-script execution vs Go 1.25 across all Plutus test scripts.

Architecture

Core Components

  • CEK Machine (cek/): Optimized evaluation engine with object pooling and memory-efficient state management
  • Syntax Layer (syn/): Parser, pretty-printer, and AST transformations with De Bruijn conversion
  • Builtin Functions (builtin/): Complete Plutus builtin function implementations
  • Data Layer (data/): CBOR encoding/decoding for Plutus data types

Design Decisions

  • Pure Go: No CGO dependencies for better portability and security
  • Memory Safety: Comprehensive nil-pointer analysis and bounds checking
  • Version Compatibility: Automatic cost model and builtin selection by Plutus version
  • Testing First: Property-based testing and fuzzing ensure correctness

Usage

Install

go get github.com/blinklabs-io/plutigo

Example

package main

import (
	"context"
	"fmt"

	"github.com/blinklabs-io/plutigo/cek"
	"github.com/blinklabs-io/plutigo/syn"
)

func main() {
	input := `
	(program 1.2.0
	  [
	    [
	      (builtin addInteger)
	      (con integer 1)
	    ]
	    (con integer 1)
	  ]
	)
	`

	pprogram, _ := syn.Parse(input)

	program, _ := syn.NameToDeBruijn(pprogram)

	// Create a machine using the default cost model at protocol major 200.
	evalCtx := cek.NewDefaultEvalContext(
		program.Version,
		cek.ProtoVersion{Major: 200},
	)
	machine := cek.NewMachine[syn.DeBruijn](program.Version, 0, evalCtx)

	runCtx := context.Background()
	term, _ := machine.RunContext(runCtx, program.Term)

	prettyTerm := syn.PrettyTerm[syn.DeBruijn](term)

	fmt.Println(prettyTerm) // Output: (con integer 2)
}

Pass the caller's context.Context as runCtx when it has a cancellation scope. Cancellation is cooperative and synchronous: the call returns only after CEK evaluation and result discharge have stopped, and it does not start an evaluator goroutine. A builtin already executing must return before the machine can observe cancellation.

Plutus Version Support

plutigo supports all major Plutus protocol versions:

  • Plutus V1 (1.0.0): Alonzo era - Basic builtin functions
  • Plutus V2 (1.1.0): Vasil era - Additional crypto builtins
  • Plutus V3 (1.2.0+): Chang+ era - Latest features and optimizations
  • Plutus V4 (1.3.0+): Initial support with placeholder cost models

The library selects cost models and builtin behavior from the Plutus ledger language supplied to NewMachine and the evaluation context. On-chain callers must use the ledger language rather than infer it from the UPLC program header.

Development

Prerequisites

  • Go 1.25+ (Go 1.26+ recommended for ~10% better performance)
  • make

Setup

git clone https://github.com/blinklabs-io/plutigo.git
cd plutigo
go mod tidy

Testing

# Run all tests
make test

# Run benchmarks
make bench

# Run fuzz tests
make fuzz

Code Quality

The project maintains high code quality standards:

  • Linting: Passes golangci-lint with zero issues
  • Nil Safety: Passes nilaway static analysis
  • Test Coverage: 49.9% coverage across all packages
  • Fuzz Testing: Continuous fuzzing for parsing and evaluation

Contributing

We welcome contributions! Please see our Development Guide for setup, workflow, and contribution guidelines.

For organization-wide policies, see the Blink Labs Contributing Guide.

About

Untyped Plutus Core in Go (Plutus VM)

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

38 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages