-
Notifications
You must be signed in to change notification settings - Fork 142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve CircuitValue #269
Improve CircuitValue #269
Changes from all commits
b1c5dd6
eb4259b
b0d8e5a
d0a6c41
a405f1d
be1d24b
928206e
0a52594
6cc99fa
c3eb8c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,17 +15,36 @@ export { | |
circuitValue, | ||
}; | ||
|
||
type Constructor<T> = { new (...args: any[]): T }; | ||
type AnyConstructor = new (...args: any) => any; | ||
|
||
// TODO: Synthesize the constructor if possible (bkase) | ||
// | ||
abstract class CircuitValue { | ||
constructor(...props: any[]) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fun fact: this function was written verbatim, completely correctly, by github copilot on the first try!!! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's pretty amazing! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is really cool! I'm going to try out copilot. |
||
const fields = (this.constructor as any).prototype._fields; | ||
if (fields === undefined || fields === null) { | ||
return; | ||
} | ||
|
||
if (props.length !== fields.length) { | ||
throw Error( | ||
`${this.constructor.name} constructor called with ${props.length} arguments, but expected ${fields.length}` | ||
); | ||
} | ||
|
||
for (let i = 0; i < fields.length; ++i) { | ||
const [key, propType] = fields[i]; | ||
(this as any)[key] = props[i]; | ||
} | ||
} | ||
|
||
static sizeInFields(): number { | ||
const fields: [string, any][] = (this as any).prototype._fields; | ||
return fields.reduce((acc, [_, typ]) => acc + typ.sizeInFields(), 0); | ||
} | ||
|
||
static toFields<T>(this: Constructor<T>, v: T): Field[] { | ||
static toFields<T extends AnyConstructor>( | ||
this: T, | ||
v: InstanceType<T> | ||
): Field[] { | ||
const res: Field[] = []; | ||
const fields = (this as any).prototype._fields; | ||
if (fields === undefined || fields === null) { | ||
|
@@ -48,15 +67,18 @@ abstract class CircuitValue { | |
return (this.constructor as any).toJSON(this); | ||
} | ||
|
||
equals(this: this, x: this): Bool { | ||
equals(x: this): Bool { | ||
return Circuit.equal(this, x); | ||
} | ||
|
||
assertEquals(this: this, x: typeof this): void { | ||
assertEquals(x: this): void { | ||
Circuit.assertEqual(this, x); | ||
} | ||
|
||
static ofFields<T>(this: Constructor<T>, xs: Field[]): T { | ||
static ofFields<T extends AnyConstructor>( | ||
this: T, | ||
xs: Field[] | ||
): InstanceType<T> { | ||
const fields = (this as any).prototype._fields; | ||
let offset = 0; | ||
const props: any[] = []; | ||
|
@@ -70,14 +92,33 @@ abstract class CircuitValue { | |
return new this(...props); | ||
} | ||
|
||
static check: (x: any) => void; | ||
static check<T extends AnyConstructor>(this: T, v: InstanceType<T>) { | ||
const fields = (this as any).prototype._fields; | ||
if (fields === undefined || fields === null) { | ||
return; | ||
} | ||
|
||
for (let i = 0; i < fields.length; ++i) { | ||
const [key, propType] = fields[i]; | ||
const value = (v as any)[key]; | ||
if (propType.check === undefined) | ||
throw Error('bug: circuit value without .check()'); | ||
propType.check(value); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this error get thrown if a CircuitValue class does not define a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no! it would get thrown if one of our primitives was missing check -- which isn't the case --, or maybe if a developer uses something which isn't a CircuitValue, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. but probably won't get thrown at all :D |
||
} | ||
} | ||
|
||
static toConstant<T>(this: Constructor<T>, t: T): T { | ||
static toConstant<T extends AnyConstructor>( | ||
this: T, | ||
t: InstanceType<T> | ||
): InstanceType<T> { | ||
const xs: Field[] = (this as any).toFields(t); | ||
return (this as any).ofFields(xs.map((x) => x.toConstant())); | ||
} | ||
|
||
static toJSON<T>(this: Constructor<T>, v: T): JSONValue { | ||
static toJSON<T extends AnyConstructor>( | ||
this: T, | ||
v: InstanceType<T> | ||
): JSONValue { | ||
const res: { [key: string]: JSONValue } = {}; | ||
if ((this as any).prototype._fields !== undefined) { | ||
const fields: [string, any][] = (this as any).prototype._fields; | ||
|
@@ -88,7 +129,10 @@ abstract class CircuitValue { | |
return res; | ||
} | ||
|
||
static fromJSON<T>(this: Constructor<T>, value: JSONValue): T | null { | ||
static fromJSON<T extends AnyConstructor>( | ||
this: T, | ||
value: JSONValue | ||
): InstanceType<T> | null { | ||
const props: any[] = []; | ||
const fields: [string, any][] = (this as any).prototype._fields; | ||
|
||
|
@@ -117,21 +161,6 @@ abstract class CircuitValue { | |
} | ||
} | ||
|
||
(CircuitValue as any).check = function (v: any) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. was able to remove this hack because I got the types working on |
||
const fields = (this as any).prototype._fields; | ||
if (fields === undefined || fields === null) { | ||
return; | ||
} | ||
|
||
for (let i = 0; i < fields.length; ++i) { | ||
const [key, propType] = fields[i]; | ||
const value = (v as any)[key]; | ||
if (propType.check === undefined) | ||
throw Error('bug: circuit value without .check()'); | ||
propType.check(value); | ||
} | ||
}; | ||
|
||
function prop(this: any, target: any, key: string) { | ||
const fieldType = Reflect.getMetadata('design:type', target, key); | ||
if (!target.hasOwnProperty('_fields')) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,11 +8,6 @@ class UInt64 extends CircuitValue implements Types.UInt64 { | |
static NUM_BITS = 64; | ||
_type?: 'UInt64'; | ||
|
||
constructor(value: Field) { | ||
super(); | ||
this.value = value; | ||
} | ||
|
||
static get zero() { | ||
return new UInt64(Field.zero); | ||
} | ||
|
@@ -182,11 +177,6 @@ class UInt32 extends CircuitValue implements Types.UInt32 { | |
static NUM_BITS = 32; | ||
_type?: 'UInt32'; | ||
|
||
constructor(value: Field) { | ||
super(); | ||
this.value = value; | ||
} | ||
|
||
static get zero(): UInt32 { | ||
return new UInt32(Field.zero); | ||
} | ||
|
@@ -364,9 +354,7 @@ class Int64 extends CircuitValue implements BalanceChange { | |
// Overall, I think the existing implementation is the optimal one. | ||
|
||
constructor(magnitude: UInt64, sgn = Field.one) { | ||
super(); | ||
this.magnitude = magnitude; | ||
this.sgn = sgn; | ||
super(magnitude, sgn); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I left this constructor because it adds something nice -- a default value for one of the arguments |
||
} | ||
|
||
private static fromFieldUnchecked(x: Field) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a fix that's unrelated to the rest of the PR