@@ -6,6 +6,11 @@ import { flattenObjectToKeyValuesList, isPositiveInteger } from '../util';
66 */
77export type EncodeFunc = ( value : unknown ) => Uint8Array ;
88
9+ /**
10+ * A function that encodes the input to a positive integer
11+ */
12+ export type ToPositiveIntFunc = ( value : unknown ) => number ;
13+
914/**
1015 * Encodes the input to a field element for signing with BBS+ in group G1.
1116 * Used when working with messages that are specified as JS objects. This encoder object will contain
@@ -29,13 +34,14 @@ export class Encoder {
2934 * Encode a message with given name and value. Will throw an error if no appropriate encoder found.
3035 * @param name
3136 * @param value
37+ * @param strict - If set to false and no appropriate encoder is found but the value is a bytearray, it will encode it using the built-in mechanism
3238 */
33- encodeMessage ( name : string , value : unknown ) : Uint8Array {
39+ encodeMessage ( name : string , value : unknown , strict = false ) : Uint8Array {
3440 const encoder = this . encoders ?. get ( name ) || this . defaultEncoder ;
3541 if ( encoder !== undefined ) {
3642 return encoder ( value ) ;
3743 } else {
38- if ( value instanceof Uint8Array ) {
44+ if ( ! strict && value instanceof Uint8Array ) {
3945 return SignatureG1 . encodeMessageForSigning ( value ) ;
4046 } else {
4147 throw new Error (
@@ -49,12 +55,13 @@ export class Encoder {
4955 * Encode messages given as JS object. It flattens the object into a sorted list and encodes each value as per the known
5056 * encoding functions Returns 2 arrays, 1st with message names and 2nd with encoded values.
5157 * @param messages
58+ * @param strict - If set to false and no appropriate encoder is found but the value is a bytearray, it will encode it using the built-in mechanism
5259 */
53- encodeMessageObject ( messages : object ) : [ string [ ] , Uint8Array [ ] ] {
60+ encodeMessageObject ( messages : object , strict = false ) : [ string [ ] , Uint8Array [ ] ] {
5461 const [ names , values ] = flattenObjectToKeyValuesList ( messages ) ;
5562 const encoded : Uint8Array [ ] = [ ] ;
5663 for ( let i = 0 ; i < names . length ; i ++ ) {
57- encoded . push ( this . encodeMessage ( names [ i ] , values [ i ] ) ) ;
64+ encoded . push ( this . encodeMessage ( names [ i ] , values [ i ] , strict ) ) ;
5865 }
5966 return [ names , encoded ] ;
6067 }
@@ -67,27 +74,58 @@ export class Encoder {
6774 if ( ! isPositiveInteger ( v ) ) {
6875 throw new Error ( `Expected positive integer but ${ v } has type ${ typeof v } ` ) ;
6976 }
70- // @ts -ignore
71- return SignatureG1 . encodePositiveNumberForSigning ( v ) ;
77+ return SignatureG1 . encodePositiveNumberForSigning ( v as number ) ;
7278 } ;
7379 }
7480
7581 /**
76- * Returns an encoding function to be used on a message that can be a positive or negative integer.
77- * @param minimum - The minimum negative value that the message can take
82+ * Returns a function that can convert any input integer to a positive integer when its minimum
83+ * negative value is known. Does that by adding an offset of abs(minimum) to the input
84+ * @param minimum
7885 */
79- static integerEncoder ( minimum : number ) : EncodeFunc {
86+ static integerToPositiveInt ( minimum : number ) : ToPositiveIntFunc {
87+ if ( ! Number . isInteger ( minimum ) ) {
88+ throw new Error ( `Expected integer but ${ minimum } has type ${ typeof minimum } ` ) ;
89+ }
8090 const offset = Math . abs ( minimum ) ;
8191 return ( v : unknown ) => {
8292 if ( ! Number . isInteger ( v ) ) {
8393 throw new Error ( `Expected integer but ${ v } has type ${ typeof v } ` ) ;
8494 }
85- // @ts -ignore
86- if ( v < minimum ) {
87- throw new Error ( `Encoder was created with minimum value ${ minimum } but was asked to encode ${ v } ` ) ;
95+ const vNum = v as number ;
96+ if ( vNum < minimum ) {
97+ throw new Error ( `Encoder was created with minimum value ${ minimum } but was asked to encode ${ vNum } ` ) ;
8898 }
89- // @ts -ignore
90- return SignatureG1 . encodePositiveNumberForSigning ( offset + v ) ;
99+ return offset + vNum ;
100+ } ;
101+ }
102+
103+ /**
104+ * Returns an encoding function to be used on a message that can be a positive or negative integer.
105+ * @param minimum - The minimum negative value that the message can take
106+ */
107+ static integerEncoder ( minimum : number ) : EncodeFunc {
108+ const f = Encoder . integerToPositiveInt ( minimum ) ;
109+ return ( v : unknown ) => {
110+ return SignatureG1 . encodePositiveNumberForSigning ( f ( v ) ) ;
111+ } ;
112+ }
113+
114+ /**
115+ * Returns a function that can convert any positive number to a positive integer when its maximum decimal
116+ * places are known. Does that by multiplying it by 10^max_decimal_places, eg. 23.452 -> 23452
117+ * @param maxDecimalPlaces
118+ */
119+ static positiveDecimalNumberToPositiveInt ( maxDecimalPlaces : number ) : ToPositiveIntFunc {
120+ if ( ! isPositiveInteger ( maxDecimalPlaces ) ) {
121+ throw new Error ( `Maximum decimal places should be a positive integer but was ${ maxDecimalPlaces } ` ) ;
122+ }
123+ const multiple = Math . pow ( 10 , maxDecimalPlaces ) ;
124+ return ( v : unknown ) => {
125+ Encoder . ensureNumber ( v ) ;
126+ const vNum = v as number ;
127+ Encoder . ensureCorrectDecimalNumberPlaces ( vNum , maxDecimalPlaces ) ;
128+ return Math . trunc ( vNum * multiple ) ;
91129 } ;
92130 }
93131
@@ -96,16 +134,32 @@ export class Encoder {
96134 * @param maxDecimalPlaces - The maximum decimal places
97135 */
98136 static positiveDecimalNumberEncoder ( maxDecimalPlaces : number ) : EncodeFunc {
99- if ( ! Number . isInteger ( maxDecimalPlaces ) || maxDecimalPlaces < 1 ) {
100- throw new Error ( `Maximum decimal places should be a positive integer greater than 1 but was ${ maxDecimalPlaces } ` ) ;
137+ const f = Encoder . positiveDecimalNumberToPositiveInt ( maxDecimalPlaces ) ;
138+ return ( v : unknown ) => {
139+ return SignatureG1 . encodePositiveNumberForSigning ( f ( v ) ) ;
140+ } ;
141+ }
142+
143+ /**
144+ * Returns a function that can convert any number to a positive integer when its minimum negative value and maximum
145+ * decimal places are known. Does that by adding an offset of abs(minimum) and then multiplying it by 10^max_decimal_places
146+ * @param minimum
147+ * @param maxDecimalPlaces
148+ */
149+ static decimalNumberToPositiveInt ( minimum : number , maxDecimalPlaces : number ) : ToPositiveIntFunc {
150+ if ( ! isPositiveInteger ( maxDecimalPlaces ) ) {
151+ throw new Error ( `Maximum decimal places should be a positive integer but was ${ maxDecimalPlaces } ` ) ;
101152 }
153+ const offset = Math . abs ( minimum ) ;
102154 const multiple = Math . pow ( 10 , maxDecimalPlaces ) ;
103155 return ( v : unknown ) => {
104156 Encoder . ensureNumber ( v ) ;
105- // @ts -ignore
106- Encoder . ensureCorrectDecimalNumberPlaces ( v , maxDecimalPlaces ) ;
107- // @ts -ignore
108- return SignatureG1 . encodePositiveNumberForSigning ( Math . trunc ( v * multiple ) ) ;
157+ const vNum = v as number ;
158+ if ( vNum < minimum ) {
159+ throw new Error ( `Encoder was created with minimum value ${ minimum } but was asked to encode ${ vNum } ` ) ;
160+ }
161+ Encoder . ensureCorrectDecimalNumberPlaces ( vNum , maxDecimalPlaces ) ;
162+ return Math . trunc ( ( offset + vNum ) * multiple ) ;
109163 } ;
110164 }
111165
@@ -115,21 +169,9 @@ export class Encoder {
115169 * @param maxDecimalPlaces - The maximum decimal places
116170 */
117171 static decimalNumberEncoder ( minimum : number , maxDecimalPlaces : number ) : EncodeFunc {
118- if ( ! Number . isInteger ( maxDecimalPlaces ) || maxDecimalPlaces < 1 ) {
119- throw new Error ( `Maximum decimal places should be a positive integer greater than 1 but was ${ maxDecimalPlaces } ` ) ;
120- }
121- const offset = Math . abs ( minimum ) ;
122- const multiple = Math . pow ( 10 , maxDecimalPlaces ) ;
172+ const f = Encoder . decimalNumberToPositiveInt ( minimum , maxDecimalPlaces ) ;
123173 return ( v : unknown ) => {
124- Encoder . ensureNumber ( v ) ;
125- // @ts -ignore
126- if ( v < minimum ) {
127- throw new Error ( `Encoder was created with minimum value ${ minimum } but was asked to encode ${ v } ` ) ;
128- }
129- // @ts -ignore
130- Encoder . ensureCorrectDecimalNumberPlaces ( v , maxDecimalPlaces ) ;
131- // @ts -ignore
132- return SignatureG1 . encodePositiveNumberForSigning ( Math . trunc ( ( offset + v ) * multiple ) ) ;
174+ return SignatureG1 . encodePositiveNumberForSigning ( f ( v ) ) ;
133175 } ;
134176 }
135177
0 commit comments