Simple Serialize is the serialization algorithm standard for all data structures common across Ethereum 2.0 client implementations. It is outlined in the official Ethereum 2.0 specification.
A more in-depth breakdown of SSZ is available in this section of our official documentation. If you still have questions, feel free to stop by either our Discord or Gitter and a member of the team or our community will be happy to assist you.
Our simple serialize API is designed to match the syntax of the popular JSON marshal / unmarshal API from the Go standard library. Below are samples of each in use:
marshal
example:
// Marshal val and output the result.
func Marshal(val interface{}) ([]byte, error)
unmarshal
example:
// Unmarshal data from input and output it into the object pointed by pointer val.
func Unmarshal(input []byte, val interface{}) error
HashTreeRoot
SSZ marshals a value and packs its serialized bytes into leaves of a Merkle trie. It then determines the root of this trie.
HashTreeRoot
example:
func HashTreeRoot(val interface{}) ([32]byte, error)
Notice: SSZ supports bool
, uint8
, uint16
, uint32
, uint64
, slice
, array
, struct
and pointer
data types.
- To begin, we create this basic struct:
type exampleStruct1 struct {
Field1 uint8
Field2 []byte
}
- Next, we can encode the defined object like so:
e1 := exampleStruct1{
Field1: 10,
Field2: []byte{1, 2, 3, 4},
}
encoded, err := Marshal(e1)
if err != nil {
return fmt.Errorf("failed to marshal: %v", err)
}
- (Optional) It is also possible to specify the size of a struct's field by utilising ssz-specific field tags:
type exampleStruct struct {
Field1 uint8
Field2 []byte `ssz:"size=32"`
}
This will treat Field2
as as [32]byte
array when marshaling.
- (Optional) For unbounded fields or multidimensional slices, SSZ size tags can also be used:
type exampleStruct struct {
Field1 uint8
Field2 [][]byte `ssz:"size=?,32"`
}
This will treat Field2
as type [][32]byte
when marshaling a struct of that type.
- Similarly, you can
unmarshal
encoded bytes into its original form:
var e2 exampleStruct
if err = Unmarshal(encoded, &e2); err != nil {
return fmt.Errorf("failed to unmarshal: %v", err)
}
reflect.DeepEqual(e1, e2) // Returns true as e2 now has the same content as e1.
- To calculate tree-hash root of the object run:
root, err := HashTreeRoot(e1)
if err != nil {
return fmt.Errorf("failed to compute Merkle root: %v", err)
}
We have put all of our contribution guidelines into CONTRIBUTING.md! Check it out to get started.
Brought to you by Prysmatic Labs with a permissive Apache License 2.0.