Dynamic SSZ is a Go library for SSZ encoding/decoding with support for dynamic field sizes and code generation. It provides runtime flexibility while maintaining high performance through optional static code generation.
- π§ Dynamic Field Sizes - Support for runtime-determined field sizes based on configuration
- β‘ Reflection-Based Processing - Works instantly with any SSZ-compatible types - no code generation required for prototyping
- ποΈ Code Generation - Optional static code generation for maximum performance (2-3x faster than dynamic processing)
- π CLI Tool - Standalone
dynssz-gencommand for easy code generation from any Go package - π‘ Streaming Support - Memory-efficient streaming to/from
io.Reader/io.Writerfor large data - π Hybrid Approach - Seamlessly combines with fastssz for optimal efficiency
- ποΈ SSZ Views - Support for multiple SSZ schemas on the same runtime type (useful for Ethereum fork handling)
- π¦ Minimal Dependencies - Core library has minimal external dependencies
- β Spec Compliant - Fully compliant with SSZ specification and Ethereum consensus tests
- π§© Extended Types - Optional support for signed integers, floats, big.Int, and optional types (non-standard)
- β Reflection-based dynamic marshaling/unmarshaling/HTR: Production ready - battle-tested in various toolings and stable
- β Code generator: Production ready - feature complete and functionally verified through extensive fuzz testing, though less battle-tested in production environments compared to the reflection code paths
go get github.com/pk910/dynamic-sszimport dynssz "github.com/pk910/dynamic-ssz"
// Define your types with SSZ tags
type MyStruct struct {
FixedArray [32]byte
DynamicList []uint64 `ssz-max:"1000"`
ConfigBased []byte `ssz-max:"1024" dynssz-max:"MAX_SIZE"`
}
// Create a DynSsz instance with your configuration
specs := map[string]any{
"MAX_SIZE": uint64(2048),
}
ds := dynssz.NewDynSsz(specs)
// Marshal
data, err := ds.MarshalSSZ(myObject)
// Unmarshal
err = ds.UnmarshalSSZ(&myObject, data)
// Hash Tree Root
root, err := ds.HashTreeRoot(myObject)The ssz-max and dynssz-max tags work together: ssz-max provides a static fallback, while dynssz-max references a spec value resolved at runtime. If the spec value is available it overrides the static default; otherwise the static value is used. This lets the same types work across different network presets (mainnet, minimal, custom testnets).
For maximum performance, use code generation with the dynssz-gen CLI tool:
go install github.com/pk910/dynamic-ssz/dynssz-gen@latestGenerate SSZ methods:
# Generate for types in current package
dynssz-gen -package . -types "MyStruct,OtherType" -output generated.go
# Generate for types in external package
dynssz-gen -package github.com/example/types -types "Block" -output block_ssz.goGenerated code produces optimized SSZ methods that eliminate reflection overhead. Important: Always use ds.MarshalSSZ(), ds.UnmarshalSSZ(), etc. as your entry points - the runtime automatically delegates to generated methods when available. Do not call generated methods (like MarshalSSZDyn) directly, as this creates a circular dependency that prevents regeneration. See the Code Generation Guide for details.
Dynamic SSZ is benchmarked against other SSZ libraries (including fastssz) in a dedicated benchmark repository: pk910/ssz-benchmark (view graphs).
The benchmarks compare encoding, decoding, and hash tree root performance across different SSZ libraries using common Ethereum consensus data structures.
View interactive benchmark results and historical trends at: https://pk910.github.io/ssz-benchmark/
The library includes comprehensive testing infrastructure:
- Unit Tests: Fast, isolated tests for core functionality
- Spec Tests: Ethereum consensus specification compliance tests
- Fuzz Testing: Continuous fuzzing via CI that generates random SSZ type structures and verifies correctness by comparing reflection and codegen implementations across marshal, unmarshal, hash tree root, and streaming operations
- Examples: Working examples that are automatically tested
- Performance Tests: Benchmarking and regression testing
- Getting Started Guide
- Supported Types
- Struct Tags & Annotations
- Code Generation Guide
- SSZ Views
- Merkle Proofs
- Streaming Support
- Type Wrapper
- Extended Types (non-standard)
- API Reference
- Performance Guide
- Troubleshooting
- Examples
Check out the examples directory for:
- Basic encoding/decoding
- Code generation setup
- Ethereum types integration
- Custom specifications
- Multi-dimensional arrays
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
Dynamic SSZ is licensed under the Apache 2.0 License.