Skip to content

Commit

Permalink
Fix empty objects in credential throws error
Browse files Browse the repository at this point in the history
Signed-off-by: Samuel Hellawell <sshellawell@gmail.com>
  • Loading branch information
cykoder committed Apr 4, 2023
1 parent f6e26c3 commit b8194f9
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 14 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@docknetwork/crypto-wasm-ts",
"version": "0.31.2",
"version": "0.31.3",
"description": "Typescript abstractions over Dock's Rust crypto library's WASM wrapper",
"homepage": "https://github.com/docknetwork/crypto-wasm-ts",
"main": "lib/index.js",
Expand Down
30 changes: 19 additions & 11 deletions src/anonymous-credentials/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,7 @@ export class CredentialSchema extends Versioned {

static validateGeneric(schema: object, ignoreKeys: Set<string> = new Set()) {
const [names, values] = this.flattenSchemaObj(schema);

for (let i = 0; i < names.length; i++) {
if (ignoreKeys.has(names[i])) {
continue;
Expand Down Expand Up @@ -644,16 +645,16 @@ export class CredentialSchema extends Versioned {
properties: {
id: {
type: 'string'
},
},
}
}
},
proof: {
type: 'object',
properties: {
type: {
type: 'string'
},
},
}
}
}
}
};
Expand Down Expand Up @@ -1101,13 +1102,20 @@ export class CredentialSchema extends Versioned {
} else if (schemaProps[key]['type'] == 'object' && typ == 'object') {
const schemaKeys = new Set([...Object.keys(schemaProps[key]['properties'])]);
const valKeys = new Set([...Object.keys(value)]);
for (const vk of valKeys) {
CredentialSchema.generateFromCredential(value, schemaProps[key]['properties']);
}
// Delete extra keys not in cred
for (const sk of schemaKeys) {
if (value[sk] === undefined) {
delete schemaKeys[sk];

// If empty object, skip it here otherwise causes problems downstream
if (schemaKeys.size === 0) {
delete schemaProps[key];
} else {
for (const vk of valKeys) {
// TODO: why this loop? seems useless?
CredentialSchema.generateFromCredential(value, schemaProps[key]['properties']);
}
// Delete extra keys not in cred
for (const sk of schemaKeys) {
if (value[sk] === undefined) {
delete schemaKeys[sk];
}
}
}
} else {
Expand Down
4 changes: 3 additions & 1 deletion src/anonymous-credentials/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { ValueType, ValueTypes } from './schema';
import { Encoder } from '../bbs-plus';
import { SetupParam, Statement, WitnessEqualityMetaStatement } from '../composite-proof';
import { SetupParamsTracker } from './setup-params-tracker';
import { isEmptyObject } from '../util';

export function dockAccumulatorParams(): AccumulatorParams {
return Accumulator.generateParams(ACCUMULATOR_PARAMS_LABEL_BYTES);
Expand All @@ -56,7 +57,8 @@ export function dockSaverEncryptionGensUncompressed(): SaverEncryptionGensUncomp
export function flattenTill2ndLastKey(obj: object): [string[], object[]] {
const flattened = {};
const temp = flatten(obj) as object;
for (const k of Object.keys(temp)) {
const tempKeys = Object.keys(temp).filter((key) => typeof temp[key] !== 'object' || !isEmptyObject(temp[key]));
for (const k of tempKeys) {
// taken from https://stackoverflow.com/a/5555607
const pos = k.lastIndexOf('.');
const name = k.substring(0, pos);
Expand Down
7 changes: 6 additions & 1 deletion src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,12 @@ export function randomFieldElement(seed?: Uint8Array): Uint8Array {
*/
export function flattenObjectToKeyValuesList(obj: object, flattenOptions = undefined): [string[], unknown[]] {
const flattened = flatten(obj, flattenOptions) as object;
const keys = Object.keys(flattened).sort();

// Sort and filter keys to remove empty objects
// this is done because schema generation removes empty objects + nothing to encode
const keys = Object.keys(flattened)
.sort()
.filter((k) => typeof flattened[k] !== 'object' || !isEmptyObject(flattened[k]));
// @ts-ignore
const values = keys.map((k) => flattened[k]);
return [keys, values];
Expand Down
13 changes: 13 additions & 0 deletions tests/anonymous-credentials/credential.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -871,4 +871,17 @@ describe('Credential signing and verification', () => {
checkResult(recreatedCred.verify(pk));
}
});

it('for credential with auto-generated schema and empty objects', () => {
const builder = new CredentialBuilder();
builder.schema = new CredentialSchema(CredentialSchema.essential());
builder.subject = {
fname: 'John',
emptyObject: {},
lname: 'Smith',
};

const cred = builder.sign(sk, undefined, {requireSameFieldsAsSchema: false});
checkResult(cred.verify(pk));
});
});

0 comments on commit b8194f9

Please sign in to comment.