import Long from 'long' ; import BN from 'bn.js' ; import crypto from 'crypto' ; import { logger } from './RadixLogger' ; export function radixHash ( data , offset ? , len ? ) { if ( offset ) { data = data . slice ( offset , len ) ; } if ( ! Buffer . isBuffer ( data ) ) { data = Buffer . from ( data ) ; } const hash1 = crypto . createHash ( 'sha256' ) ; hash1 . update ( data ) ; const hash2 = crypto . createHash ( 'sha256' ) ; hash2 . update ( hash1 . digest ( ) ) ; return hash2 . digest ( ) ; } export function bigIntFromByteArray ( bytes ) { return new BN ( bytes ) . fromTwos ( bytes . length * 8 ) ; } export function byteArrayFromBigInt ( num ) { const byteLength = Math . ceil ( ( num . bitLength ( ) + 1 ) / 8 ) ; const result = num . toTwos ( 8 * byteLength ) . toArrayLike ( Buffer ) ; if ( result . length !== byteLength ) { const newResult = Buffer . alloc ( byteLength , 0 ) ; result . copy ( newResult , byteLength - result . length ) ; return newResult ; } return result ; } export function longFromBigInt ( num ) { const byteLength = Math . max ( 8 , num . byteLength ( ) ) ; const bytes = num . toTwos ( 8 * byteLength ) . toArray ( 'be' , byteLength ) ; const truncatedBytes = bytes . slice ( bytes . length - 8 , bytes . length ) ; return Long . fromBytesBE ( truncatedBytes ) ; } export function bigIntFromLong ( num ) { return new BN ( num . toBytesBE ( ) , 'be' ) . fromTwos ( 64 ) ; } export function powTargetFromAtomSize ( size ) { const target = Buffer . alloc ( 32 , 0xff ) ; const leadingBits = Math . ceil ( Math . log ( size * 8 ) ) ; const leadingBytes = Math . floor ( leadingBits / 8 ) ; const leftOverBits = leadingBits % 8 ; target . fill ( 0 , 0 , leadingBytes ) ; const middleByte = ~ ( 0xff << ( 8 - leftOverBits ) ) & 0xff ; target . writeUInt8 ( middleByte , leadingBytes ) ; return target ; } export function shuffleArray ( arr ) { return arr . map ( a => [ Math . random ( ) , a ] ) . sort ( ( a , b ) => a [ 0 ] - b [ 0 ] ) . map ( a => a [ 1 ] ) ; } export function isEmpty ( val ) { return val === undefined || val === null || val . length === 0 || ( Object . keys ( val ) . length === 0 && val . constructor === Object ) ; } export async function linearBackingOffRetry < T > ( attempt , maxNumberOfRetries , incrementOfTimeoutMS = 1000 , initialTimeoutMS = 1000 ) { let sleepAmount = initialTimeoutMS ; return new Promise ( async ( resolve , reject ) => { for ( let attemptIndex = 0 ; attemptIndex < maxNumberOfRetries ; attemptIndex ++ ) { let result ; try { result = attempt ( ) ; resolve ( result ) ; return ; } catch ( e ) { await sleep ( sleepAmount ) ; sleepAmount += incrementOfTimeoutMS ; } } reject ( new Error ( `Timedout after ${ maxNumberOfRetries } attempts` ) ) ; } ) ; } export async function sleep ( ms ) { await new Promise ( ( resolve , reject ) => { setTimeout ( ( ) => resolve ( ) , ms ) ; } ) ; }