ssz
Simple Serialize (SSZ)
Install
npm install @chainsafe/ssz
Usage
See https://chainsafe.github.io/ssz-js for the autogenerated API docs.
In order to properly serialize/deserialize/hash values, we need both the value and the "type" of the value.
Types
The simple serialization spec operates over a few specific types.
Types are either specified in a simplified form (eg: "uint32"
) or an extended form
(eg: {type: Type.uint, byteLength: 4, offset: 0, useNumber: false}
). In most cases, the simplified form suffices.
Uint
A uint serialization value may be either a js number
or a BN
from bn.js.
A uint type is specified by either "uintN"
or "numberN"
, where N is the number of bits to serialize.
uintN
> 48 bits is deserialized to a BN
else deserialized to a number
.
Every numberN
is deserialized to a number.
Boolean
A boolean serialization value must be either true
or false
. Anything other input will throw an Error
.
The boolean type is specified as "bool"
.
Vector
A "vector" according to the spec is a fixed-length list with every element of the same type.
A vector serialization value may be either an Array
or Buffer
.
Vector types are specified as either "bytesN"
or [elementType, vectorlength]
bytesN
is deserialized to Buffer
.
[elementType, vectorLength]
is deserialized to Array<elementType>
unless elementType is byte
, when the value is deserialized to Buffer
.
List
A "list" according to the spec is a list of unspecified length with every element of the same type.
A list serialization value may be either an Array
or Buffer
.
Tuple types are specified as either "bytes"
or [elementType]
bytes
is deserialized to Buffer
.
[elementType]
is deserialized to Array<elementType>
unless elementType is byte
, when the value is deserialized to Buffer
.
Container
A "container" according to the spec is a collection of values where the type of each element may differ.
A container serialization value must be an Object
.
The container serialization type must be an Object
, with a string name
, and a fields
value of `Array<[fieldName, fieldType]>.
Extended form
See FullSSZType
in src/types.ts
for more information.
Examples
Serialize:
Serialize takes a value and a type as input and returns a Buffer.
let buf: Buffer
buf = ssz.serialize(true, 'bool')
buf = ssz.serialize(16, 'uint32')
const BN = require('bn.js')
buf = ssc.serialize(new BN(0xFFFFFFFFFFFFFFF0), 'uint64')
let bytes = Buffer.from([1, 2, 3, 4])
buf = ssz.serialize(bytes, 'bytes')
buf = ssz.serialize(bytes, 'bytes4')
let array = [1, 2, 3]
buf = ssz.serialize(array, ['uint16'])
let obj = {
a: Buffer.from('hello'),
b: 10,
c: false
}
let myType = {
name: 'myType',
fields: [
['a', 'bytes'],
['b', 'int16'],
['c', 'bool'],
],
}
buf = ssz.serialize(obj, myType)
Deserialize
Deserialize takes a Buffer and a type as input and returns a value.
let b: boolean = ssz.deserialize(buf, 'bool')
let n: BN = ssz.deserialize(buf, 'uint64')
let n: number = ssz.deserialize(buf, 'number64')
let b: Buffer = ssz.deserialize(buf, 'bytes')
let a: number[] = ssz.deserialize(buf, ['uint32'])
interface myType {
a: boolean;
b: number;
}
let myType = {
name: 'myType',
fields: [
['a', 'bool'],
['b', 'uint8'],
],
}
let o: myType = ssz.deserialize(buf, myType)
Hash Tree Root
Hash Tree Root returns a hash of a SSZ-able value.
ssz.hashTreeRoot(true, 'bool')
ssz.hashTreeRoot(5, 'uint16')
ssz.hashTreeRoot(Buffer.from([1, 2, 3, 4]), 'bytes')
ssz.hashTreeRoot([true, true], ['bool'])
let myType = {
fields: [
['a', 'bool'],
['b', 'uint8'],
],
}
ssz.hashTreeRoot({a: true, b: 5}, myType)
Signing Root
An object type can be hashed without its final field using signingRoot
. This is useful if we assume the final field is a signature.
let myType = {
fields: [
['a', 'bool'],
['b', 'bool'],
['c', 'bytes48'],
],
}
let data = {
a: true,
b: true,
c: null,
}
let signingRoot = ssz.signingRoot(data, myType)
data.c = privateKey.sign(signingRoot)
publicKey.verify(signingRoot(data, myType))
License
Apache 2.0