@ -47,7 +47,6 @@ var cnUtil = function(currencyConfig) {
config . coinUnits = new JSBigInt ( 10 ) . pow ( config . coinUnitPlaces ) ;
var HASH _STATE _BYTES = 200 ;
var HASH _SIZE = 32 ;
var ADDRESS _CHECKSUM _SIZE = 4 ;
var INTEGRATED _ID _SIZE = 8 ;
@ -278,21 +277,6 @@ var cnUtil = function(currencyConfig) {
return swapEndianC ( ( padding + a . toString ( 2 ) ) . slice ( - 64 ) ) ;
}
//convert integer string to 64bit base 4 little-endian string
function d2b4 ( integer ) {
if ( typeof integer !== "string" && integer . toString ( ) . length > 15 ) {
throw "integer should be entered as a string for precision" ;
}
var padding = "" ;
for ( var i = 0 ; i < 31 ; i ++ ) {
padding += "0" ;
}
var a = new JSBigInt ( integer ) ;
if ( a . toString ( 2 ) . length > 64 ) {
throw "amount overflows uint64!" ;
}
return swapEndianC ( ( padding + a . toString ( 4 ) ) . slice ( - 32 ) ) ;
}
//end rct new functions
this . valid _hex = function ( hex ) {
@ -387,41 +371,16 @@ var cnUtil = function(currencyConfig) {
return bintohex ( output ) ;
} ;
this . cn _fast _hash = function ( input , inlen ) {
/ * i f ( i n l e n = = = u n d e f i n e d | | ! i n l e n ) {
inlen = Math . floor ( input . length / 2 ) ;
} * /
this . cn _fast _hash = function ( input ) {
if ( input . length % 2 !== 0 || ! this . valid _hex ( input ) ) {
throw "Input invalid" ;
}
//update to use new keccak impl (approx 45x faster)
//var state = this.keccak(input, inlen, HASH_STATE_BYTES);
//return state.substr(0, HASH_SIZE * 2);
const hasher = new SHA3 ( 256 ) ;
hasher . update ( hextobin ( input ) ) ;
return hasher . digest ( "hex" ) ;
} ;
//many functions below are commented out now, and duplicated with the faster nacl impl --luigi1111
// to be removed completely later
/ * t h i s . s e c _ k e y _ t o _ p u b = f u n c t i o n ( s e c ) {
var input = hextobin ( sec ) ;
if ( input . length !== 32 ) {
throw "Invalid input length" ;
}
var input _mem = CNCrypto . _malloc ( KEY _SIZE ) ;
CNCrypto . HEAPU8 . set ( input , input _mem ) ;
var ge _p3 = CNCrypto . _malloc ( STRUCT _SIZES . GE _P3 ) ;
var out _mem = CNCrypto . _malloc ( KEY _SIZE ) ;
CNCrypto . ccall ( 'ge_scalarmult_base' , 'void' , [ 'number' , 'number' ] , [ ge _p3 , input _mem ] ) ;
CNCrypto . ccall ( 'ge_p3_tobytes' , 'void' , [ 'number' , 'number' ] , [ out _mem , ge _p3 ] ) ;
var output = CNCrypto . HEAPU8 . subarray ( out _mem , out _mem + KEY _SIZE ) ;
CNCrypto . _free ( ge _p3 ) ;
CNCrypto . _free ( input _mem ) ;
CNCrypto . _free ( out _mem ) ;
return bintohex ( output ) ;
} ; * /
this . sec _key _to _pub = function ( sec ) {
if ( sec . length !== 64 ) {
throw "Invalid sec length" ;
@ -434,33 +393,6 @@ var cnUtil = function(currencyConfig) {
return this . sec _key _to _pub ( sec ) ;
} ;
//accepts arbitrary point, rather than G
/ * t h i s . g e _ s c a l a r m u l t = f u n c t i o n ( p u b , s e c ) {
if ( pub . length !== 64 || sec . length !== 64 ) {
throw "Invalid input length" ;
}
var pub _b = hextobin ( pub ) ;
var sec _b = hextobin ( sec ) ;
var pub _m = CNCrypto . _malloc ( KEY _SIZE ) ;
CNCrypto . HEAPU8 . set ( pub _b , pub _m ) ;
var sec _m = CNCrypto . _malloc ( KEY _SIZE ) ;
CNCrypto . HEAPU8 . set ( sec _b , sec _m ) ;
var ge _p3 _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _P3 ) ;
var ge _p2 _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _P2 ) ;
if ( CNCrypto . ccall ( "ge_frombytes_vartime" , "bool" , [ "number" , "number" ] , [ ge _p3 _m , pub _m ] ) !== 0 ) {
throw "ge_frombytes_vartime returned non-zero error code" ;
}
CNCrypto . ccall ( "ge_scalarmult" , "void" , [ "number" , "number" , "number" ] , [ ge _p2 _m , sec _m , ge _p3 _m ] ) ;
var derivation _m = CNCrypto . _malloc ( KEY _SIZE ) ;
CNCrypto . ccall ( "ge_tobytes" , "void" , [ "number" , "number" ] , [ derivation _m , ge _p2 _m ] ) ;
var res = CNCrypto . HEAPU8 . subarray ( derivation _m , derivation _m + KEY _SIZE ) ;
CNCrypto . _free ( pub _m ) ;
CNCrypto . _free ( sec _m ) ;
CNCrypto . _free ( ge _p3 _m ) ;
CNCrypto . _free ( ge _p2 _m ) ;
CNCrypto . _free ( derivation _m ) ;
return bintohex ( res ) ;
} ; * /
this . ge _scalarmult = function ( pub , sec ) {
if ( pub . length !== 64 || sec . length !== 64 ) {
throw "Invalid input length" ;
@ -526,24 +458,6 @@ var cnUtil = function(currencyConfig) {
// alias
this . skGen = random _scalar ;
/ * n o l o n g e r u s e d
this . keccak = function ( hex , inlen , outlen ) {
var input = hextobin ( hex ) ;
if ( input . length !== inlen ) {
throw "Invalid input length" ;
}
if ( outlen <= 0 ) {
throw "Invalid output length" ;
}
var input _mem = CNCrypto . _malloc ( inlen ) ;
CNCrypto . HEAPU8 . set ( input , input _mem ) ;
var out _mem = CNCrypto . _malloc ( outlen ) ;
CNCrypto . _keccak ( input _mem , inlen | 0 , out _mem , outlen | 0 ) ;
var output = CNCrypto . HEAPU8 . subarray ( out _mem , out _mem + outlen ) ;
CNCrypto . _free ( input _mem ) ;
CNCrypto . _free ( out _mem ) ;
return bintohex ( output ) ;
} ; * /
this . create _address = function ( seed , nettype ) {
var keys = { } ;
@ -656,37 +570,6 @@ var cnUtil = function(currencyConfig) {
return scalar ;
} ;
/ * t h i s . g e n e r a t e _ k e y _ d e r i v a t i o n = f u n c t i o n ( p u b , s e c ) {
if ( pub . length !== 64 || sec . length !== 64 ) {
throw "Invalid input length" ;
}
var pub _b = hextobin ( pub ) ;
var sec _b = hextobin ( sec ) ;
var pub _m = CNCrypto . _malloc ( KEY _SIZE ) ;
CNCrypto . HEAPU8 . set ( pub _b , pub _m ) ;
var sec _m = CNCrypto . _malloc ( KEY _SIZE ) ;
CNCrypto . HEAPU8 . set ( sec _b , sec _m ) ;
var ge _p3 _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _P3 ) ;
var ge _p2 _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _P2 ) ;
var ge _p1p1 _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _P1P1 ) ;
if ( CNCrypto . ccall ( "ge_frombytes_vartime" , "bool" , [ "number" , "number" ] , [ ge _p3 _m , pub _m ] ) !== 0 ) {
throw "ge_frombytes_vartime returned non-zero error code" ;
}
CNCrypto . ccall ( "ge_scalarmult" , "void" , [ "number" , "number" , "number" ] , [ ge _p2 _m , sec _m , ge _p3 _m ] ) ;
CNCrypto . ccall ( "ge_mul8" , "void" , [ "number" , "number" ] , [ ge _p1p1 _m , ge _p2 _m ] ) ;
CNCrypto . ccall ( "ge_p1p1_to_p2" , "void" , [ "number" , "number" ] , [ ge _p2 _m , ge _p1p1 _m ] ) ;
var derivation _m = CNCrypto . _malloc ( KEY _SIZE ) ;
CNCrypto . ccall ( "ge_tobytes" , "void" , [ "number" , "number" ] , [ derivation _m , ge _p2 _m ] ) ;
var res = CNCrypto . HEAPU8 . subarray ( derivation _m , derivation _m + KEY _SIZE ) ;
CNCrypto . _free ( pub _m ) ;
CNCrypto . _free ( sec _m ) ;
CNCrypto . _free ( ge _p3 _m ) ;
CNCrypto . _free ( ge _p2 _m ) ;
CNCrypto . _free ( ge _p1p1 _m ) ;
CNCrypto . _free ( derivation _m ) ;
return bintohex ( res ) ;
} ; * /
this . generate _key _derivation = function ( pub , sec ) {
if ( pub . length !== 64 || sec . length !== 64 ) {
throw "Invalid input length" ;
@ -737,46 +620,6 @@ var cnUtil = function(currencyConfig) {
return bintohex ( res ) ;
} ;
/ * t h i s . d e r i v e _ p u b l i c _ k e y = f u n c t i o n ( d e r i v a t i o n , o u t _ i n d e x , p u b ) {
if ( derivation . length !== 64 || pub . length !== 64 ) {
throw "Invalid input length!" ;
}
var derivation _m = CNCrypto . _malloc ( KEY _SIZE ) ;
var derivation _b = hextobin ( derivation ) ;
CNCrypto . HEAPU8 . set ( derivation _b , derivation _m ) ;
var base _m = CNCrypto . _malloc ( KEY _SIZE ) ;
var base _b = hextobin ( pub ) ;
CNCrypto . HEAPU8 . set ( base _b , base _m ) ;
var point1 _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _P3 ) ;
var point2 _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _P3 ) ;
var point3 _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _CACHED ) ;
var point4 _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _P1P1 ) ;
var point5 _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _P2 ) ;
var derived _key _m = CNCrypto . _malloc ( KEY _SIZE ) ;
if ( CNCrypto . ccall ( "ge_frombytes_vartime" , "bool" , [ "number" , "number" ] , [ point1 _m , base _m ] ) !== 0 ) {
throw "ge_frombytes_vartime returned non-zero error code" ;
}
var scalar _m = CNCrypto . _malloc ( STRUCT _SIZES . EC _SCALAR ) ;
var scalar _b = hextobin ( this . derivation _to _scalar ( bintohex ( CNCrypto . HEAPU8 . subarray ( derivation _m , derivation _m + STRUCT _SIZES . EC _POINT ) ) , out _index ) ) ;
CNCrypto . HEAPU8 . set ( scalar _b , scalar _m ) ;
CNCrypto . ccall ( "ge_scalarmult_base" , "void" , [ "number" , "number" ] , [ point2 _m , scalar _m ] ) ;
CNCrypto . ccall ( "ge_p3_to_cached" , "void" , [ "number" , "number" ] , [ point3 _m , point2 _m ] ) ;
CNCrypto . ccall ( "ge_add" , "void" , [ "number" , "number" , "number" ] , [ point4 _m , point1 _m , point3 _m ] ) ;
CNCrypto . ccall ( "ge_p1p1_to_p2" , "void" , [ "number" , "number" ] , [ point5 _m , point4 _m ] ) ;
CNCrypto . ccall ( "ge_tobytes" , "void" , [ "number" , "number" ] , [ derived _key _m , point5 _m ] ) ;
var res = CNCrypto . HEAPU8 . subarray ( derived _key _m , derived _key _m + KEY _SIZE ) ;
CNCrypto . _free ( derivation _m ) ;
CNCrypto . _free ( base _m ) ;
CNCrypto . _free ( scalar _m ) ;
CNCrypto . _free ( point1 _m ) ;
CNCrypto . _free ( point2 _m ) ;
CNCrypto . _free ( point3 _m ) ;
CNCrypto . _free ( point4 _m ) ;
CNCrypto . _free ( point5 _m ) ;
CNCrypto . _free ( derived _key _m ) ;
return bintohex ( res ) ;
} ; * /
this . derive _public _key = function ( derivation , out _index , pub ) {
if ( derivation . length !== 64 || pub . length !== 64 ) {
throw "Invalid input length!" ;
@ -1014,40 +857,6 @@ var cnUtil = function(currencyConfig) {
) ;
} ;
//adds two points together, order does not matter
/ * t h i s . g e _ a d d 2 = f u n c t i o n ( p o i n t 1 , p o i n t 2 ) {
var point1 _m = CNCrypto . _malloc ( KEY _SIZE ) ;
var point2 _m = CNCrypto . _malloc ( KEY _SIZE ) ;
var point1 _m2 = CNCrypto . _malloc ( STRUCT _SIZES . GE _P3 ) ;
var point2 _m2 = CNCrypto . _malloc ( STRUCT _SIZES . GE _P3 ) ;
CNCrypto . HEAPU8 . set ( hextobin ( point1 ) , point1 _m ) ;
CNCrypto . HEAPU8 . set ( hextobin ( point2 ) , point2 _m ) ;
if ( CNCrypto . ccall ( "ge_frombytes_vartime" , "bool" , [ "number" , "number" ] , [ point1 _m2 , point1 _m ] ) !== 0 ) {
throw "ge_frombytes_vartime returned non-zero error code" ;
}
if ( CNCrypto . ccall ( "ge_frombytes_vartime" , "bool" , [ "number" , "number" ] , [ point2 _m2 , point2 _m ] ) !== 0 ) {
throw "ge_frombytes_vartime returned non-zero error code" ;
}
var sum _m = CNCrypto . _malloc ( KEY _SIZE ) ;
var p2 _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _P2 ) ;
var p1 _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _P1P1 ) ;
var p3 _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _CACHED ) ;
CNCrypto . ccall ( "ge_p3_to_cached" , "void" , [ "number" , "number" ] , [ p3 _m , point2 _m2 ] ) ;
CNCrypto . ccall ( "ge_add" , "void" , [ "number" , "number" , "number" ] , [ p1 _m , point1 _m2 , p3 _m ] ) ;
CNCrypto . ccall ( "ge_p1p1_to_p2" , "void" , [ "number" , "number" ] , [ p2 _m , p1 _m ] ) ;
CNCrypto . ccall ( "ge_tobytes" , "void" , [ "number" , "number" ] , [ sum _m , p2 _m ] ) ;
var res = CNCrypto . HEAPU8 . subarray ( sum _m , sum _m + KEY _SIZE ) ;
CNCrypto . _free ( point1 _m ) ;
CNCrypto . _free ( point1 _m2 ) ;
CNCrypto . _free ( point2 _m ) ;
CNCrypto . _free ( point2 _m2 ) ;
CNCrypto . _free ( p2 _m ) ;
CNCrypto . _free ( p1 _m ) ;
CNCrypto . _free ( sum _m ) ;
CNCrypto . _free ( p3 _m ) ;
return bintohex ( res ) ;
} ; * /
this . ge _add = function ( p1 , p2 ) {
if ( p1 . length !== 64 || p2 . length !== 64 ) {
throw "Invalid input length!" ;
@ -1160,35 +969,6 @@ var cnUtil = function(currencyConfig) {
return bintohex ( res ) ;
} ;
//res = aB + cG; argument names copied from the signature implementation
/ * t h i s . g e _ d o u b l e _ s c a l a r m u l t _ b a s e _ v a r t i m e = f u n c t i o n ( s i g c , p u b , s i g r ) {
var pub _m = CNCrypto . _malloc ( KEY _SIZE ) ;
var pub2 _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _P3 ) ;
CNCrypto . HEAPU8 . set ( hextobin ( pub ) , pub _m ) ;
if ( CNCrypto . ccall ( "ge_frombytes_vartime" , "void" , [ "number" , "number" ] , [ pub2 _m , pub _m ] ) !== 0 ) {
throw "Failed to call ge_frombytes_vartime" ;
}
var sigc _m = CNCrypto . _malloc ( KEY _SIZE ) ;
CNCrypto . HEAPU8 . set ( hextobin ( sigc ) , sigc _m ) ;
var sigr _m = CNCrypto . _malloc ( KEY _SIZE ) ;
CNCrypto . HEAPU8 . set ( hextobin ( sigr ) , sigr _m ) ;
if ( CNCrypto . ccall ( "sc_check" , "number" , [ "number" ] , [ sigc _m ] ) !== 0 || CNCrypto . ccall ( "sc_check" , "number" , [ "number" ] , [ sigr _m ] ) !== 0 ) {
throw "bad scalar(s)" ;
}
var tmp _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _P2 ) ;
var res _m = CNCrypto . _malloc ( KEY _SIZE ) ;
CNCrypto . ccall ( "ge_double_scalarmult_base_vartime" , "void" , [ "number" , "number" , "number" , "number" ] , [ tmp _m , sigc _m , pub2 _m , sigr _m ] ) ;
CNCrypto . ccall ( "ge_tobytes" , "void" , [ "number" , "number" ] , [ res _m , tmp _m ] ) ;
var res = CNCrypto . HEAPU8 . subarray ( res _m , res _m + KEY _SIZE ) ;
CNCrypto . _free ( pub _m ) ;
CNCrypto . _free ( pub2 _m ) ;
CNCrypto . _free ( sigc _m ) ;
CNCrypto . _free ( sigr _m ) ;
CNCrypto . _free ( tmp _m ) ;
CNCrypto . _free ( res _m ) ;
return bintohex ( res ) ;
} ; * /
this . ge _double _scalarmult _base _vartime = function ( c , P , r ) {
if ( c . length !== 64 || P . length !== 64 || r . length !== 64 ) {
throw "Invalid input length!" ;
@ -1202,40 +982,6 @@ var cnUtil = function(currencyConfig) {
) ;
} ;
//res = a * Hp(B) + c*D
//res = sigr * Hp(pub) + sigc * k_image; argument names also copied from the signature implementation; note precomp AND hash_to_ec are done internally!!
/ * t h i s . g e _ d o u b l e _ s c a l a r m u l t _ p o s t c o m p _ v a r t i m e = f u n c t i o n ( s i g r , p u b , s i g c , k _ i m a g e ) {
var image _m = CNCrypto . _malloc ( STRUCT _SIZES . KEY _IMAGE ) ;
CNCrypto . HEAPU8 . set ( hextobin ( k _image ) , image _m ) ;
var image _unp _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _P3 ) ;
var image _pre _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _DSMP ) ;
var tmp3 _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _P3 ) ;
var sigr _m = CNCrypto . _malloc ( STRUCT _SIZES . EC _SCALAR ) ;
var sigc _m = CNCrypto . _malloc ( STRUCT _SIZES . EC _SCALAR ) ;
var tmp2 _m = CNCrypto . _malloc ( STRUCT _SIZES . GE _P2 ) ;
var res _m = CNCrypto . _malloc ( STRUCT _SIZES . EC _POINT ) ;
if ( CNCrypto . ccall ( "ge_frombytes_vartime" , "void" , [ "number" , "number" ] , [ image _unp _m , image _m ] ) !== 0 ) {
throw "Failed to call ge_frombytes_vartime" ;
}
CNCrypto . ccall ( "ge_dsm_precomp" , "void" , [ "number" , "number" ] , [ image _pre _m , image _unp _m ] ) ;
var ec = this . hash _to _ec ( pub ) ;
CNCrypto . HEAPU8 . set ( hextobin ( ec ) , tmp3 _m ) ;
CNCrypto . HEAPU8 . set ( hextobin ( sigc ) , sigc _m ) ;
CNCrypto . HEAPU8 . set ( hextobin ( sigr ) , sigr _m ) ;
CNCrypto . ccall ( "ge_double_scalarmult_precomp_vartime" , "void" , [ "number" , "number" , "number" , "number" , "number" ] , [ tmp2 _m , sigr _m , tmp3 _m , sigc _m , image _pre _m ] ) ;
CNCrypto . ccall ( "ge_tobytes" , "void" , [ "number" , "number" ] , [ res _m , tmp2 _m ] ) ;
var res = CNCrypto . HEAPU8 . subarray ( res _m , res _m + STRUCT _SIZES . EC _POINT ) ;
CNCrypto . _free ( image _m ) ;
CNCrypto . _free ( image _unp _m ) ;
CNCrypto . _free ( image _pre _m ) ;
CNCrypto . _free ( tmp3 _m ) ;
CNCrypto . _free ( sigr _m ) ;
CNCrypto . _free ( sigc _m ) ;
CNCrypto . _free ( tmp2 _m ) ;
CNCrypto . _free ( res _m ) ;
return bintohex ( res ) ;
} ; * /
this . ge _double _scalarmult _postcomp _vartime = function ( r , P , c , I ) {
if (
c . length !== 64 ||
@ -1376,13 +1122,7 @@ var cnUtil = function(currencyConfig) {
// thus this proves that "amount" is in [0, s^n] (we assume s to be 4) (2 for now with v2 txes)
// mask is a such that C = aG + bH, and b = amount
//commitMaskObj = {C: commit, mask: mask}
this . proveRange = function (
commitMaskObj ,
amount ,
nrings ,
enc _seed ,
exponent ,
) {
this . proveRange = function ( commitMaskObj , amount , nrings ) {
var size = 2 ;
var C = I ; //identity
var mask = Z ; //zero scalar
@ -1391,13 +1131,7 @@ var cnUtil = function(currencyConfig) {
Ci : [ ] ,
//exp: exponent //doesn't exist for now
} ;
/ * p a y l o a d s t u f f - i g n o r e f o r n o w
seeds = new Array ( 3 ) ;
for ( var i = 0 ; i < seeds . length ; i ++ ) {
seeds [ i ] = new Array ( 1 ) ;
}
genSeeds ( seeds , enc _seed ) ;
* /
var ai = [ ] ;
var PM = [ ] ;
for ( var i = 0 ; i < size ; i ++ ) {
@ -1429,13 +1163,7 @@ var cnUtil = function(currencyConfig) {
sig . Ci [ i ] = PM [ 0 ] [ i ] ;
C = ge _add ( C , PM [ 0 ] [ i ] ) ;
}
/ * e x p o n e n t s t u f f - i g n o r e f o r n o w
if ( exponent ) {
n = JSBigInt ( 10 ) ;
n = n . pow ( exponent ) . toString ( ) ;
mask = sc _mul ( mask , d2s ( n ) ) ; //new sum
}
* /
sig . bsig = this . genBorromean ( ai , PM , indices , size , nrings ) ;
commitMaskObj . C = C ;
commitMaskObj . mask = mask ;
@ -1770,7 +1498,7 @@ var cnUtil = function(currencyConfig) {
message ,
inSk ,
kimg ,
/*destinations, */ inAmounts ,
inAmounts ,
outAmounts ,
mixRing ,
amountKeys ,
@ -3059,20 +2787,9 @@ var cnUtil = function(currencyConfig) {
} ;
this . decompose _amount _into _digits = function ( amount ) {
/ * i f ( d u s t _ t h r e s h o l d = = = u n d e f i n e d ) {
dust _threshold = config . dustThreshold ;
} * /
amount = amount . toString ( ) ;
var ret = [ ] ;
while ( amount . length > 0 ) {
//split all the way down since v2 fork
/ * v a r r e m a i n i n g = n e w J S B i g I n t ( a m o u n t ) ;
if ( remaining . compare ( config . dustThreshold ) <= 0 ) {
if ( remaining . compare ( 0 ) > 0 ) {
ret . push ( remaining ) ;
}
break ;
} * /
//check so we don't create 0s
if ( amount [ 0 ] !== "0" ) {
var digit = amount [ 0 ] ;
@ -3164,12 +2881,6 @@ var cnUtil = function(currencyConfig) {
}
} ;
function assert ( stmt , val ) {
if ( ! stmt ) {
throw "assert failed" + ( val !== undefined ? ": " + val : "" ) ;
}
}
return this ;
} ;
exports . cnUtil = cnUtil ;