Skip to content

Commit

Permalink
Prevent future time drift timestamp (#92)
Browse files Browse the repository at this point in the history
  • Loading branch information
Siegrift authored Oct 24, 2023
1 parent 5a118a1 commit 0b6edd4
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 0 deletions.
16 changes: 16 additions & 0 deletions packages/api/src/handlers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,22 @@ describe(batchInsertData.name, () => {
expect(cacheModule.getCache()[storedSignedData.airnode]![storedSignedData.templateId]!).toHaveLength(1);
});

it('rejects a batch if there is a beacon with timestamp too far in the future', async () => {
const batchData = [await createSignedData({ timestamp: (Math.floor(Date.now() / 1000) + 60 * 60 * 2).toString() })];

const result = await batchInsertData(batchData);

expect(result).toStrictEqual({
body: JSON.stringify({ message: 'Request timestamp is too far in the future', extra: batchData[0] }),
headers: {
'access-control-allow-methods': '*',
'access-control-allow-origin': '*',
'content-type': 'application/json',
},
statusCode: 400,
});
});

it('inserts the batch if data is valid', async () => {
const batchData = [await createSignedData(), await createSignedData()];

Expand Down
6 changes: 6 additions & 0 deletions packages/api/src/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ export const batchInsertData = async (requestBody: unknown): Promise<ApiResponse

// Check validations that can be done without using http request, returns fail response in first error
const signedDataValidationResults = batchSignedData.map((signedData) => {
// The on-chain contract prevents time drift by making sure the timestamp is at most 1 hour in the future. System
// time drift is less common, but we mirror the contract implementation.
if (Number.parseInt(signedData.timestamp, 10) > Math.floor(Date.now() / 1000) + 60 * 60) {
return generateErrorResponse(400, 'Request timestamp is too far in the future', undefined, signedData);
}

const goRecoverSigner = goSync(() => recoverSignerAddress(signedData));
if (!goRecoverSigner.success) {
return generateErrorResponse(400, 'Unable to recover signer address', goRecoverSigner.error.message, signedData);
Expand Down

0 comments on commit 0b6edd4

Please sign in to comment.