A convenient interface for specifying types
In most cases, types are specified by users in simple form. They will be parsed to a FullSSZType before any processing.
Assert that value is valid for the type.
Throws an [[Error]] if the value is invalid.
const myDataType: SimpleContainerType = {
fields: [
["a", "uint16"],
["b", "bool"],
["c", "bytes96"],
],
};
assertValidValue({
a: 10,
b: true,
c: Buffer.alloc(96),
}, myDataType); // no error
assertValidValue({
a: 10,
b: true,
c: 10, // errors, expects Buffer, length 96
}, myDataType); // error because of `c`
Deeply clone a value of an SSZ type
Most useful to clone arrays/objects
const n: number = clone(10, "uint64");
const b: boolean = clone(true, "bool");
const buf: Buffer = clone(
Buffer.from("abcd", "hex"),
{
elementType: "byte",
maxLength: 10,
}
);
const arr: number[] = clone(
[0, 1, 2, 3, 4, 5],
{
elementType: "uint32",
maxLength: 10,
}
);
interface myData {
a: number;
b: boolean;
c: Buffer;
}
const myDataType: SimpleContainerType = {
fields: [
["a", "uint16"],
["b", "bool"],
["c", "bytes96"],
],
};
const obj: myData = clone(
{a: 10, b: false, c: Buffer.alloc(96)},
myDataType
);
Deserialize, according to the SSZ spec
let data: Buffer = sszSerializedData;
// deserialize a number
const n: number = deserialize(
data,
"uint32" // "uintN", N == length in bits, N <= 32
);
// deserialize a BN bignumber
import BN from "bn.js";
const bn: BN = deserialize(
data,
"uint64" // "uintN", N == length in bits, N >= 64
);
// deserialize a number (forced)
const m: number = deserialize(
data,
"number64" // "numberN", N == length in bits
);
// deserialize a boolean
const b: boolean = deserialize(data, "bool");
// deserialize a bit list
import {BitList} from "@chainsafe/bit-utils";
const bl: BitList = deserialize(data, {
elementType: "bool",
maxLength: 10, // max number of bits
});
// deserialize a bit vector
import {BitVector} from "@chainsafe/bit-utils";
const bv: BitVector = deserialize(data, {
elementType: "bool",
length: 10, // length in bits
});
// deserialize a variable-length byte array, max-length required
const buf1: Buffer = deserialize(data, {
elementType: "byte", // "byte", "uint8", or "number8"
maxLength: 10, // max number of bytes
});
// deserialize a fixed-length byte array
const buf2: Buffer = serialize(
data,
"bytes2" // "bytesN", N == length in bytes
);
// deserialize a variable-length array, max-length required
const arr1: number[] = deserialize(data, {
elementType: "uint32",
maxLength: 10, // max number of elements
});
// deserialize a fixed-length array
const arr2: number[] = deserialize([0, 1, 2, 3, 4, 5], {
elementType: "uint32",
length: 6,
});
// deserialize an object
interface myData {
a: number;
b: boolean;
c: Buffer;
}
const myDataType: SimpleContainerType = {
fields: [
["a", "uint16"], // [fieldName, fieldType]
["b", "bool"],
["c", "bytes96"],
],
};
const obj: myData = deserialize(data, myDataType);
Equality of two values of an SSZ type
Most useful to compare arrays/objects
equals(10, 10, "uint64");
equals(true, true, "bool");
equals(
Buffer.from("abcd", "hex"),
Buffer.from("abcd", "hex"),
{
elementType: "byte",
maxLength: 100,
}
);
equals(
[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
{
elementType: "uint32",
maxLength: 10,
}
);
const myDataType: SimpleContainerType = {
fields: [
["a", "uint16"],
["b", "bool"],
["c", "bytes96"],
],
};
equals(
{a: 10, b: false, c: Buffer.alloc(96)},
{a: 10, b: false, c: Buffer.alloc(96)},
myDataType
);
Hash used for hashTreeRoot
Merkleize an SSZ value
let buf: Buffer;
// merkleize a number
buf = hashTreeRoot(
10,
"uint64" // "uintN", N == length in bits
);
// merkleize a BN bignumber
import BN from "bn.js";
buf = hashTreeRoot(new BN("1000000000000000000"), "uint64");
// merkleize a boolean
buf = hashTreeRoot(true, "bool");
// merkleize a bit list
import {BitList} from "@chainsafe/bit-utils";
buf = hashTreeRoot(BitList.fromBitfield(Buffer.alloc(1), 8), {
elementType: "bool",
maxLength: 10, // max number of bits
});
// merkleize a bit vector
import {BitVector} from "@chainsafe/bit-utils";
buf = hashTreeRoot(BitVector.fromBitfield(Buffer.alloc(1), 8), {
elementType: "bool",
length: 8, // length in bits
});
// merkleize a variable-length byte array, max-length required
buf = hashTreeRoot(Buffer.from("abcd", "hex"), {
elementType: "byte", // "byte", "uint8", or "number8"
maxLength: 10, // max number of bytes
});
// merkleize a fixed-length byte array
buf = hashTreeRoot(
Buffer.from("abcd", "hex"),
"bytes2" // "bytesN", N == length in bytes
);
// merkleize a variable-length array, max-length required
buf = hashTreeRoot([0, 1, 2, 3, 4, 5], {
elementType: "uint32",
maxLength: 10, // max number of elements
});
// merkleize a fixed-length array
buf = hashTreeRoot([0, 1, 2, 3, 4, 5], {
elementType: "uint32",
length: 6,
});
// merkleize an object
const myDataType: SimpleContainerType = {
fields: [
["a", "uint16"], // [fieldName, fieldType]
["b", "bool"],
["c", "bytes96"],
],
};
buf = hashTreeRoot({a: 10, b: false, c: Buffer.alloc(96)}, myDataType);
A variable-size type is a list and all types that contain a variable-size type.
All other types are said to be fixed-size
Recursively expand an AnySSZType into a FullSSZType
Serialize, according to the SSZ spec
let buf: Buffer;
// serialize a number
buf = serialize(
10,
"uint64" // "uintN", N == length in bits
);
// serialize a BN bignumber
import BN from "bn.js";
buf = serialize(new BN("1000000000000000000"), "uint64");
// serialize a boolean
buf = serialize(true, "bool");
// serialize a bit list
import {BitList} from "@chainsafe/bit-utils";
buf = serialize(BitList.fromBitfield(Buffer.alloc(1), 8), {
elementType: "bool",
maxLength: 10, // max number of bits
});
// serialize a bit vector
import {BitVector} from "@chainsafe/bit-utils";
buf = serialize(BitVector.fromBitfield(Buffer.alloc(1), 8), {
elementType: "bool",
length: 8, // length in bits
});
// serialize a variable-length byte array, max-length required
buf = serialize(Buffer.from("abcd", "hex"), {
elementType: "byte", // "byte", "uint8", or "number8"
maxLength: 10, // max number of bytes
});
// serialize a fixed-length byte array
buf = serialize(
Buffer.from("abcd", "hex"),
"bytes2" // "bytesN", N == length in bytes
);
// serialize a variable-length array, max-length required
buf = serialize([0, 1, 2, 3, 4, 5], {
elementType: "uint32",
maxLength: 10, // max number of elements
});
// serialize a fixed-length array
buf = serialize([0, 1, 2, 3, 4, 5], {
elementType: "uint32",
length: 6,
});
// serialize an object
const myDataType: SimpleContainerType = {
fields: [
["a", "uint16"], // [fieldName, fieldType]
["b", "bool"],
["c", "bytes96"],
],
};
buf = serialize({a: 10, b: false, c: Buffer.alloc(96)}, myDataType);
hashTreeRoot an SSZ object w/o its last field
This is useful if we assume the final field is a signature. Used for signing/verifying signed data
interface myData {
a: number;
b: boolean;
c: Buffer; // <- signature
}
const myDataType: SimpleContainerType = {
fields: [
["a", "uint16"],
["b", "bool"],
["c", "bytes96"],
],
};
let d: myData = {
a: 5,
b: false,
c: Buffer.alloc(0),
};
// create the signing root
const root: Buffer = signingRoot(d, myDataType);
// sign the signing root, store as the final field
d.c = sign(privateKey, root); // hypothetical `sign` function
// if others receive `d`, they can verify the signature
verify(publicKey, signingRoot(d, myDataType), d.c); // hypothetical `verify` function
Generated using TypeDoc
A more consistent and verbose interface for specifying types
Full types are used internally.