import { Blake2b , Curl } from "@iota/crypto.js" ; import { BigIntHelper } from "@iota/util.js" ; import bigInt , { BigInteger } from "big-integer" ; import { B1T6 } from "../encoding/b1t6" ; /**
 * Helper methods for POW.
 */ export class PowHelper { /**
     * LN3 Const see https://oeis.org/A002391.
     * 1.098612288668109691395245236922525704647490557822749451734694333 .
     */ public static readonly LN3 : number = 1.0986122886681098 ; param message returns public static score ( message ) { const powRelevantData = message . slice ( 0 , - 8 ) ; const powDigest = Blake2b . sum256 ( powRelevantData ) ; const nonce = BigIntHelper . read8 ( message , message . length - 8 ) ; const zeros = PowHelper . trailingZeros ( powDigest , nonce ) ; return Math . pow ( 3 , zeros ) / message . length ; } param message param targetScore returns public static calculateTargetZeros ( message , targetScore ) { return Math . ceil ( Math . log ( message . length * targetScore ) / this . LN3 ) ; } param powDigest param nonce returns public static trailingZeros ( powDigest , nonce ) { const buf = new Int8Array ( Curl . HASH_LENGTH ) ; const digestTritsLen = B1T6 . encode ( buf , 0 , powDigest ) ; const biArr = new Uint8Array ( 8 ) ; BigIntHelper . write8 ( nonce , biArr , 0 ) ; B1T6 . encode ( buf , digestTritsLen , biArr ) ; const curl = new Curl ( ) ; curl . absorb ( buf , 0 , Curl . HASH_LENGTH ) ; const hash = new Int8Array ( Curl . HASH_LENGTH ) ; curl . squeeze ( hash , 0 , Curl . HASH_LENGTH ) ; return PowHelper . trinaryTrailingZeros ( hash ) ; } param trits param endPos returns public static trinaryTrailingZeros ( trits , endPos = trits . length ) { let z = 0 ; for ( let i = endPos - 1 ; i >= 0 && trits [ i ] === 0 ; i -- ) { z ++ ; } return z ; } param powDigest param targetZeros param startIndex returns public static performPow ( powDigest , targetZeros , startIndex ) { let nonce = bigInt ( startIndex ) ; let returnNonce ; const buf = new Int8Array ( Curl . HASH_LENGTH ) ; const digestTritsLen = B1T6 . encode ( buf , 0 , powDigest ) ; const biArr = new Uint8Array ( 8 ) ; do { BigIntHelper . write8 ( nonce , biArr , 0 ) ; B1T6 . encode ( buf , digestTritsLen , biArr ) ; const curlState = new Int8Array ( Curl . STATE_LENGTH ) ; curlState . set ( buf , 0 ) ; Curl . transform ( curlState , 81 ) ; if ( PowHelper . trinaryTrailingZeros ( curlState , Curl . HASH_LENGTH ) >= targetZeros ) { returnNonce = nonce ; } else { nonce = nonce . plus ( 1 ) ; } } while ( returnNonce === undefined ) ; return returnNonce ? returnNonce . toString ( ) : "0" ; } }