@@ -6,6 +6,7 @@ import { Tuple, TupleMap, TupleN } from '../util/types.js';
66import { Gadgets } from './gadgets/gadgets.js' ;
77import { ForeignField as FF , Field3 } from './gadgets/foreign-field.js' ;
88import { assert } from './gadgets/common.js' ;
9+ import { fieldToField3 } from './gadgets/comparison.js' ;
910import { l3 , l } from './gadgets/range-check.js' ;
1011import { ProvablePureExtended } from './types/struct.js' ;
1112
@@ -42,6 +43,36 @@ class ForeignField {
4243 return this . constructor as typeof ForeignField ;
4344 }
4445
46+ /**
47+ * Unsafe constructor methods for advanced usage.
48+ */
49+ static get Unsafe ( ) {
50+ const Constructor = this ;
51+ return {
52+ /**
53+ * Converts a {@link Field} into a {@link ForeignField}. This is an **unsafe** operation
54+ * as the native Field size may be larger than the Foreign Field size, and changes in modulus
55+ * can have unintended consequences.
56+ *
57+ * Only use this if you have already constrained the Field element to be within the foreign field modulus.
58+ *
59+ * @param x a {@link Field}
60+ */
61+ fromField ( x : Field ) {
62+ const p = Constructor . modulus ;
63+ if ( x . isConstant ( ) ) {
64+ let value = x . toBigInt ( ) ;
65+ if ( value >= p ) {
66+ throw new Error (
67+ `Field value ${ value } exceeds foreign field modulus ${ p } . Please ensure the value is reduced to the modulus.`
68+ ) ;
69+ }
70+ }
71+ return new Constructor . Canonical ( fieldToField3 ( x ) ) ;
72+ } ,
73+ } ;
74+ }
75+
4576 /**
4677 * Sibling classes that represent different ranges of field elements.
4778 */
@@ -76,10 +107,11 @@ class ForeignField {
76107 }
77108
78109 /**
79- * Create a new {@link ForeignField} from a bigint, number, string or another ForeignField.
110+ * Create a new {@link ForeignField} from a bigint, number, string, or another ForeignField.
80111 * @example
81112 * ```ts
82113 * let x = new ForeignField(5);
114+ * let y = ForeignField.from(10n);
83115 * ```
84116 *
85117 * Note: Inputs must be range checked if they originate from a different field with a different modulus or if they are not constants.
@@ -110,6 +142,7 @@ class ForeignField {
110142
111143 /**
112144 * Coerce the input to a {@link ForeignField}.
145+ * @param x - The value to convert. Can be a {@link ForeignField}, bigint, number, or string.
113146 */
114147 static from ( x : bigint | number | string ) : CanonicalForeignField ;
115148 static from ( x : ForeignField | bigint | number | string ) : ForeignField ;
@@ -689,7 +722,7 @@ type Constructor<T> = new (...args: any[]) => T;
689722function provable <
690723 F extends ForeignField & {
691724 type : 'Unreduced' | 'AlmostReduced' | 'FullyReduced' ;
692- } ,
725+ }
693726> (
694727 Class : Constructor < F > & { check ( x : ForeignField ) : void }
695728) : ProvablePureExtended < F , bigint , string > {
0 commit comments