import { createHash } from "crypto" ; import { cryptoHasherProvider , HashReader , makeHashReader } from "ion-hash-js" ; import { makeReader , makeTextWriter , Writer } from "ion-js" ; const HASH_SIZE = 32 ; internal export class QldbHash { private _qldbHash : Uint8Array ; param qldbHash throws constructor ( qldbHash ) { if ( qldbHash . length !== HASH_SIZE || qldbHash . length === 0 ) { throw new RangeError ( `Hash must be either empty or ${ HASH_SIZE } bytes long.` ) ; } this . _qldbHash = qldbHash ; } param that returns dot ( that ) { const concatenated = QldbHash . _joinHashesPairwise ( this . getQldbHash ( ) , that . getQldbHash ( ) ) ; const newHashLib = createHash ( "sha256" ) ; newHashLib . update ( concatenated ) ; const newDigest = newHashLib . digest ( ) ; return new QldbHash ( newDigest ) ; } equals ( other ) { return ( QldbHash . _hashComparator ( this . getQldbHash ( ) , other . getQldbHash ( ) ) === 0 ) ; } getHashSize ( ) { return this . _qldbHash . length ; } getQldbHash ( ) { return this . _qldbHash ; } isEmpty ( ) { return ( this . _qldbHash . length === 0 ) ; } param value returns static toQldbHash ( value ) { if ( typeof value === "string" ) { const writer = makeTextWriter ( ) ; writer . writeString ( value ) ; writer . close ( ) ; value = writer . getBytes ( ) ; } const hashReader = makeHashReader ( makeReader ( value ) , cryptoHasherProvider ( "sha256" ) ) ; hashReader . next ( ) ; hashReader . next ( ) ; const digest = hashReader . digest ( ) ; return new QldbHash ( digest ) ; } param arrays returns static _concatenate ( ... arrays ) { let totalLength = 0 ; for ( const arr of arrays ) { totalLength += arr . length ; } const result = new Uint8Array ( totalLength ) ; let offset = 0 ; for ( const arr of arrays ) { result . set ( arr , offset ) ; offset += arr . length ; } return result ; } param hash1 param hash2 returns throws static _hashComparator ( hash1 , hash2 ) { if ( hash1 . length !== HASH_SIZE || hash2 . length !== HASH_SIZE ) { throw new RangeError ( "Invalid hash." ) ; } for ( let i = hash1 . length - 1 ; i >= 0 ; i -- ) { const difference = ( hash1 [ i ] << 24 >> 24 ) - ( hash2 [ i ] << 24 >> 24 ) ; if ( difference !== 0 ) { return difference ; } } return 0 ; } param h1 param h2 returns static _joinHashesPairwise ( h1 , h2 ) { if ( h1 . length === 0 ) { return h2 ; } if ( h2 . length === 0 ) { return h1 ; } let concatenated ; if ( this . _hashComparator ( h1 , h2 ) < 0 ) { concatenated = this . _concatenate ( h1 , h2 ) ; } else { concatenated = this . _concatenate ( h2 , h1 ) ; } return concatenated ; } }