searchCredentialsForPresentationDefinition function

List<FilterResult> searchCredentialsForPresentationDefinition(
  1. List credentials,
  2. PresentationDefinition presentationDefinition
)

Implementation

List<FilterResult> searchCredentialsForPresentationDefinition(
    List<dynamic> credentials, PresentationDefinition presentationDefinition) {
  //cast everything
  var creds = <VerifiableCredential>[];
  for (var entry in credentials) {
    if (entry is VerifiableCredential) {
      creds.add(entry);
    } else {
      creds.add(VerifiableCredential.fromJson(entry));
    }
  }

  var globalFormat = presentationDefinition.format;
  if (globalFormat != null) {
    if (globalFormat.ldpVp == null &&
        globalFormat.ldp == null &&
        globalFormat.ldpVc == null) {
      throw Exception('Only supported Formats are Linked Data proofs');
    }
  }

  if (presentationDefinition.submissionRequirement != null) {
    Map<String, FilterResult> filterResultPerDescriptor = {};
    Map<String, dynamic> descriptorGroups = {};

    //search things for all descriptors
    for (var descriptor in presentationDefinition.inputDescriptors) {
      if (descriptor.group == null) {
        throw Exception('Ungrouped input descriptor');
      }

      //input descriptors per group
      for (var g in descriptor.group!) {
        if (descriptorGroups.containsKey(g)) {
          List<dynamic> gl = descriptorGroups[g];
          gl.add(descriptor.id);
          descriptorGroups[g] = gl;
        } else {
          descriptorGroups[g] = [descriptor.id];
        }
      }

      //credentials per descriptor
      var filteredCreds =
          _processInputDescriptor(descriptor, globalFormat, creds);
      print(filteredCreds.credentials.length);
      filterResultPerDescriptor[descriptor.id] = filteredCreds;
    }

    //Evaluate submission requirements
    List<FilterResult> finalCredList = [];
    for (var requirement in presentationDefinition.submissionRequirement!) {
      finalCredList.add(_processSubmissionRequirement(filterResultPerDescriptor,
          descriptorGroups, requirement, presentationDefinition.id));
    }
    print(
        '${finalCredList.length} / ${finalCredList.first.credentials.length}');
    return finalCredList;
  } else {
    List<VerifiableCredential> inputCreds = creds;
    List<String> allDescriptorIds = [];
    List<InputDescriptorConstraints> allSelfIssuables = [];
    for (var descriptor in presentationDefinition.inputDescriptors) {
      //Without any requirements, all input_descriptors must be fulfilled
      allDescriptorIds.add(descriptor.id);
      var res = _processInputDescriptor(descriptor, globalFormat, inputCreds);
      // TODO: I think this way is wrong. The input_descriptor can be fulfilled by multiple credentials.
      inputCreds = res.credentials;
      if (res.selfIssuable != null) {
        allSelfIssuables.addAll(res.selfIssuable!);
      }
    }
    return [
      FilterResult(
          selfIssuable: allSelfIssuables.isNotEmpty ? allSelfIssuables : null,
          credentials: inputCreds,
          matchingDescriptorIds: allDescriptorIds,
          presentationDefinitionId: presentationDefinition.id,
          fulfilled: inputCreds.isEmpty || allSelfIssuables.isEmpty)
    ];
  }
}