Thanks to visit codestin.com
Credit goes to github.com

Skip to content

ferranbt/fastssz

Repository files navigation

FastSSZ

Chat Badge

The FastSSZ project in this repository is a combination of two things: a high performant low level library to work with SSZ encodings (root of this project) and the (sszgen) code generator that generates the SSZ encodings for Go structs using the SSZ library. By combining both, this library achieves peak Go native performance and zero memory allocation. The repository uses as test the official Ethereum SSZ tests (spectests) for the Consensus Spec data structures.

⚠️ Version 0.2.0 Notice
Version 0.2.0 is a major release with significant breaking changes and represents a substantial refactor of the codebase. Code generated with v1.x is not compatible with the v2.0 API and must be regenerated. This version has not gone through all the production environments as previous releases, so use with caution.

If you are only looking for the Consensus data structures and types with the SSZ support, it is recommended to use go-eth-consensus instead, since it is already integrated with other parts of the Consensus stack, like the Beacon http API.

Clone:

$ git clone [email protected]:ferranbt/fastssz.git

Download the eth2.0 spec tests

$ make get-spec-tests

Regenerate the test spec encodings:

$ make build-spec-tests

Generate encodings for a specific package:

$ go run sszgen/*.go --path ./ethereumapis/eth/v1alpha1 [--objs BeaconBlock,Eth1Data]

Optionally, you can specify the objs you want to generate. Otherwise, it will generate encodings for all structs in the package. Note that if a struct does not have 'ssz' tags when required (i.e size of arrays), the generator will fail.

By default, it generates a file with the prefix '_encoding.go' for each file that contains a generated struct. Optionally, you can combine all the outputs in a single file with the 'output' flag.

$ go run sszgen/*.go --path ./ethereumapis/eth/v1alpha1 --output ./ethereumapis/eth/v1alpha1/encoding.go

Test the spectests:

$ go test -v ./spectests/... -run TestSpec

Run the fuzzer:

$ FUZZ_TESTS=True go test -v ./spectests/... -run TestFuzz

To install the generator run:

$ go get github.com/ferranbt/fastssz/sszgen

Benchmark (BeaconBlock):

$ go test -v ./spectests/... -run=XXX -bench=.
goos: linux
goarch: amd64
pkg: github.com/ferranbt/fastssz/spectests
cpu: AMD Ryzen 5 3600 6-Core Processor
BenchmarkMarshal_Fast
BenchmarkMarshal_Fast-12                  511036              3208 ns/op            8192 B/op          1 allocs/op
BenchmarkMarshal_SuperFast
BenchmarkMarshal_SuperFast-12            1448364               770.2 ns/op             0 B/op          0 allocs/op
BenchmarkUnMarshal_Fast
BenchmarkUnMarshal_Fast-12                 93079             15928 ns/op           12280 B/op        230 allocs/op
BenchmarkHashTreeRoot_Fast
BenchmarkHashTreeRoot_Fast-12              29918             39231 ns/op               0 B/op          0 allocs/op
BenchmarkHashTreeRoot_SuperFast
BenchmarkHashTreeRoot_SuperFast-12         53028             20088 ns/op               0 B/op          0 allocs/op
BenchmarkProof_Tree
BenchmarkProof_Tree-12                      4958            245046 ns/op          117661 B/op       1601 allocs/op
PASS
ok      github.com/ferranbt/fastssz/spectests   9.404s

Package reference

To reference a struct from another package use the '--include' flag to point to that package.

Example:

$ go run sszgen/*.go --path ./example2
$ go run sszgen/*.go --path ./example
[ERR]: could not find struct with name 'Checkpoint'
$ go run sszgen/*.go --path ./example --include ./example2

There are some caveats required to use this functionality.

  • If multiple input paths import the same package, all of them need to import it with the same alias if any.
  • If the folder of the package is not the same as the name of the package, any input file that imports this package needs to do it with an alias.

Fast HashTreeRoot

Fastssz integrates with Prysm gohashtree library to do high performance and concurrent Sha256 hashing. It achieves a 2x performance improvement with respect to the normal sequential hashing.

In order to use this feature, enable manually the hash function in the Hasher like in the benchmark example.

Dynamic Struct Tags for Multi-Chain Support

FastSSZ supports dynamic struct tags to accommodate different chain specifications and network presets using variable-based sizing. This feature addresses the need to support multiple blockchain networks (like Ethereum, Gnosis, etc.) and different network presets.

Use the var(<variable_name>) syntax in SSZ tags to define variable-based sizing:

type ExecutionPayload struct {
    Withdrawals []*Withdrawal `ssz-max:"var(maxWithdrawals)"`
    BlockRoots  [][]byte      `ssz-size:"var(historicalRootSize),32"`
}

FastSSZ generates code that references the specified variable for size constraints and comparisons, but does not generate the variable itself. You must provide a uint64 variable with the specified name in the destination package.

This feature has been tested on the Ethereum eth2.0 specs and all types from there are supported. However, some edge cases might not be fully ready yet - please open an issue if you encounter any problems.

Using these variables does not add any performance overhead to the generated SSZ operations.

About

Fast Ethereum2.0 SSZ encoder/decoder

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 28

Languages