Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
501 views
in Technique[技术] by (71.8m points)

node.js - How to get/compute CommitDigest when committing a transaction in AWS QLDB?

I've been reading through the docs trying to figure out how to commit a transaction in QLDB, and in order to do so, a CommitDigest is required, and the docs describe it as:

Specifies the commit digest for the transaction to commit. For every active transaction, the commit digest must be passed. QLDB validates CommitDigest and rejects the commit with an error if the digest computed on the client does not match the digest computed by QLDB.

So CommitDigest must be computed, but I'm not quite sure what's required for its computation given this example:

// ** 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();

What do I need to hash for CommitDigest in the CommitTransaction api call?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Update: the Node.js driver is now available. Take a look at https://github.com/awslabs/amazon-qldb-driver-nodejs/.

At the time of writing, the QLDB Node.js driver is still in development. It is going to be fairly difficult if you try and create one yourself, so I would caution against doing so. That said, I can explain both the purpose and algorithm behind CommitDigest.

The purpose is fairly straight-forward: to ensure that transactions are only committed iff the server has processed the exact set of statements sent by the client (all, in order, no duplicates). HTTP is request-response and it is therefore possible that requests may be dropped, processed out of order or duplicated. The QLDB drivers manage the communication with QLDB correctly, but having commit digest being in the protocol makes it impossible for an implementation to incorrectly retry requests and still commit the transaction. For example, consider incrementing a bank balance twice because a HTTP message is retried even though the first request succeeded.

The algorithm is also pretty straight-forward: a hash value is seeded with the transaction id and then updated with the QLDB ‘dot’ operator. Each update ‘dots’ in the statement hash (sha256 of the PartiQL string) as well as the IonHash of all of the bind values. The dot operator is the way QLDB merges hash values (this is the same operator used in the verification APIs) and is defined as the hash of the concatenation of the two hashes, ordered by the (signed, little-endian) byte-wise comparison between the two hashes. The client and server run this algorithm in lock-step and the server will only process the commit command if the value the client passes matches what the server computed. In this way, the server will never commit a transaction that isn’t exactly what the client requested.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...