mina-attestations
Version:
Private Attestations on Mina
197 lines • 6.99 kB
JavaScript
/**
* This file exports types and functions that actually should be exported from o1js
*/
import { Bool, Field, Poseidon, Provable, Struct, Undefined, } from 'o1js';
import { assert, assertHasProperty, hasProperty } from "./util.js";
export { ProvableType, assertPure, array, toFieldsPacked, hashPacked, empty, toInput, HashInput, };
const ProvableType = {
get(type) {
return (hasProperty(type, 'provable') ? type.provable : type);
},
// TODO o1js should make sure this is possible for _all_ provable types
fromValue(value) {
if (value === undefined)
return Undefined;
if (value instanceof Field)
return Field;
if (value instanceof Bool)
return Bool;
if (Array.isArray(value))
return array(ProvableType.fromValue(value[0]), value.length);
assertHasProperty(value, 'constructor', 'Encountered provable value without a constructor: Cannot obtain provable type.');
let constructor = value.constructor;
assertIsProvable(ProvableType.get(constructor));
return constructor;
},
synthesize(type_) {
let type = ProvableType.get(type_);
let fields = Array.from({ length: type.sizeInFields() }, () => Field(0));
return type.fromFields(fields, type.toAuxiliary());
},
isProvableType(type) {
let type_ = ProvableType.get(type);
return hasProperty(type_, 'toFields') && hasProperty(type_, 'fromFields');
},
isProvableHashableType(type) {
let type_ = ProvableType.get(type);
return (ProvableType.isProvableType(type_) &&
hasProperty(type_, 'toInput') &&
hasProperty(type_, 'empty'));
},
constant(value) {
return {
serialize() {
return { _type: 'Constant', value };
},
sizeInFields: () => 0,
toFields: () => [],
fromFields: () => value,
toValue: (v) => v,
fromValue: (v) => v,
toAuxiliary: () => [],
check() { },
};
},
};
function assertPure(type) {
let aux = ProvableType.get(type).toAuxiliary();
assert(lengthRecursive(aux) === 0, 'Expected pure provable type to have no auxiliary fields');
}
function lengthRecursive(array) {
if (!Array.isArray(array))
return 1;
let length = 0;
for (let i = 0; i < array.length; i++) {
length += lengthRecursive(array[i]);
}
return length;
}
function assertIsProvable(type) {
assertHasProperty(type, 'toFields', 'Expected provable type to have a toFields method');
assertHasProperty(type, 'fromFields', 'Expected provable type to have a fromFields method');
}
/**
* Pack a value to as few field elements as possible using `toInput()`, falling back to `toFields()` if that's not available.
*
* Note: Different than `Packed` in o1js, this uses little-endian packing.
*/
function toFieldsPacked(type_, value) {
let type = ProvableType.get(type_);
if (type.toInput === undefined)
return type.toFields(value);
let { fields = [], packed = [] } = toInput(type, value);
let result = [...fields];
let current = Field(0);
let currentSize = 0;
for (let [field, size] of packed) {
if (currentSize + size < Field.sizeInBits) {
current = current.add(field.mul(1n << BigInt(currentSize)));
currentSize += size;
}
else {
result.push(current.seal());
current = field;
currentSize = size;
}
}
if (currentSize > 0)
result.push(current.seal());
return result;
}
/**
* Hash a provable value efficiently, by first packing it into as few field elements as possible.
*
* Note: Different than `Poseidon.hashPacked()` and `Hashed` (by default) in o1js, this uses little-endian packing.
*/
function hashPacked(type, value) {
let fields = toFieldsPacked(type, value);
return Poseidon.hash(fields);
}
// temporary, until we land `StaticArray`
// this is copied from o1js and then modified: https://github.com/o1-labs/o1js
// License here: https://github.com/o1-labs/o1js/blob/main/LICENSE
function array(elementType, length) {
let type = ProvableType.isProvableType(elementType)
? ProvableType.get(elementType)
: Struct(elementType);
return {
_isArray: true,
innerType: elementType,
size: length,
/**
* Returns the size of this structure in {@link Field} elements.
* @returns size of this structure
*/
sizeInFields() {
let elementLength = type.sizeInFields();
return elementLength * length;
},
/**
* Serializes this structure into {@link Field} elements.
* @returns an array of {@link Field} elements
*/
toFields(array) {
return array.map((e) => type.toFields(e)).flat();
},
/**
* Serializes this structure's auxiliary data.
* @returns auxiliary data
*/
toAuxiliary(array) {
let array_ = array ?? Array(length).fill(undefined);
return array_?.map((e) => type.toAuxiliary(e));
},
/**
* Deserializes an array of {@link Field} elements into this structure.
*/
fromFields(fields, aux) {
let array = [];
let size = type.sizeInFields();
let n = length;
for (let i = 0, offset = 0; i < n; i++, offset += size) {
array[i] = type.fromFields(fields.slice(offset, offset + size), aux?.[i]);
}
return array;
},
check(array) {
for (let i = 0; i < length; i++) {
type.check(array[i]);
}
},
toCanonical(x) {
return x.map((v) => Provable.toCanonical(type, v));
},
toValue(x) {
return x.map((v) => type.toValue(v));
},
fromValue(x) {
return x.map((v) => type.fromValue(v));
},
toInput(array) {
return array.reduce((curr, value) => HashInput.append(curr, toInput(type, value)), HashInput.empty);
},
empty() {
return Array.from({ length }, () => empty(type));
},
};
}
// this is copied from o1js and then modified: https://github.com/o1-labs/o1js
// License here: https://github.com/o1-labs/o1js/blob/main/LICENSE
const HashInput = {
get empty() {
return {};
},
append(input1, input2) {
return {
fields: (input1.fields ?? []).concat(input2.fields ?? []),
packed: (input1.packed ?? []).concat(input2.packed ?? []),
};
},
};
function toInput(type, value) {
return type.toInput?.(value) ?? { fields: type.toFields(value) };
}
function empty(type) {
return type.empty?.() ?? ProvableType.synthesize(type);
}
//# sourceMappingURL=o1js-missing.js.map