ox
Version:
244 lines • 9.33 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.InvalidVersionedHashVersionError = exports.InvalidVersionedHashSizeError = exports.EmptyBlobVersionedHashesError = exports.EmptyBlobError = exports.BlobSizeTooLargeError = exports.maxBytesPerTransaction = exports.bytesPerBlob = exports.fieldElementsPerBlob = exports.bytesPerFieldElement = void 0;
exports.commitmentsToVersionedHashes = commitmentsToVersionedHashes;
exports.commitmentToVersionedHash = commitmentToVersionedHash;
exports.from = from;
exports.sidecarsToVersionedHashes = sidecarsToVersionedHashes;
exports.to = to;
exports.toHex = toHex;
exports.toBytes = toBytes;
exports.toCommitments = toCommitments;
exports.toProofs = toProofs;
exports.toSidecars = toSidecars;
exports.toVersionedHashes = toVersionedHashes;
const Bytes = require("./Bytes.js");
const Errors = require("./Errors.js");
const Hash = require("./Hash.js");
const Hex = require("./Hex.js");
const Cursor = require("./internal/cursor.js");
const Kzg = require("./Kzg.js");
const blobsPerTransaction = 6;
exports.bytesPerFieldElement = 32;
exports.fieldElementsPerBlob = 4096;
exports.bytesPerBlob = exports.bytesPerFieldElement * exports.fieldElementsPerBlob;
exports.maxBytesPerTransaction = exports.bytesPerBlob * blobsPerTransaction -
1 -
1 * exports.fieldElementsPerBlob * blobsPerTransaction;
function commitmentsToVersionedHashes(commitments, options = {}) {
const { version } = options;
const as = options.as ?? (typeof commitments[0] === 'string' ? 'Hex' : 'Bytes');
const hashes = [];
for (const commitment of commitments) {
hashes.push(commitmentToVersionedHash(commitment, {
as,
version,
}));
}
return hashes;
}
function commitmentToVersionedHash(commitment, options = {}) {
const { version = 1 } = options;
const as = options.as ?? (typeof commitment === 'string' ? 'Hex' : 'Bytes');
const versionedHash = Hash.sha256(commitment, { as: 'Bytes' });
versionedHash.set([version], 0);
return (as === 'Bytes' ? versionedHash : Hex.fromBytes(versionedHash));
}
function from(data, options = {}) {
const as = options.as ?? (typeof data === 'string' ? 'Hex' : 'Bytes');
const data_ = (typeof data === 'string' ? Bytes.fromHex(data) : data);
const size_ = Bytes.size(data_);
if (!size_)
throw new EmptyBlobError();
if (size_ > exports.maxBytesPerTransaction)
throw new BlobSizeTooLargeError({
maxSize: exports.maxBytesPerTransaction,
size: size_,
});
const blobs = [];
let active = true;
let position = 0;
while (active) {
const blob = Cursor.create(new Uint8Array(exports.bytesPerBlob));
let size = 0;
while (size < exports.fieldElementsPerBlob) {
const bytes = data_.slice(position, position + (exports.bytesPerFieldElement - 1));
blob.pushByte(0x00);
blob.pushBytes(bytes);
if (bytes.length < 31) {
blob.pushByte(0x80);
active = false;
break;
}
size++;
position += 31;
}
blobs.push(blob);
}
return (as === 'Bytes'
? blobs.map((x) => x.bytes)
: blobs.map((x) => Hex.fromBytes(x.bytes)));
}
function sidecarsToVersionedHashes(sidecars, options = {}) {
const { version } = options;
const as = options.as ?? (typeof sidecars[0].blob === 'string' ? 'Hex' : 'Bytes');
const hashes = [];
for (const { commitment } of sidecars) {
hashes.push(commitmentToVersionedHash(commitment, {
as,
version,
}));
}
return hashes;
}
function to(blobs, to) {
const to_ = to ?? (typeof blobs[0] === 'string' ? 'Hex' : 'Bytes');
const blobs_ = (typeof blobs[0] === 'string'
? blobs.map((x) => Bytes.fromHex(x))
: blobs);
const length = blobs_.reduce((length, blob) => length + blob.length, 0);
const data = Cursor.create(new Uint8Array(length));
let active = true;
for (const blob of blobs_) {
const cursor = Cursor.create(blob);
while (active && cursor.position < blob.length) {
cursor.incrementPosition(1);
let consume = 31;
if (blob.length - cursor.position < 31)
consume = blob.length - cursor.position;
for (const _ in Array.from({ length: consume })) {
const byte = cursor.readByte();
const isTerminator = byte === 0x80 && !cursor.inspectBytes(cursor.remaining).includes(0x80);
if (isTerminator) {
active = false;
break;
}
data.pushByte(byte);
}
}
}
const trimmedData = data.bytes.slice(0, data.position);
return (to_ === 'Hex' ? Hex.fromBytes(trimmedData) : trimmedData);
}
function toHex(blobs) {
return to(blobs, 'Hex');
}
function toBytes(blobs) {
return to(blobs, 'Bytes');
}
function toCommitments(blobs, options) {
const { kzg } = options;
const as = options.as ?? (typeof blobs[0] === 'string' ? 'Hex' : 'Bytes');
const blobs_ = (typeof blobs[0] === 'string'
? blobs.map((x) => Bytes.fromHex(x))
: blobs);
const commitments = [];
for (const blob of blobs_)
commitments.push(Uint8Array.from(kzg.blobToKzgCommitment(blob)));
return (as === 'Bytes' ? commitments : commitments.map((x) => Hex.fromBytes(x)));
}
function toProofs(blobs, options) {
const { kzg } = options;
const as = options.as ?? (typeof blobs[0] === 'string' ? 'Hex' : 'Bytes');
const blobs_ = (typeof blobs[0] === 'string'
? blobs.map((x) => Bytes.fromHex(x))
: blobs);
const commitments = (typeof options.commitments[0] === 'string'
? options.commitments.map((x) => Bytes.fromHex(x))
: options.commitments);
const proofs = [];
for (let i = 0; i < blobs_.length; i++) {
const blob = blobs_[i];
const commitment = commitments[i];
proofs.push(Uint8Array.from(kzg.computeBlobKzgProof(blob, commitment)));
}
return (as === 'Bytes' ? proofs : proofs.map((x) => Hex.fromBytes(x)));
}
function toSidecars(blobs, options) {
const { kzg } = options;
const commitments = options.commitments ?? toCommitments(blobs, { kzg: kzg });
const proofs = options.proofs ??
toProofs(blobs, { commitments: commitments, kzg: kzg });
const sidecars = [];
for (let i = 0; i < blobs.length; i++)
sidecars.push({
blob: blobs[i],
commitment: commitments[i],
proof: proofs[i],
});
return sidecars;
}
function toVersionedHashes(blobs, options) {
const commitments = toCommitments(blobs, options);
return commitmentsToVersionedHashes(commitments, options);
}
class BlobSizeTooLargeError extends Errors.BaseError {
constructor({ maxSize, size }) {
super('Blob size is too large.', {
metaMessages: [`Max: ${maxSize} bytes`, `Given: ${size} bytes`],
});
Object.defineProperty(this, "name", {
enumerable: true,
configurable: true,
writable: true,
value: 'Blobs.BlobSizeTooLargeError'
});
}
}
exports.BlobSizeTooLargeError = BlobSizeTooLargeError;
class EmptyBlobError extends Errors.BaseError {
constructor() {
super('Blob data must not be empty.');
Object.defineProperty(this, "name", {
enumerable: true,
configurable: true,
writable: true,
value: 'Blobs.EmptyBlobError'
});
}
}
exports.EmptyBlobError = EmptyBlobError;
class EmptyBlobVersionedHashesError extends Errors.BaseError {
constructor() {
super('Blob versioned hashes must not be empty.');
Object.defineProperty(this, "name", {
enumerable: true,
configurable: true,
writable: true,
value: 'Blobs.EmptyBlobVersionedHashesError'
});
}
}
exports.EmptyBlobVersionedHashesError = EmptyBlobVersionedHashesError;
class InvalidVersionedHashSizeError extends Errors.BaseError {
constructor({ hash, size, }) {
super(`Versioned hash "${hash}" size is invalid.`, {
metaMessages: ['Expected: 32', `Received: ${size}`],
});
Object.defineProperty(this, "name", {
enumerable: true,
configurable: true,
writable: true,
value: 'Blobs.InvalidVersionedHashSizeError'
});
}
}
exports.InvalidVersionedHashSizeError = InvalidVersionedHashSizeError;
class InvalidVersionedHashVersionError extends Errors.BaseError {
constructor({ hash, version, }) {
super(`Versioned hash "${hash}" version is invalid.`, {
metaMessages: [
`Expected: ${Kzg.versionedHashVersion}`,
`Received: ${version}`,
],
});
Object.defineProperty(this, "name", {
enumerable: true,
configurable: true,
writable: true,
value: 'Blobs.InvalidVersionedHashVersionError'
});
}
}
exports.InvalidVersionedHashVersionError = InvalidVersionedHashVersionError;
//# sourceMappingURL=Blobs.js.map
;