Files
aitbc/dev/env/node_modules/micro-eth-signer/ssz.js
aitbc 816e258d4c refactor: move brother_node development artifact to dev/test-nodes subdirectory
Development Artifact Cleanup:
 BROTHER_NODE REORGANIZATION: Moved development test node to appropriate location
- dev/test-nodes/brother_node/: Moved from root directory for better organization
- Contains development configuration, test logs, and test chain data
- No impact on production systems - purely development/testing artifact

 DEVELOPMENT ARTIFACTS IDENTIFIED:
- Chain ID: aitbc-brother-chain (test/development chain)
- Ports: 8010 (P2P) and 8011 (RPC) - different from production
- Environment: .env file with test configuration
- Logs: rpc.log and node.log from development testing session (March 15, 2026)

 ROOT DIRECTORY CLEANUP: Removed development clutter from production directory
- brother_node/ moved to dev/test-nodes/brother_node/
- Root directory now contains only production-ready components
- Development artifacts properly organized in dev/ subdirectory

DIRECTORY STRUCTURE IMPROVEMENT:
📁 dev/test-nodes/: Development and testing node configurations
🏗️ Root Directory: Clean production structure with only essential components
🧪 Development Isolation: Test environments separated from production

BENEFITS:
 Clean Production Directory: No development artifacts in root
 Better Organization: Development nodes grouped in dev/ subdirectory
 Clear Separation: Production vs development environments clearly distinguished
 Maintainability: Easier to identify and manage development components

RESULT: Successfully moved brother_node development artifact to dev/test-nodes/ subdirectory, cleaning up the root directory while preserving development testing environment for future use.
2026-03-30 17:09:06 +02:00

1675 lines
70 KiB
JavaScript
Executable File

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Phase0BeaconState = exports.Phase0SignedBeaconBlock = exports.Phase0BeaconBlock = exports.AltairBeaconState = exports.AltairSignedBeaconBlock = exports.AltairBeaconBlock = exports.BellatrixBeaconState = exports.BellatrixSignedBeaconBlock = exports.BellatrixBeaconBlock = exports.BellatrixExecutionPayloadHeader = exports.CapellaBeaconState = exports.CapellaSignedBeaconBlock = exports.CapellaBeaconBlock = exports.CapellaExecutionPayloadHeader = exports.ETH2_PROFILES = exports.ETH2_CONSENSUS = exports.ETH2_TYPES = exports.bytes = exports.bool = exports.bit = exports.byte = exports.profile = exports.stableContainer = exports.bytevector = exports.bytelist = exports.union = exports.bitlist = exports.bitvector = exports.container = exports.list = exports.vector = exports.boolean = exports.uint256 = exports.uint128 = exports.uint64 = exports.uint32 = exports.uint16 = exports.uint8 = exports.ForkSlots = void 0;
const sha2_1 = require("@noble/hashes/sha2");
const P = require("micro-packed");
const utils_ts_1 = require("./utils.js");
/*
Simple serialize (SSZ) is the serialization method used on the Beacon Chain.
SSZ is designed to be deterministic and also to Merkleize efficiently.
SSZ can be thought of as having two components:
a serialization scheme and a Merkleization scheme
that is designed to work efficiently with the serialized data structure.
- https://github.com/ethereum/consensus-specs/blob/f5277700e3b89c4d62bd4e88a559c2b938c6b0a5/ssz/simple-serialize.md
- https://github.com/ethereum/consensus-specs/blob/f5277700e3b89c4d62bd4e88a559c2b938c6b0a5/ssz/merkle-proofs.md
- https://www.ssz.dev/show
API difference:
- containers (vec/list) have arguments like (len, child).
this is different from other SSZ library, but compatible with packed.
there is good reason to do that: it allows create anonymous structures inside:
`const t = SSZ.vector(10, SSZ.container({
...long multiline definition here...
}))`
if length is second argument it would look more complex and harder to read.
- bytes provided as bytes instead of hex strings (same as other libs)
*/
const BYTES_PER_CHUNK = 32; // Should be equal to digest size of hash
const EMPTY_CHUNK = new Uint8Array(BYTES_PER_CHUNK);
exports.ForkSlots = {
Phase0: 0,
Altair: 2375680,
Bellatrix: 4700013,
Capella: 6209536,
Deneb: 8626176,
};
// Utils for hashing
function chunks(data) {
const res = [];
for (let i = 0; i < Math.ceil(data.length / BYTES_PER_CHUNK); i++) {
const chunk = data.subarray(i * BYTES_PER_CHUNK, (i + 1) * BYTES_PER_CHUNK);
if (chunk.length === BYTES_PER_CHUNK)
res.push(chunk);
else {
const tmp = EMPTY_CHUNK.slice();
tmp.set(chunk);
res.push(tmp);
}
}
return res;
}
const hash = (a, b) => sha2_1.sha256.create().update(a).update(b).digest();
const mixInLength = (root, length) => hash(root, P.U256LE.encode(BigInt(length)));
// Will OOM without this, because tree padded to next power of two.
const zeroHashes = /* @__PURE__ */ (() => {
const res = [EMPTY_CHUNK];
for (let i = 0; i < 64; i++)
res.push(hash(res[i], res[i]));
return res;
})();
const merkleize = (chunks, limit) => {
let chunksLen = chunks.length;
if (limit !== undefined) {
if (limit < chunks.length) {
throw new Error(`SSZ/merkleize: limit (${limit}) is less than the number of chunks (${chunks.length})`);
}
chunksLen = limit;
}
// log2(next power of two), we cannot use binary ops since it can be bigger than 2**32.
const depth = Math.ceil(Math.log2(chunksLen));
if (chunks.length == 0)
return zeroHashes[depth];
for (let l = 0; l < depth; l++) {
const level = [];
for (let i = 0; i < chunks.length; i += 2)
level.push(hash(chunks[i], i + 1 < chunks.length ? chunks[i + 1] : zeroHashes[l]));
chunks = level;
}
return chunks[0];
};
const checkSSZ = (o) => {
if (typeof o !== 'object' ||
o === null ||
typeof o.encode !== 'function' ||
typeof o.decode !== 'function' ||
typeof o.merkleRoot !== 'function' ||
typeof o.composite !== 'boolean' ||
typeof o.chunkCount !== 'number') {
throw new Error(`SSZ: wrong element: ${o} (${typeof o})`);
}
};
// TODO: improve
const isStableCompat = (a, b) => {
if (a === b)
return true; // fast path
const _a = a;
const _b = b;
if (_a.info && _b.info) {
const aI = _a.info;
const bI = _b.info;
// Bitlist[N] / Bitvector[N] field types are compatible if they share the same capacity N.
const bitTypes = ['bitList', 'bitVector'];
if (bitTypes.includes(aI.type) && bitTypes.includes(bI.type) && aI.N === bI.N)
return true;
// List[T, N] / Vector[T, N] field types are compatible if T is compatible and if they also share the same capacity N.
const listTypes = ['list', 'vector'];
if (listTypes.includes(aI.type) &&
listTypes.includes(bI.type) &&
aI.N === bI.N &&
aI.inner._isStableCompat(bI.inner)) {
return true;
}
// Container / StableContainer[N] field types are compatible if all inner field types are compatible,
// if they also share the same field names in the same order, and for StableContainer[N] if they also
// share the same capacity N.
const contType = ['container', 'stableContainer'];
if (contType.includes(aI.type) && contType.includes(bI.type)) {
// both stable containers, but different capacity
if (aI.N !== undefined && bI.N !== undefined && aI.N !== bI.N)
return false;
const kA = Object.keys(aI.fields);
const kB = Object.keys(bI.fields);
if (kA.length !== kB.length)
return false;
for (let i = 0; i < kA.length; i++) {
const fA = kA[i];
const fB = kB[i];
if (fA !== fB)
return false;
if (!aI.fields[fA]._isStableCompat(bI.fields[fA]))
return false;
}
return true;
}
// Profile[X] field types are compatible with StableContainer types compatible with X, and
// are compatible with Profile[Y] where Y is compatible with X if also all inner field types
// are compatible. Differences solely in optionality do not affect merkleization compatibility.
if (aI.type === 'profile' || bI.type === 'profile') {
//console.log('PROF PROF?', aI.type, bI.type, aI.container._isStableCompat(bI));
if (aI.type === 'profile' && bI.type === 'stableContainer')
return aI.container._isStableCompat(b);
if (aI.type === 'stableContainer' && bI.type === 'profile')
return a._isStableCompat(bI.container);
if (aI.type === 'profile' && bI.type === 'profile')
return aI.container._isStableCompat(bI.container);
}
}
return false;
};
const basic = (type, inner, def) => ({
...inner,
default: def,
chunkCount: 1,
composite: false,
info: { type },
_isStableCompat(other) {
return isStableCompat(this, other);
},
chunks(value) {
return [this.merkleRoot(value)];
},
merkleRoot: (value) => {
const res = new Uint8Array(32);
res.set(inner.encode(value));
return res;
},
});
const int = (len, small = true) => P.apply(P.bigint(len, true), {
encode: (from) => {
if (!small)
return from;
if (BigInt(Number(from)) !== BigInt(from))
throw new Error('ssz int: small integer is too big');
return Number(from);
},
decode: (to) => {
if (typeof to === 'bigint')
return to;
if (typeof to !== 'number' || !Number.isSafeInteger(to))
throw new Error(`wrong type=${typeof to} expected number`);
return BigInt(to);
},
});
const _0n = BigInt(0);
exports.uint8 = basic('uint8', int(1), 0);
exports.uint16 = basic('uint16', int(2), 0);
exports.uint32 = basic('uint32', int(4), 0);
exports.uint64 = basic('uint64', int(8, false), _0n);
exports.uint128 = basic('uint128', int(16, false), _0n);
exports.uint256 = basic('uint256', int(32, false), _0n);
exports.boolean = basic('boolean', P.bool, false);
const array = (len, inner) => {
checkSSZ(inner);
let arr = P.array(len, inner);
// variable size arrays
if (inner.size === undefined) {
arr = P.wrap({
encodeStream: P.array(len, P.pointer(P.U32LE, inner)).encodeStream,
decodeStream: (r) => {
const res = [];
if (!r.leftBytes)
return res;
const first = P.U32LE.decodeStream(r);
const len = (first - r.pos) / P.U32LE.size;
if (!Number.isSafeInteger(len))
throw r.err('SSZ/array: wrong fixed size length');
const rest = P.array(len, P.U32LE).decodeStream(r);
const offsets = [first, ...rest];
// SSZ decoding requires very specific encoding and should throw on data constructed differently.
// There is also ZST problem here (as in ETH ABI), but it is impossible to exploit since
// definitions are hardcoded. Also, pointers very strict here.
for (let i = 0; i < offsets.length; i++) {
const pos = offsets[i];
const next = i + 1 < offsets.length ? offsets[i + 1] : r.totalBytes;
if (next < pos)
throw r.err('SSZ/array: decreasing offset');
const len = next - pos;
if (r.pos !== pos)
throw r.err('SSZ/array: wrong offset');
res.push(inner.decode(r.bytes(len)));
}
return res;
},
});
}
return arr;
};
/**
* Vector: fixed size ('len') array of elements 'inner'
*/
const vector = (len, inner) => {
if (!Number.isSafeInteger(len) || len <= 0)
throw new Error(`SSZ/vector: wrong length=${len} (should be positive integer)`);
return {
...array(len, inner),
info: { type: 'vector', N: len, inner },
_isStableCompat(other) {
return isStableCompat(this, other);
},
default: new Array(len).fill(inner.default),
composite: true,
chunkCount: inner.composite ? Math.ceil((len * inner.size) / 32) : len,
chunks(value) {
if (!inner.composite)
return chunks(this.encode(value));
return value.map((i) => inner.merkleRoot(i));
},
merkleRoot(value) {
return merkleize(this.chunks(value));
},
};
};
exports.vector = vector;
/**
* List: dynamic array of 'inner' elements with length limit maxLen
*/
const list = (maxLen, inner) => {
checkSSZ(inner);
const coder = P.validate(array(null, inner), (value) => {
if (!Array.isArray(value) || value.length > maxLen)
throw new Error(`SSZ/list: wrong value=${value} (len=${value.length} maxLen=${maxLen})`);
return value;
});
return {
...coder,
info: { type: 'list', N: maxLen, inner },
_isStableCompat(other) {
return isStableCompat(this, other);
},
composite: true,
chunkCount: !inner.composite ? Math.ceil((maxLen * inner.size) / BYTES_PER_CHUNK) : maxLen,
default: [],
chunks(value) {
if (inner.composite)
return value.map((i) => inner.merkleRoot(i));
return chunks(this.encode(value));
},
merkleRoot(value) {
return mixInLength(merkleize(this.chunks(value), this.chunkCount), value.length);
},
};
};
exports.list = list;
const wrapPointer = (p) => (p.size === undefined ? P.pointer(P.U32LE, p) : p);
const wrapRawPointer = (p) => (p.size === undefined ? P.U32LE : p);
// TODO: improve, unclear how
const fixOffsets = (r, fields, offsetFields, obj, offset) => {
const offsets = [];
for (const f of offsetFields)
offsets.push(obj[f] + offset);
for (let i = 0; i < offsets.length; i++) {
// TODO: how to merge this with array?
const name = offsetFields[i];
const pos = offsets[i];
const next = i + 1 < offsets.length ? offsets[i + 1] : r.totalBytes;
if (next < pos)
throw r.err('SSZ/container: decreasing offset');
const len = next - pos;
if (r.pos !== pos)
throw r.err('SSZ/container: wrong offset');
obj[name] = fields[name].decode(r.bytes(len));
}
return obj;
};
/**
* Container: Encodes object with multiple fields. P.struct for SSZ.
*/
const container = (fields) => {
if (!Object.keys(fields).length)
throw new Error('SSZ/container: no fields');
const ptrCoder = P.struct(Object.fromEntries(Object.entries(fields).map(([k, v]) => [k, wrapPointer(v)])));
const fixedCoder = P.struct(Object.fromEntries(Object.entries(fields).map(([k, v]) => [k, wrapRawPointer(v)])));
const offsetFields = Object.keys(fields).filter((i) => fields[i].size === undefined);
const coder = P.wrap({
encodeStream: ptrCoder.encodeStream,
decodeStream: (r) => fixOffsets(r, fields, offsetFields, fixedCoder.decodeStream(r), 0),
});
return {
...coder,
info: { type: 'container', fields },
_isStableCompat(other) {
return isStableCompat(this, other);
},
size: offsetFields.length ? undefined : fixedCoder.size, // structure is fixed size if all fields is fixed size
default: Object.fromEntries(Object.entries(fields).map(([k, v]) => [k, v.default])),
composite: true,
chunkCount: Object.keys(fields).length,
chunks(value) {
return Object.entries(fields).map(([k, v]) => v.merkleRoot(value[k]));
},
merkleRoot(value) {
return merkleize(this.chunks(value));
},
};
};
exports.container = container;
// Like 'P.bits', but different direction
const bitsCoder = (len) => ({
encode: (data) => {
const res = [];
for (const byte of data)
for (let i = 0; i < 8; i++)
res.push(!!(byte & (1 << i)));
for (let i = len; i < res.length; i++) {
if (res[i])
throw new Error('SSZ/bitsCoder/encode: non-zero padding');
}
return res.slice(0, len);
},
decode: (data) => {
const res = new Uint8Array(Math.ceil(len / 8));
for (let i = 0; i < data.length; i++)
if (data[i])
res[Math.floor(i / 8)] |= 1 << i % 8;
return res;
},
});
/**
* BitVector: array of booleans with fixed size
*/
const bitvector = (len) => {
if (!Number.isSafeInteger(len) || len <= 0)
throw new Error(`SSZ/bitVector: wrong length=${len} (should be positive integer)`);
const bytesLen = Math.ceil(len / 8);
const coder = P.apply(P.bytes(bytesLen), bitsCoder(len));
return {
...coder,
info: { type: 'bitVector', N: len },
_isStableCompat(other) {
return isStableCompat(this, other);
},
default: new Array(len).fill(false),
composite: true,
chunkCount: Math.ceil(len / 256),
chunks(value) {
return chunks(this.encode(value));
},
merkleRoot(value) {
return merkleize(this.chunks(value), this.chunkCount);
},
};
};
exports.bitvector = bitvector;
/**
* BitList: array of booleans with dynamic size (but maxLen limit)
*/
const bitlist = (maxLen) => {
if (!Number.isSafeInteger(maxLen) || maxLen <= 0)
throw new Error(`SSZ/bitList: wrong max length=${maxLen} (should be positive integer)`);
let coder = P.wrap({
encodeStream: (w, value) => {
w.bytes(bitsCoder(value.length + 1).decode([...value, true])); // last true bit is terminator
},
decodeStream: (r) => {
const bytes = r.bytes(r.leftBytes); // use everything
if (!bytes.length || bytes[bytes.length - 1] === 0)
throw new Error('SSZ/bitlist: empty trailing byte');
const bits = bitsCoder(bytes.length * 8).encode(bytes);
const terminator = bits.lastIndexOf(true);
if (terminator === -1)
throw new Error('SSZ/bitList: no terminator');
return bits.slice(0, terminator);
},
});
coder = P.validate(coder, (value) => {
if (!Array.isArray(value) || value.length > maxLen)
throw new Error(`SSZ/bitList/encode: wrong value=${value} (${typeof value})`);
return value;
});
return {
...coder,
info: { type: 'bitList', N: maxLen },
_isStableCompat(other) {
return isStableCompat(this, other);
},
size: undefined,
default: [],
chunkCount: Math.ceil(maxLen / 256),
composite: true,
chunks(value) {
const data = value.length ? (0, exports.bitvector)(value.length).encode(value) : EMPTY_CHUNK;
return chunks(data);
},
merkleRoot(value) {
return mixInLength(merkleize(this.chunks(value), this.chunkCount), value.length);
},
};
};
exports.bitlist = bitlist;
/**
* Union type (None is null)
* */
const union = (...types) => {
if (types.length < 1 || types.length >= 128)
throw Error('SSZ/union: should have [1...128) types');
if (types[0] === null && types.length < 2)
throw new Error('SSZ/union: should have at least 2 types if first is null');
for (let i = 0; i < types.length; i++) {
if (i > 0 && types[i] === null)
throw new Error('SSZ/union: only first type can be null');
if (types[i] !== null)
checkSSZ(types[i]);
}
const coder = P.apply(P.tag(P.U8, Object.fromEntries(types.map((t, i) => [i, t === null ? P.magicBytes(P.EMPTY) : P.prefix(null, t)]))), {
encode: ({ TAG, data }) => ({ selector: TAG, value: data }),
decode: ({ selector, value }) => ({ TAG: selector, data: value }),
});
return {
...coder,
size: undefined, // union is always variable size
chunkCount: NaN,
default: { selector: 0, value: types[0] === null ? null : types[0].default },
_isStableCompat(other) {
return isStableCompat(this, other);
},
composite: true,
chunks({ selector, value }) {
const type = types[selector];
if (type === null)
return EMPTY_CHUNK;
return [types[selector].merkleRoot(value)];
},
merkleRoot: ({ selector, value }) => {
const type = types[selector];
if (type === null)
return mixInLength(EMPTY_CHUNK, 0);
return mixInLength(types[selector].merkleRoot(value), selector);
},
};
};
exports.union = union;
/**
* ByteList: same as List(len, SSZ.byte), but returns Uint8Array
*/
const bytelist = (maxLen) => {
const coder = P.validate(P.bytes(null), (value) => {
if (!(0, utils_ts_1.isBytes)(value) || value.length > maxLen)
throw new Error(`SSZ/bytelist: wrong value=${value}`);
return value;
});
return {
...coder,
info: { type: 'list', N: maxLen, inner: exports.byte },
_isStableCompat(other) {
return isStableCompat(this, other);
},
default: new Uint8Array([]),
composite: true,
chunkCount: Math.ceil(maxLen / 32),
chunks(value) {
return chunks(this.encode(value));
},
merkleRoot(value) {
return mixInLength(merkleize(this.chunks(value), this.chunkCount), value.length);
},
};
};
exports.bytelist = bytelist;
/**
* ByteVector: same as Vector(len, SSZ.byte), but returns Uint8Array
*/
const bytevector = (len) => {
if (!Number.isSafeInteger(len) || len <= 0)
throw new Error(`SSZ/vector: wrong length=${len} (should be positive integer)`);
return {
...P.bytes(len),
info: { type: 'vector', N: len, inner: exports.byte },
_isStableCompat(other) {
return isStableCompat(this, other);
},
default: new Uint8Array(len),
composite: true,
chunkCount: Math.ceil(len / 32),
chunks(value) {
return chunks(this.encode(value));
},
merkleRoot(value) {
return merkleize(this.chunks(value));
},
};
};
exports.bytevector = bytevector;
/**
* Same as container, but all values are optional using bitvector as prefix which indicates active fields
*/
const stableContainer = (N, fields) => {
const fieldsNames = Object.keys(fields);
const fieldsLen = fieldsNames.length;
if (!fieldsLen)
throw new Error('SSZ/stableContainer: no fields');
if (fieldsLen > N)
throw new Error('SSZ/stableContainer: more fields than N');
const bv = (0, exports.bitvector)(N);
const coder = P.wrap({
encodeStream: (w, value) => {
const bsVal = new Array(N).fill(false);
for (let i = 0; i < fieldsLen; i++)
if (value[fieldsNames[i]] !== undefined)
bsVal[i] = true;
bv.encodeStream(w, bsVal);
const activeFields = fieldsNames.filter((_, i) => bsVal[i]);
const ptrCoder = P.struct(Object.fromEntries(activeFields.map((k) => [k, wrapPointer(fields[k])])));
w.bytes(ptrCoder.encode(value));
},
decodeStream: (r) => {
const bsVal = bv.decodeStream(r);
for (let i = fieldsLen; i < bsVal.length; i++) {
if (bsVal[i] !== false)
throw new Error('stableContainer: non-zero padding');
}
const activeFields = fieldsNames.filter((_, i) => bsVal[i]);
const fixedCoder = P.struct(Object.fromEntries(activeFields.map((k) => [k, wrapRawPointer(fields[k])])));
const offsetFields = activeFields.filter((i) => fields[i].size === undefined);
return fixOffsets(r, fields, offsetFields, fixedCoder.decodeStream(r), bv.size);
},
});
return {
...coder,
info: { type: 'stableContainer', N, fields },
size: undefined,
default: Object.fromEntries(Object.entries(fields).map(([k, _v]) => [k, undefined])),
_isStableCompat(other) {
return isStableCompat(this, other);
},
composite: true,
chunkCount: N,
chunks(value) {
const res = Object.entries(fields).map(([k, v]) => value[k] === undefined ? new Uint8Array(32) : v.merkleRoot(value[k]));
while (res.length < N)
res.push(new Uint8Array(32));
return res;
},
merkleRoot(value) {
const bsVal = new Array(N).fill(false);
for (let i = 0; i < fieldsLen; i++)
if (value[fieldsNames[i]] !== undefined)
bsVal[i] = true;
return hash(merkleize(this.chunks(value)), bv.merkleRoot(bsVal));
},
};
};
exports.stableContainer = stableContainer;
/**
* Profile - fixed subset of stableContainer.
* - fields and order of fields is exactly same as in underlying container
* - some fields may be excluded or required in profile (all fields in stable container are always optional)
* - adding new fields to underlying container won't change profile's constructed on top of it,
* because it is required to provide all list of optional fields.
* - type of field can be changed inside profile (but we should be very explicit about this) to same shape type.
*
* @example
* // class Shape(StableContainer[4]):
* // side: Optional[uint16]
* // color: Optional[uint8]
* // radius: Optional[uint16]
*
* // class Square(Profile[Shape]):
* // side: uint16
* // color: uint8
*
* // class Circle(Profile[Shape]):
* // color: uint8
* // radius: Optional[uint16]
* // ->
* const Shape = SSZ.stableContainer(4, {
* side: SSZ.uint16,
* color: SSZ.uint8,
* radius: SSZ.uint16,
* });
* const Square = profile(Shape, [], ['side', 'color']);
* const Circle = profile(Shape, ['radius'], ['color']);
* const Circle2 = profile(Shape, ['radius'], ['color'], { color: SSZ.byte });
*/
const profile = (c, optFields, requiredFields = [], replaceType = {}) => {
checkSSZ(c);
if (c.info.type !== 'stableContainer')
throw new Error('profile: expected stableContainer');
const containerFields = new Set(Object.keys(c.info.fields));
if (!Array.isArray(optFields))
throw new Error('profile: optional fields should be array');
const optFS = new Set(optFields);
for (const f of optFS) {
if (!containerFields.has(f))
throw new Error(`profile: unexpected optional field ${f}`);
}
if (!Array.isArray(requiredFields))
throw new Error('profile: required fields should be array');
const reqFS = new Set(requiredFields);
for (const f of reqFS) {
if (!containerFields.has(f))
throw new Error(`profile: unexpected required field ${f}`);
if (optFS.has(f))
throw new Error(`profile: field ${f} is declared both as optional and required`);
}
if (!(0, utils_ts_1.isObject)(replaceType))
throw new Error('profile: replaceType should be object');
for (const k in replaceType) {
if (!containerFields.has(k))
throw new Error(`profile/replaceType: unexpected field ${k}`);
if (!replaceType[k]._isStableCompat(c.info.fields[k]))
throw new Error(`profile/replaceType: incompatible field ${k}`);
}
// Order should be same
const allFields = Object.keys(c.info.fields).filter((i) => optFS.has(i) || reqFS.has(i));
// bv is omitted if all fields are required!
const fieldCoders = { ...c.info.fields, ...replaceType };
let coder;
if (optFS.size === 0) {
// All fields are required, it is just container, possible with size
coder = (0, exports.container)(Object.fromEntries(allFields.map((k) => [k, fieldCoders[k]])));
}
else {
// NOTE: we cannot merge this with stable container,
// because some fields are active and some is not (based on required/non-required)
const bv = (0, exports.bitvector)(optFS.size);
const forFields = (fn) => {
let optPos = 0;
for (const f of allFields) {
const isOpt = optFS.has(f);
fn(f, isOpt ? optPos : undefined);
if (isOpt)
optPos++;
}
};
coder = {
...P.wrap({
encodeStream: (w, value) => {
const bsVal = new Array(optFS.size).fill(false);
const ptrCoder = {};
forFields((f, optPos) => {
const val = value[f];
if (optPos !== undefined && val !== undefined)
bsVal[optPos] = true;
if (optPos === undefined && val === undefined)
throw new Error(`profile.encode: empty required field ${f}`);
if (val !== undefined)
ptrCoder[f] = wrapPointer(fieldCoders[f]);
});
bv.encodeStream(w, bsVal);
w.bytes(P.struct(ptrCoder).encode(value));
},
decodeStream: (r) => {
let bsVal = bv.decodeStream(r);
const fixedCoder = {};
const offsetFields = [];
forFields((f, optPos) => {
if (optPos !== undefined && bsVal[optPos] === false)
return;
if (fieldCoders[f].size === undefined)
offsetFields.push(f);
fixedCoder[f] = wrapRawPointer(fieldCoders[f]);
});
return fixOffsets(r, fieldCoders, offsetFields, P.struct(fixedCoder).decodeStream(r), bv.size);
},
}),
size: undefined,
};
}
return {
...coder,
info: { type: 'profile', container: c },
default: Object.fromEntries(Array.from(reqFS).map((f) => [f, fieldCoders[f].default])),
_isStableCompat(other) {
return isStableCompat(this, other);
},
composite: true,
chunkCount: c.info.N,
chunks(value) {
return c.chunks(value);
},
merkleRoot(value) {
return c.merkleRoot(value);
},
};
};
exports.profile = profile;
// Aliases
exports.byte = exports.uint8;
exports.bit = exports.boolean;
exports.bool = exports.boolean;
exports.bytes = exports.bytevector;
// TODO: this required for tests, but can be useful for other ETH related stuff.
// Also, blobs here. Since lib is pretty small (thanks to packed), why not?
// Deneb (last eth2 fork) types:
const MAX_VALIDATORS_PER_COMMITTEE = 2048;
const MAX_PROPOSER_SLASHINGS = 16;
const MAX_ATTESTER_SLASHINGS = 2;
const MAX_ATTESTATIONS = 128;
const MAX_DEPOSITS = 16;
const MAX_VOLUNTARY_EXITS = 16;
const MAX_TRANSACTIONS_PER_PAYLOAD = 1048576;
const BYTES_PER_LOGS_BLOOM = 256;
const MAX_EXTRA_DATA_BYTES = 32;
const DEPOSIT_CONTRACT_TREE_DEPTH = 2 ** 5;
const SYNC_COMMITTEE_SIZE = 512;
const MAX_BYTES_PER_TRANSACTION = 1073741824;
const MAX_BLS_TO_EXECUTION_CHANGES = 16;
const MAX_WITHDRAWALS_PER_PAYLOAD = 16;
const MAX_BLOB_COMMITMENTS_PER_BLOCK = 4096;
const SLOTS_PER_HISTORICAL_ROOT = 8192;
const HISTORICAL_ROOTS_LIMIT = 16777216;
const SLOTS_PER_EPOCH = 32;
const EPOCHS_PER_ETH1_VOTING_PERIOD = 64;
const VALIDATOR_REGISTRY_LIMIT = 1099511627776;
const EPOCHS_PER_HISTORICAL_VECTOR = 65536;
const EPOCHS_PER_SLASHINGS_VECTOR = 8192;
const JUSTIFICATION_BITS_LENGTH = 4;
const BYTES_PER_FIELD_ELEMENT = 32;
const FIELD_ELEMENTS_PER_BLOB = 4096;
const KZG_COMMITMENT_INCLUSION_PROOF_DEPTH = 17;
const SYNC_COMMITTEE_SUBNET_COUNT = 4;
const NEXT_SYNC_COMMITTEE_DEPTH = 5;
const BLOCK_BODY_EXECUTION_PAYLOAD_DEPTH = 4;
const FINALIZED_ROOT_DEPTH = 6;
// Electra
const MAX_COMMITTEES_PER_SLOT = 64;
const PENDING_PARTIAL_WITHDRAWALS_LIMIT = 134217728;
const PENDING_BALANCE_DEPOSITS_LIMIT = 134217728;
const PENDING_CONSOLIDATIONS_LIMIT = 262144;
const MAX_ATTESTER_SLASHINGS_ELECTRA = 1;
const MAX_ATTESTATIONS_ELECTRA = 8;
const MAX_DEPOSIT_REQUESTS_PER_PAYLOAD = 8192;
const MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD = 16;
const MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD = 1;
// We can reduce size if we inline these. But updates for new forks would be hard.
const Slot = exports.uint64;
const Epoch = exports.uint64;
const CommitteeIndex = exports.uint64;
const ValidatorIndex = exports.uint64;
const WithdrawalIndex = exports.uint64;
const BlobIndex = exports.uint64;
const Gwei = exports.uint64;
const Root = (0, exports.bytevector)(32);
const Hash32 = (0, exports.bytevector)(32);
const Bytes32 = (0, exports.bytevector)(32);
const Version = (0, exports.bytevector)(4);
const DomainType = (0, exports.bytevector)(4);
const ForkDigest = (0, exports.bytevector)(4);
const Domain = (0, exports.bytevector)(32);
const BLSPubkey = (0, exports.bytevector)(48);
const KZGCommitment = (0, exports.bytevector)(48);
const KZGProof = (0, exports.bytevector)(48);
const BLSSignature = (0, exports.bytevector)(96);
const Ether = exports.uint64;
const ParticipationFlags = exports.uint8;
const ExecutionAddress = (0, exports.bytevector)(20);
const PayloadId = (0, exports.bytevector)(8);
const Transaction = (0, exports.bytelist)(MAX_BYTES_PER_TRANSACTION);
const Blob = (0, exports.bytevector)(BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB);
const Checkpoint = (0, exports.container)({ epoch: Epoch, root: Root });
const AttestationData = (0, exports.container)({
slot: Slot,
index: CommitteeIndex,
beacon_block_root: Root,
source: Checkpoint,
target: Checkpoint,
});
const Attestation = (0, exports.container)({
aggregation_bits: (0, exports.bitlist)(MAX_VALIDATORS_PER_COMMITTEE),
data: AttestationData,
signature: BLSSignature,
});
const AggregateAndProof = (0, exports.container)({
aggregator_index: ValidatorIndex,
aggregate: Attestation,
selection_proof: BLSSignature,
});
const IndexedAttestation = (0, exports.container)({
attesting_indices: (0, exports.list)(MAX_VALIDATORS_PER_COMMITTEE, ValidatorIndex),
data: AttestationData,
signature: BLSSignature,
});
const AttesterSlashing = (0, exports.container)({
attestation_1: IndexedAttestation,
attestation_2: IndexedAttestation,
});
const BLSToExecutionChange = (0, exports.container)({
validator_index: ValidatorIndex,
from_bls_pubkey: BLSPubkey,
to_execution_address: ExecutionAddress,
});
const Withdrawal = (0, exports.container)({
index: WithdrawalIndex,
validator_index: ValidatorIndex,
address: ExecutionAddress,
amount: Gwei,
});
const ExecutionPayload = (0, exports.container)({
parent_hash: Hash32,
fee_recipient: ExecutionAddress,
state_root: Bytes32,
receipts_root: Bytes32,
logs_bloom: (0, exports.bytevector)(BYTES_PER_LOGS_BLOOM),
prev_randao: Bytes32,
block_number: exports.uint64,
gas_limit: exports.uint64,
gas_used: exports.uint64,
timestamp: exports.uint64,
extra_data: (0, exports.bytelist)(MAX_EXTRA_DATA_BYTES),
base_fee_per_gas: exports.uint256,
block_hash: Hash32,
transactions: (0, exports.list)(MAX_TRANSACTIONS_PER_PAYLOAD, Transaction),
withdrawals: (0, exports.list)(MAX_WITHDRAWALS_PER_PAYLOAD, Withdrawal),
blob_gas_used: exports.uint64,
excess_blob_gas: exports.uint64,
});
MAX_WITHDRAWALS_PER_PAYLOAD;
const SigningData = (0, exports.container)({ object_root: Root, domain: Domain });
const BeaconBlockHeader = (0, exports.container)({
slot: Slot,
proposer_index: ValidatorIndex,
parent_root: Root,
state_root: Root,
body_root: Root,
});
const SignedBeaconBlockHeader = (0, exports.container)({ message: BeaconBlockHeader, signature: BLSSignature });
const ProposerSlashing = (0, exports.container)({
signed_header_1: SignedBeaconBlockHeader,
signed_header_2: SignedBeaconBlockHeader,
});
const DepositData = (0, exports.container)({
pubkey: BLSPubkey,
withdrawal_credentials: Bytes32,
amount: Gwei,
signature: BLSSignature,
});
const Deposit = (0, exports.container)({
proof: (0, exports.vector)(DEPOSIT_CONTRACT_TREE_DEPTH + 1, Bytes32),
data: DepositData,
});
const VoluntaryExit = (0, exports.container)({ epoch: Epoch, validator_index: ValidatorIndex });
const SyncAggregate = (0, exports.container)({
sync_committee_bits: (0, exports.bitvector)(SYNC_COMMITTEE_SIZE),
sync_committee_signature: BLSSignature,
});
const Eth1Data = (0, exports.container)({
deposit_root: Root,
deposit_count: exports.uint64,
block_hash: Hash32,
});
const SignedVoluntaryExit = (0, exports.container)({ message: VoluntaryExit, signature: BLSSignature });
const SignedBLSToExecutionChange = (0, exports.container)({
message: BLSToExecutionChange,
signature: BLSSignature,
});
const BeaconBlockBody = (0, exports.container)({
randao_reveal: BLSSignature,
eth1_data: Eth1Data,
graffiti: Bytes32,
proposer_slashings: (0, exports.list)(MAX_PROPOSER_SLASHINGS, ProposerSlashing),
attester_slashings: (0, exports.list)(MAX_ATTESTER_SLASHINGS, AttesterSlashing),
attestations: (0, exports.list)(MAX_ATTESTATIONS, Attestation),
deposits: (0, exports.list)(MAX_DEPOSITS, Deposit),
voluntary_exits: (0, exports.list)(MAX_VOLUNTARY_EXITS, SignedVoluntaryExit),
sync_aggregate: SyncAggregate,
execution_payload: ExecutionPayload,
bls_to_execution_changes: (0, exports.list)(MAX_BLS_TO_EXECUTION_CHANGES, SignedBLSToExecutionChange),
blob_kzg_commitments: (0, exports.list)(MAX_BLOB_COMMITMENTS_PER_BLOCK, KZGCommitment),
});
const BeaconBlock = (0, exports.container)({
slot: Slot,
proposer_index: ValidatorIndex,
parent_root: Root,
state_root: Root,
body: BeaconBlockBody,
});
const SyncCommittee = (0, exports.container)({
pubkeys: (0, exports.vector)(SYNC_COMMITTEE_SIZE, BLSPubkey),
aggregate_pubkey: BLSPubkey,
});
const Fork = (0, exports.container)({
previous_version: Version,
current_version: Version,
epoch: Epoch,
});
const Validator = (0, exports.container)({
pubkey: BLSPubkey,
withdrawal_credentials: Bytes32,
effective_balance: Gwei,
slashed: exports.boolean,
activation_eligibility_epoch: Epoch,
activation_epoch: Epoch,
exit_epoch: Epoch,
withdrawable_epoch: Epoch,
});
const ExecutionPayloadHeader = (0, exports.container)({
parent_hash: Hash32,
fee_recipient: ExecutionAddress,
state_root: Bytes32,
receipts_root: Bytes32,
logs_bloom: (0, exports.bytevector)(BYTES_PER_LOGS_BLOOM),
prev_randao: Bytes32,
block_number: exports.uint64,
gas_limit: exports.uint64,
gas_used: exports.uint64,
timestamp: exports.uint64,
extra_data: (0, exports.bytelist)(MAX_EXTRA_DATA_BYTES),
base_fee_per_gas: exports.uint256,
block_hash: Hash32,
transactions_root: Root,
withdrawals_root: Root,
blob_gas_used: exports.uint64,
excess_blob_gas: exports.uint64,
});
const HistoricalSummary = (0, exports.container)({
block_summary_root: Root,
state_summary_root: Root,
});
const BeaconState = (0, exports.container)({
genesis_time: exports.uint64,
genesis_validators_root: Root,
slot: Slot,
fork: Fork,
latest_block_header: BeaconBlockHeader,
block_roots: (0, exports.vector)(SLOTS_PER_HISTORICAL_ROOT, Root),
state_roots: (0, exports.vector)(SLOTS_PER_HISTORICAL_ROOT, Root),
historical_roots: (0, exports.list)(HISTORICAL_ROOTS_LIMIT, Root),
eth1_data: Eth1Data,
eth1_data_votes: (0, exports.list)(EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH, Eth1Data),
eth1_deposit_index: exports.uint64,
validators: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, Validator),
balances: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, Gwei),
randao_mixes: (0, exports.vector)(EPOCHS_PER_HISTORICAL_VECTOR, Bytes32),
slashings: (0, exports.vector)(EPOCHS_PER_SLASHINGS_VECTOR, Gwei),
previous_epoch_participation: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, ParticipationFlags),
current_epoch_participation: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, ParticipationFlags),
justification_bits: (0, exports.bitvector)(JUSTIFICATION_BITS_LENGTH),
previous_justified_checkpoint: Checkpoint,
current_justified_checkpoint: Checkpoint,
finalized_checkpoint: Checkpoint,
inactivity_scores: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.uint64),
current_sync_committee: SyncCommittee,
next_sync_committee: SyncCommittee,
latest_execution_payload_header: ExecutionPayloadHeader,
next_withdrawal_index: WithdrawalIndex,
next_withdrawal_validator_index: ValidatorIndex,
historical_summaries: (0, exports.list)(HISTORICAL_ROOTS_LIMIT, HistoricalSummary),
});
const BlobIdentifier = (0, exports.container)({
block_root: Root,
index: BlobIndex,
});
const BlobSidecar = (0, exports.container)({
index: BlobIndex,
blob: Blob,
kzg_commitment: KZGCommitment,
kzg_proof: KZGProof,
signed_block_header: SignedBeaconBlockHeader,
kzg_commitment_inclusion_proof: (0, exports.vector)(KZG_COMMITMENT_INCLUSION_PROOF_DEPTH, Bytes32),
});
const SyncCommitteeContribution = (0, exports.container)({
slot: Slot,
beacon_block_root: Root,
subcommittee_index: exports.uint64,
aggregation_bits: (0, exports.bitvector)(SYNC_COMMITTEE_SIZE / SYNC_COMMITTEE_SUBNET_COUNT),
signature: BLSSignature,
});
const ContributionAndProof = (0, exports.container)({
aggregator_index: ValidatorIndex,
contribution: SyncCommitteeContribution,
selection_proof: BLSSignature,
});
const DepositMessage = (0, exports.container)({
pubkey: BLSPubkey,
withdrawal_credentials: Bytes32,
amount: Gwei,
});
const Eth1Block = (0, exports.container)({
timestamp: exports.uint64,
deposit_root: Root,
deposit_count: exports.uint64,
});
const ForkData = (0, exports.container)({ current_version: Version, genesis_validators_root: Root });
const HistoricalBatch = (0, exports.container)({
block_roots: (0, exports.vector)(SLOTS_PER_HISTORICAL_ROOT, Root),
state_roots: (0, exports.vector)(SLOTS_PER_HISTORICAL_ROOT, Root),
});
const PendingAttestation = (0, exports.container)({
aggregation_bits: (0, exports.bitlist)(MAX_VALIDATORS_PER_COMMITTEE),
data: AttestationData,
inclusion_delay: Slot,
proposer_index: ValidatorIndex,
});
const PowBlock = (0, exports.container)({
block_hash: Hash32,
parent_hash: Hash32,
total_difficulty: exports.uint256,
});
const SignedAggregateAndProof = (0, exports.container)({ message: AggregateAndProof, signature: BLSSignature });
const SignedBeaconBlock = (0, exports.container)({ message: BeaconBlock, signature: BLSSignature });
const SignedContributionAndProof = (0, exports.container)({
message: ContributionAndProof,
signature: BLSSignature,
});
const SyncAggregatorSelectionData = (0, exports.container)({ slot: Slot, subcommittee_index: exports.uint64 });
const SyncCommitteeMessage = (0, exports.container)({
slot: Slot,
beacon_block_root: Root,
validator_index: ValidatorIndex,
signature: BLSSignature,
});
const LightClientHeader = (0, exports.container)({
beacon: BeaconBlockHeader,
execution: ExecutionPayloadHeader,
execution_branch: (0, exports.vector)(BLOCK_BODY_EXECUTION_PAYLOAD_DEPTH, Bytes32),
});
const LightClientBootstrap = (0, exports.container)({
header: LightClientHeader,
current_sync_committee: SyncCommittee,
current_sync_committee_branch: (0, exports.vector)(NEXT_SYNC_COMMITTEE_DEPTH, Bytes32),
});
const LightClientUpdate = (0, exports.container)({
attested_header: LightClientHeader,
next_sync_committee: SyncCommittee,
next_sync_committee_branch: (0, exports.vector)(NEXT_SYNC_COMMITTEE_DEPTH, Bytes32),
finalized_header: LightClientHeader,
finality_branch: (0, exports.vector)(FINALIZED_ROOT_DEPTH, Bytes32),
sync_aggregate: SyncAggregate,
signature_slot: Slot,
});
const LightClientFinalityUpdate = (0, exports.container)({
attested_header: LightClientHeader,
finalized_header: LightClientHeader,
finality_branch: (0, exports.vector)(FINALIZED_ROOT_DEPTH, Bytes32),
sync_aggregate: SyncAggregate,
signature_slot: Slot,
});
const LightClientOptimisticUpdate = (0, exports.container)({
attested_header: LightClientHeader,
sync_aggregate: SyncAggregate,
signature_slot: Slot,
});
// Electra
const DepositRequest = (0, exports.container)({
pubkey: BLSPubkey,
withdrawal_credentials: Bytes32,
amount: Gwei,
signature: BLSSignature,
index: exports.uint64,
});
const WithdrawalRequest = (0, exports.container)({
source_address: ExecutionAddress,
validator_pubkey: BLSPubkey,
amount: Gwei,
});
const ConsolidationRequest = (0, exports.container)({
source_address: ExecutionAddress,
source_pubkey: BLSPubkey,
target_pubkey: BLSPubkey,
});
const PendingBalanceDeposit = (0, exports.container)({
index: ValidatorIndex,
amount: Gwei,
});
const PendingPartialWithdrawal = (0, exports.container)({
index: ValidatorIndex,
amount: Gwei,
withdrawable_epoch: Epoch,
});
const PendingConsolidation = (0, exports.container)({
source_index: ValidatorIndex,
target_index: ValidatorIndex,
});
exports.ETH2_TYPES = {
Slot,
Epoch,
CommitteeIndex,
ValidatorIndex,
WithdrawalIndex,
Gwei,
Root,
Hash32,
Bytes32,
Version,
DomainType,
ForkDigest,
Domain,
BLSPubkey,
BLSSignature,
Ether,
ParticipationFlags,
ExecutionAddress,
PayloadId,
KZGCommitment,
KZGProof,
// Containters
Checkpoint,
AttestationData,
Attestation,
AggregateAndProof,
IndexedAttestation,
AttesterSlashing,
BLSToExecutionChange,
ExecutionPayload,
SyncAggregate,
VoluntaryExit,
BeaconBlockHeader,
SigningData,
SignedBeaconBlockHeader,
ProposerSlashing,
DepositData,
Deposit,
SignedVoluntaryExit,
Eth1Data,
Withdrawal,
BeaconBlockBody,
BeaconBlock,
SyncCommittee,
Fork,
Validator,
ExecutionPayloadHeader,
HistoricalSummary,
BeaconState,
BlobIdentifier,
BlobSidecar,
ContributionAndProof,
DepositMessage,
Eth1Block,
ForkData,
HistoricalBatch,
PendingAttestation,
PowBlock,
Transaction,
SignedAggregateAndProof,
SignedBLSToExecutionChange,
SignedBeaconBlock,
SignedContributionAndProof,
SyncAggregatorSelectionData,
SyncCommitteeContribution,
SyncCommitteeMessage,
// Light client
LightClientHeader,
LightClientBootstrap,
LightClientUpdate,
LightClientOptimisticUpdate,
LightClientFinalityUpdate,
// Electra
DepositRequest,
WithdrawalRequest,
ConsolidationRequest,
PendingBalanceDeposit,
PendingPartialWithdrawal,
PendingConsolidation,
};
// EIP-7688
const MAX_ATTESTATION_FIELDS = 8;
const MAX_INDEXED_ATTESTATION_FIELDS = 8;
const MAX_EXECUTION_PAYLOAD_FIELDS = 64;
const MAX_BEACON_BLOCK_BODY_FIELDS = 64;
const MAX_BEACON_STATE_FIELDS = 128;
const MAX_EXECUTION_REQUESTS_FIELDS = 16;
const StableAttestation = (0, exports.stableContainer)(MAX_ATTESTATION_FIELDS, {
aggregation_bits: (0, exports.bitlist)(MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT),
data: AttestationData,
signature: BLSSignature,
committee_bits: (0, exports.bitvector)(MAX_COMMITTEES_PER_SLOT),
});
const StableIndexedAttestation = (0, exports.stableContainer)(MAX_INDEXED_ATTESTATION_FIELDS, {
attesting_indices: (0, exports.list)(MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT, ValidatorIndex),
data: AttestationData,
signature: BLSSignature,
});
const StableAttesterSlashing = (0, exports.container)({
attestation_1: StableIndexedAttestation,
attestation_2: StableIndexedAttestation,
});
const StableExecutionRequests = (0, exports.stableContainer)(MAX_EXECUTION_REQUESTS_FIELDS, {
deposits: (0, exports.list)(MAX_DEPOSIT_REQUESTS_PER_PAYLOAD, DepositRequest), // [New in Electra:EIP6110]
withdrawals: (0, exports.list)(MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD, WithdrawalRequest), // [New in Electra:EIP7002:EIP7251]
consolidations: (0, exports.list)(MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD, ConsolidationRequest), // [New in Electra:EIP7251]
});
const StableExecutionPayload = (0, exports.stableContainer)(MAX_EXECUTION_PAYLOAD_FIELDS, {
parent_hash: Hash32,
fee_recipient: ExecutionAddress,
state_root: Bytes32,
receipts_root: Bytes32,
logs_bloom: (0, exports.bytevector)(BYTES_PER_LOGS_BLOOM),
prev_randao: Bytes32,
block_number: exports.uint64,
gas_limit: exports.uint64,
gas_used: exports.uint64,
timestamp: exports.uint64,
extra_data: (0, exports.bytelist)(MAX_EXTRA_DATA_BYTES),
base_fee_per_gas: exports.uint256,
block_hash: Hash32,
transactions: (0, exports.list)(MAX_TRANSACTIONS_PER_PAYLOAD, Transaction),
withdrawals: (0, exports.list)(MAX_WITHDRAWALS_PER_PAYLOAD, Withdrawal), // [New in Capella]
blob_gas_used: exports.uint64,
excess_blob_gas: exports.uint64,
deposit_requests: (0, exports.list)(MAX_DEPOSIT_REQUESTS_PER_PAYLOAD, DepositRequest), // [New in Electra:EIP6110]
withdrawal_requests: (0, exports.list)(MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD, WithdrawalRequest), // [New in Electra:EIP7002:EIP7251]
consolidation_requests: (0, exports.list)(MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD, ConsolidationRequest), // [New in Electra:EIP7251]
});
const StableExecutionPayloadHeader = (0, exports.stableContainer)(MAX_EXECUTION_PAYLOAD_FIELDS, {
parent_hash: Hash32,
fee_recipient: ExecutionAddress,
state_root: Bytes32,
receipts_root: Bytes32,
logs_bloom: (0, exports.bytevector)(BYTES_PER_LOGS_BLOOM),
prev_randao: Bytes32,
block_number: exports.uint64,
gas_limit: exports.uint64,
gas_used: exports.uint64,
timestamp: exports.uint64,
extra_data: (0, exports.bytelist)(MAX_EXTRA_DATA_BYTES),
base_fee_per_gas: exports.uint256,
block_hash: Hash32,
transactions_root: Root,
withdrawals_root: Root, // [New in Capella]
blob_gas_used: exports.uint64, // [New in Deneb:EIP4844]
excess_blob_gas: exports.uint64, // [New in Deneb:EIP4844]
deposit_requests_root: Root, // [New in Electra:EIP6110]
withdrawal_requests_root: Root, // [New in Electra:EIP7002:EIP7251]
consolidation_requests_root: Root, // [New in Electra:EIP7251]
});
const StableBeaconBlockBody = (0, exports.stableContainer)(MAX_BEACON_BLOCK_BODY_FIELDS, {
randao_reveal: BLSSignature,
eth1_data: Eth1Data,
graffiti: Bytes32,
proposer_slashings: (0, exports.list)(MAX_PROPOSER_SLASHINGS, ProposerSlashing),
attester_slashings: (0, exports.list)(MAX_ATTESTER_SLASHINGS_ELECTRA, StableAttesterSlashing), // [Modified in Electra:EIP7549]
attestations: (0, exports.list)(MAX_ATTESTATIONS_ELECTRA, StableAttestation), // [Modified in Electra:EIP7549]
deposits: (0, exports.list)(MAX_DEPOSITS, Deposit),
voluntary_exits: (0, exports.list)(MAX_VOLUNTARY_EXITS, SignedVoluntaryExit),
sync_aggregate: SyncAggregate,
execution_payload: StableExecutionPayload,
bls_to_execution_changes: (0, exports.list)(MAX_BLS_TO_EXECUTION_CHANGES, SignedBLSToExecutionChange),
blob_kzg_commitments: (0, exports.list)(MAX_BLOB_COMMITMENTS_PER_BLOCK, KZGCommitment),
execution_requests: StableExecutionRequests,
});
const StableBeaconState = (0, exports.stableContainer)(MAX_BEACON_STATE_FIELDS, {
genesis_time: exports.uint64,
genesis_validators_root: Root,
slot: Slot,
fork: Fork,
latest_block_header: BeaconBlockHeader,
block_roots: (0, exports.vector)(SLOTS_PER_HISTORICAL_ROOT, Root),
state_roots: (0, exports.vector)(SLOTS_PER_HISTORICAL_ROOT, Root),
historical_roots: (0, exports.list)(HISTORICAL_ROOTS_LIMIT, Root),
eth1_data: Eth1Data,
eth1_data_votes: (0, exports.list)(EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH, Eth1Data),
eth1_deposit_index: exports.uint64,
validators: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, Validator),
balances: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, Gwei),
randao_mixes: (0, exports.vector)(EPOCHS_PER_HISTORICAL_VECTOR, Bytes32),
slashings: (0, exports.vector)(EPOCHS_PER_SLASHINGS_VECTOR, Gwei),
previous_epoch_participation: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, ParticipationFlags),
current_epoch_participation: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, ParticipationFlags),
justification_bits: (0, exports.bitvector)(JUSTIFICATION_BITS_LENGTH),
previous_justified_checkpoint: Checkpoint,
current_justified_checkpoint: Checkpoint,
finalized_checkpoint: Checkpoint,
inactivity_scores: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.uint64),
current_sync_committee: SyncCommittee,
next_sync_committee: SyncCommittee,
latest_execution_payload_header: StableExecutionPayloadHeader,
next_withdrawal_index: WithdrawalIndex,
next_withdrawal_validator_index: ValidatorIndex,
historical_summaries: (0, exports.list)(HISTORICAL_ROOTS_LIMIT, HistoricalSummary),
deposit_requests_start_index: exports.uint64, // [New in Electra:EIP6110]
deposit_balance_to_consume: Gwei, // [New in Electra:EIP7251]
exit_balance_to_consume: Gwei, // [New in Electra:EIP7251]
earliest_exit_epoch: Epoch, // [New in Electra:EIP7251]
consolidation_balance_to_consume: Gwei, // [New in Electra:EIP7251]
earliest_consolidation_epoch: Epoch, // [New in Electra:EIP7251]
pending_balance_deposits: (0, exports.list)(PENDING_BALANCE_DEPOSITS_LIMIT, PendingBalanceDeposit), // [New in Electra:EIP7251]
pending_partial_withdrawals: (0, exports.list)(PENDING_PARTIAL_WITHDRAWALS_LIMIT, PendingPartialWithdrawal), // [New in Electra:EIP7251]
pending_consolidations: (0, exports.list)(PENDING_CONSOLIDATIONS_LIMIT, PendingConsolidation), // [New in Electra:EIP7251]
});
exports.ETH2_CONSENSUS = {
StableAttestation,
StableIndexedAttestation,
StableAttesterSlashing,
StableExecutionPayload,
StableExecutionRequests,
StableExecutionPayloadHeader,
StableBeaconBlockBody,
StableBeaconState,
};
// Tests (electra profiles): https://github.com/ethereum/consensus-specs/pull/3844#issuecomment-2239285376
// NOTE: these are different from EIP-7688 by some reasons, but since nothing is merged/completed in eth side, we just trying
// to pass these tests for now.
const IndexedAttestationElectra = (0, exports.profile)(StableIndexedAttestation, [], ['attesting_indices', 'data', 'signature']);
const AttesterSlashingElectra = (0, exports.container)({
attestation_1: IndexedAttestationElectra,
attestation_2: IndexedAttestationElectra,
});
const ExecutionPayloadHeaderElectra = (0, exports.profile)(StableExecutionPayloadHeader, [], [
'parent_hash',
'fee_recipient',
'state_root',
'receipts_root',
'logs_bloom',
'prev_randao',
'block_number',
'gas_limit',
'gas_used',
'timestamp',
'extra_data',
'base_fee_per_gas',
'block_hash',
'transactions_root',
'withdrawals_root',
'blob_gas_used',
'excess_blob_gas',
]);
const ExecutionRequests = (0, exports.profile)(StableExecutionRequests, [], ['deposits', 'withdrawals', 'consolidations']);
const AttestationElectra = (0, exports.profile)(StableAttestation, [], ['aggregation_bits', 'data', 'signature', 'committee_bits']);
const ExecutionPayloadElectra = (0, exports.profile)(StableExecutionPayload, [], [
'parent_hash',
'fee_recipient',
'state_root',
'receipts_root',
'logs_bloom',
'prev_randao',
'block_number',
'gas_limit',
'gas_used',
'timestamp',
'extra_data',
'base_fee_per_gas',
'block_hash',
'transactions',
'withdrawals',
'blob_gas_used',
'excess_blob_gas',
]);
exports.ETH2_PROFILES = {
electra: {
Attestation: AttestationElectra,
AttesterSlashing: AttesterSlashingElectra,
IndexedAttestation: IndexedAttestationElectra,
ExecutionRequests,
ExecutionPayloadHeader: ExecutionPayloadHeaderElectra,
ExecutionPayload: ExecutionPayloadElectra,
BeaconBlockBody: (0, exports.profile)(StableBeaconBlockBody, [], [
'randao_reveal',
'eth1_data',
'graffiti',
'proposer_slashings',
'attester_slashings',
'attestations',
'deposits',
'voluntary_exits',
'sync_aggregate',
'execution_payload',
'bls_to_execution_changes',
'blob_kzg_commitments',
'execution_requests',
], {
attester_slashings: (0, exports.list)(MAX_ATTESTER_SLASHINGS_ELECTRA, AttesterSlashingElectra),
attestations: (0, exports.list)(MAX_ATTESTATIONS_ELECTRA, AttestationElectra),
execution_payload: ExecutionPayloadElectra,
execution_requests: ExecutionRequests,
}),
BeaconState: (0, exports.profile)(StableBeaconState, [], [
'genesis_time',
'genesis_validators_root',
'slot',
'fork',
'latest_block_header',
'block_roots',
'state_roots',
'historical_roots',
'eth1_data',
'eth1_data_votes',
'eth1_deposit_index',
'validators',
'balances',
'randao_mixes',
'slashings',
'previous_epoch_participation',
'current_epoch_participation',
'justification_bits',
'previous_justified_checkpoint',
'current_justified_checkpoint',
'finalized_checkpoint',
'inactivity_scores',
'current_sync_committee',
'next_sync_committee',
'latest_execution_payload_header',
'next_withdrawal_index',
'next_withdrawal_validator_index',
'historical_summaries',
'deposit_requests_start_index',
'deposit_balance_to_consume',
'exit_balance_to_consume',
'earliest_exit_epoch',
'consolidation_balance_to_consume',
'earliest_consolidation_epoch',
'pending_balance_deposits',
'pending_partial_withdrawals',
'pending_consolidations',
], {
latest_execution_payload_header: ExecutionPayloadHeaderElectra,
}),
},
};
/** Capella Types */
exports.CapellaExecutionPayloadHeader = (0, exports.container)({
parent_hash: exports.ETH2_TYPES.Hash32,
fee_recipient: exports.ETH2_TYPES.ExecutionAddress,
state_root: exports.ETH2_TYPES.Bytes32,
receipts_root: exports.ETH2_TYPES.Bytes32,
logs_bloom: (0, exports.bytevector)(BYTES_PER_LOGS_BLOOM),
prev_randao: exports.ETH2_TYPES.Bytes32,
block_number: exports.uint64,
gas_limit: exports.uint64,
gas_used: exports.uint64,
timestamp: exports.uint64,
extra_data: (0, exports.bytelist)(MAX_EXTRA_DATA_BYTES),
base_fee_per_gas: exports.uint256,
block_hash: exports.ETH2_TYPES.Hash32,
transactions_root: exports.ETH2_TYPES.Root,
withdrawals_root: exports.ETH2_TYPES.Root,
});
const CapellaBeaconBlockBody = (0, exports.container)({
randao_reveal: exports.ETH2_TYPES.BLSSignature,
eth1_data: exports.ETH2_TYPES.Eth1Data,
graffiti: exports.ETH2_TYPES.Bytes32,
proposer_slashings: (0, exports.list)(MAX_PROPOSER_SLASHINGS, exports.ETH2_TYPES.ProposerSlashing),
attester_slashings: (0, exports.list)(MAX_ATTESTER_SLASHINGS, exports.ETH2_TYPES.AttesterSlashing),
attestations: (0, exports.list)(MAX_ATTESTATIONS, exports.ETH2_TYPES.Attestation),
deposits: (0, exports.list)(MAX_DEPOSITS, exports.ETH2_TYPES.Deposit),
voluntary_exits: (0, exports.list)(MAX_VOLUNTARY_EXITS, exports.ETH2_TYPES.SignedVoluntaryExit),
sync_aggregate: exports.ETH2_TYPES.SyncAggregate,
execution_payload: exports.CapellaExecutionPayloadHeader,
bls_to_execution_changes: (0, exports.list)(MAX_BLS_TO_EXECUTION_CHANGES, exports.ETH2_TYPES.SignedBLSToExecutionChange),
});
exports.CapellaBeaconBlock = (0, exports.container)({
slot: exports.ETH2_TYPES.Slot,
proposer_index: exports.ETH2_TYPES.ValidatorIndex,
parent_root: exports.ETH2_TYPES.Root,
state_root: exports.ETH2_TYPES.Root,
body: CapellaBeaconBlockBody,
});
exports.CapellaSignedBeaconBlock = (0, exports.container)({
message: exports.CapellaBeaconBlock,
signature: exports.ETH2_TYPES.BLSSignature,
});
exports.CapellaBeaconState = (0, exports.container)({
genesis_time: exports.uint64,
genesis_validators_root: exports.ETH2_TYPES.Root,
slot: exports.ETH2_TYPES.Slot,
fork: exports.ETH2_TYPES.Fork,
latest_block_header: exports.ETH2_TYPES.BeaconBlockHeader,
block_roots: (0, exports.vector)(SLOTS_PER_HISTORICAL_ROOT, exports.ETH2_TYPES.Root),
state_roots: (0, exports.vector)(SLOTS_PER_HISTORICAL_ROOT, exports.ETH2_TYPES.Root),
historical_roots: (0, exports.list)(HISTORICAL_ROOTS_LIMIT, exports.ETH2_TYPES.Root),
eth1_data: exports.ETH2_TYPES.Eth1Data,
eth1_data_votes: (0, exports.list)(EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH, exports.ETH2_TYPES.Eth1Data),
eth1_deposit_index: exports.uint64,
validators: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.ETH2_TYPES.Validator),
balances: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.ETH2_TYPES.Gwei),
randao_mixes: (0, exports.vector)(EPOCHS_PER_HISTORICAL_VECTOR, exports.ETH2_TYPES.Bytes32),
slashings: (0, exports.vector)(EPOCHS_PER_SLASHINGS_VECTOR, exports.ETH2_TYPES.Gwei),
previous_epoch_participation: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.ETH2_TYPES.ParticipationFlags),
current_epoch_participation: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.ETH2_TYPES.ParticipationFlags),
justification_bits: (0, exports.bitvector)(JUSTIFICATION_BITS_LENGTH),
previous_justified_checkpoint: exports.ETH2_TYPES.Checkpoint,
current_justified_checkpoint: exports.ETH2_TYPES.Checkpoint,
finalized_checkpoint: exports.ETH2_TYPES.Checkpoint,
inactivity_scores: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.uint64),
current_sync_committee: exports.ETH2_TYPES.SyncCommittee,
next_sync_committee: exports.ETH2_TYPES.SyncCommittee,
latest_execution_payload_header: exports.CapellaExecutionPayloadHeader,
next_withdrawal_index: exports.uint64,
next_withdrawal_validator_index: exports.uint64,
historical_summaries: (0, exports.list)(HISTORICAL_ROOTS_LIMIT, exports.ETH2_TYPES.HistoricalSummary),
});
/** Bellatrix Types */
exports.BellatrixExecutionPayloadHeader = (0, exports.container)({
parent_hash: exports.ETH2_TYPES.Hash32,
fee_recipient: exports.ETH2_TYPES.ExecutionAddress,
state_root: exports.ETH2_TYPES.Bytes32,
receipts_root: exports.ETH2_TYPES.Bytes32,
logs_bloom: (0, exports.bytevector)(BYTES_PER_LOGS_BLOOM),
prev_randao: exports.ETH2_TYPES.Bytes32,
block_number: exports.uint64,
gas_limit: exports.uint64,
gas_used: exports.uint64,
timestamp: exports.uint64,
extra_data: (0, exports.bytelist)(MAX_EXTRA_DATA_BYTES),
base_fee_per_gas: exports.uint256,
block_hash: exports.ETH2_TYPES.Hash32,
transactions_root: exports.ETH2_TYPES.Root,
});
const BellatrixBeaconBlockBody = (0, exports.container)({
randao_reveal: exports.ETH2_TYPES.BLSSignature,
eth1_data: exports.ETH2_TYPES.Eth1Data,
graffiti: exports.ETH2_TYPES.Bytes32,
proposer_slashings: (0, exports.list)(MAX_PROPOSER_SLASHINGS, exports.ETH2_TYPES.ProposerSlashing),
attester_slashings: (0, exports.list)(MAX_ATTESTER_SLASHINGS, exports.ETH2_TYPES.AttesterSlashing),
attestations: (0, exports.list)(MAX_ATTESTATIONS, exports.ETH2_TYPES.Attestation),
deposits: (0, exports.list)(MAX_DEPOSITS, exports.ETH2_TYPES.Deposit),
voluntary_exits: (0, exports.list)(MAX_VOLUNTARY_EXITS, exports.ETH2_TYPES.SignedVoluntaryExit),
sync_aggregate: exports.ETH2_TYPES.SyncAggregate,
execution_payload: exports.BellatrixExecutionPayloadHeader,
bls_to_execution_changes: (0, exports.list)(MAX_BLS_TO_EXECUTION_CHANGES, exports.ETH2_TYPES.SignedBLSToExecutionChange),
});
exports.BellatrixBeaconBlock = (0, exports.container)({
slot: exports.ETH2_TYPES.Slot,
proposer_index: exports.ETH2_TYPES.ValidatorIndex,
parent_root: exports.ETH2_TYPES.Root,
state_root: exports.ETH2_TYPES.Root,
body: BellatrixBeaconBlockBody,
});
exports.BellatrixSignedBeaconBlock = (0, exports.container)({
message: exports.BellatrixBeaconBlock,
signature: exports.ETH2_TYPES.BLSSignature,
});
exports.BellatrixBeaconState = (0, exports.container)({
genesis_time: exports.uint64,
genesis_validators_root: exports.ETH2_TYPES.Root,
slot: exports.ETH2_TYPES.Slot,
fork: exports.ETH2_TYPES.Fork,
latest_block_header: exports.ETH2_TYPES.BeaconBlockHeader,
block_roots: (0, exports.vector)(SLOTS_PER_HISTORICAL_ROOT, exports.ETH2_TYPES.Root),
state_roots: (0, exports.vector)(SLOTS_PER_HISTORICAL_ROOT, exports.ETH2_TYPES.Root),
historical_roots: (0, exports.list)(HISTORICAL_ROOTS_LIMIT, exports.ETH2_TYPES.Root),
eth1_data: exports.ETH2_TYPES.Eth1Data,
eth1_data_votes: (0, exports.list)(EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH, exports.ETH2_TYPES.Eth1Data),
eth1_deposit_index: exports.uint64,
validators: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.ETH2_TYPES.Validator),
balances: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.ETH2_TYPES.Gwei),
randao_mixes: (0, exports.vector)(EPOCHS_PER_HISTORICAL_VECTOR, exports.ETH2_TYPES.Bytes32),
slashings: (0, exports.vector)(EPOCHS_PER_SLASHINGS_VECTOR, exports.ETH2_TYPES.Gwei),
previous_epoch_participation: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.ETH2_TYPES.ParticipationFlags),
current_epoch_participation: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.ETH2_TYPES.ParticipationFlags),
justification_bits: (0, exports.bitvector)(JUSTIFICATION_BITS_LENGTH),
previous_justified_checkpoint: exports.ETH2_TYPES.Checkpoint,
current_justified_checkpoint: exports.ETH2_TYPES.Checkpoint,
finalized_checkpoint: exports.ETH2_TYPES.Checkpoint,
inactivity_scores: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.uint64),
current_sync_committee: exports.ETH2_TYPES.SyncCommittee,
next_sync_committee: exports.ETH2_TYPES.SyncCommittee,
latest_execution_payload_header: exports.BellatrixExecutionPayloadHeader,
});
/** Altair Types */
const AltairBeaconBlockBody = (0, exports.container)({
randao_reveal: exports.ETH2_TYPES.BLSSignature,
eth1_data: exports.ETH2_TYPES.Eth1Data,
graffiti: exports.ETH2_TYPES.Bytes32,
proposer_slashings: (0, exports.list)(MAX_PROPOSER_SLASHINGS, exports.ETH2_TYPES.ProposerSlashing),
attester_slashings: (0, exports.list)(MAX_ATTESTER_SLASHINGS, exports.ETH2_TYPES.AttesterSlashing),
attestations: (0, exports.list)(MAX_ATTESTATIONS, exports.ETH2_TYPES.Attestation),
deposits: (0, exports.list)(MAX_DEPOSITS, exports.ETH2_TYPES.Deposit),
voluntary_exits: (0, exports.list)(MAX_VOLUNTARY_EXITS, exports.ETH2_TYPES.SignedVoluntaryExit),
sync_aggregate: exports.ETH2_TYPES.SyncAggregate,
});
exports.AltairBeaconBlock = (0, exports.container)({
slot: exports.ETH2_TYPES.Slot,
proposer_index: exports.ETH2_TYPES.ValidatorIndex,
parent_root: exports.ETH2_TYPES.Root,
state_root: exports.ETH2_TYPES.Root,
body: AltairBeaconBlockBody,
});
exports.AltairSignedBeaconBlock = (0, exports.container)({
message: exports.AltairBeaconBlock,
signature: exports.ETH2_TYPES.BLSSignature,
});
exports.AltairBeaconState = (0, exports.container)({
genesis_time: exports.uint64,
genesis_validators_root: exports.ETH2_TYPES.Root,
slot: exports.ETH2_TYPES.Slot,
fork: exports.ETH2_TYPES.Fork,
latest_block_header: exports.ETH2_TYPES.BeaconBlockHeader,
block_roots: (0, exports.vector)(SLOTS_PER_HISTORICAL_ROOT, exports.ETH2_TYPES.Root),
state_roots: (0, exports.vector)(SLOTS_PER_HISTORICAL_ROOT, exports.ETH2_TYPES.Root),
historical_roots: (0, exports.list)(HISTORICAL_ROOTS_LIMIT, exports.ETH2_TYPES.Root),
eth1_data: exports.ETH2_TYPES.Eth1Data,
eth1_data_votes: (0, exports.list)(EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH, exports.ETH2_TYPES.Eth1Data),
eth1_deposit_index: exports.uint64,
validators: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.ETH2_TYPES.Validator),
balances: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.ETH2_TYPES.Gwei),
randao_mixes: (0, exports.vector)(EPOCHS_PER_HISTORICAL_VECTOR, exports.ETH2_TYPES.Bytes32),
slashings: (0, exports.vector)(EPOCHS_PER_SLASHINGS_VECTOR, exports.ETH2_TYPES.Gwei),
previous_epoch_participation: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.ETH2_TYPES.ParticipationFlags),
current_epoch_participation: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.ETH2_TYPES.ParticipationFlags),
justification_bits: (0, exports.bitvector)(JUSTIFICATION_BITS_LENGTH),
previous_justified_checkpoint: exports.ETH2_TYPES.Checkpoint,
current_justified_checkpoint: exports.ETH2_TYPES.Checkpoint,
finalized_checkpoint: exports.ETH2_TYPES.Checkpoint,
inactivity_scores: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.uint64),
current_sync_committee: exports.ETH2_TYPES.SyncCommittee,
next_sync_committee: exports.ETH2_TYPES.SyncCommittee,
});
/** Phase0 Types */
const Phase0BeaconBlockBody = (0, exports.container)({
randao_reveal: exports.ETH2_TYPES.BLSSignature,
eth1_data: exports.ETH2_TYPES.Eth1Data,
graffiti: exports.ETH2_TYPES.Bytes32,
proposer_slashings: (0, exports.list)(MAX_PROPOSER_SLASHINGS, exports.ETH2_TYPES.ProposerSlashing),
attester_slashings: (0, exports.list)(MAX_ATTESTER_SLASHINGS, exports.ETH2_TYPES.AttesterSlashing),
attestations: (0, exports.list)(MAX_ATTESTATIONS, exports.ETH2_TYPES.Attestation),
deposits: (0, exports.list)(MAX_DEPOSITS, exports.ETH2_TYPES.Deposit),
voluntary_exits: (0, exports.list)(MAX_VOLUNTARY_EXITS, exports.ETH2_TYPES.SignedVoluntaryExit),
});
exports.Phase0BeaconBlock = (0, exports.container)({
slot: exports.ETH2_TYPES.Slot,
proposer_index: exports.ETH2_TYPES.ValidatorIndex,
parent_root: exports.ETH2_TYPES.Root,
state_root: exports.ETH2_TYPES.Root,
body: Phase0BeaconBlockBody,
});
exports.Phase0SignedBeaconBlock = (0, exports.container)({
message: exports.Phase0BeaconBlock,
signature: exports.ETH2_TYPES.BLSSignature,
});
exports.Phase0BeaconState = (0, exports.container)({
genesis_time: exports.uint64,
genesis_validators_root: exports.ETH2_TYPES.Root,
slot: exports.ETH2_TYPES.Slot,
fork: exports.ETH2_TYPES.Fork,
latest_block_header: exports.ETH2_TYPES.BeaconBlockHeader,
block_roots: (0, exports.vector)(SLOTS_PER_HISTORICAL_ROOT, exports.ETH2_TYPES.Root),
state_roots: (0, exports.vector)(SLOTS_PER_HISTORICAL_ROOT, exports.ETH2_TYPES.Root),
historical_roots: (0, exports.list)(HISTORICAL_ROOTS_LIMIT, exports.ETH2_TYPES.Root),
eth1_data: exports.ETH2_TYPES.Eth1Data,
eth1_data_votes: (0, exports.list)(EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH, exports.ETH2_TYPES.Eth1Data),
eth1_deposit_index: exports.uint64,
validators: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.ETH2_TYPES.Validator),
balances: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.ETH2_TYPES.Gwei),
randao_mixes: (0, exports.vector)(EPOCHS_PER_HISTORICAL_VECTOR, exports.ETH2_TYPES.Bytes32),
slashings: (0, exports.vector)(EPOCHS_PER_SLASHINGS_VECTOR, exports.ETH2_TYPES.Gwei),
previous_epoch_participation: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.ETH2_TYPES.ParticipationFlags),
current_epoch_participation: (0, exports.list)(VALIDATOR_REGISTRY_LIMIT, exports.ETH2_TYPES.ParticipationFlags),
justification_bits: (0, exports.bitvector)(JUSTIFICATION_BITS_LENGTH),
previous_justified_checkpoint: exports.ETH2_TYPES.Checkpoint,
current_justified_checkpoint: exports.ETH2_TYPES.Checkpoint,
finalized_checkpoint: exports.ETH2_TYPES.Checkpoint,
});
//# sourceMappingURL=ssz.js.map