web-dev-qa-db-ja.com

AWS QLDBでトランザクションをコミットするときにCommitDigestを取得/計算するにはどうすればよいですか?

私はQLDBでトランザクションをコミットする方法を理解しようとするドキュメントを読んでいます。そのためには、CommitDigestが必要であり、ドキュメントはそれを次のように説明しています。

トランザクションがコミットするコミットダイジェストを指定します。アクティブなトランザクションごとに、コミットダイジェストを渡す必要があります。 QLDBは​​CommitDigestを検証し、クライアントで計算されたダイジェストがQLDBで計算されたダイジェストと一致しない場合は、コミットをエラーで拒否します。

したがって、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();

CommitDigest api呼び出しでCommitTransactionをハッシュするために何が必要ですか?

9
Mike Richards

更新:Node.jsドライバーが利用可能になりました。 https://github.com/awslabs/Amazon-qldb-driver-nodejs/ をご覧ください。

執筆時点では、QLDB Node.jsドライバーはまだ開発中です。自分で作成して作成するのはかなり難しいので注意してください。つまり、CommitDigestの目的とアルゴリズムの両方を説明できます。

目的はかなり単純明快です。サーバーがクライアントから送信されたステートメントの正確なセットを処理した場合にのみトランザクションが確実にコミットされるようにします(すべて、順序どおりに、重複はありません)。 HTTPは要求/応答であるため、要求がドロップされたり、順不同で処理されたり、複製されたりする可能性があります。 QLDBドライバーはQLDBとの通信を正しく管理しますが、プロトコルにコミットダイジェストが含まれていると、実装が要求を誤って再試行してトランザクションをコミットすることができなくなります。たとえば、最初のリクエストが成功してもHTTPメッセージが再試行されるため、銀行残高を2回増やすことを検討してください。

アルゴリズムも非常に単純です。ハッシュ値にトランザクションIDがシードされ、QLDBの「ドット」演算子で更新されます。ステートメントハッシュ(PartiQL文字列のsha256)のすべての「ドット」と、すべてのバインド値の IonHash を更新します。ドット演算子は、QLDBがハッシュ値をマージする方法(これは 検証API で使用される演算子と同じです)であり、2つのハッシュの連結のハッシュとして定義され、 -endian)2つのハッシュ間のバイト単位の比較。クライアントとサーバーはこのアルゴリズムをロックステップで実行し、クライアントが渡す値がサーバーが計算した値と一致する場合にのみ、サーバーはcommitコマンドを処理します。このようにして、サーバーは、クライアントが要求したものと正確に一致しないトランザクションをコミットすることはありません。

5
Marc

コメントを追加するのに十分な評判はありませんが、このライブラリが役立つ可能性があることがわかりました: 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();
0
FroiD