10

我一直在阅读文档,试图弄清楚如何在 QLDB 中提交事务,为此,CommitDigest需要 a ,文档将其描述为:

指定要提交的事务的提交摘要。对于每个活动事务,必须传递提交摘要。如果在客户端计算的摘要与 QLDB 计算的摘要不匹配,QLDB 会验证 CommitDigest 并拒绝提交并返回错误。

所以 CommitDigest 必须被计算,但我不太确定在这个例子中它的计算需要什么:

// ** Start Session **
const startSessionResult = await qldbSession.sendCommand({
        StartSession: {
            LedgerName: ledgerName
        }
    }).promise(),
    sessionToken = startSessionResult.StartSession!.SessionToken!;

// ** Start Transaction **
const startTransactionResult = await qldbSession.sendCommand({
        StartTransaction: {},
        SessionToken: sessionToken
    }).promise(),
    transactionId = startTransactionResult.StartTransaction!.TransactionId!;

// ** Insert Document **
const executeStatementResult = await qldbSession.sendCommand({
        ExecuteStatement: {
            TransactionId: transactionId,
            Statement: `INSERT INTO sometable { 'id': 'abc123', 'userId': '123abc' }`
        },
        SessionToken: sessionToken
    }).promise(),
    documentId = getDocumentIdFromExecuteStateResult(executeStatementResult)

// ** Get Ledger Digest
const getDigestResult = await qldb.getDigest({
        Name: ledgerName
    }).promise(),
    ledgerDigest = getDigestResult.Digest;


// ** Commit Transaction **
// ** **The API call in question** **
const commitTransactionResult = await qldbSession.sendCommand({
    CommitTransaction: {
        TransactionId: transactionId,
        CommitDigest: `${commitDigest}` // <-- How to compute?
    },
    SessionToken: sessionToken
}).promise();
// *******************************


// ** End Session **
const endSession = await qldbSession.sendCommand({
    EndSession: {},
    SessionToken: sessionToken
}).promise();

CommitDigestCommitTransactionapi 调用中我需要散列什么?

4

2 回答 2

7

更新:Node.js 驱动程序现在可用。看看https://github.com/awslabs/amazon-qldb-driver-nodejs/

在撰写本文时,QLDB Node.js 驱动程序仍在开发中。如果您尝试自己创建一个,这将是相当困难的,所以我会告诫不要这样做。也就是说,我可以解释 CommitDigest 背后的目的和算法。

目的相当简单:确保仅在服务器已处理客户端发送的确切语句集(所有,按顺序,无重复)时才提交事务。HTTP 是请求-响应,因此请求可能会被丢弃、乱序处理或重复。QLDB 驱动程序正确管理与 QLDB 的通信,但是在协议中包含提交摘要使得实现不可能错误地重试请求并仍然提交事务。例如,考虑将银行余额增加两次,因为即使第一次请求成功,也会重试 HTTP 消息。

该算法也非常简单:哈希值以事务 id 为种子,然后使用 QLDB 'dot' 运算符进行更新。语句哈希(PartiQL 字符串的 sha256)以及所有绑定值的IonHash中的每个更新“点”。点运算符是 QLDB 合并哈希值的方式(这与验证 API中使用的运算符相同) 并定义为两个散列连接的散列,按两个散列之间的(有符号,小端)字节比较排序。客户端和服务器以锁步方式运行此算法,如果客户端传递的值与服务器计算的值匹配,服务器将只处理提交命令。这样,服务器将永远不会提交与客户端请求不完全一致的事务。

于 2019-09-16T21:37:03.563 回答
0

我没有足够的声誉来添加评论,但我发现这里的这个库可能会有所帮助:https ://github.com/amzn/ion-hash-js

我现在在这里:

const ionHashJS = require("ion-hash-js/dist/commonjs/es5/src/IonHash");
const ionStr =
  "INSERT INTO Vehicle { 'VIN': '12345', 'Type': 'Semi', 'Year': '2020', 'Make': 'Frank', 'Model': '313373', 'Color': 'Blue'  }";
const hashReader = ionHashJS.makeHashReader(
  ionJs.makeReader(ionStr),
  ionHashJS.cryptoIonHasherProvider("sha256")
);
hashReader.next();
hashReader.next();
const digest = hashReader.digest();
于 2019-09-23T12:43:23.447 回答