in src/governance/ccf-app/js/src/endpoints/events.ts [227:329]
export function putEvent(
request: ccfapp.Request<PutEventRequest>
): ccfapp.Response {
const body = request.body.json();
if (!body.attestation) {
return {
statusCode: 400,
body: new ErrorResponse(
"AttestationMissing",
"Attestation payload must be supplied."
)
};
}
if (!body.sign) {
return {
statusCode: 400,
body: new ErrorResponse(
"SignatureMissing",
"Signature payload must be supplied."
)
};
}
if (!body.timestamp) {
return {
statusCode: 400,
body: new ErrorResponse("TimestampMissing", "Timestamp must be supplied.")
};
}
// Similar logic below (but milliseconds instead of seconds) as created_at parameter value for
// CCF governance proposals.
// timestamp, submitted as a integer number of milliseconds since epoch, is converted to a
// decimal representation in ASCII, stored as a string, and
// compared alphanumerically. This is partly to keep governance as
// text-based as possible, to facilitate audit, but also to be able
// to benefit from future planned ordering support in the KV. To
// compare correctly, the string representation needs to be padded
// with leading zeroes, and must therefore not exceed a fixed
// digit width. 13 digits is enough to last until November 2286,
// ie. long enough.
const timestampNumber = Number(body.timestamp);
if (timestampNumber > 9999999999999) {
return {
statusCode: 400,
body: new ErrorResponse(
"TimestampTooLarge",
"Timestamp value is too large."
)
};
}
// First validate attestation report.
const contractId = request.params.contractId;
let snpAttestationResult: SnpAttestationResult;
try {
snpAttestationResult = verifySnpAttestation(contractId, body.attestation);
} catch (e) {
return {
statusCode: 400,
body: new ErrorResponse("VerifySnpAttestationFailed", e.message)
};
}
// Then validate the report data value.
try {
verifyReportData(snpAttestationResult, body.sign.publicKey);
} catch (e) {
return {
statusCode: 400,
body: new ErrorResponse("ReportDataMismatch", e.message)
};
}
// Attestation report and report data values are verified. Now check the signature.
const data: ArrayBuffer = b64ToBuf(body.data);
try {
verifySignature(body.sign, data);
} catch (e) {
return {
statusCode: 400,
body: new ErrorResponse("SignatureMismatch", e.message)
};
}
// All verifications pass. Now insert the event.
const parsedQuery = parseRequestQuery(request);
const id = getIdFromQuery(parsedQuery, contractId);
const { scope } = parsedQuery;
const eventsMap = ccfapp.typedKv(
getEventsMapName(contractId, scope),
ccfapp.string,
ccfapp.json<EventStoreItem>()
);
const jsonObject = JSON.parse(ccf.bufToStr(data));
const timestamp = body.timestamp.padStart(13, "0");
eventsMap.set(id, { timestamp: timestamp, data: jsonObject });
return {
statusCode: 204
};
}