UNPKG

amazon-qldb-kvs-nodejs

Version:

A helper module, simplifying basic interactions with Amazon Quantum Ledger Database for Node.js through a simple key-value store interface.

134 lines (131 loc) 6.92 kB
"use strict"; /* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.verifyBlock = void 0; const ion_js_1 = require("ion-js"); const GetDigest_1 = require("./GetDigest"); const Logging_1 = require("./Logging"); const logger = Logging_1.log.getLogger("qldb-helper"); const Util_1 = require("./Util"); const Verifier_1 = require("./Verifier"); /** * Get the block of a ledger's journal. * @param ledgerName Name of the ledger to operate on. * @param blockAddress The location of the block to request. * @param qldbClient The QLDB control plane client to use. * @returns Promise which fulfills with a GetBlockResponse. */ function getBlock(ledgerName, blockAddress, qldbClient) { return __awaiter(this, void 0, void 0, function* () { logger.debug(`Let's get the block for block address \n${(0, Util_1.valueHolderToString)(blockAddress)} \nof the ledger ` + `named ${ledgerName}.`); const request = { Name: ledgerName, BlockAddress: blockAddress }; const result = yield qldbClient.getBlock(request); logger.debug(`Success. GetBlock: \n${(0, Util_1.blockResponseToString)(result)}.`); return result; }); } /** * Get the block of a ledger's journal. Also returns a proof of the block for verification. * @param ledgerName Name of the ledger to operate on. * @param blockAddress The location of the block to request. * @param digestTipAddress The location of the digest tip. * @param qldbClient The QLDB control plane client to use. * @returns Promise which fulfills with a GetBlockResponse. */ function getBlockWithProof(ledgerName, blockAddress, digestTipAddress, qldbClient) { return __awaiter(this, void 0, void 0, function* () { logger.debug(`Let's get the block for block address \n${(0, Util_1.valueHolderToString)(blockAddress)}, \ndigest tip address: ${(0, Util_1.valueHolderToString)(digestTipAddress)} \nof the ledger named ${ledgerName}.`); const request = { Name: ledgerName, BlockAddress: blockAddress, DigestTipAddress: digestTipAddress }; const result = yield qldbClient.getBlock(request); logger.debug(`Success. GetBlock: \n${(0, Util_1.blockResponseToString)(result)}.`); return result; }); } /** * Verify block by validating the proof returned in the getBlock response. * @param ledgerName The ledger to get the digest from. * @param blockAddress The address of the block to verify. * @param qldbClient The QLDB control plane client to use. * @returns Promise which fulfills with void. * @throws Error: When verification fails. */ function verifyBlock(ledgerName, blockAddress, qldbClient) { return __awaiter(this, void 0, void 0, function* () { logger.debug(`Let's verify blocks for ledger with name = ${ledgerName}.`); try { logger.debug("First, let's get a digest."); const digestResult = yield (0, GetDigest_1.getLedgerDigest)(ledgerName, qldbClient); const digestBytes = digestResult.Digest; const digestTipAddress = digestResult.DigestTipAddress; logger.debug(`Got a ledger digest. Digest end address = \n${(0, Util_1.valueHolderToString)(digestTipAddress)}, ` + `\ndigest = ${(0, ion_js_1.toBase64)(digestBytes)}.`); const getBlockResult = yield getBlockWithProof(ledgerName, blockAddress, digestTipAddress, qldbClient); const block = getBlockResult.Block; const blockHash = (0, Verifier_1.parseBlock)(block); const digestBase64 = (0, ion_js_1.toBase64)(digestBytes); let verified = (0, Verifier_1.verifyDocumentMetadata)(blockHash, digestBase64, getBlockResult.Proof); if (!verified) { throw new Error("Block is not verified!"); } else { logger.debug("Success! The block is verified!"); } const alteredDigest = (0, Verifier_1.flipRandomBit)(digestBytes); logger.debug(`Let's try flipping one bit in the digest and assert that the block is NOT verified. The altered digest is: ${(0, ion_js_1.toBase64)(alteredDigest)}.`); const alteredDigestBase64 = (0, ion_js_1.toBase64)(alteredDigest); verified = (0, Verifier_1.verifyDocumentMetadata)(blockHash, alteredDigestBase64, getBlockResult.Proof); if (verified) { throw new Error("Expected block to not be verified against altered digest."); } else { logger.debug("Success! As expected flipping a bit in the digest causes verification to fail."); } const alteredBlockHash = (0, Verifier_1.flipRandomBit)(blockHash); logger.debug(`Let's try flipping one bit in the block's hash and assert that the block is NOT verified. The altered block hash is: ${(0, ion_js_1.toBase64)(alteredBlockHash)}.`); verified = (0, Verifier_1.verifyDocumentMetadata)(alteredBlockHash, digestBase64, getBlockResult.Proof); if (verified) { throw new Error("Expected altered block hash to not be verified against digest."); } else { logger.debug("Success! As expected flipping a bit in the block hash causes verification to fail."); } } catch (e) { logger.debug(`Failed to verify blocks in the ledger with name = ${ledgerName}.`); throw e; } }); } exports.verifyBlock = verifyBlock;