How to get/compute CommitDigest when committing a transaction in AWS QLDB using php?

422 views Asked by At

Whenever i am trying to commit the transaction. It gives an error that digest should be 32 bytes and i try to commit the binary value of digest then it gives an error that the commit digest does not match with the qldb (Ledger) Digest.

    public function insert()
{
    $client = AwsFacade::createClient('qldb-session');
    $clientA = AwsFacade::createClient('qldb');
    $result = $client->sendCommand([
        'StartSession' => [
            'LedgerName' => 'LawHq',
        ],
    ]);
    $sessiontoken = ((object)$result->get('StartSession'))->SessionToken;
    
    $result = $client->sendCommand([
        'StartTransaction' =>
        [],
        'SessionToken' => $sessiontoken
    ]);
    $transectiontoken = ((object)$result->get('StartTransaction'))->TransactionId;
    $result = $client->sendCommand([
        'ExecuteStatement' => [
            'Statement' => 'INSERT INTO Employee {`Name`:`wow`,`Designation`:`ok`, `Address`:`hmm`}',
            'TransactionId' => $transectiontoken,
        ],
        'SessionToken' => $sessiontoken
    ]);
    $result = $clientA->getDigest([
        'Name' => 'LawHq',
    ]);
    $digest = $result->get("Digest");
    $diges = base64_encode($result->get("Digest"));
    $result = $client->sendCommand([
        'CommitTransaction' => [
            'CommitDigest' => $digest,
            'TransactionId' => $transectiontoken
        ],

        'SessionToken' => $sessiontoken
    ]);
}
1

There are 1 answers

0
Ymartin On

The Digest you get via $clientA->getDigest(['Name' => 'LawHq']); is the digest of the ledger and is different than CommitDigest. You can learn more about Ledger digest here.

The mechanism works in the following way: For every transaction (which can contain multiple PartiQL statements) the client has to compute CommitDigest(using the algorithm noted below). At the same time, QLDB also computes CommitDigest using the same algorithm, on the server side. When you then decide to commit the transaction, you have to pass your CommitDigest to QLDB (via CommitTransaction API). If the CommitDigest you passed is same as the CommitDigest QLDB computed, then your transaction gets committed(assuming no other error), else QLDB will reject your transaction.

The CommitDigest computation relies on the ability to compute IonHash. Computing the IonHash is non-trivial and usually done by IonHash libraries. Unfortunately, there is no IonHash library for PHP. If you wish to implement one yourself, you can have a look at the IonHash specification https://amzn.github.io/ion-hash/docs/spec.html as a starting point to compute IonHash. Once you have a way to compute the IonHash, you can implement the algorithm to compute the CommitDigest, similar to the one done by other QLDB drivers.

Marc had outlined the motivation behind CommitDigest and the algorithm, in an answer to a similar question, when QLDB did not have a driver for Node.js: How to get/compute CommitDigest when committing a transaction in AWS QLDB?.

I encourage you to read his full answer to get more context. Quoting a relevant snippet from his answer

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.

Please note that when Marc wrote the answer, although there was no Node.js driver for QLDB, the ion-hash-js library was available, which is not the case for PHP.

Alternatively, I would highly recommend using one of the existing drivers, if possible, since it makes it easy to interact with QLDB. The drivers are available in Python, Nodejs, Java, .Net and Golang(in preview).