export function getAcceptedDocument()

in src/governance/ccf-app/js/src/endpoints/documents.ts [267:392]


export function getAcceptedDocument(
  request: ccfapp.Request<GetAcceptedDocumentRequest>
):
  | ccfapp.Response<GetAcceptedDocumentResponse>
  | ccfapp.Response<ErrorResponse> {
  const id = request.params.documentId;
  const requestBody = request.body.json();
  if (!requestBody.attestation) {
    return {
      statusCode: 400,
      body: new ErrorResponse(
        "AttestationMissing",
        "Attestation payload must be supplied."
      )
    };
  }

  if (!requestBody.encrypt) {
    return {
      statusCode: 400,
      body: new ErrorResponse(
        "EncryptionMissing",
        "Encrypt payload must be supplied."
      )
    };
  }

  // Validate attestation report.
  const contractId = request.params.contractId;
  let snpAttestationResult: SnpAttestationResult;
  try {
    snpAttestationResult = verifySnpAttestation(
      contractId,
      requestBody.attestation
    );
  } catch (e) {
    return {
      statusCode: 400,
      body: new ErrorResponse("VerifySnpAttestationFailed", e.message)
    };
  }

  // Then validate the report data value.
  try {
    verifyReportData(snpAttestationResult, requestBody.encrypt.publicKey);
  } catch (e) {
    return {
      statusCode: 400,
      body: new ErrorResponse("ReportDataMismatch", e.message)
    };
  }

  // Only accepted documents are exposed.
  if (!acceptedDocumentsStore.has(id)) {
    return {
      statusCode: 404,
      body: new ErrorResponse(
        "DocumentNotFound",
        "A document with the specified id was not found or has not been accepted."
      )
    };
  }

  const documentItem = acceptedDocumentsStore.get(id);
  if (contractId != documentItem.contractId) {
    // Something is amiss. The values should match.
    return {
      statusCode: 400,
      body: new ErrorResponse(
        "ContractIdMismatch",
        `The contractId value specified in the URL ${contractId} and that in the document ${documentItem.contractId} don't match.`
      )
    };
  }

  // Attestation report and report data values are verified.
  // Wrap the document with the encryption key before returning it.
  const seqno = acceptedDocumentsStore.getVersionOfPreviousWrite(id);
  const view = ccf.consensus.getViewForSeqno(seqno);
  if (view == null) {
    return {
      statusCode: 503,
      body: new ErrorResponse(
        "ViewNotKnown",
        "View for given sequence number not known to the node at this time."
      )
    };
  }
  const version = view + "." + seqno;
  const finalVotes: { memberId: string; vote: boolean }[] = [];
  if (documentItem.finalVotes !== undefined) {
    for (const [memberId, vote] of Object.entries(documentItem.finalVotes)) {
      finalVotes.push({
        memberId: memberId,
        vote: vote === true ? true : false
      });
    }
  }

  const body: GetDocumentResponse = {
    id: id,
    version: version,
    state: "Accepted",
    contractId: documentItem.contractId,
    data: documentItem.data,
    proposalId: documentItem.proposalId,
    finalVotes: finalVotes
  };

  const wrapAlgo = {
    name: "RSA-OAEP-AES-KWP",
    aesKeySize: 256
  } as RsaOaepAesKwpParams;
  const wrapped: ArrayBuffer = ccf.crypto.wrapKey(
    ccf.jsonCompatibleToBuf(body),
    ccf.strToBuf(Base64.decode(requestBody.encrypt.publicKey)),
    wrapAlgo
  );
  const wrappedBase64 = Base64.fromUint8Array(new Uint8Array(wrapped));
  return {
    statusCode: 200,
    body: {
      value: wrappedBase64
    }
  };
}