2018-06-04 03:50:21 +03:00
( function ( f ) { if ( typeof exports === "object" && typeof module !== "undefined" ) { module . exports = f ( ) } else if ( typeof define === "function" && define . amd ) { define ( [ ] , f ) } else { var g ; if ( typeof window !== "undefined" ) { g = window } else if ( typeof global !== "undefined" ) { g = global } else if ( typeof self !== "undefined" ) { g = self } else { g = this } g . ethers = f ( ) } } ) ( function ( ) { var define , module , exports ; return ( function ( ) { function e ( t , n , r ) { function s ( o , u ) { if ( ! n [ o ] ) { if ( ! t [ o ] ) { var a = typeof require == "function" && require ; if ( ! u && a ) return a ( o , ! 0 ) ; if ( i ) return i ( o , ! 0 ) ; var f = new Error ( "Cannot find module '" + o + "'" ) ; throw f . code = "MODULE_NOT_FOUND" , f } var l = n [ o ] = { exports : { } } ; t [ o ] [ 0 ] . call ( l . exports , function ( e ) { var n = t [ o ] [ 1 ] [ e ] ; return s ( n ? n : e ) } , l , l . exports , e , t , n , r ) } return n [ o ] . exports } var i = typeof require == "function" && require ; for ( var o = 0 ; o < r . length ; o ++ ) s ( r [ o ] ) ; return s } return e } ) ( ) ( { 1 : [ function ( require , module , exports ) {
2017-02-27 08:09:47 +03:00
'use strict' ;
2017-04-05 01:53:59 +03:00
var Interface = require ( './interface.js' ) ;
2017-02-27 08:09:47 +03:00
var utils = ( function ( ) {
return {
2018-03-05 03:31:09 +03:00
defineProperty : require ( '../utils/properties.js' ) . defineProperty ,
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
getAddress : require ( '../utils/address.js' ) . getAddress ,
2017-04-05 01:53:59 +03:00
2018-03-05 03:31:09 +03:00
bigNumberify : require ( '../utils/bignumber.js' ) . bigNumberify ,
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
hexlify : require ( '../utils/convert.js' ) . hexlify ,
2017-02-27 08:09:47 +03:00
} ;
} ) ( ) ;
2018-04-17 04:42:17 +03:00
var errors = require ( '../utils/errors' ) ;
2017-02-27 08:09:47 +03:00
var allowedTransactionKeys = {
2017-12-02 10:52:36 +03:00
data : true , from : true , gasLimit : true , gasPrice : true , nonce : true , to : true , value : true
2017-02-27 08:09:47 +03:00
}
2017-11-22 05:28:58 +03:00
function copyObject ( object ) {
var result = { } ;
for ( var key in object ) {
result [ key ] = object [ key ] ;
}
return result ;
}
2017-05-22 03:38:41 +03:00
function Contract ( addressOrName , contractInterface , signerOrProvider ) {
2017-04-05 01:53:59 +03:00
if ( ! ( this instanceof Contract ) ) { throw new Error ( 'missing new' ) ; }
2017-02-27 08:09:47 +03:00
2017-05-22 03:38:41 +03:00
// @TODO: Maybe still check the addressOrName looks like a valid address or name?
//address = utils.getAddress(address);
2017-02-27 08:09:47 +03:00
2017-04-05 01:53:59 +03:00
if ( ! ( contractInterface instanceof Interface ) ) {
contractInterface = new Interface ( contractInterface ) ;
}
2017-02-27 08:09:47 +03:00
2017-11-10 03:54:28 +03:00
if ( ! signerOrProvider ) { throw new Error ( 'missing signer or provider' ) ; }
2017-04-05 01:53:59 +03:00
var signer = signerOrProvider ;
var provider = null ;
2017-11-10 03:54:28 +03:00
2017-04-05 01:53:59 +03:00
if ( signerOrProvider . provider ) {
provider = signerOrProvider . provider ;
2017-11-10 03:54:28 +03:00
} else {
2017-04-05 01:53:59 +03:00
provider = signerOrProvider ;
signer = null ;
}
2017-02-27 08:09:47 +03:00
2017-05-22 03:38:41 +03:00
utils . defineProperty ( this , 'address' , addressOrName ) ;
2017-04-05 01:53:59 +03:00
utils . defineProperty ( this , 'interface' , contractInterface ) ;
utils . defineProperty ( this , 'signer' , signer ) ;
utils . defineProperty ( this , 'provider' , provider ) ;
2017-02-27 08:09:47 +03:00
2017-12-05 11:25:08 +03:00
var addressPromise = provider . resolveName ( addressOrName ) ;
2017-02-27 08:09:47 +03:00
function runMethod ( method , estimateOnly ) {
return function ( ) {
var transaction = { }
var params = Array . prototype . slice . call ( arguments ) ;
2017-04-05 01:53:59 +03:00
// If 1 extra parameter was passed in, it contains overrides
2018-04-17 04:42:17 +03:00
if ( params . length === method . inputs . types . length + 1 && typeof ( params [ params . length - 1 ] ) === 'object' ) {
transaction = copyObject ( params . pop ( ) ) ;
2017-04-05 01:53:59 +03:00
// Check for unexpected keys (e.g. using "gas" instead of "gasLimit")
2017-02-27 08:09:47 +03:00
for ( var key in transaction ) {
if ( ! allowedTransactionKeys [ key ] ) {
throw new Error ( 'unknown transaction override ' + key ) ;
}
}
}
2017-04-05 01:53:59 +03:00
// Check overrides make sense
[ 'data' , 'to' ] . forEach ( function ( key ) {
if ( transaction [ key ] != null ) {
throw new Error ( 'cannot override ' + key ) ;
}
} ) ;
var call = method . apply ( contractInterface , params ) ;
// Send to the contract address
2017-05-22 03:38:41 +03:00
transaction . to = addressOrName ;
2017-04-05 01:53:59 +03:00
// Set the transaction data
transaction . data = call . data ;
2017-02-27 08:09:47 +03:00
switch ( call . type ) {
case 'call' :
2017-04-05 01:53:59 +03:00
// Call (constant functions) always cost 0 ether
if ( estimateOnly ) {
return Promise . resolve ( new utils . bigNumberify ( 0 ) ) ;
}
// Check overrides make sense
[ 'gasLimit' , 'gasPrice' , 'value' ] . forEach ( function ( key ) {
2017-02-27 08:09:47 +03:00
if ( transaction [ key ] != null ) {
throw new Error ( 'call cannot override ' + key ) ;
}
} ) ;
2017-04-05 01:53:59 +03:00
var fromPromise = null ;
if ( transaction . from == null && signer && signer . getAddress ) {
fromPromise = signer . getAddress ( ) ;
2017-05-22 03:38:41 +03:00
if ( ! ( fromPromise instanceof Promise ) ) {
2017-04-05 01:53:59 +03:00
fromPromise = Promise . resolve ( fromPromise ) ;
}
} else {
fromPromise = Promise . resolve ( null ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 01:53:59 +03:00
return fromPromise . then ( function ( address ) {
if ( address ) {
transaction . from = utils . getAddress ( address ) ;
}
return provider . call ( transaction ) ;
} ) . then ( function ( value ) {
2018-04-17 04:42:17 +03:00
try {
var result = call . parse ( value ) ;
} catch ( error ) {
2018-06-06 02:40:28 +03:00
if ( value === '0x' && method . outputs . types . length > 0 ) {
2018-04-17 04:42:17 +03:00
errors . throwError ( 'call exception' , errors . CALL _EXCEPTION , {
address : addressOrName ,
method : call . signature ,
value : params
} ) ;
}
throw error ;
}
2018-03-05 05:17:16 +03:00
if ( method . outputs . types . length === 1 ) {
result = result [ 0 ] ;
}
return result ;
2017-02-27 08:09:47 +03:00
} ) ;
case 'transaction' :
2017-04-05 01:53:59 +03:00
if ( ! signer ) { return Promise . reject ( new Error ( 'missing signer' ) ) ; }
// Make sure they aren't overriding something they shouldn't
if ( transaction . from != null ) {
throw new Error ( 'transaction cannot override from' ) ;
}
// Only computing the transaction estimate
if ( estimateOnly ) {
if ( signer && signer . estimateGas ) {
return signer . estimateGas ( transaction ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 01:53:59 +03:00
return provider . estimateGas ( transaction )
}
// If the signer supports sendTrasaction, use it
if ( signer . sendTransaction ) {
return signer . sendTransaction ( transaction ) ;
}
if ( ! signer . sign ) {
return Promise . reject ( new Error ( 'custom signer does not support signing' ) ) ;
}
2017-02-27 08:09:47 +03:00
if ( transaction . gasLimit == null ) {
2017-04-05 01:53:59 +03:00
transaction . gasLimit = signer . defaultGasLimit || 2000000 ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 01:53:59 +03:00
var noncePromise = null ;
if ( transaction . nonce ) {
noncePromise = Promise . resolve ( transaction . nonce )
2017-05-11 02:09:58 +03:00
} else if ( signer . getTransactionCount ) {
2017-11-22 05:28:58 +03:00
noncePromise = signer . getTransactionCount ( ) ;
2017-05-11 02:09:58 +03:00
if ( ! ( noncePromise instanceof Promise ) ) {
noncePromise = Promise . resolve ( noncePromise ) ;
}
2017-04-05 01:53:59 +03:00
} else {
2017-05-11 02:09:58 +03:00
var addressPromise = signer . getAddress ( ) ;
if ( ! ( addressPromise instanceof Promise ) ) {
addressPromise = Promise . resolve ( addressPromise ) ;
}
noncePromise = addressPromise . then ( function ( address ) {
return provider . getTransactionCount ( address , 'pending' ) ;
} ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 01:53:59 +03:00
var gasPricePromise = null ;
if ( transaction . gasPrice ) {
gasPricePromise = Promise . resolve ( transaction . gasPrice ) ;
} else {
gasPricePromise = provider . getGasPrice ( ) ;
}
return Promise . all ( [
noncePromise ,
gasPricePromise
] ) . then ( function ( results ) {
transaction . nonce = results [ 0 ] ;
transaction . gasPrice = results [ 1 ] ;
return signer . sign ( transaction ) ;
} ) . then ( function ( signedTransaction ) {
return provider . sendTransaction ( signedTransaction ) ;
2017-02-27 08:09:47 +03:00
} ) ;
}
} ;
}
var estimate = { } ;
utils . defineProperty ( this , 'estimate' , estimate ) ;
2017-04-05 01:53:59 +03:00
var functions = { } ;
utils . defineProperty ( this , 'functions' , functions ) ;
var events = { } ;
utils . defineProperty ( this , 'events' , events ) ;
Object . keys ( contractInterface . functions ) . forEach ( function ( methodName ) {
var method = contractInterface . functions [ methodName ] ;
var run = runMethod ( method , false ) ;
if ( this [ methodName ] == null ) {
utils . defineProperty ( this , methodName , run ) ;
} else {
console . log ( 'WARNING: Multiple definitions for ' + method ) ;
}
if ( functions [ method ] == null ) {
utils . defineProperty ( functions , methodName , run ) ;
utils . defineProperty ( estimate , methodName , runMethod ( method , true ) ) ;
}
2017-02-27 08:09:47 +03:00
} , this ) ;
2017-04-05 01:53:59 +03:00
Object . keys ( contractInterface . events ) . forEach ( function ( eventName ) {
2018-03-05 03:31:09 +03:00
var eventInfo = contractInterface . events [ eventName ] ;
2017-04-05 01:53:59 +03:00
var eventCallback = null ;
function handleEvent ( log ) {
2017-12-05 11:25:08 +03:00
addressPromise . then ( function ( address ) {
// Not meant for us (the topics just has the same name)
if ( address != log . address ) { return ; }
try {
var result = eventInfo . parse ( log . topics , log . data ) ;
// Some useful things to have with the log
log . args = result ;
log . event = eventName ;
log . parse = eventInfo . parse ;
log . removeListener = function ( ) {
provider . removeListener ( eventInfo . topics , handleEvent ) ;
}
2017-12-30 22:05:40 +03:00
2018-03-07 02:40:11 +03:00
log . getBlock = function ( ) { return provider . getBlock ( log . blockHash ) ; ; }
log . getTransaction = function ( ) { return provider . getTransaction ( log . transactionHash ) ; }
log . getTransactionReceipt = function ( ) { return provider . getTransactionReceipt ( log . transactionHash ) ; }
2017-12-05 11:25:08 +03:00
log . eventSignature = eventInfo . signature ;
eventCallback . apply ( log , Array . prototype . slice . call ( result ) ) ;
} catch ( error ) {
console . log ( error ) ;
}
} ) ;
2017-04-05 01:53:59 +03:00
}
var property = {
2017-02-27 08:09:47 +03:00
enumerable : true ,
get : function ( ) {
2017-04-05 01:53:59 +03:00
return eventCallback ;
2017-02-27 08:09:47 +03:00
} ,
set : function ( value ) {
2017-04-05 01:53:59 +03:00
if ( ! value ) { value = null ; }
if ( ! value && eventCallback ) {
provider . removeListener ( eventInfo . topics , handleEvent ) ;
} else if ( value && ! eventCallback ) {
provider . on ( eventInfo . topics , handleEvent ) ;
}
eventCallback = value ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 01:53:59 +03:00
} ;
var propertyName = 'on' + eventName . toLowerCase ( ) ;
if ( this [ propertyName ] == null ) {
Object . defineProperty ( this , propertyName , property ) ;
}
Object . defineProperty ( events , eventName , property ) ;
2017-02-27 08:09:47 +03:00
} , this ) ;
}
2017-11-10 03:54:28 +03:00
utils . defineProperty ( Contract . prototype , 'connect' , function ( signerOrProvider ) {
return new Contract ( this . address , this . interface , signerOrProvider ) ;
} ) ;
2017-04-05 01:53:59 +03:00
utils . defineProperty ( Contract , 'getDeployTransaction' , function ( bytecode , contractInterface ) {
2017-05-11 02:09:58 +03:00
if ( ! ( contractInterface instanceof Interface ) ) {
2017-04-05 01:53:59 +03:00
contractInterface = new Interface ( contractInterface ) ;
}
var args = Array . prototype . slice . call ( arguments ) ;
args . splice ( 1 , 1 ) ;
return {
data : contractInterface . deployFunction . apply ( contractInterface , args ) . bytecode
}
} ) ;
2017-02-27 08:09:47 +03:00
module . exports = Contract ;
2018-04-17 04:42:17 +03:00
} , { "../utils/address.js" : 9 , "../utils/bignumber.js" : 10 , "../utils/convert.js" : 11 , "../utils/errors" : 12 , "../utils/properties.js" : 14 , "./interface.js" : 3 } ] , 2 : [ function ( require , module , exports ) {
2017-04-05 01:53:59 +03:00
'use strict' ;
2017-02-27 08:09:47 +03:00
var Contract = require ( './contract.js' ) ;
var Interface = require ( './interface.js' ) ;
module . exports = {
2017-04-05 01:53:59 +03:00
Contract : Contract ,
2017-02-27 08:09:47 +03:00
Interface : Interface ,
}
2017-04-05 01:53:59 +03:00
2018-03-05 03:31:09 +03:00
} , { "./contract.js" : 1 , "./interface.js" : 3 } ] , 3 : [ function ( require , module , exports ) {
2017-02-27 08:09:47 +03:00
'use strict' ;
2017-04-05 01:53:59 +03:00
// See: https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI
2017-02-27 08:09:47 +03:00
var utils = ( function ( ) {
2018-06-04 03:50:21 +03:00
var AbiCoder = require ( '../utils/abi-coder' ) ;
2018-03-05 03:31:09 +03:00
var convert = require ( '../utils/convert' ) ;
var properties = require ( '../utils/properties' ) ;
var utf8 = require ( '../utils/utf8' ) ;
2017-02-27 08:09:47 +03:00
return {
2018-03-05 03:31:09 +03:00
defineFrozen : properties . defineFrozen ,
defineProperty : properties . defineProperty ,
2017-02-27 08:09:47 +03:00
2018-06-04 03:50:21 +03:00
coder : AbiCoder . defaultCoder ,
parseSignature : AbiCoder . parseSignature ,
2017-04-05 01:53:59 +03:00
2018-03-05 03:31:09 +03:00
arrayify : convert . arrayify ,
2017-02-27 08:09:47 +03:00
concat : convert . concat ,
2018-03-05 03:31:09 +03:00
isHexString : convert . isHexString ,
2017-02-27 08:09:47 +03:00
toUtf8Bytes : utf8 . toUtf8Bytes ,
2018-03-05 03:31:09 +03:00
keccak256 : require ( '../utils/keccak256' ) ,
2017-02-27 08:09:47 +03:00
} ;
} ) ( ) ;
2018-04-17 04:42:17 +03:00
var errors = require ( '../utils/errors' ) ;
2017-11-22 05:28:58 +03:00
function parseParams ( params ) {
var names = [ ] ;
var types = [ ] ;
2018-03-05 03:31:09 +03:00
2017-11-22 05:28:58 +03:00
params . forEach ( function ( param ) {
if ( param . components != null ) {
if ( param . type . substring ( 0 , 5 ) !== 'tuple' ) {
throw new Error ( 'internal error; report on GitHub' ) ;
}
var suffix = '' ;
var arrayBracket = param . type . indexOf ( '[' ) ;
if ( arrayBracket >= 0 ) { suffix = param . type . substring ( arrayBracket ) ; }
var result = parseParams ( param . components ) ;
names . push ( { name : ( param . name || null ) , names : result . names } ) ;
types . push ( 'tuple(' + result . types . join ( ',' ) + ')' + suffix )
} else {
names . push ( param . name || null ) ;
types . push ( param . type ) ;
}
} ) ;
2018-03-05 03:31:09 +03:00
2017-11-22 05:28:58 +03:00
return {
names : names ,
types : types
}
}
2018-03-05 03:31:09 +03:00
function populateDescription ( object , items ) {
for ( var key in items ) {
utils . defineProperty ( object , key , items [ key ] ) ;
}
return object ;
}
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
/ * *
* - bytecode ( optional ; only for deploy )
* - type ( "deploy" )
* /
function DeployDescription ( ) { }
2017-04-05 01:53:59 +03:00
2018-03-05 03:31:09 +03:00
/ * *
* - name
* - signature
* - sighash
* -
* -
* -
* -
* - type : ( "call" | "transaction" )
* /
function FunctionDescription ( ) { }
2017-04-05 01:53:59 +03:00
2018-03-05 03:31:09 +03:00
/ * *
* - anonymous
* - name
* - signature
* - parse
* - topics
* - inputs
* - type ( "event" )
* /
function EventDescription ( ) { }
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
function Indexed ( value ) {
utils . defineProperty ( this , 'indexed' , true ) ;
utils . defineProperty ( this , 'hash' , value ) ;
2017-02-27 08:09:47 +03:00
}
2018-03-05 03:31:09 +03:00
function Result ( ) { }
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
function Interface ( abi ) {
if ( ! ( this instanceof Interface ) ) { throw new Error ( 'missing new' ) ; }
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
if ( typeof ( abi ) === 'string' ) {
try {
abi = JSON . parse ( abi ) ;
} catch ( error ) {
2018-04-17 04:42:17 +03:00
errors . throwError ( 'could not parse ABI JSON' , errors . INVALID _ARGUMENT , {
arg : 'abi' ,
errorMessage : error . message ,
value : abi
} ) ;
2017-02-27 08:09:47 +03:00
}
}
2018-06-04 03:50:21 +03:00
var _abi = [ ] ;
abi . forEach ( function ( fragment ) {
if ( typeof ( fragment ) === 'string' ) {
fragment = utils . parseSignature ( fragment ) ;
}
_abi . push ( fragment ) ;
} ) ;
utils . defineFrozen ( this , 'abi' , _abi ) ;
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
var methods = { } , events = { } , deploy = null ;
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
utils . defineProperty ( this , 'functions' , methods ) ;
utils . defineProperty ( this , 'events' , events ) ;
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
function addMethod ( method ) {
switch ( method . type ) {
case 'constructor' :
var func = ( function ( ) {
var inputParams = parseParams ( method . inputs ) ;
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
var func = function ( bytecode ) {
if ( ! utils . isHexString ( bytecode ) ) {
2018-04-17 04:42:17 +03:00
errors . throwError ( 'invalid contract bytecode' , errors . INVALID _ARGUMENT , {
arg : 'bytecode' ,
type : typeof ( bytecode ) ,
value : bytecode
} ) ;
2018-03-05 03:31:09 +03:00
}
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
var params = Array . prototype . slice . call ( arguments , 1 ) ;
if ( params . length < inputParams . types . length ) {
2018-04-17 04:42:17 +03:00
errors . throwError ( 'missing constructor argument' , errors . MISSING _ARGUMENT , {
arg : ( inputParams . names [ params . length ] || 'unknown' ) ,
count : params . length ,
expectedCount : inputParams . types . length
} ) ;
2018-03-05 03:31:09 +03:00
} else if ( params . length > inputParams . types . length ) {
2018-04-17 04:42:17 +03:00
errors . throwError ( 'too many constructor arguments' , errors . UNEXPECTED _ARGUMENT , {
count : params . length ,
expectedCount : inputParams . types . length
} ) ;
}
try {
2018-06-06 02:40:28 +03:00
var encodedParams = utils . coder . encode ( method . inputs , params )
2018-04-17 04:42:17 +03:00
} catch ( error ) {
errors . throwError ( 'invalid constructor argument' , errors . INVALID _ARGUMENT , {
arg : error . arg ,
reason : error . reason ,
value : error . value
} ) ;
2018-03-05 03:31:09 +03:00
}
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
var result = {
2018-04-17 04:42:17 +03:00
bytecode : bytecode + encodedParams . substring ( 2 ) ,
2018-03-05 03:31:09 +03:00
type : 'deploy'
}
2018-01-11 04:29:50 +03:00
2018-03-05 03:31:09 +03:00
return populateDescription ( new DeployDescription ( ) , result ) ;
}
2018-01-11 04:29:50 +03:00
2018-03-05 03:31:09 +03:00
utils . defineFrozen ( func , 'inputs' , inputParams ) ;
utils . defineProperty ( func , 'payable' , ( method . payable == null || ! ! method . payable ) )
2018-01-11 04:29:50 +03:00
2018-03-05 03:31:09 +03:00
return func ;
} ) ( ) ;
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
if ( ! deploy ) { deploy = func ; }
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
break ;
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
case 'function' :
var func = ( function ( ) {
var inputParams = parseParams ( method . inputs ) ;
var outputParams = parseParams ( method . outputs ) ;
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
var signature = '(' + inputParams . types . join ( ',' ) + ')' ;
signature = signature . replace ( /tuple/g , '' ) ;
signature = method . name + signature ;
2017-11-10 03:54:28 +03:00
2018-04-05 22:48:46 +03:00
var parse = function ( data ) {
2018-04-17 04:42:17 +03:00
try {
2018-06-06 02:40:28 +03:00
return utils . coder . decode ( method . outputs , utils . arrayify ( data ) ) ;
2018-04-17 04:42:17 +03:00
} catch ( error ) {
errors . throwError ( 'invalid data for function output' , errors . INVALID _ARGUMENT , {
arg : 'data' ,
errorArg : error . arg ,
errorValue : error . value ,
value : data ,
reason : error . reason
} ) ;
}
2018-04-05 22:48:46 +03:00
} ;
2018-03-05 03:31:09 +03:00
var sighash = utils . keccak256 ( utils . toUtf8Bytes ( signature ) ) . substring ( 0 , 10 ) ;
var func = function ( ) {
var result = {
name : method . name ,
signature : signature ,
sighash : sighash ,
type : ( ( method . constant ) ? 'call' : 'transaction' )
} ;
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
var params = Array . prototype . slice . call ( arguments , 0 ) ;
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
if ( params . length < inputParams . types . length ) {
2018-04-17 04:42:17 +03:00
errors . throwError ( 'missing input argument' , errors . MISSING _ARGUMENT , {
arg : ( inputParams . names [ params . length ] || 'unknown' ) ,
count : params . length ,
expectedCount : inputParams . types . length ,
name : method . name
} ) ;
2018-03-05 03:31:09 +03:00
} else if ( params . length > inputParams . types . length ) {
2018-04-17 04:42:17 +03:00
errors . throwError ( 'too many input arguments' , errors . UNEXPECTED _ARGUMENT , {
count : params . length ,
expectedCount : inputParams . types . length
} ) ;
2018-03-05 03:31:09 +03:00
}
2017-11-10 03:54:28 +03:00
2018-04-17 04:42:17 +03:00
try {
2018-06-06 02:40:28 +03:00
var encodedParams = utils . coder . encode ( method . inputs , params ) ;
2018-04-17 04:42:17 +03:00
} catch ( error ) {
errors . throwError ( 'invalid input argument' , errors . INVALID _ARGUMENT , {
arg : error . arg ,
reason : error . reason ,
value : error . value
} ) ;
}
result . data = sighash + encodedParams . substring ( 2 ) ;
2018-04-05 22:48:46 +03:00
result . parse = parse ;
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
return populateDescription ( new FunctionDescription ( ) , result ) ;
}
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
utils . defineFrozen ( func , 'inputs' , inputParams ) ;
utils . defineFrozen ( func , 'outputs' , outputParams ) ;
2017-11-22 05:28:58 +03:00
2018-03-05 03:31:09 +03:00
utils . defineProperty ( func , 'payable' , ( method . payable == null || ! ! method . payable ) )
2017-11-22 05:28:58 +03:00
2018-04-05 22:48:46 +03:00
utils . defineProperty ( func , 'parseResult' , parse ) ;
2018-03-05 03:31:09 +03:00
utils . defineProperty ( func , 'signature' , signature ) ;
utils . defineProperty ( func , 'sighash' , sighash ) ;
2017-11-22 05:28:58 +03:00
2018-03-05 03:31:09 +03:00
return func ;
} ) ( ) ;
2017-11-22 05:28:58 +03:00
2018-03-05 03:31:09 +03:00
// Expose the first (and hopefully unique named function
if ( method . name && methods [ method . name ] == null ) {
utils . defineProperty ( methods , method . name , func ) ;
}
2017-11-22 05:28:58 +03:00
2018-03-05 03:31:09 +03:00
// Expose all methods by their signature, for overloaded functions
if ( methods [ func . signature ] == null ) {
utils . defineProperty ( methods , func . signature , func ) ;
}
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
break ;
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
case 'event' :
var func = ( function ( ) {
var inputParams = parseParams ( method . inputs ) ;
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
var signature = '(' + inputParams . types . join ( ',' ) + ')' ;
signature = signature . replace ( /tuple/g , '' ) ;
signature = method . name + signature ;
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
var result = {
anonymous : ( ! ! method . anonymous ) ,
name : method . name ,
signature : signature ,
type : 'event'
} ;
result . parse = function ( topics , data ) {
if ( data == null ) {
data = topics ;
topics = null ;
}
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
// Strip the signature off of non-anonymous topics
if ( topics != null && ! method . anonymous ) { topics = topics . slice ( 1 ) ; }
2017-02-27 08:09:47 +03:00
2018-06-06 02:40:28 +03:00
var inputIndexed = [ ] , inputNonIndexed = [ ] ;
2018-03-05 03:31:09 +03:00
var inputDynamic = [ ] ;
2018-06-06 02:40:28 +03:00
method . inputs . forEach ( function ( param , index ) {
2017-02-27 08:09:47 +03:00
2018-06-06 02:40:28 +03:00
if ( param . indexed ) {
if ( param . type === 'string' || param . type === 'bytes' || param . type . indexOf ( '[' ) >= 0 || param . type . substring ( 0 , 5 ) === 'tuple' ) {
inputIndexed . push ( { type : 'bytes32' , name : ( param . name || '' ) } ) ;
2018-03-05 03:31:09 +03:00
inputDynamic . push ( true ) ;
} else {
2018-06-06 02:40:28 +03:00
inputIndexed . push ( param ) ;
2018-03-05 03:31:09 +03:00
inputDynamic . push ( false ) ;
}
} else {
2018-06-06 02:40:28 +03:00
inputNonIndexed . push ( param ) ;
2018-03-05 03:31:09 +03:00
inputDynamic . push ( false ) ;
}
} ) ;
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
if ( topics != null ) {
var resultIndexed = utils . coder . decode (
2018-06-06 02:40:28 +03:00
inputIndexed ,
2018-03-05 03:31:09 +03:00
utils . concat ( topics )
) ;
}
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
var resultNonIndexed = utils . coder . decode (
2018-06-06 02:40:28 +03:00
inputNonIndexed ,
2018-03-05 03:31:09 +03:00
utils . arrayify ( data )
) ;
var result = new Result ( ) ;
var nonIndexedIndex = 0 , indexedIndex = 0 ;
method . inputs . forEach ( function ( input , index ) {
if ( input . indexed ) {
if ( topics == null ) {
result [ index ] = new Indexed ( null ) ;
} else if ( inputDynamic [ index ] ) {
result [ index ] = new Indexed ( resultIndexed [ indexedIndex ++ ] ) ;
} else {
result [ index ] = resultIndexed [ indexedIndex ++ ] ;
}
} else {
result [ index ] = resultNonIndexed [ nonIndexedIndex ++ ] ;
}
if ( input . name ) { result [ input . name ] = result [ index ] ; }
} ) ;
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
result . length = method . inputs . length ;
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
return result ;
} ;
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
var func = populateDescription ( new EventDescription ( ) , result )
utils . defineFrozen ( func , 'topics' , [ utils . keccak256 ( utils . toUtf8Bytes ( signature ) ) ] ) ;
utils . defineFrozen ( func , 'inputs' , inputParams ) ;
return func ;
} ) ( ) ;
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
// Expose the first (and hopefully unique) event name
if ( method . name && events [ method . name ] == null ) {
utils . defineProperty ( events , method . name , func ) ;
}
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
// Expose all events by their signature, for overloaded functions
if ( methods [ func . signature ] == null ) {
utils . defineProperty ( methods , func . signature , func ) ;
}
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
break ;
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
case 'fallback' :
// Nothing to do for fallback
break ;
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
default :
console . log ( 'WARNING: unsupported ABI type - ' + method . type ) ;
break ;
}
2017-11-10 03:54:28 +03:00
} ;
2017-02-27 08:09:47 +03:00
2018-06-04 03:50:21 +03:00
_abi . forEach ( addMethod , this ) ;
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
// If there wasn't a constructor, create the default constructor
if ( ! deploy ) {
addMethod ( { type : 'constructor' , inputs : [ ] } ) ;
2017-11-10 03:54:28 +03:00
}
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
utils . defineProperty ( this , 'deployFunction' , deploy ) ;
2017-11-10 03:54:28 +03:00
}
2017-02-27 08:09:47 +03:00
2018-06-04 03:50:21 +03:00
utils . defineProperty ( Interface . prototype , 'parseTransaction' , function ( tx ) {
var sighash = tx . data . substring ( 0 , 10 ) . toLowerCase ( ) ;
for ( var name in this . functions ) {
if ( name . indexOf ( '(' ) === - 1 ) { continue ; }
var func = this . functions [ name ] ;
if ( func . sighash === sighash ) {
var result = utils . coder . decode ( func . inputs . types , '0x' + tx . data . substring ( 10 ) ) ;
return {
args : result ,
signature : func . signature ,
sighash : func . sighash ,
parse : func . parseResult ,
value : tx . value ,
} ;
}
}
return null ;
} ) ;
2018-03-05 03:31:09 +03:00
module . exports = Interface ;
2017-02-27 08:09:47 +03:00
2018-04-17 04:42:17 +03:00
} , { "../utils/abi-coder" : 8 , "../utils/convert" : 11 , "../utils/errors" : 12 , "../utils/keccak256" : 13 , "../utils/properties" : 14 , "../utils/utf8" : 16 } ] , 4 : [ function ( require , module , exports ) {
2018-03-05 03:31:09 +03:00
( function ( module , exports ) {
'use strict' ;
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
// Utils
function assert ( val , msg ) {
if ( ! val ) throw new Error ( msg || 'Assertion failed' ) ;
}
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
// Could use `inherits` module, but don't want to move from single file
// architecture yet.
function inherits ( ctor , superCtor ) {
ctor . super _ = superCtor ;
var TempCtor = function ( ) { } ;
TempCtor . prototype = superCtor . prototype ;
ctor . prototype = new TempCtor ( ) ;
ctor . prototype . constructor = ctor ;
}
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
// BN
2017-11-10 03:54:28 +03:00
2018-03-05 03:31:09 +03:00
function BN ( number , base , endian ) {
if ( BN . isBN ( number ) ) {
return number ;
2017-11-10 03:54:28 +03:00
}
2018-03-05 03:31:09 +03:00
this . negative = 0 ;
this . words = null ;
this . length = 0 ;
2017-02-27 08:09:47 +03:00
2018-03-05 03:31:09 +03:00
// Reduction context
this . red = null ;
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
if ( number !== null ) {
if ( base === 'le' || base === 'be' ) {
endian = base ;
base = 10 ;
}
this . _init ( number || 0 , base || 10 , endian || 'be' ) ;
2017-04-05 01:53:59 +03:00
}
2017-04-05 23:53:29 +03:00
}
if ( typeof module === 'object' ) {
module . exports = BN ;
} else {
exports . BN = BN ;
}
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
BN . BN = BN ;
BN . wordSize = 26 ;
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
var Buffer ;
try {
2017-11-10 03:54:28 +03:00
Buffer = require ( 'buffer' ) . Buffer ;
2017-04-05 23:53:29 +03:00
} catch ( e ) {
}
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
BN . isBN = function isBN ( num ) {
if ( num instanceof BN ) {
return true ;
}
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
return num !== null && typeof num === 'object' &&
num . constructor . wordSize === BN . wordSize && Array . isArray ( num . words ) ;
} ;
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
BN . max = function max ( left , right ) {
if ( left . cmp ( right ) > 0 ) return left ;
return right ;
} ;
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
BN . min = function min ( left , right ) {
if ( left . cmp ( right ) < 0 ) return left ;
return right ;
} ;
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . _init = function init ( number , base , endian ) {
if ( typeof number === 'number' ) {
return this . _initNumber ( number , base , endian ) ;
}
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
if ( typeof number === 'object' ) {
return this . _initArray ( number , base , endian ) ;
}
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
if ( base === 'hex' ) {
base = 16 ;
}
assert ( base === ( base | 0 ) && base >= 2 && base <= 36 ) ;
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
number = number . toString ( ) . replace ( /\s+/g , '' ) ;
var start = 0 ;
if ( number [ 0 ] === '-' ) {
start ++ ;
}
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
if ( base === 16 ) {
this . _parseHex ( number , start ) ;
} else {
this . _parseBase ( number , base , start ) ;
2017-04-05 01:53:59 +03:00
}
2017-04-05 23:53:29 +03:00
if ( number [ 0 ] === '-' ) {
this . negative = 1 ;
}
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
this . strip ( ) ;
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
if ( endian !== 'le' ) return ;
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
this . _initArray ( this . toArray ( ) , base , endian ) ;
} ;
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . _initNumber = function _initNumber ( number , base , endian ) {
if ( number < 0 ) {
this . negative = 1 ;
number = - number ;
}
if ( number < 0x4000000 ) {
this . words = [ number & 0x3ffffff ] ;
this . length = 1 ;
} else if ( number < 0x10000000000000 ) {
this . words = [
number & 0x3ffffff ,
( number / 0x4000000 ) & 0x3ffffff
] ;
this . length = 2 ;
} else {
assert ( number < 0x20000000000000 ) ; // 2 ^ 53 (unsafe)
this . words = [
number & 0x3ffffff ,
( number / 0x4000000 ) & 0x3ffffff ,
1
] ;
this . length = 3 ;
}
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
if ( endian !== 'le' ) return ;
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
// Reverse the bytes
this . _initArray ( this . toArray ( ) , base , endian ) ;
} ;
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . _initArray = function _initArray ( number , base , endian ) {
// Perhaps a Uint8Array
assert ( typeof number . length === 'number' ) ;
if ( number . length <= 0 ) {
this . words = [ 0 ] ;
this . length = 1 ;
return this ;
2017-04-05 01:53:59 +03:00
}
2017-04-05 23:53:29 +03:00
this . length = Math . ceil ( number . length / 3 ) ;
this . words = new Array ( this . length ) ;
for ( var i = 0 ; i < this . length ; i ++ ) {
this . words [ i ] = 0 ;
2017-04-05 01:53:59 +03:00
}
2017-04-05 23:53:29 +03:00
var j , w ;
var off = 0 ;
if ( endian === 'be' ) {
for ( i = number . length - 1 , j = 0 ; i >= 0 ; i -= 3 ) {
w = number [ i ] | ( number [ i - 1 ] << 8 ) | ( number [ i - 2 ] << 16 ) ;
this . words [ j ] |= ( w << off ) & 0x3ffffff ;
this . words [ j + 1 ] = ( w >>> ( 26 - off ) ) & 0x3ffffff ;
off += 24 ;
if ( off >= 26 ) {
off -= 26 ;
j ++ ;
}
}
} else if ( endian === 'le' ) {
for ( i = 0 , j = 0 ; i < number . length ; i += 3 ) {
w = number [ i ] | ( number [ i + 1 ] << 8 ) | ( number [ i + 2 ] << 16 ) ;
this . words [ j ] |= ( w << off ) & 0x3ffffff ;
this . words [ j + 1 ] = ( w >>> ( 26 - off ) ) & 0x3ffffff ;
off += 24 ;
if ( off >= 26 ) {
off -= 26 ;
j ++ ;
}
}
}
return this . strip ( ) ;
} ;
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
function parseHex ( str , start , end ) {
var r = 0 ;
var len = Math . min ( str . length , end ) ;
for ( var i = start ; i < len ; i ++ ) {
var c = str . charCodeAt ( i ) - 48 ;
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
r <<= 4 ;
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
// 'a' - 'f'
if ( c >= 49 && c <= 54 ) {
r |= c - 49 + 0xa ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// 'A' - 'F'
} else if ( c >= 17 && c <= 22 ) {
r |= c - 17 + 0xa ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// '0' - '9'
} else {
r |= c & 0xf ;
}
}
return r ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . _parseHex = function _parseHex ( number , start ) {
// Create possibly bigger array to ensure that it fits the number
this . length = Math . ceil ( ( number . length - start ) / 6 ) ;
this . words = new Array ( this . length ) ;
for ( var i = 0 ; i < this . length ; i ++ ) {
this . words [ i ] = 0 ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var j , w ;
// Scan 24-bit chunks and add them to the number
var off = 0 ;
for ( i = number . length - 6 , j = 0 ; i >= start ; i -= 6 ) {
w = parseHex ( number , i , i + 6 ) ;
this . words [ j ] |= ( w << off ) & 0x3ffffff ;
// NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb
this . words [ j + 1 ] |= w >>> ( 26 - off ) & 0x3fffff ;
off += 24 ;
if ( off >= 26 ) {
off -= 26 ;
j ++ ;
}
}
if ( i + 6 !== start ) {
w = parseHex ( number , start , i + 6 ) ;
this . words [ j ] |= ( w << off ) & 0x3ffffff ;
this . words [ j + 1 ] |= w >>> ( 26 - off ) & 0x3fffff ;
}
this . strip ( ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
function parseBase ( str , start , end , mul ) {
var r = 0 ;
var len = Math . min ( str . length , end ) ;
for ( var i = start ; i < len ; i ++ ) {
var c = str . charCodeAt ( i ) - 48 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
r *= mul ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// 'a'
if ( c >= 49 ) {
r += c - 49 + 0xa ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// 'A'
} else if ( c >= 17 ) {
r += c - 17 + 0xa ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// '0' - '9'
} else {
r += c ;
}
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return r ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . _parseBase = function _parseBase ( number , base , start ) {
// Initialize as zero
this . words = [ 0 ] ;
this . length = 1 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Find length of limb in base
for ( var limbLen = 0 , limbPow = 1 ; limbPow <= 0x3ffffff ; limbPow *= base ) {
limbLen ++ ;
}
limbLen -- ;
limbPow = ( limbPow / base ) | 0 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var total = number . length - start ;
var mod = total % limbLen ;
var end = Math . min ( total , total - mod ) + start ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var word = 0 ;
for ( var i = start ; i < end ; i += limbLen ) {
word = parseBase ( number , i , i + limbLen , base ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
this . imuln ( limbPow ) ;
if ( this . words [ 0 ] + word < 0x4000000 ) {
this . words [ 0 ] += word ;
} else {
this . _iaddn ( word ) ;
}
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
if ( mod !== 0 ) {
var pow = 1 ;
word = parseBase ( number , i , number . length , base ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
for ( i = 0 ; i < mod ; i ++ ) {
pow *= base ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
this . imuln ( pow ) ;
if ( this . words [ 0 ] + word < 0x4000000 ) {
this . words [ 0 ] += word ;
} else {
this . _iaddn ( word ) ;
}
}
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . copy = function copy ( dest ) {
dest . words = new Array ( this . length ) ;
for ( var i = 0 ; i < this . length ; i ++ ) {
dest . words [ i ] = this . words [ i ] ;
}
dest . length = this . length ;
dest . negative = this . negative ;
dest . red = this . red ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . clone = function clone ( ) {
var r = new BN ( null ) ;
this . copy ( r ) ;
return r ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . _expand = function _expand ( size ) {
while ( this . length < size ) {
this . words [ this . length ++ ] = 0 ;
}
return this ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Remove leading `0` from `this`
BN . prototype . strip = function strip ( ) {
while ( this . length > 1 && this . words [ this . length - 1 ] === 0 ) {
this . length -- ;
}
return this . _normSign ( ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . _normSign = function _normSign ( ) {
// -0 = 0
if ( this . length === 1 && this . words [ 0 ] === 0 ) {
this . negative = 0 ;
}
return this ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . inspect = function inspect ( ) {
return ( this . red ? '<BN-R: ' : '<BN: ' ) + this . toString ( 16 ) + '>' ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
/ *
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var zeros = [ ] ;
var groupSizes = [ ] ;
var groupBases = [ ] ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var s = '' ;
var i = - 1 ;
while ( ++ i < BN . wordSize ) {
zeros [ i ] = s ;
s += '0' ;
}
groupSizes [ 0 ] = 0 ;
groupSizes [ 1 ] = 0 ;
groupBases [ 0 ] = 0 ;
groupBases [ 1 ] = 0 ;
var base = 2 - 1 ;
while ( ++ base < 36 + 1 ) {
var groupSize = 0 ;
var groupBase = 1 ;
while ( groupBase < ( 1 << BN . wordSize ) / base ) {
groupBase *= base ;
groupSize += 1 ;
}
groupSizes [ base ] = groupSize ;
groupBases [ base ] = groupBase ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
* /
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var zeros = [
'' ,
'0' ,
'00' ,
'000' ,
'0000' ,
'00000' ,
'000000' ,
'0000000' ,
'00000000' ,
'000000000' ,
'0000000000' ,
'00000000000' ,
'000000000000' ,
'0000000000000' ,
'00000000000000' ,
'000000000000000' ,
'0000000000000000' ,
'00000000000000000' ,
'000000000000000000' ,
'0000000000000000000' ,
'00000000000000000000' ,
'000000000000000000000' ,
'0000000000000000000000' ,
'00000000000000000000000' ,
'000000000000000000000000' ,
'0000000000000000000000000'
] ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var groupSizes = [
0 , 0 ,
25 , 16 , 12 , 11 , 10 , 9 , 8 ,
8 , 7 , 7 , 7 , 7 , 6 , 6 ,
6 , 6 , 6 , 6 , 6 , 5 , 5 ,
5 , 5 , 5 , 5 , 5 , 5 , 5 ,
5 , 5 , 5 , 5 , 5 , 5 , 5
] ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var groupBases = [
0 , 0 ,
33554432 , 43046721 , 16777216 , 48828125 , 60466176 , 40353607 , 16777216 ,
43046721 , 10000000 , 19487171 , 35831808 , 62748517 , 7529536 , 11390625 ,
16777216 , 24137569 , 34012224 , 47045881 , 64000000 , 4084101 , 5153632 ,
6436343 , 7962624 , 9765625 , 11881376 , 14348907 , 17210368 , 20511149 ,
24300000 , 28629151 , 33554432 , 39135393 , 45435424 , 52521875 , 60466176
] ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . toString = function toString ( base , padding ) {
base = base || 10 ;
padding = padding | 0 || 1 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var out ;
if ( base === 16 || base === 'hex' ) {
out = '' ;
var off = 0 ;
var carry = 0 ;
for ( var i = 0 ; i < this . length ; i ++ ) {
var w = this . words [ i ] ;
var word = ( ( ( w << off ) | carry ) & 0xffffff ) . toString ( 16 ) ;
carry = ( w >>> ( 24 - off ) ) & 0xffffff ;
if ( carry !== 0 || i !== this . length - 1 ) {
out = zeros [ 6 - word . length ] + word + out ;
} else {
out = word + out ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
off += 2 ;
if ( off >= 26 ) {
off -= 26 ;
i -- ;
}
}
if ( carry !== 0 ) {
out = carry . toString ( 16 ) + out ;
}
while ( out . length % padding !== 0 ) {
out = '0' + out ;
}
if ( this . negative !== 0 ) {
out = '-' + out ;
}
return out ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
if ( base === ( base | 0 ) && base >= 2 && base <= 36 ) {
// var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
var groupSize = groupSizes [ base ] ;
// var groupBase = Math.pow(base, groupSize);
var groupBase = groupBases [ base ] ;
out = '' ;
var c = this . clone ( ) ;
c . negative = 0 ;
while ( ! c . isZero ( ) ) {
var r = c . modn ( groupBase ) . toString ( base ) ;
c = c . idivn ( groupBase ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
if ( ! c . isZero ( ) ) {
out = zeros [ groupSize - r . length ] + r + out ;
} else {
out = r + out ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
}
if ( this . isZero ( ) ) {
out = '0' + out ;
}
while ( out . length % padding !== 0 ) {
out = '0' + out ;
}
if ( this . negative !== 0 ) {
out = '-' + out ;
}
return out ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
assert ( false , 'Base should be between 2 and 36' ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . toNumber = function toNumber ( ) {
var ret = this . words [ 0 ] ;
if ( this . length === 2 ) {
ret += this . words [ 1 ] * 0x4000000 ;
} else if ( this . length === 3 && this . words [ 2 ] === 0x01 ) {
// NOTE: at this stage it is known that the top bit is set
ret += 0x10000000000000 + ( this . words [ 1 ] * 0x4000000 ) ;
} else if ( this . length > 2 ) {
assert ( false , 'Number can only safely store up to 53 bits' ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return ( this . negative !== 0 ) ? - ret : ret ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . toJSON = function toJSON ( ) {
return this . toString ( 16 ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . toBuffer = function toBuffer ( endian , length ) {
assert ( typeof Buffer !== 'undefined' ) ;
return this . toArrayLike ( Buffer , endian , length ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . toArray = function toArray ( endian , length ) {
return this . toArrayLike ( Array , endian , length ) ;
} ;
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . toArrayLike = function toArrayLike ( ArrayType , endian , length ) {
var byteLength = this . byteLength ( ) ;
var reqLength = length || Math . max ( 1 , byteLength ) ;
assert ( byteLength <= reqLength , 'byte array longer than desired length' ) ;
assert ( reqLength > 0 , 'Requested array length <= 0' ) ;
2017-04-05 01:53:59 +03:00
2017-04-05 23:53:29 +03:00
this . strip ( ) ;
var littleEndian = endian === 'le' ;
var res = new ArrayType ( reqLength ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var b , i ;
var q = this . clone ( ) ;
if ( ! littleEndian ) {
// Assume big-endian
for ( i = 0 ; i < reqLength - byteLength ; i ++ ) {
res [ i ] = 0 ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
for ( i = 0 ; ! q . isZero ( ) ; i ++ ) {
b = q . andln ( 0xff ) ;
q . iushrn ( 8 ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
res [ reqLength - i - 1 ] = b ;
}
} else {
for ( i = 0 ; ! q . isZero ( ) ; i ++ ) {
b = q . andln ( 0xff ) ;
q . iushrn ( 8 ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
res [ i ] = b ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
for ( ; i < reqLength ; i ++ ) {
res [ i ] = 0 ;
}
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return res ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
if ( Math . clz32 ) {
BN . prototype . _countBits = function _countBits ( w ) {
return 32 - Math . clz32 ( w ) ;
} ;
} else {
BN . prototype . _countBits = function _countBits ( w ) {
var t = w ;
var r = 0 ;
if ( t >= 0x1000 ) {
r += 13 ;
t >>>= 13 ;
}
if ( t >= 0x40 ) {
r += 7 ;
t >>>= 7 ;
}
if ( t >= 0x8 ) {
r += 4 ;
t >>>= 4 ;
}
if ( t >= 0x02 ) {
r += 2 ;
t >>>= 2 ;
}
return r + t ;
} ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . _zeroBits = function _zeroBits ( w ) {
// Short-cut
if ( w === 0 ) return 26 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var t = w ;
var r = 0 ;
if ( ( t & 0x1fff ) === 0 ) {
r += 13 ;
t >>>= 13 ;
}
if ( ( t & 0x7f ) === 0 ) {
r += 7 ;
t >>>= 7 ;
}
if ( ( t & 0xf ) === 0 ) {
r += 4 ;
t >>>= 4 ;
}
if ( ( t & 0x3 ) === 0 ) {
r += 2 ;
t >>>= 2 ;
}
if ( ( t & 0x1 ) === 0 ) {
r ++ ;
}
return r ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Return number of used bits in a BN
BN . prototype . bitLength = function bitLength ( ) {
var w = this . words [ this . length - 1 ] ;
var hi = this . _countBits ( w ) ;
return ( this . length - 1 ) * 26 + hi ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
function toBitArray ( num ) {
var w = new Array ( num . bitLength ( ) ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
for ( var bit = 0 ; bit < w . length ; bit ++ ) {
var off = ( bit / 26 ) | 0 ;
var wbit = bit % 26 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
w [ bit ] = ( num . words [ off ] & ( 1 << wbit ) ) >>> wbit ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
return w ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
// Number of trailing zero bits
BN . prototype . zeroBits = function zeroBits ( ) {
if ( this . isZero ( ) ) return 0 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var r = 0 ;
for ( var i = 0 ; i < this . length ; i ++ ) {
var b = this . _zeroBits ( this . words [ i ] ) ;
r += b ;
if ( b !== 26 ) break ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return r ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . byteLength = function byteLength ( ) {
return Math . ceil ( this . bitLength ( ) / 8 ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . toTwos = function toTwos ( width ) {
if ( this . negative !== 0 ) {
return this . abs ( ) . inotn ( width ) . iaddn ( 1 ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return this . clone ( ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . fromTwos = function fromTwos ( width ) {
if ( this . testn ( width - 1 ) ) {
return this . notn ( width ) . iaddn ( 1 ) . ineg ( ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return this . clone ( ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . isNeg = function isNeg ( ) {
return this . negative !== 0 ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
// Return negative clone of `this`
BN . prototype . neg = function neg ( ) {
return this . clone ( ) . ineg ( ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . ineg = function ineg ( ) {
if ( ! this . isZero ( ) ) {
this . negative ^= 1 ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return this ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Or `num` with `this` in-place
BN . prototype . iuor = function iuor ( num ) {
while ( this . length < num . length ) {
this . words [ this . length ++ ] = 0 ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
for ( var i = 0 ; i < num . length ; i ++ ) {
this . words [ i ] = this . words [ i ] | num . words [ i ] ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return this . strip ( ) ;
} ;
BN . prototype . ior = function ior ( num ) {
assert ( ( this . negative | num . negative ) === 0 ) ;
return this . iuor ( num ) ;
} ;
// Or `num` with `this`
BN . prototype . or = function or ( num ) {
if ( this . length > num . length ) return this . clone ( ) . ior ( num ) ;
return num . clone ( ) . ior ( this ) ;
} ;
BN . prototype . uor = function uor ( num ) {
if ( this . length > num . length ) return this . clone ( ) . iuor ( num ) ;
return num . clone ( ) . iuor ( this ) ;
} ;
// And `num` with `this` in-place
BN . prototype . iuand = function iuand ( num ) {
// b = min-length(num, this)
var b ;
if ( this . length > num . length ) {
b = num ;
2017-02-27 08:09:47 +03:00
} else {
2017-04-05 23:53:29 +03:00
b = this ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
for ( var i = 0 ; i < b . length ; i ++ ) {
this . words [ i ] = this . words [ i ] & num . words [ i ] ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
this . length = b . length ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
return this . strip ( ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . iand = function iand ( num ) {
assert ( ( this . negative | num . negative ) === 0 ) ;
return this . iuand ( num ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// And `num` with `this`
BN . prototype . and = function and ( num ) {
if ( this . length > num . length ) return this . clone ( ) . iand ( num ) ;
return num . clone ( ) . iand ( this ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . uand = function uand ( num ) {
if ( this . length > num . length ) return this . clone ( ) . iuand ( num ) ;
return num . clone ( ) . iuand ( this ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
// Xor `num` with `this` in-place
BN . prototype . iuxor = function iuxor ( num ) {
// a.length > b.length
var a ;
var b ;
if ( this . length > num . length ) {
a = this ;
b = num ;
} else {
a = num ;
b = this ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
for ( var i = 0 ; i < b . length ; i ++ ) {
this . words [ i ] = a . words [ i ] ^ b . words [ i ] ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
if ( this !== a ) {
for ( ; i < a . length ; i ++ ) {
this . words [ i ] = a . words [ i ] ;
2017-02-27 08:09:47 +03:00
}
}
2017-04-05 23:53:29 +03:00
this . length = a . length ;
2017-02-27 08:09:47 +03:00
return this . strip ( ) ;
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . ixor = function ixor ( num ) {
assert ( ( this . negative | num . negative ) === 0 ) ;
return this . iuxor ( num ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Xor `num` with `this`
BN . prototype . xor = function xor ( num ) {
if ( this . length > num . length ) return this . clone ( ) . ixor ( num ) ;
return num . clone ( ) . ixor ( this ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . uxor = function uxor ( num ) {
if ( this . length > num . length ) return this . clone ( ) . iuxor ( num ) ;
return num . clone ( ) . iuxor ( this ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Not ``this`` with ``width`` bitwidth
BN . prototype . inotn = function inotn ( width ) {
assert ( typeof width === 'number' && width >= 0 ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var bytesNeeded = Math . ceil ( width / 26 ) | 0 ;
var bitsLeft = width % 26 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Extend the buffer with leading zeroes
this . _expand ( bytesNeeded ) ;
if ( bitsLeft > 0 ) {
bytesNeeded -- ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
// Handle complete words
for ( var i = 0 ; i < bytesNeeded ; i ++ ) {
this . words [ i ] = ~ this . words [ i ] & 0x3ffffff ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
// Handle the residue
if ( bitsLeft > 0 ) {
this . words [ i ] = ~ this . words [ i ] & ( 0x3ffffff >> ( 26 - bitsLeft ) ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
// And remove leading zeroes
return this . strip ( ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . notn = function notn ( width ) {
return this . clone ( ) . inotn ( width ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Set `bit` of `this`
BN . prototype . setn = function setn ( bit , val ) {
assert ( typeof bit === 'number' && bit >= 0 ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var off = ( bit / 26 ) | 0 ;
var wbit = bit % 26 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
this . _expand ( off + 1 ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
if ( val ) {
this . words [ off ] = this . words [ off ] | ( 1 << wbit ) ;
} else {
this . words [ off ] = this . words [ off ] & ~ ( 1 << wbit ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return this . strip ( ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Add `num` to `this` in-place
BN . prototype . iadd = function iadd ( num ) {
var r ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// negative + positive
if ( this . negative !== 0 && num . negative === 0 ) {
this . negative = 0 ;
r = this . isub ( num ) ;
this . negative ^= 1 ;
return this . _normSign ( ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// positive + negative
} else if ( this . negative === 0 && num . negative !== 0 ) {
num . negative = 0 ;
r = this . isub ( num ) ;
num . negative = 1 ;
return r . _normSign ( ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
// a.length > b.length
var a , b ;
if ( this . length > num . length ) {
a = this ;
b = num ;
} else {
a = num ;
b = this ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var carry = 0 ;
for ( var i = 0 ; i < b . length ; i ++ ) {
r = ( a . words [ i ] | 0 ) + ( b . words [ i ] | 0 ) + carry ;
this . words [ i ] = r & 0x3ffffff ;
carry = r >>> 26 ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
for ( ; carry !== 0 && i < a . length ; i ++ ) {
r = ( a . words [ i ] | 0 ) + carry ;
this . words [ i ] = r & 0x3ffffff ;
carry = r >>> 26 ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
this . length = a . length ;
if ( carry !== 0 ) {
this . words [ this . length ] = carry ;
this . length ++ ;
// Copy the rest of the words
} else if ( a !== this ) {
for ( ; i < a . length ; i ++ ) {
this . words [ i ] = a . words [ i ] ;
}
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return this ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
// Add `num` to `this`
BN . prototype . add = function add ( num ) {
var res ;
if ( num . negative !== 0 && this . negative === 0 ) {
num . negative = 0 ;
res = this . sub ( num ) ;
num . negative ^= 1 ;
return res ;
} else if ( num . negative === 0 && this . negative !== 0 ) {
2017-02-27 08:09:47 +03:00
this . negative = 0 ;
2017-04-05 23:53:29 +03:00
res = num . sub ( this ) ;
this . negative = 1 ;
return res ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
if ( this . length > num . length ) return this . clone ( ) . iadd ( num ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
return num . clone ( ) . iadd ( this ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Subtract `num` from `this` in-place
BN . prototype . isub = function isub ( num ) {
// this - (-num) = this + num
if ( num . negative !== 0 ) {
num . negative = 0 ;
var r = this . iadd ( num ) ;
num . negative = 1 ;
return r . _normSign ( ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// -this - num = -(this + num)
} else if ( this . negative !== 0 ) {
this . negative = 0 ;
this . iadd ( num ) ;
this . negative = 1 ;
return this . _normSign ( ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
// At this point both numbers are positive
var cmp = this . cmp ( num ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Optimization - zeroify
if ( cmp === 0 ) {
this . negative = 0 ;
this . length = 1 ;
this . words [ 0 ] = 0 ;
return this ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// a > b
var a , b ;
if ( cmp > 0 ) {
a = this ;
b = num ;
} else {
a = num ;
b = this ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var carry = 0 ;
for ( var i = 0 ; i < b . length ; i ++ ) {
r = ( a . words [ i ] | 0 ) - ( b . words [ i ] | 0 ) + carry ;
carry = r >> 26 ;
this . words [ i ] = r & 0x3ffffff ;
}
for ( ; carry !== 0 && i < a . length ; i ++ ) {
r = ( a . words [ i ] | 0 ) + carry ;
carry = r >> 26 ;
this . words [ i ] = r & 0x3ffffff ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Copy rest of the words
if ( carry === 0 && i < a . length && a !== this ) {
for ( ; i < a . length ; i ++ ) {
this . words [ i ] = a . words [ i ] ;
2017-02-27 08:09:47 +03:00
}
}
2017-04-05 23:53:29 +03:00
this . length = Math . max ( this . length , i ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
if ( a !== this ) {
this . negative = 1 ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return this . strip ( ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
// Subtract `num` from `this`
BN . prototype . sub = function sub ( num ) {
return this . clone ( ) . isub ( num ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
function smallMulTo ( self , num , out ) {
out . negative = num . negative ^ self . negative ;
var len = ( self . length + num . length ) | 0 ;
out . length = len ;
len = ( len - 1 ) | 0 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Peel one iteration (compiler can't do it, because of code complexity)
var a = self . words [ 0 ] | 0 ;
var b = num . words [ 0 ] | 0 ;
var r = a * b ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var lo = r & 0x3ffffff ;
var carry = ( r / 0x4000000 ) | 0 ;
out . words [ 0 ] = lo ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
for ( var k = 1 ; k < len ; k ++ ) {
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
// note that ncarry could be >= 0x3ffffff
var ncarry = carry >>> 26 ;
var rword = carry & 0x3ffffff ;
var maxJ = Math . min ( k , num . length - 1 ) ;
for ( var j = Math . max ( 0 , k - self . length + 1 ) ; j <= maxJ ; j ++ ) {
var i = ( k - j ) | 0 ;
a = self . words [ i ] | 0 ;
b = num . words [ j ] | 0 ;
r = a * b + rword ;
ncarry += ( r / 0x4000000 ) | 0 ;
rword = r & 0x3ffffff ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
out . words [ k ] = rword | 0 ;
carry = ncarry | 0 ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
if ( carry !== 0 ) {
out . words [ k ] = carry | 0 ;
} else {
out . length -- ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return out . strip ( ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
// TODO(indutny): it may be reasonable to omit it for users who don't need
// to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit
// multiplication (like elliptic secp256k1).
var comb10MulTo = function comb10MulTo ( self , num , out ) {
var a = self . words ;
var b = num . words ;
var o = out . words ;
var c = 0 ;
var lo ;
var mid ;
var hi ;
var a0 = a [ 0 ] | 0 ;
var al0 = a0 & 0x1fff ;
var ah0 = a0 >>> 13 ;
var a1 = a [ 1 ] | 0 ;
var al1 = a1 & 0x1fff ;
var ah1 = a1 >>> 13 ;
var a2 = a [ 2 ] | 0 ;
var al2 = a2 & 0x1fff ;
var ah2 = a2 >>> 13 ;
var a3 = a [ 3 ] | 0 ;
var al3 = a3 & 0x1fff ;
var ah3 = a3 >>> 13 ;
var a4 = a [ 4 ] | 0 ;
var al4 = a4 & 0x1fff ;
var ah4 = a4 >>> 13 ;
var a5 = a [ 5 ] | 0 ;
var al5 = a5 & 0x1fff ;
var ah5 = a5 >>> 13 ;
var a6 = a [ 6 ] | 0 ;
var al6 = a6 & 0x1fff ;
var ah6 = a6 >>> 13 ;
var a7 = a [ 7 ] | 0 ;
var al7 = a7 & 0x1fff ;
var ah7 = a7 >>> 13 ;
var a8 = a [ 8 ] | 0 ;
var al8 = a8 & 0x1fff ;
var ah8 = a8 >>> 13 ;
var a9 = a [ 9 ] | 0 ;
var al9 = a9 & 0x1fff ;
var ah9 = a9 >>> 13 ;
var b0 = b [ 0 ] | 0 ;
var bl0 = b0 & 0x1fff ;
var bh0 = b0 >>> 13 ;
var b1 = b [ 1 ] | 0 ;
var bl1 = b1 & 0x1fff ;
var bh1 = b1 >>> 13 ;
var b2 = b [ 2 ] | 0 ;
var bl2 = b2 & 0x1fff ;
var bh2 = b2 >>> 13 ;
var b3 = b [ 3 ] | 0 ;
var bl3 = b3 & 0x1fff ;
var bh3 = b3 >>> 13 ;
var b4 = b [ 4 ] | 0 ;
var bl4 = b4 & 0x1fff ;
var bh4 = b4 >>> 13 ;
var b5 = b [ 5 ] | 0 ;
var bl5 = b5 & 0x1fff ;
var bh5 = b5 >>> 13 ;
var b6 = b [ 6 ] | 0 ;
var bl6 = b6 & 0x1fff ;
var bh6 = b6 >>> 13 ;
var b7 = b [ 7 ] | 0 ;
var bl7 = b7 & 0x1fff ;
var bh7 = b7 >>> 13 ;
var b8 = b [ 8 ] | 0 ;
var bl8 = b8 & 0x1fff ;
var bh8 = b8 >>> 13 ;
var b9 = b [ 9 ] | 0 ;
var bl9 = b9 & 0x1fff ;
var bh9 = b9 >>> 13 ;
2017-02-27 08:09:47 +03:00
out . negative = self . negative ^ num . negative ;
out . length = 19 ;
/* k = 0 */
lo = Math . imul ( al0 , bl0 ) ;
mid = Math . imul ( al0 , bh0 ) ;
mid = ( mid + Math . imul ( ah0 , bl0 ) ) | 0 ;
hi = Math . imul ( ah0 , bh0 ) ;
var w0 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w0 >>> 26 ) ) | 0 ;
w0 &= 0x3ffffff ;
/* k = 1 */
lo = Math . imul ( al1 , bl0 ) ;
mid = Math . imul ( al1 , bh0 ) ;
mid = ( mid + Math . imul ( ah1 , bl0 ) ) | 0 ;
hi = Math . imul ( ah1 , bh0 ) ;
lo = ( lo + Math . imul ( al0 , bl1 ) ) | 0 ;
mid = ( mid + Math . imul ( al0 , bh1 ) ) | 0 ;
mid = ( mid + Math . imul ( ah0 , bl1 ) ) | 0 ;
hi = ( hi + Math . imul ( ah0 , bh1 ) ) | 0 ;
var w1 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w1 >>> 26 ) ) | 0 ;
w1 &= 0x3ffffff ;
/* k = 2 */
lo = Math . imul ( al2 , bl0 ) ;
mid = Math . imul ( al2 , bh0 ) ;
mid = ( mid + Math . imul ( ah2 , bl0 ) ) | 0 ;
hi = Math . imul ( ah2 , bh0 ) ;
lo = ( lo + Math . imul ( al1 , bl1 ) ) | 0 ;
mid = ( mid + Math . imul ( al1 , bh1 ) ) | 0 ;
mid = ( mid + Math . imul ( ah1 , bl1 ) ) | 0 ;
hi = ( hi + Math . imul ( ah1 , bh1 ) ) | 0 ;
lo = ( lo + Math . imul ( al0 , bl2 ) ) | 0 ;
mid = ( mid + Math . imul ( al0 , bh2 ) ) | 0 ;
mid = ( mid + Math . imul ( ah0 , bl2 ) ) | 0 ;
hi = ( hi + Math . imul ( ah0 , bh2 ) ) | 0 ;
var w2 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w2 >>> 26 ) ) | 0 ;
w2 &= 0x3ffffff ;
/* k = 3 */
lo = Math . imul ( al3 , bl0 ) ;
mid = Math . imul ( al3 , bh0 ) ;
mid = ( mid + Math . imul ( ah3 , bl0 ) ) | 0 ;
hi = Math . imul ( ah3 , bh0 ) ;
lo = ( lo + Math . imul ( al2 , bl1 ) ) | 0 ;
mid = ( mid + Math . imul ( al2 , bh1 ) ) | 0 ;
mid = ( mid + Math . imul ( ah2 , bl1 ) ) | 0 ;
hi = ( hi + Math . imul ( ah2 , bh1 ) ) | 0 ;
lo = ( lo + Math . imul ( al1 , bl2 ) ) | 0 ;
mid = ( mid + Math . imul ( al1 , bh2 ) ) | 0 ;
mid = ( mid + Math . imul ( ah1 , bl2 ) ) | 0 ;
hi = ( hi + Math . imul ( ah1 , bh2 ) ) | 0 ;
lo = ( lo + Math . imul ( al0 , bl3 ) ) | 0 ;
mid = ( mid + Math . imul ( al0 , bh3 ) ) | 0 ;
mid = ( mid + Math . imul ( ah0 , bl3 ) ) | 0 ;
hi = ( hi + Math . imul ( ah0 , bh3 ) ) | 0 ;
var w3 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w3 >>> 26 ) ) | 0 ;
w3 &= 0x3ffffff ;
/* k = 4 */
lo = Math . imul ( al4 , bl0 ) ;
mid = Math . imul ( al4 , bh0 ) ;
mid = ( mid + Math . imul ( ah4 , bl0 ) ) | 0 ;
hi = Math . imul ( ah4 , bh0 ) ;
lo = ( lo + Math . imul ( al3 , bl1 ) ) | 0 ;
mid = ( mid + Math . imul ( al3 , bh1 ) ) | 0 ;
mid = ( mid + Math . imul ( ah3 , bl1 ) ) | 0 ;
hi = ( hi + Math . imul ( ah3 , bh1 ) ) | 0 ;
lo = ( lo + Math . imul ( al2 , bl2 ) ) | 0 ;
mid = ( mid + Math . imul ( al2 , bh2 ) ) | 0 ;
mid = ( mid + Math . imul ( ah2 , bl2 ) ) | 0 ;
hi = ( hi + Math . imul ( ah2 , bh2 ) ) | 0 ;
lo = ( lo + Math . imul ( al1 , bl3 ) ) | 0 ;
mid = ( mid + Math . imul ( al1 , bh3 ) ) | 0 ;
mid = ( mid + Math . imul ( ah1 , bl3 ) ) | 0 ;
hi = ( hi + Math . imul ( ah1 , bh3 ) ) | 0 ;
lo = ( lo + Math . imul ( al0 , bl4 ) ) | 0 ;
mid = ( mid + Math . imul ( al0 , bh4 ) ) | 0 ;
mid = ( mid + Math . imul ( ah0 , bl4 ) ) | 0 ;
hi = ( hi + Math . imul ( ah0 , bh4 ) ) | 0 ;
var w4 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w4 >>> 26 ) ) | 0 ;
w4 &= 0x3ffffff ;
/* k = 5 */
lo = Math . imul ( al5 , bl0 ) ;
mid = Math . imul ( al5 , bh0 ) ;
mid = ( mid + Math . imul ( ah5 , bl0 ) ) | 0 ;
hi = Math . imul ( ah5 , bh0 ) ;
lo = ( lo + Math . imul ( al4 , bl1 ) ) | 0 ;
mid = ( mid + Math . imul ( al4 , bh1 ) ) | 0 ;
mid = ( mid + Math . imul ( ah4 , bl1 ) ) | 0 ;
hi = ( hi + Math . imul ( ah4 , bh1 ) ) | 0 ;
lo = ( lo + Math . imul ( al3 , bl2 ) ) | 0 ;
mid = ( mid + Math . imul ( al3 , bh2 ) ) | 0 ;
mid = ( mid + Math . imul ( ah3 , bl2 ) ) | 0 ;
hi = ( hi + Math . imul ( ah3 , bh2 ) ) | 0 ;
lo = ( lo + Math . imul ( al2 , bl3 ) ) | 0 ;
mid = ( mid + Math . imul ( al2 , bh3 ) ) | 0 ;
mid = ( mid + Math . imul ( ah2 , bl3 ) ) | 0 ;
hi = ( hi + Math . imul ( ah2 , bh3 ) ) | 0 ;
lo = ( lo + Math . imul ( al1 , bl4 ) ) | 0 ;
mid = ( mid + Math . imul ( al1 , bh4 ) ) | 0 ;
mid = ( mid + Math . imul ( ah1 , bl4 ) ) | 0 ;
hi = ( hi + Math . imul ( ah1 , bh4 ) ) | 0 ;
lo = ( lo + Math . imul ( al0 , bl5 ) ) | 0 ;
mid = ( mid + Math . imul ( al0 , bh5 ) ) | 0 ;
mid = ( mid + Math . imul ( ah0 , bl5 ) ) | 0 ;
hi = ( hi + Math . imul ( ah0 , bh5 ) ) | 0 ;
var w5 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w5 >>> 26 ) ) | 0 ;
w5 &= 0x3ffffff ;
/* k = 6 */
lo = Math . imul ( al6 , bl0 ) ;
mid = Math . imul ( al6 , bh0 ) ;
mid = ( mid + Math . imul ( ah6 , bl0 ) ) | 0 ;
hi = Math . imul ( ah6 , bh0 ) ;
lo = ( lo + Math . imul ( al5 , bl1 ) ) | 0 ;
mid = ( mid + Math . imul ( al5 , bh1 ) ) | 0 ;
mid = ( mid + Math . imul ( ah5 , bl1 ) ) | 0 ;
hi = ( hi + Math . imul ( ah5 , bh1 ) ) | 0 ;
lo = ( lo + Math . imul ( al4 , bl2 ) ) | 0 ;
mid = ( mid + Math . imul ( al4 , bh2 ) ) | 0 ;
mid = ( mid + Math . imul ( ah4 , bl2 ) ) | 0 ;
hi = ( hi + Math . imul ( ah4 , bh2 ) ) | 0 ;
lo = ( lo + Math . imul ( al3 , bl3 ) ) | 0 ;
mid = ( mid + Math . imul ( al3 , bh3 ) ) | 0 ;
mid = ( mid + Math . imul ( ah3 , bl3 ) ) | 0 ;
hi = ( hi + Math . imul ( ah3 , bh3 ) ) | 0 ;
lo = ( lo + Math . imul ( al2 , bl4 ) ) | 0 ;
mid = ( mid + Math . imul ( al2 , bh4 ) ) | 0 ;
mid = ( mid + Math . imul ( ah2 , bl4 ) ) | 0 ;
hi = ( hi + Math . imul ( ah2 , bh4 ) ) | 0 ;
lo = ( lo + Math . imul ( al1 , bl5 ) ) | 0 ;
mid = ( mid + Math . imul ( al1 , bh5 ) ) | 0 ;
mid = ( mid + Math . imul ( ah1 , bl5 ) ) | 0 ;
hi = ( hi + Math . imul ( ah1 , bh5 ) ) | 0 ;
lo = ( lo + Math . imul ( al0 , bl6 ) ) | 0 ;
mid = ( mid + Math . imul ( al0 , bh6 ) ) | 0 ;
mid = ( mid + Math . imul ( ah0 , bl6 ) ) | 0 ;
hi = ( hi + Math . imul ( ah0 , bh6 ) ) | 0 ;
var w6 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w6 >>> 26 ) ) | 0 ;
w6 &= 0x3ffffff ;
/* k = 7 */
lo = Math . imul ( al7 , bl0 ) ;
mid = Math . imul ( al7 , bh0 ) ;
mid = ( mid + Math . imul ( ah7 , bl0 ) ) | 0 ;
hi = Math . imul ( ah7 , bh0 ) ;
lo = ( lo + Math . imul ( al6 , bl1 ) ) | 0 ;
mid = ( mid + Math . imul ( al6 , bh1 ) ) | 0 ;
mid = ( mid + Math . imul ( ah6 , bl1 ) ) | 0 ;
hi = ( hi + Math . imul ( ah6 , bh1 ) ) | 0 ;
lo = ( lo + Math . imul ( al5 , bl2 ) ) | 0 ;
mid = ( mid + Math . imul ( al5 , bh2 ) ) | 0 ;
mid = ( mid + Math . imul ( ah5 , bl2 ) ) | 0 ;
hi = ( hi + Math . imul ( ah5 , bh2 ) ) | 0 ;
lo = ( lo + Math . imul ( al4 , bl3 ) ) | 0 ;
mid = ( mid + Math . imul ( al4 , bh3 ) ) | 0 ;
mid = ( mid + Math . imul ( ah4 , bl3 ) ) | 0 ;
hi = ( hi + Math . imul ( ah4 , bh3 ) ) | 0 ;
lo = ( lo + Math . imul ( al3 , bl4 ) ) | 0 ;
mid = ( mid + Math . imul ( al3 , bh4 ) ) | 0 ;
mid = ( mid + Math . imul ( ah3 , bl4 ) ) | 0 ;
hi = ( hi + Math . imul ( ah3 , bh4 ) ) | 0 ;
lo = ( lo + Math . imul ( al2 , bl5 ) ) | 0 ;
mid = ( mid + Math . imul ( al2 , bh5 ) ) | 0 ;
mid = ( mid + Math . imul ( ah2 , bl5 ) ) | 0 ;
hi = ( hi + Math . imul ( ah2 , bh5 ) ) | 0 ;
lo = ( lo + Math . imul ( al1 , bl6 ) ) | 0 ;
mid = ( mid + Math . imul ( al1 , bh6 ) ) | 0 ;
mid = ( mid + Math . imul ( ah1 , bl6 ) ) | 0 ;
hi = ( hi + Math . imul ( ah1 , bh6 ) ) | 0 ;
lo = ( lo + Math . imul ( al0 , bl7 ) ) | 0 ;
mid = ( mid + Math . imul ( al0 , bh7 ) ) | 0 ;
mid = ( mid + Math . imul ( ah0 , bl7 ) ) | 0 ;
hi = ( hi + Math . imul ( ah0 , bh7 ) ) | 0 ;
var w7 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w7 >>> 26 ) ) | 0 ;
w7 &= 0x3ffffff ;
/* k = 8 */
lo = Math . imul ( al8 , bl0 ) ;
mid = Math . imul ( al8 , bh0 ) ;
mid = ( mid + Math . imul ( ah8 , bl0 ) ) | 0 ;
hi = Math . imul ( ah8 , bh0 ) ;
lo = ( lo + Math . imul ( al7 , bl1 ) ) | 0 ;
mid = ( mid + Math . imul ( al7 , bh1 ) ) | 0 ;
mid = ( mid + Math . imul ( ah7 , bl1 ) ) | 0 ;
hi = ( hi + Math . imul ( ah7 , bh1 ) ) | 0 ;
lo = ( lo + Math . imul ( al6 , bl2 ) ) | 0 ;
mid = ( mid + Math . imul ( al6 , bh2 ) ) | 0 ;
mid = ( mid + Math . imul ( ah6 , bl2 ) ) | 0 ;
hi = ( hi + Math . imul ( ah6 , bh2 ) ) | 0 ;
lo = ( lo + Math . imul ( al5 , bl3 ) ) | 0 ;
mid = ( mid + Math . imul ( al5 , bh3 ) ) | 0 ;
mid = ( mid + Math . imul ( ah5 , bl3 ) ) | 0 ;
hi = ( hi + Math . imul ( ah5 , bh3 ) ) | 0 ;
lo = ( lo + Math . imul ( al4 , bl4 ) ) | 0 ;
mid = ( mid + Math . imul ( al4 , bh4 ) ) | 0 ;
mid = ( mid + Math . imul ( ah4 , bl4 ) ) | 0 ;
hi = ( hi + Math . imul ( ah4 , bh4 ) ) | 0 ;
lo = ( lo + Math . imul ( al3 , bl5 ) ) | 0 ;
mid = ( mid + Math . imul ( al3 , bh5 ) ) | 0 ;
mid = ( mid + Math . imul ( ah3 , bl5 ) ) | 0 ;
hi = ( hi + Math . imul ( ah3 , bh5 ) ) | 0 ;
lo = ( lo + Math . imul ( al2 , bl6 ) ) | 0 ;
mid = ( mid + Math . imul ( al2 , bh6 ) ) | 0 ;
mid = ( mid + Math . imul ( ah2 , bl6 ) ) | 0 ;
hi = ( hi + Math . imul ( ah2 , bh6 ) ) | 0 ;
lo = ( lo + Math . imul ( al1 , bl7 ) ) | 0 ;
mid = ( mid + Math . imul ( al1 , bh7 ) ) | 0 ;
mid = ( mid + Math . imul ( ah1 , bl7 ) ) | 0 ;
hi = ( hi + Math . imul ( ah1 , bh7 ) ) | 0 ;
lo = ( lo + Math . imul ( al0 , bl8 ) ) | 0 ;
mid = ( mid + Math . imul ( al0 , bh8 ) ) | 0 ;
mid = ( mid + Math . imul ( ah0 , bl8 ) ) | 0 ;
hi = ( hi + Math . imul ( ah0 , bh8 ) ) | 0 ;
var w8 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w8 >>> 26 ) ) | 0 ;
w8 &= 0x3ffffff ;
/* k = 9 */
lo = Math . imul ( al9 , bl0 ) ;
mid = Math . imul ( al9 , bh0 ) ;
mid = ( mid + Math . imul ( ah9 , bl0 ) ) | 0 ;
hi = Math . imul ( ah9 , bh0 ) ;
lo = ( lo + Math . imul ( al8 , bl1 ) ) | 0 ;
mid = ( mid + Math . imul ( al8 , bh1 ) ) | 0 ;
mid = ( mid + Math . imul ( ah8 , bl1 ) ) | 0 ;
hi = ( hi + Math . imul ( ah8 , bh1 ) ) | 0 ;
lo = ( lo + Math . imul ( al7 , bl2 ) ) | 0 ;
mid = ( mid + Math . imul ( al7 , bh2 ) ) | 0 ;
mid = ( mid + Math . imul ( ah7 , bl2 ) ) | 0 ;
hi = ( hi + Math . imul ( ah7 , bh2 ) ) | 0 ;
lo = ( lo + Math . imul ( al6 , bl3 ) ) | 0 ;
mid = ( mid + Math . imul ( al6 , bh3 ) ) | 0 ;
mid = ( mid + Math . imul ( ah6 , bl3 ) ) | 0 ;
hi = ( hi + Math . imul ( ah6 , bh3 ) ) | 0 ;
lo = ( lo + Math . imul ( al5 , bl4 ) ) | 0 ;
mid = ( mid + Math . imul ( al5 , bh4 ) ) | 0 ;
mid = ( mid + Math . imul ( ah5 , bl4 ) ) | 0 ;
hi = ( hi + Math . imul ( ah5 , bh4 ) ) | 0 ;
lo = ( lo + Math . imul ( al4 , bl5 ) ) | 0 ;
mid = ( mid + Math . imul ( al4 , bh5 ) ) | 0 ;
mid = ( mid + Math . imul ( ah4 , bl5 ) ) | 0 ;
hi = ( hi + Math . imul ( ah4 , bh5 ) ) | 0 ;
lo = ( lo + Math . imul ( al3 , bl6 ) ) | 0 ;
mid = ( mid + Math . imul ( al3 , bh6 ) ) | 0 ;
mid = ( mid + Math . imul ( ah3 , bl6 ) ) | 0 ;
hi = ( hi + Math . imul ( ah3 , bh6 ) ) | 0 ;
lo = ( lo + Math . imul ( al2 , bl7 ) ) | 0 ;
mid = ( mid + Math . imul ( al2 , bh7 ) ) | 0 ;
mid = ( mid + Math . imul ( ah2 , bl7 ) ) | 0 ;
hi = ( hi + Math . imul ( ah2 , bh7 ) ) | 0 ;
lo = ( lo + Math . imul ( al1 , bl8 ) ) | 0 ;
mid = ( mid + Math . imul ( al1 , bh8 ) ) | 0 ;
mid = ( mid + Math . imul ( ah1 , bl8 ) ) | 0 ;
hi = ( hi + Math . imul ( ah1 , bh8 ) ) | 0 ;
lo = ( lo + Math . imul ( al0 , bl9 ) ) | 0 ;
mid = ( mid + Math . imul ( al0 , bh9 ) ) | 0 ;
mid = ( mid + Math . imul ( ah0 , bl9 ) ) | 0 ;
hi = ( hi + Math . imul ( ah0 , bh9 ) ) | 0 ;
var w9 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w9 >>> 26 ) ) | 0 ;
w9 &= 0x3ffffff ;
/* k = 10 */
lo = Math . imul ( al9 , bl1 ) ;
mid = Math . imul ( al9 , bh1 ) ;
mid = ( mid + Math . imul ( ah9 , bl1 ) ) | 0 ;
hi = Math . imul ( ah9 , bh1 ) ;
lo = ( lo + Math . imul ( al8 , bl2 ) ) | 0 ;
mid = ( mid + Math . imul ( al8 , bh2 ) ) | 0 ;
mid = ( mid + Math . imul ( ah8 , bl2 ) ) | 0 ;
hi = ( hi + Math . imul ( ah8 , bh2 ) ) | 0 ;
lo = ( lo + Math . imul ( al7 , bl3 ) ) | 0 ;
mid = ( mid + Math . imul ( al7 , bh3 ) ) | 0 ;
mid = ( mid + Math . imul ( ah7 , bl3 ) ) | 0 ;
hi = ( hi + Math . imul ( ah7 , bh3 ) ) | 0 ;
lo = ( lo + Math . imul ( al6 , bl4 ) ) | 0 ;
mid = ( mid + Math . imul ( al6 , bh4 ) ) | 0 ;
mid = ( mid + Math . imul ( ah6 , bl4 ) ) | 0 ;
hi = ( hi + Math . imul ( ah6 , bh4 ) ) | 0 ;
lo = ( lo + Math . imul ( al5 , bl5 ) ) | 0 ;
mid = ( mid + Math . imul ( al5 , bh5 ) ) | 0 ;
mid = ( mid + Math . imul ( ah5 , bl5 ) ) | 0 ;
hi = ( hi + Math . imul ( ah5 , bh5 ) ) | 0 ;
lo = ( lo + Math . imul ( al4 , bl6 ) ) | 0 ;
mid = ( mid + Math . imul ( al4 , bh6 ) ) | 0 ;
mid = ( mid + Math . imul ( ah4 , bl6 ) ) | 0 ;
hi = ( hi + Math . imul ( ah4 , bh6 ) ) | 0 ;
lo = ( lo + Math . imul ( al3 , bl7 ) ) | 0 ;
mid = ( mid + Math . imul ( al3 , bh7 ) ) | 0 ;
mid = ( mid + Math . imul ( ah3 , bl7 ) ) | 0 ;
hi = ( hi + Math . imul ( ah3 , bh7 ) ) | 0 ;
lo = ( lo + Math . imul ( al2 , bl8 ) ) | 0 ;
mid = ( mid + Math . imul ( al2 , bh8 ) ) | 0 ;
mid = ( mid + Math . imul ( ah2 , bl8 ) ) | 0 ;
hi = ( hi + Math . imul ( ah2 , bh8 ) ) | 0 ;
lo = ( lo + Math . imul ( al1 , bl9 ) ) | 0 ;
mid = ( mid + Math . imul ( al1 , bh9 ) ) | 0 ;
mid = ( mid + Math . imul ( ah1 , bl9 ) ) | 0 ;
hi = ( hi + Math . imul ( ah1 , bh9 ) ) | 0 ;
var w10 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w10 >>> 26 ) ) | 0 ;
w10 &= 0x3ffffff ;
/* k = 11 */
lo = Math . imul ( al9 , bl2 ) ;
mid = Math . imul ( al9 , bh2 ) ;
mid = ( mid + Math . imul ( ah9 , bl2 ) ) | 0 ;
hi = Math . imul ( ah9 , bh2 ) ;
lo = ( lo + Math . imul ( al8 , bl3 ) ) | 0 ;
mid = ( mid + Math . imul ( al8 , bh3 ) ) | 0 ;
mid = ( mid + Math . imul ( ah8 , bl3 ) ) | 0 ;
hi = ( hi + Math . imul ( ah8 , bh3 ) ) | 0 ;
lo = ( lo + Math . imul ( al7 , bl4 ) ) | 0 ;
mid = ( mid + Math . imul ( al7 , bh4 ) ) | 0 ;
mid = ( mid + Math . imul ( ah7 , bl4 ) ) | 0 ;
hi = ( hi + Math . imul ( ah7 , bh4 ) ) | 0 ;
lo = ( lo + Math . imul ( al6 , bl5 ) ) | 0 ;
mid = ( mid + Math . imul ( al6 , bh5 ) ) | 0 ;
mid = ( mid + Math . imul ( ah6 , bl5 ) ) | 0 ;
hi = ( hi + Math . imul ( ah6 , bh5 ) ) | 0 ;
lo = ( lo + Math . imul ( al5 , bl6 ) ) | 0 ;
mid = ( mid + Math . imul ( al5 , bh6 ) ) | 0 ;
mid = ( mid + Math . imul ( ah5 , bl6 ) ) | 0 ;
hi = ( hi + Math . imul ( ah5 , bh6 ) ) | 0 ;
lo = ( lo + Math . imul ( al4 , bl7 ) ) | 0 ;
mid = ( mid + Math . imul ( al4 , bh7 ) ) | 0 ;
mid = ( mid + Math . imul ( ah4 , bl7 ) ) | 0 ;
hi = ( hi + Math . imul ( ah4 , bh7 ) ) | 0 ;
lo = ( lo + Math . imul ( al3 , bl8 ) ) | 0 ;
mid = ( mid + Math . imul ( al3 , bh8 ) ) | 0 ;
mid = ( mid + Math . imul ( ah3 , bl8 ) ) | 0 ;
hi = ( hi + Math . imul ( ah3 , bh8 ) ) | 0 ;
lo = ( lo + Math . imul ( al2 , bl9 ) ) | 0 ;
mid = ( mid + Math . imul ( al2 , bh9 ) ) | 0 ;
mid = ( mid + Math . imul ( ah2 , bl9 ) ) | 0 ;
hi = ( hi + Math . imul ( ah2 , bh9 ) ) | 0 ;
var w11 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w11 >>> 26 ) ) | 0 ;
w11 &= 0x3ffffff ;
/* k = 12 */
lo = Math . imul ( al9 , bl3 ) ;
mid = Math . imul ( al9 , bh3 ) ;
mid = ( mid + Math . imul ( ah9 , bl3 ) ) | 0 ;
hi = Math . imul ( ah9 , bh3 ) ;
lo = ( lo + Math . imul ( al8 , bl4 ) ) | 0 ;
mid = ( mid + Math . imul ( al8 , bh4 ) ) | 0 ;
mid = ( mid + Math . imul ( ah8 , bl4 ) ) | 0 ;
hi = ( hi + Math . imul ( ah8 , bh4 ) ) | 0 ;
lo = ( lo + Math . imul ( al7 , bl5 ) ) | 0 ;
mid = ( mid + Math . imul ( al7 , bh5 ) ) | 0 ;
mid = ( mid + Math . imul ( ah7 , bl5 ) ) | 0 ;
hi = ( hi + Math . imul ( ah7 , bh5 ) ) | 0 ;
lo = ( lo + Math . imul ( al6 , bl6 ) ) | 0 ;
mid = ( mid + Math . imul ( al6 , bh6 ) ) | 0 ;
mid = ( mid + Math . imul ( ah6 , bl6 ) ) | 0 ;
hi = ( hi + Math . imul ( ah6 , bh6 ) ) | 0 ;
lo = ( lo + Math . imul ( al5 , bl7 ) ) | 0 ;
mid = ( mid + Math . imul ( al5 , bh7 ) ) | 0 ;
mid = ( mid + Math . imul ( ah5 , bl7 ) ) | 0 ;
hi = ( hi + Math . imul ( ah5 , bh7 ) ) | 0 ;
lo = ( lo + Math . imul ( al4 , bl8 ) ) | 0 ;
mid = ( mid + Math . imul ( al4 , bh8 ) ) | 0 ;
mid = ( mid + Math . imul ( ah4 , bl8 ) ) | 0 ;
hi = ( hi + Math . imul ( ah4 , bh8 ) ) | 0 ;
lo = ( lo + Math . imul ( al3 , bl9 ) ) | 0 ;
mid = ( mid + Math . imul ( al3 , bh9 ) ) | 0 ;
mid = ( mid + Math . imul ( ah3 , bl9 ) ) | 0 ;
hi = ( hi + Math . imul ( ah3 , bh9 ) ) | 0 ;
var w12 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w12 >>> 26 ) ) | 0 ;
w12 &= 0x3ffffff ;
/* k = 13 */
lo = Math . imul ( al9 , bl4 ) ;
mid = Math . imul ( al9 , bh4 ) ;
mid = ( mid + Math . imul ( ah9 , bl4 ) ) | 0 ;
hi = Math . imul ( ah9 , bh4 ) ;
lo = ( lo + Math . imul ( al8 , bl5 ) ) | 0 ;
mid = ( mid + Math . imul ( al8 , bh5 ) ) | 0 ;
mid = ( mid + Math . imul ( ah8 , bl5 ) ) | 0 ;
hi = ( hi + Math . imul ( ah8 , bh5 ) ) | 0 ;
lo = ( lo + Math . imul ( al7 , bl6 ) ) | 0 ;
mid = ( mid + Math . imul ( al7 , bh6 ) ) | 0 ;
mid = ( mid + Math . imul ( ah7 , bl6 ) ) | 0 ;
hi = ( hi + Math . imul ( ah7 , bh6 ) ) | 0 ;
lo = ( lo + Math . imul ( al6 , bl7 ) ) | 0 ;
mid = ( mid + Math . imul ( al6 , bh7 ) ) | 0 ;
mid = ( mid + Math . imul ( ah6 , bl7 ) ) | 0 ;
hi = ( hi + Math . imul ( ah6 , bh7 ) ) | 0 ;
lo = ( lo + Math . imul ( al5 , bl8 ) ) | 0 ;
mid = ( mid + Math . imul ( al5 , bh8 ) ) | 0 ;
mid = ( mid + Math . imul ( ah5 , bl8 ) ) | 0 ;
hi = ( hi + Math . imul ( ah5 , bh8 ) ) | 0 ;
lo = ( lo + Math . imul ( al4 , bl9 ) ) | 0 ;
mid = ( mid + Math . imul ( al4 , bh9 ) ) | 0 ;
mid = ( mid + Math . imul ( ah4 , bl9 ) ) | 0 ;
hi = ( hi + Math . imul ( ah4 , bh9 ) ) | 0 ;
var w13 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w13 >>> 26 ) ) | 0 ;
w13 &= 0x3ffffff ;
/* k = 14 */
lo = Math . imul ( al9 , bl5 ) ;
mid = Math . imul ( al9 , bh5 ) ;
mid = ( mid + Math . imul ( ah9 , bl5 ) ) | 0 ;
hi = Math . imul ( ah9 , bh5 ) ;
lo = ( lo + Math . imul ( al8 , bl6 ) ) | 0 ;
mid = ( mid + Math . imul ( al8 , bh6 ) ) | 0 ;
mid = ( mid + Math . imul ( ah8 , bl6 ) ) | 0 ;
hi = ( hi + Math . imul ( ah8 , bh6 ) ) | 0 ;
lo = ( lo + Math . imul ( al7 , bl7 ) ) | 0 ;
mid = ( mid + Math . imul ( al7 , bh7 ) ) | 0 ;
mid = ( mid + Math . imul ( ah7 , bl7 ) ) | 0 ;
hi = ( hi + Math . imul ( ah7 , bh7 ) ) | 0 ;
lo = ( lo + Math . imul ( al6 , bl8 ) ) | 0 ;
mid = ( mid + Math . imul ( al6 , bh8 ) ) | 0 ;
mid = ( mid + Math . imul ( ah6 , bl8 ) ) | 0 ;
hi = ( hi + Math . imul ( ah6 , bh8 ) ) | 0 ;
lo = ( lo + Math . imul ( al5 , bl9 ) ) | 0 ;
mid = ( mid + Math . imul ( al5 , bh9 ) ) | 0 ;
mid = ( mid + Math . imul ( ah5 , bl9 ) ) | 0 ;
hi = ( hi + Math . imul ( ah5 , bh9 ) ) | 0 ;
var w14 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w14 >>> 26 ) ) | 0 ;
w14 &= 0x3ffffff ;
/* k = 15 */
lo = Math . imul ( al9 , bl6 ) ;
mid = Math . imul ( al9 , bh6 ) ;
mid = ( mid + Math . imul ( ah9 , bl6 ) ) | 0 ;
hi = Math . imul ( ah9 , bh6 ) ;
lo = ( lo + Math . imul ( al8 , bl7 ) ) | 0 ;
mid = ( mid + Math . imul ( al8 , bh7 ) ) | 0 ;
mid = ( mid + Math . imul ( ah8 , bl7 ) ) | 0 ;
hi = ( hi + Math . imul ( ah8 , bh7 ) ) | 0 ;
lo = ( lo + Math . imul ( al7 , bl8 ) ) | 0 ;
mid = ( mid + Math . imul ( al7 , bh8 ) ) | 0 ;
mid = ( mid + Math . imul ( ah7 , bl8 ) ) | 0 ;
hi = ( hi + Math . imul ( ah7 , bh8 ) ) | 0 ;
lo = ( lo + Math . imul ( al6 , bl9 ) ) | 0 ;
mid = ( mid + Math . imul ( al6 , bh9 ) ) | 0 ;
mid = ( mid + Math . imul ( ah6 , bl9 ) ) | 0 ;
hi = ( hi + Math . imul ( ah6 , bh9 ) ) | 0 ;
var w15 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w15 >>> 26 ) ) | 0 ;
w15 &= 0x3ffffff ;
/* k = 16 */
lo = Math . imul ( al9 , bl7 ) ;
mid = Math . imul ( al9 , bh7 ) ;
mid = ( mid + Math . imul ( ah9 , bl7 ) ) | 0 ;
hi = Math . imul ( ah9 , bh7 ) ;
lo = ( lo + Math . imul ( al8 , bl8 ) ) | 0 ;
mid = ( mid + Math . imul ( al8 , bh8 ) ) | 0 ;
mid = ( mid + Math . imul ( ah8 , bl8 ) ) | 0 ;
hi = ( hi + Math . imul ( ah8 , bh8 ) ) | 0 ;
lo = ( lo + Math . imul ( al7 , bl9 ) ) | 0 ;
mid = ( mid + Math . imul ( al7 , bh9 ) ) | 0 ;
mid = ( mid + Math . imul ( ah7 , bl9 ) ) | 0 ;
hi = ( hi + Math . imul ( ah7 , bh9 ) ) | 0 ;
var w16 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w16 >>> 26 ) ) | 0 ;
w16 &= 0x3ffffff ;
/* k = 17 */
lo = Math . imul ( al9 , bl8 ) ;
mid = Math . imul ( al9 , bh8 ) ;
mid = ( mid + Math . imul ( ah9 , bl8 ) ) | 0 ;
hi = Math . imul ( ah9 , bh8 ) ;
lo = ( lo + Math . imul ( al8 , bl9 ) ) | 0 ;
mid = ( mid + Math . imul ( al8 , bh9 ) ) | 0 ;
mid = ( mid + Math . imul ( ah8 , bl9 ) ) | 0 ;
hi = ( hi + Math . imul ( ah8 , bh9 ) ) | 0 ;
var w17 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w17 >>> 26 ) ) | 0 ;
w17 &= 0x3ffffff ;
/* k = 18 */
lo = Math . imul ( al9 , bl9 ) ;
mid = Math . imul ( al9 , bh9 ) ;
mid = ( mid + Math . imul ( ah9 , bl9 ) ) | 0 ;
hi = Math . imul ( ah9 , bh9 ) ;
var w18 = ( ( ( c + lo ) | 0 ) + ( ( mid & 0x1fff ) << 13 ) ) | 0 ;
c = ( ( ( hi + ( mid >>> 13 ) ) | 0 ) + ( w18 >>> 26 ) ) | 0 ;
w18 &= 0x3ffffff ;
o [ 0 ] = w0 ;
o [ 1 ] = w1 ;
o [ 2 ] = w2 ;
o [ 3 ] = w3 ;
o [ 4 ] = w4 ;
o [ 5 ] = w5 ;
o [ 6 ] = w6 ;
o [ 7 ] = w7 ;
o [ 8 ] = w8 ;
o [ 9 ] = w9 ;
o [ 10 ] = w10 ;
o [ 11 ] = w11 ;
o [ 12 ] = w12 ;
o [ 13 ] = w13 ;
o [ 14 ] = w14 ;
o [ 15 ] = w15 ;
o [ 16 ] = w16 ;
o [ 17 ] = w17 ;
o [ 18 ] = w18 ;
if ( c !== 0 ) {
o [ 19 ] = c ;
out . length ++ ;
}
2017-04-05 23:53:29 +03:00
return out ;
} ;
// Polyfill comb
if ( ! Math . imul ) {
comb10MulTo = smallMulTo ;
}
function bigMulTo ( self , num , out ) {
out . negative = num . negative ^ self . negative ;
out . length = self . length + num . length ;
var carry = 0 ;
var hncarry = 0 ;
for ( var k = 0 ; k < out . length - 1 ; k ++ ) {
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
// note that ncarry could be >= 0x3ffffff
var ncarry = hncarry ;
hncarry = 0 ;
var rword = carry & 0x3ffffff ;
var maxJ = Math . min ( k , num . length - 1 ) ;
for ( var j = Math . max ( 0 , k - self . length + 1 ) ; j <= maxJ ; j ++ ) {
var i = k - j ;
var a = self . words [ i ] | 0 ;
var b = num . words [ j ] | 0 ;
var r = a * b ;
var lo = r & 0x3ffffff ;
ncarry = ( ncarry + ( ( r / 0x4000000 ) | 0 ) ) | 0 ;
lo = ( lo + rword ) | 0 ;
rword = lo & 0x3ffffff ;
ncarry = ( ncarry + ( lo >>> 26 ) ) | 0 ;
hncarry += ncarry >>> 26 ;
ncarry &= 0x3ffffff ;
}
out . words [ k ] = rword ;
carry = ncarry ;
ncarry = hncarry ;
}
if ( carry !== 0 ) {
out . words [ k ] = carry ;
} else {
out . length -- ;
}
return out . strip ( ) ;
}
function jumboMulTo ( self , num , out ) {
var fftm = new FFTM ( ) ;
return fftm . mulp ( self , num , out ) ;
}
BN . prototype . mulTo = function mulTo ( num , out ) {
var res ;
var len = this . length + num . length ;
if ( this . length === 10 && num . length === 10 ) {
res = comb10MulTo ( this , num , out ) ;
} else if ( len < 63 ) {
res = smallMulTo ( this , num , out ) ;
} else if ( len < 1024 ) {
res = bigMulTo ( this , num , out ) ;
} else {
res = jumboMulTo ( this , num , out ) ;
}
return res ;
} ;
// Cooley-Tukey algorithm for FFT
// slightly revisited to rely on looping instead of recursion
function FFTM ( x , y ) {
this . x = x ;
this . y = y ;
}
FFTM . prototype . makeRBT = function makeRBT ( N ) {
var t = new Array ( N ) ;
var l = BN . prototype . _countBits ( N ) - 1 ;
for ( var i = 0 ; i < N ; i ++ ) {
t [ i ] = this . revBin ( i , l , N ) ;
}
return t ;
} ;
// Returns binary-reversed representation of `x`
FFTM . prototype . revBin = function revBin ( x , l , N ) {
if ( x === 0 || x === N - 1 ) return x ;
var rb = 0 ;
for ( var i = 0 ; i < l ; i ++ ) {
rb |= ( x & 1 ) << ( l - i - 1 ) ;
x >>= 1 ;
}
return rb ;
} ;
// Performs "tweedling" phase, therefore 'emulating'
// behaviour of the recursive algorithm
FFTM . prototype . permute = function permute ( rbt , rws , iws , rtws , itws , N ) {
for ( var i = 0 ; i < N ; i ++ ) {
rtws [ i ] = rws [ rbt [ i ] ] ;
itws [ i ] = iws [ rbt [ i ] ] ;
}
} ;
FFTM . prototype . transform = function transform ( rws , iws , rtws , itws , N , rbt ) {
this . permute ( rbt , rws , iws , rtws , itws , N ) ;
for ( var s = 1 ; s < N ; s <<= 1 ) {
var l = s << 1 ;
var rtwdf = Math . cos ( 2 * Math . PI / l ) ;
var itwdf = Math . sin ( 2 * Math . PI / l ) ;
for ( var p = 0 ; p < N ; p += l ) {
var rtwdf _ = rtwdf ;
var itwdf _ = itwdf ;
for ( var j = 0 ; j < s ; j ++ ) {
var re = rtws [ p + j ] ;
var ie = itws [ p + j ] ;
var ro = rtws [ p + j + s ] ;
var io = itws [ p + j + s ] ;
var rx = rtwdf _ * ro - itwdf _ * io ;
io = rtwdf _ * io + itwdf _ * ro ;
ro = rx ;
rtws [ p + j ] = re + ro ;
itws [ p + j ] = ie + io ;
rtws [ p + j + s ] = re - ro ;
itws [ p + j + s ] = ie - io ;
/* jshint maxdepth : false */
if ( j !== l ) {
rx = rtwdf * rtwdf _ - itwdf * itwdf _ ;
itwdf _ = rtwdf * itwdf _ + itwdf * rtwdf _ ;
rtwdf _ = rx ;
}
}
}
}
} ;
FFTM . prototype . guessLen13b = function guessLen13b ( n , m ) {
var N = Math . max ( m , n ) | 1 ;
var odd = N & 1 ;
var i = 0 ;
for ( N = N / 2 | 0 ; N ; N = N >>> 1 ) {
i ++ ;
}
return 1 << i + 1 + odd ;
} ;
FFTM . prototype . conjugate = function conjugate ( rws , iws , N ) {
if ( N <= 1 ) return ;
for ( var i = 0 ; i < N / 2 ; i ++ ) {
var t = rws [ i ] ;
rws [ i ] = rws [ N - i - 1 ] ;
rws [ N - i - 1 ] = t ;
t = iws [ i ] ;
iws [ i ] = - iws [ N - i - 1 ] ;
iws [ N - i - 1 ] = - t ;
}
} ;
FFTM . prototype . normalize13b = function normalize13b ( ws , N ) {
var carry = 0 ;
for ( var i = 0 ; i < N / 2 ; i ++ ) {
var w = Math . round ( ws [ 2 * i + 1 ] / N ) * 0x2000 +
Math . round ( ws [ 2 * i ] / N ) +
carry ;
ws [ i ] = w & 0x3ffffff ;
if ( w < 0x4000000 ) {
carry = 0 ;
} else {
carry = w / 0x4000000 | 0 ;
}
}
return ws ;
} ;
FFTM . prototype . convert13b = function convert13b ( ws , len , rws , N ) {
var carry = 0 ;
for ( var i = 0 ; i < len ; i ++ ) {
carry = carry + ( ws [ i ] | 0 ) ;
rws [ 2 * i ] = carry & 0x1fff ; carry = carry >>> 13 ;
rws [ 2 * i + 1 ] = carry & 0x1fff ; carry = carry >>> 13 ;
}
// Pad with zeroes
for ( i = 2 * len ; i < N ; ++ i ) {
rws [ i ] = 0 ;
}
assert ( carry === 0 ) ;
assert ( ( carry & ~ 0x1fff ) === 0 ) ;
} ;
FFTM . prototype . stub = function stub ( N ) {
var ph = new Array ( N ) ;
for ( var i = 0 ; i < N ; i ++ ) {
ph [ i ] = 0 ;
}
return ph ;
} ;
FFTM . prototype . mulp = function mulp ( x , y , out ) {
var N = 2 * this . guessLen13b ( x . length , y . length ) ;
var rbt = this . makeRBT ( N ) ;
var _ = this . stub ( N ) ;
var rws = new Array ( N ) ;
var rwst = new Array ( N ) ;
var iwst = new Array ( N ) ;
var nrws = new Array ( N ) ;
var nrwst = new Array ( N ) ;
var niwst = new Array ( N ) ;
var rmws = out . words ;
rmws . length = N ;
this . convert13b ( x . words , x . length , rws , N ) ;
this . convert13b ( y . words , y . length , nrws , N ) ;
this . transform ( rws , _ , rwst , iwst , N , rbt ) ;
this . transform ( nrws , _ , nrwst , niwst , N , rbt ) ;
for ( var i = 0 ; i < N ; i ++ ) {
var rx = rwst [ i ] * nrwst [ i ] - iwst [ i ] * niwst [ i ] ;
iwst [ i ] = rwst [ i ] * niwst [ i ] + iwst [ i ] * nrwst [ i ] ;
rwst [ i ] = rx ;
}
this . conjugate ( rwst , iwst , N ) ;
this . transform ( rwst , iwst , rmws , _ , N , rbt ) ;
this . conjugate ( rmws , _ , N ) ;
this . normalize13b ( rmws , N ) ;
out . negative = x . negative ^ y . negative ;
out . length = x . length + y . length ;
return out . strip ( ) ;
} ;
// Multiply `this` by `num`
BN . prototype . mul = function mul ( num ) {
var out = new BN ( null ) ;
out . words = new Array ( this . length + num . length ) ;
return this . mulTo ( num , out ) ;
} ;
// Multiply employing FFT
BN . prototype . mulf = function mulf ( num ) {
var out = new BN ( null ) ;
out . words = new Array ( this . length + num . length ) ;
return jumboMulTo ( this , num , out ) ;
} ;
// In-place Multiplication
BN . prototype . imul = function imul ( num ) {
return this . clone ( ) . mulTo ( num , this ) ;
} ;
BN . prototype . imuln = function imuln ( num ) {
assert ( typeof num === 'number' ) ;
assert ( num < 0x4000000 ) ;
// Carry
var carry = 0 ;
for ( var i = 0 ; i < this . length ; i ++ ) {
var w = ( this . words [ i ] | 0 ) * num ;
var lo = ( w & 0x3ffffff ) + ( carry & 0x3ffffff ) ;
carry >>= 26 ;
carry += ( w / 0x4000000 ) | 0 ;
// NOTE: lo is 27bit maximum
carry += lo >>> 26 ;
this . words [ i ] = lo & 0x3ffffff ;
}
if ( carry !== 0 ) {
this . words [ i ] = carry ;
this . length ++ ;
}
return this ;
} ;
BN . prototype . muln = function muln ( num ) {
return this . clone ( ) . imuln ( num ) ;
} ;
// `this` * `this`
BN . prototype . sqr = function sqr ( ) {
return this . mul ( this ) ;
} ;
// `this` * `this` in-place
BN . prototype . isqr = function isqr ( ) {
return this . imul ( this . clone ( ) ) ;
} ;
// Math.pow(`this`, `num`)
BN . prototype . pow = function pow ( num ) {
var w = toBitArray ( num ) ;
if ( w . length === 0 ) return new BN ( 1 ) ;
// Skip leading zeroes
var res = this ;
for ( var i = 0 ; i < w . length ; i ++ , res = res . sqr ( ) ) {
if ( w [ i ] !== 0 ) break ;
}
if ( ++ i < w . length ) {
for ( var q = res . sqr ( ) ; i < w . length ; i ++ , q = q . sqr ( ) ) {
if ( w [ i ] === 0 ) continue ;
res = res . mul ( q ) ;
}
}
return res ;
} ;
// Shift-left in-place
BN . prototype . iushln = function iushln ( bits ) {
assert ( typeof bits === 'number' && bits >= 0 ) ;
var r = bits % 26 ;
var s = ( bits - r ) / 26 ;
var carryMask = ( 0x3ffffff >>> ( 26 - r ) ) << ( 26 - r ) ;
var i ;
if ( r !== 0 ) {
var carry = 0 ;
for ( i = 0 ; i < this . length ; i ++ ) {
var newCarry = this . words [ i ] & carryMask ;
var c = ( ( this . words [ i ] | 0 ) - newCarry ) << r ;
this . words [ i ] = c | carry ;
carry = newCarry >>> ( 26 - r ) ;
}
if ( carry ) {
this . words [ i ] = carry ;
this . length ++ ;
}
}
if ( s !== 0 ) {
for ( i = this . length - 1 ; i >= 0 ; i -- ) {
this . words [ i + s ] = this . words [ i ] ;
}
for ( i = 0 ; i < s ; i ++ ) {
this . words [ i ] = 0 ;
}
this . length += s ;
}
return this . strip ( ) ;
} ;
BN . prototype . ishln = function ishln ( bits ) {
// TODO(indutny): implement me
assert ( this . negative === 0 ) ;
return this . iushln ( bits ) ;
} ;
// Shift-right in-place
// NOTE: `hint` is a lowest bit before trailing zeroes
// NOTE: if `extended` is present - it will be filled with destroyed bits
BN . prototype . iushrn = function iushrn ( bits , hint , extended ) {
assert ( typeof bits === 'number' && bits >= 0 ) ;
var h ;
if ( hint ) {
h = ( hint - ( hint % 26 ) ) / 26 ;
} else {
h = 0 ;
}
var r = bits % 26 ;
var s = Math . min ( ( bits - r ) / 26 , this . length ) ;
var mask = 0x3ffffff ^ ( ( 0x3ffffff >>> r ) << r ) ;
var maskedWords = extended ;
h -= s ;
h = Math . max ( 0 , h ) ;
// Extended mode, copy masked part
if ( maskedWords ) {
for ( var i = 0 ; i < s ; i ++ ) {
maskedWords . words [ i ] = this . words [ i ] ;
}
maskedWords . length = s ;
}
if ( s === 0 ) {
// No-op, we should not move anything at all
} else if ( this . length > s ) {
this . length -= s ;
for ( i = 0 ; i < this . length ; i ++ ) {
this . words [ i ] = this . words [ i + s ] ;
}
} else {
this . words [ 0 ] = 0 ;
this . length = 1 ;
}
var carry = 0 ;
for ( i = this . length - 1 ; i >= 0 && ( carry !== 0 || i >= h ) ; i -- ) {
var word = this . words [ i ] | 0 ;
this . words [ i ] = ( carry << ( 26 - r ) ) | ( word >>> r ) ;
carry = word & mask ;
}
// Push carried bits as a mask
if ( maskedWords && carry !== 0 ) {
maskedWords . words [ maskedWords . length ++ ] = carry ;
}
if ( this . length === 0 ) {
this . words [ 0 ] = 0 ;
this . length = 1 ;
}
return this . strip ( ) ;
} ;
BN . prototype . ishrn = function ishrn ( bits , hint , extended ) {
// TODO(indutny): implement me
assert ( this . negative === 0 ) ;
return this . iushrn ( bits , hint , extended ) ;
} ;
// Shift-left
BN . prototype . shln = function shln ( bits ) {
return this . clone ( ) . ishln ( bits ) ;
} ;
BN . prototype . ushln = function ushln ( bits ) {
return this . clone ( ) . iushln ( bits ) ;
} ;
// Shift-right
BN . prototype . shrn = function shrn ( bits ) {
return this . clone ( ) . ishrn ( bits ) ;
} ;
BN . prototype . ushrn = function ushrn ( bits ) {
return this . clone ( ) . iushrn ( bits ) ;
} ;
// Test if n bit is set
BN . prototype . testn = function testn ( bit ) {
assert ( typeof bit === 'number' && bit >= 0 ) ;
var r = bit % 26 ;
var s = ( bit - r ) / 26 ;
var q = 1 << r ;
// Fast case: bit is much higher than all existing words
if ( this . length <= s ) return false ;
// Check bit and return
var w = this . words [ s ] ;
return ! ! ( w & q ) ;
} ;
// Return only lowers bits of number (in-place)
BN . prototype . imaskn = function imaskn ( bits ) {
assert ( typeof bits === 'number' && bits >= 0 ) ;
var r = bits % 26 ;
var s = ( bits - r ) / 26 ;
assert ( this . negative === 0 , 'imaskn works only with positive numbers' ) ;
if ( this . length <= s ) {
return this ;
}
if ( r !== 0 ) {
s ++ ;
}
this . length = Math . min ( s , this . length ) ;
if ( r !== 0 ) {
var mask = 0x3ffffff ^ ( ( 0x3ffffff >>> r ) << r ) ;
this . words [ this . length - 1 ] &= mask ;
}
return this . strip ( ) ;
} ;
// Return only lowers bits of number
BN . prototype . maskn = function maskn ( bits ) {
return this . clone ( ) . imaskn ( bits ) ;
} ;
// Add plain number `num` to `this`
BN . prototype . iaddn = function iaddn ( num ) {
assert ( typeof num === 'number' ) ;
assert ( num < 0x4000000 ) ;
if ( num < 0 ) return this . isubn ( - num ) ;
// Possible sign change
if ( this . negative !== 0 ) {
if ( this . length === 1 && ( this . words [ 0 ] | 0 ) < num ) {
this . words [ 0 ] = num - ( this . words [ 0 ] | 0 ) ;
this . negative = 0 ;
return this ;
}
this . negative = 0 ;
this . isubn ( num ) ;
this . negative = 1 ;
return this ;
}
// Add without checks
return this . _iaddn ( num ) ;
} ;
BN . prototype . _iaddn = function _iaddn ( num ) {
this . words [ 0 ] += num ;
// Carry
for ( var i = 0 ; i < this . length && this . words [ i ] >= 0x4000000 ; i ++ ) {
this . words [ i ] -= 0x4000000 ;
if ( i === this . length - 1 ) {
this . words [ i + 1 ] = 1 ;
} else {
this . words [ i + 1 ] ++ ;
}
}
this . length = Math . max ( this . length , i + 1 ) ;
return this ;
} ;
// Subtract plain number `num` from `this`
BN . prototype . isubn = function isubn ( num ) {
assert ( typeof num === 'number' ) ;
assert ( num < 0x4000000 ) ;
if ( num < 0 ) return this . iaddn ( - num ) ;
if ( this . negative !== 0 ) {
this . negative = 0 ;
this . iaddn ( num ) ;
this . negative = 1 ;
return this ;
}
this . words [ 0 ] -= num ;
if ( this . length === 1 && this . words [ 0 ] < 0 ) {
this . words [ 0 ] = - this . words [ 0 ] ;
this . negative = 1 ;
} else {
// Carry
for ( var i = 0 ; i < this . length && this . words [ i ] < 0 ; i ++ ) {
this . words [ i ] += 0x4000000 ;
this . words [ i + 1 ] -= 1 ;
}
}
return this . strip ( ) ;
} ;
BN . prototype . addn = function addn ( num ) {
return this . clone ( ) . iaddn ( num ) ;
} ;
BN . prototype . subn = function subn ( num ) {
return this . clone ( ) . isubn ( num ) ;
} ;
BN . prototype . iabs = function iabs ( ) {
this . negative = 0 ;
return this ;
} ;
BN . prototype . abs = function abs ( ) {
return this . clone ( ) . iabs ( ) ;
} ;
BN . prototype . _ishlnsubmul = function _ishlnsubmul ( num , mul , shift ) {
var len = num . length + shift ;
var i ;
this . _expand ( len ) ;
var w ;
var carry = 0 ;
for ( i = 0 ; i < num . length ; i ++ ) {
w = ( this . words [ i + shift ] | 0 ) + carry ;
var right = ( num . words [ i ] | 0 ) * mul ;
w -= right & 0x3ffffff ;
carry = ( w >> 26 ) - ( ( right / 0x4000000 ) | 0 ) ;
this . words [ i + shift ] = w & 0x3ffffff ;
}
for ( ; i < this . length - shift ; i ++ ) {
w = ( this . words [ i + shift ] | 0 ) + carry ;
carry = w >> 26 ;
this . words [ i + shift ] = w & 0x3ffffff ;
}
if ( carry === 0 ) return this . strip ( ) ;
// Subtraction overflow
assert ( carry === - 1 ) ;
carry = 0 ;
for ( i = 0 ; i < this . length ; i ++ ) {
w = - ( this . words [ i ] | 0 ) + carry ;
carry = w >> 26 ;
this . words [ i ] = w & 0x3ffffff ;
}
this . negative = 1 ;
return this . strip ( ) ;
} ;
BN . prototype . _wordDiv = function _wordDiv ( num , mode ) {
var shift = this . length - num . length ;
var a = this . clone ( ) ;
var b = num ;
// Normalize
var bhi = b . words [ b . length - 1 ] | 0 ;
var bhiBits = this . _countBits ( bhi ) ;
shift = 26 - bhiBits ;
if ( shift !== 0 ) {
b = b . ushln ( shift ) ;
a . iushln ( shift ) ;
bhi = b . words [ b . length - 1 ] | 0 ;
}
// Initialize quotient
var m = a . length - b . length ;
var q ;
if ( mode !== 'mod' ) {
q = new BN ( null ) ;
q . length = m + 1 ;
q . words = new Array ( q . length ) ;
for ( var i = 0 ; i < q . length ; i ++ ) {
q . words [ i ] = 0 ;
}
}
var diff = a . clone ( ) . _ishlnsubmul ( b , 1 , m ) ;
if ( diff . negative === 0 ) {
a = diff ;
if ( q ) {
q . words [ m ] = 1 ;
}
}
for ( var j = m - 1 ; j >= 0 ; j -- ) {
var qj = ( a . words [ b . length + j ] | 0 ) * 0x4000000 +
( a . words [ b . length + j - 1 ] | 0 ) ;
// NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
// (0x7ffffff)
qj = Math . min ( ( qj / bhi ) | 0 , 0x3ffffff ) ;
a . _ishlnsubmul ( b , qj , j ) ;
while ( a . negative !== 0 ) {
qj -- ;
a . negative = 0 ;
a . _ishlnsubmul ( b , 1 , j ) ;
if ( ! a . isZero ( ) ) {
a . negative ^= 1 ;
}
}
if ( q ) {
q . words [ j ] = qj ;
}
}
if ( q ) {
q . strip ( ) ;
}
a . strip ( ) ;
// Denormalize
if ( mode !== 'div' && shift !== 0 ) {
a . iushrn ( shift ) ;
}
return {
div : q || null ,
mod : a
} ;
} ;
// NOTE: 1) `mode` can be set to `mod` to request mod only,
// to `div` to request div only, or be absent to
// request both div & mod
// 2) `positive` is true if unsigned mod is requested
BN . prototype . divmod = function divmod ( num , mode , positive ) {
assert ( ! num . isZero ( ) ) ;
if ( this . isZero ( ) ) {
return {
div : new BN ( 0 ) ,
mod : new BN ( 0 )
} ;
}
var div , mod , res ;
if ( this . negative !== 0 && num . negative === 0 ) {
res = this . neg ( ) . divmod ( num , mode ) ;
if ( mode !== 'mod' ) {
div = res . div . neg ( ) ;
}
if ( mode !== 'div' ) {
mod = res . mod . neg ( ) ;
if ( positive && mod . negative !== 0 ) {
mod . iadd ( num ) ;
}
}
return {
div : div ,
mod : mod
} ;
}
if ( this . negative === 0 && num . negative !== 0 ) {
res = this . divmod ( num . neg ( ) , mode ) ;
if ( mode !== 'mod' ) {
div = res . div . neg ( ) ;
}
return {
div : div ,
mod : res . mod
} ;
}
if ( ( this . negative & num . negative ) !== 0 ) {
res = this . neg ( ) . divmod ( num . neg ( ) , mode ) ;
if ( mode !== 'div' ) {
mod = res . mod . neg ( ) ;
if ( positive && mod . negative !== 0 ) {
mod . isub ( num ) ;
}
}
return {
div : res . div ,
mod : mod
} ;
}
// Both numbers are positive at this point
// Strip both numbers to approximate shift value
if ( num . length > this . length || this . cmp ( num ) < 0 ) {
return {
div : new BN ( 0 ) ,
mod : this
} ;
}
// Very short reduction
if ( num . length === 1 ) {
if ( mode === 'div' ) {
return {
div : this . divn ( num . words [ 0 ] ) ,
mod : null
} ;
}
if ( mode === 'mod' ) {
return {
div : null ,
mod : new BN ( this . modn ( num . words [ 0 ] ) )
} ;
}
return {
div : this . divn ( num . words [ 0 ] ) ,
mod : new BN ( this . modn ( num . words [ 0 ] ) )
} ;
}
return this . _wordDiv ( num , mode ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
// Find `this` / `num`
BN . prototype . div = function div ( num ) {
return this . divmod ( num , 'div' , false ) . div ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Find `this` % `num`
BN . prototype . mod = function mod ( num ) {
return this . divmod ( num , 'mod' , false ) . mod ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . umod = function umod ( num ) {
return this . divmod ( num , 'mod' , true ) . mod ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Find Round(`this` / `num`)
BN . prototype . divRound = function divRound ( num ) {
var dm = this . divmod ( num ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Fast case - exact division
if ( dm . mod . isZero ( ) ) return dm . div ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var mod = dm . div . negative !== 0 ? dm . mod . isub ( num ) : dm . mod ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var half = num . ushrn ( 1 ) ;
var r2 = num . andln ( 1 ) ;
var cmp = mod . cmp ( half ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Round down
if ( cmp < 0 || r2 === 1 && cmp === 0 ) return dm . div ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Round up
return dm . div . negative !== 0 ? dm . div . isubn ( 1 ) : dm . div . iaddn ( 1 ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . modn = function modn ( num ) {
assert ( num <= 0x3ffffff ) ;
var p = ( 1 << 26 ) % num ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var acc = 0 ;
for ( var i = this . length - 1 ; i >= 0 ; i -- ) {
acc = ( p * acc + ( this . words [ i ] | 0 ) ) % num ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return acc ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
// In-place division by number
BN . prototype . idivn = function idivn ( num ) {
assert ( num <= 0x3ffffff ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var carry = 0 ;
for ( var i = this . length - 1 ; i >= 0 ; i -- ) {
var w = ( this . words [ i ] | 0 ) + carry * 0x4000000 ;
this . words [ i ] = ( w / num ) | 0 ;
carry = w % num ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return this . strip ( ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . divn = function divn ( num ) {
return this . clone ( ) . idivn ( num ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . egcd = function egcd ( p ) {
assert ( p . negative === 0 ) ;
assert ( ! p . isZero ( ) ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var x = this ;
var y = p . clone ( ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
if ( x . negative !== 0 ) {
x = x . umod ( p ) ;
} else {
x = x . clone ( ) ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// A * x + B * y = x
var A = new BN ( 1 ) ;
var B = new BN ( 0 ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// C * x + D * y = y
var C = new BN ( 0 ) ;
var D = new BN ( 1 ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var g = 0 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
while ( x . isEven ( ) && y . isEven ( ) ) {
x . iushrn ( 1 ) ;
y . iushrn ( 1 ) ;
++ g ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var yp = y . clone ( ) ;
var xp = x . clone ( ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
while ( ! x . isZero ( ) ) {
for ( var i = 0 , im = 1 ; ( x . words [ 0 ] & im ) === 0 && i < 26 ; ++ i , im <<= 1 ) ;
if ( i > 0 ) {
x . iushrn ( i ) ;
while ( i -- > 0 ) {
if ( A . isOdd ( ) || B . isOdd ( ) ) {
A . iadd ( yp ) ;
B . isub ( xp ) ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
A . iushrn ( 1 ) ;
B . iushrn ( 1 ) ;
}
}
for ( var j = 0 , jm = 1 ; ( y . words [ 0 ] & jm ) === 0 && j < 26 ; ++ j , jm <<= 1 ) ;
if ( j > 0 ) {
y . iushrn ( j ) ;
while ( j -- > 0 ) {
if ( C . isOdd ( ) || D . isOdd ( ) ) {
C . iadd ( yp ) ;
D . isub ( xp ) ;
}
C . iushrn ( 1 ) ;
D . iushrn ( 1 ) ;
}
}
if ( x . cmp ( y ) >= 0 ) {
x . isub ( y ) ;
A . isub ( C ) ;
B . isub ( D ) ;
} else {
y . isub ( x ) ;
C . isub ( A ) ;
D . isub ( B ) ;
}
}
return {
a : C ,
b : D ,
gcd : y . iushln ( g )
} ;
} ;
// This is reduced incarnation of the binary EEA
// above, designated to invert members of the
// _prime_ fields F(p) at a maximal speed
BN . prototype . _invmp = function _invmp ( p ) {
assert ( p . negative === 0 ) ;
assert ( ! p . isZero ( ) ) ;
var a = this ;
var b = p . clone ( ) ;
if ( a . negative !== 0 ) {
a = a . umod ( p ) ;
} else {
a = a . clone ( ) ;
}
var x1 = new BN ( 1 ) ;
var x2 = new BN ( 0 ) ;
var delta = b . clone ( ) ;
while ( a . cmpn ( 1 ) > 0 && b . cmpn ( 1 ) > 0 ) {
for ( var i = 0 , im = 1 ; ( a . words [ 0 ] & im ) === 0 && i < 26 ; ++ i , im <<= 1 ) ;
if ( i > 0 ) {
a . iushrn ( i ) ;
while ( i -- > 0 ) {
if ( x1 . isOdd ( ) ) {
x1 . iadd ( delta ) ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
x1 . iushrn ( 1 ) ;
}
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
for ( var j = 0 , jm = 1 ; ( b . words [ 0 ] & jm ) === 0 && j < 26 ; ++ j , jm <<= 1 ) ;
if ( j > 0 ) {
b . iushrn ( j ) ;
while ( j -- > 0 ) {
if ( x2 . isOdd ( ) ) {
x2 . iadd ( delta ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
x2 . iushrn ( 1 ) ;
2017-02-27 08:09:47 +03:00
}
}
2017-04-05 23:53:29 +03:00
if ( a . cmp ( b ) >= 0 ) {
a . isub ( b ) ;
x1 . isub ( x2 ) ;
} else {
b . isub ( a ) ;
x2 . isub ( x1 ) ;
}
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
var res ;
if ( a . cmpn ( 1 ) === 0 ) {
res = x1 ;
} else {
res = x2 ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
if ( res . cmpn ( 0 ) < 0 ) {
res . iadd ( p ) ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
return res ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . gcd = function gcd ( num ) {
if ( this . isZero ( ) ) return num . abs ( ) ;
if ( num . isZero ( ) ) return this . abs ( ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var a = this . clone ( ) ;
var b = num . clone ( ) ;
a . negative = 0 ;
b . negative = 0 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Remove common factor of two
for ( var shift = 0 ; a . isEven ( ) && b . isEven ( ) ; shift ++ ) {
a . iushrn ( 1 ) ;
b . iushrn ( 1 ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
do {
while ( a . isEven ( ) ) {
a . iushrn ( 1 ) ;
}
while ( b . isEven ( ) ) {
b . iushrn ( 1 ) ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var r = a . cmp ( b ) ;
if ( r < 0 ) {
// Swap `a` and `b` to make `a` always bigger than `b`
var t = a ;
a = b ;
b = t ;
} else if ( r === 0 || b . cmpn ( 1 ) === 0 ) {
break ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
a . isub ( b ) ;
} while ( true ) ;
return b . iushln ( shift ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
// Invert number in the field F(num)
BN . prototype . invm = function invm ( num ) {
return this . egcd ( num ) . a . umod ( num ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . isEven = function isEven ( ) {
return ( this . words [ 0 ] & 1 ) === 0 ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . isOdd = function isOdd ( ) {
return ( this . words [ 0 ] & 1 ) === 1 ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// And first word and num
BN . prototype . andln = function andln ( num ) {
return this . words [ 0 ] & num ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
// Increment at the bit position in-line
BN . prototype . bincn = function bincn ( bit ) {
assert ( typeof bit === 'number' ) ;
var r = bit % 26 ;
var s = ( bit - r ) / 26 ;
var q = 1 << r ;
// Fast case: bit is much higher than all existing words
if ( this . length <= s ) {
this . _expand ( s + 1 ) ;
this . words [ s ] |= q ;
return this ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
// Add bit and propagate, if needed
var carry = q ;
for ( var i = s ; carry !== 0 && i < this . length ; i ++ ) {
var w = this . words [ i ] | 0 ;
w += carry ;
carry = w >>> 26 ;
w &= 0x3ffffff ;
this . words [ i ] = w ;
}
if ( carry !== 0 ) {
this . words [ i ] = carry ;
this . length ++ ;
}
return this ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . isZero = function isZero ( ) {
return this . length === 1 && this . words [ 0 ] === 0 ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . cmpn = function cmpn ( num ) {
var negative = num < 0 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
if ( this . negative !== 0 && ! negative ) return - 1 ;
if ( this . negative === 0 && negative ) return 1 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
this . strip ( ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var res ;
if ( this . length > 1 ) {
res = 1 ;
} else {
if ( negative ) {
num = - num ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
assert ( num <= 0x3ffffff , 'Number is too big' ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var w = this . words [ 0 ] | 0 ;
res = w === num ? 0 : w < num ? - 1 : 1 ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
if ( this . negative !== 0 ) return - res | 0 ;
return res ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
// Compare two numbers and return:
// 1 - if `this` > `num`
// 0 - if `this` == `num`
// -1 - if `this` < `num`
BN . prototype . cmp = function cmp ( num ) {
if ( this . negative !== 0 && num . negative === 0 ) return - 1 ;
if ( this . negative === 0 && num . negative !== 0 ) return 1 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var res = this . ucmp ( num ) ;
if ( this . negative !== 0 ) return - res | 0 ;
return res ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
// Unsigned comparison
BN . prototype . ucmp = function ucmp ( num ) {
// At this point both numbers have the same sign
if ( this . length > num . length ) return 1 ;
if ( this . length < num . length ) return - 1 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var res = 0 ;
for ( var i = this . length - 1 ; i >= 0 ; i -- ) {
var a = this . words [ i ] | 0 ;
var b = num . words [ i ] | 0 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
if ( a === b ) continue ;
if ( a < b ) {
res = - 1 ;
} else if ( a > b ) {
res = 1 ;
}
break ;
}
return res ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . gtn = function gtn ( num ) {
return this . cmpn ( num ) === 1 ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . gt = function gt ( num ) {
return this . cmp ( num ) === 1 ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . gten = function gten ( num ) {
return this . cmpn ( num ) >= 0 ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . gte = function gte ( num ) {
return this . cmp ( num ) >= 0 ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . ltn = function ltn ( num ) {
return this . cmpn ( num ) === - 1 ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . lt = function lt ( num ) {
return this . cmp ( num ) === - 1 ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . lten = function lten ( num ) {
return this . cmpn ( num ) <= 0 ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . lte = function lte ( num ) {
return this . cmp ( num ) <= 0 ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . eqn = function eqn ( num ) {
return this . cmpn ( num ) === 0 ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . eq = function eq ( num ) {
return this . cmp ( num ) === 0 ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
//
// A reduce context, could be using montgomery or something better, depending
// on the `m` itself.
//
BN . red = function red ( num ) {
return new Red ( num ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . toRed = function toRed ( ctx ) {
assert ( ! this . red , 'Already a number in reduction context' ) ;
assert ( this . negative === 0 , 'red works only with positives' ) ;
return ctx . convertTo ( this ) . _forceRed ( ctx ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . fromRed = function fromRed ( ) {
assert ( this . red , 'fromRed works only with numbers in reduction context' ) ;
return this . red . convertFrom ( this ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . _forceRed = function _forceRed ( ctx ) {
this . red = ctx ;
return this ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . forceRed = function forceRed ( ctx ) {
assert ( ! this . red , 'Already a number in reduction context' ) ;
return this . _forceRed ( ctx ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . redAdd = function redAdd ( num ) {
assert ( this . red , 'redAdd works only with red numbers' ) ;
return this . red . add ( this , num ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . redIAdd = function redIAdd ( num ) {
assert ( this . red , 'redIAdd works only with red numbers' ) ;
return this . red . iadd ( this , num ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . redSub = function redSub ( num ) {
assert ( this . red , 'redSub works only with red numbers' ) ;
return this . red . sub ( this , num ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . redISub = function redISub ( num ) {
assert ( this . red , 'redISub works only with red numbers' ) ;
return this . red . isub ( this , num ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . redShl = function redShl ( num ) {
assert ( this . red , 'redShl works only with red numbers' ) ;
return this . red . shl ( this , num ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . redMul = function redMul ( num ) {
assert ( this . red , 'redMul works only with red numbers' ) ;
this . red . _verify2 ( this , num ) ;
return this . red . mul ( this , num ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . redIMul = function redIMul ( num ) {
assert ( this . red , 'redMul works only with red numbers' ) ;
this . red . _verify2 ( this , num ) ;
return this . red . imul ( this , num ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . prototype . redSqr = function redSqr ( ) {
assert ( this . red , 'redSqr works only with red numbers' ) ;
this . red . _verify1 ( this ) ;
return this . red . sqr ( this ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . redISqr = function redISqr ( ) {
assert ( this . red , 'redISqr works only with red numbers' ) ;
this . red . _verify1 ( this ) ;
return this . red . isqr ( this ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
// Square root over p
BN . prototype . redSqrt = function redSqrt ( ) {
assert ( this . red , 'redSqrt works only with red numbers' ) ;
this . red . _verify1 ( this ) ;
return this . red . sqrt ( this ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . redInvm = function redInvm ( ) {
assert ( this . red , 'redInvm works only with red numbers' ) ;
this . red . _verify1 ( this ) ;
return this . red . invm ( this ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
// Return negative clone of `this` % `red modulo`
BN . prototype . redNeg = function redNeg ( ) {
assert ( this . red , 'redNeg works only with red numbers' ) ;
this . red . _verify1 ( this ) ;
return this . red . neg ( this ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
BN . prototype . redPow = function redPow ( num ) {
assert ( this . red && ! num . red , 'redPow(normalNum)' ) ;
this . red . _verify1 ( this ) ;
return this . red . pow ( this , num ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
// Prime numbers with efficient reduction
var primes = {
k256 : null ,
p224 : null ,
p192 : null ,
p25519 : null
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Pseudo-Mersenne prime
function MPrime ( name , p ) {
// P = 2 ^ N - K
this . name = name ;
this . p = new BN ( p , 16 ) ;
this . n = this . p . bitLength ( ) ;
this . k = new BN ( 1 ) . iushln ( this . n ) . isub ( this . p ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
this . tmp = this . _tmp ( ) ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
MPrime . prototype . _tmp = function _tmp ( ) {
var tmp = new BN ( null ) ;
tmp . words = new Array ( Math . ceil ( this . n / 13 ) ) ;
return tmp ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
MPrime . prototype . ireduce = function ireduce ( num ) {
// Assumes that `num` is less than `P^2`
// num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
var r = num ;
var rlen ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
do {
this . split ( r , this . tmp ) ;
r = this . imulK ( r ) ;
r = r . iadd ( this . tmp ) ;
rlen = r . bitLength ( ) ;
} while ( rlen > this . n ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var cmp = rlen < this . n ? - 1 : r . ucmp ( this . p ) ;
if ( cmp === 0 ) {
r . words [ 0 ] = 0 ;
r . length = 1 ;
} else if ( cmp > 0 ) {
r . isub ( this . p ) ;
} else {
r . strip ( ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return r ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
MPrime . prototype . split = function split ( input , out ) {
input . iushrn ( this . n , 0 , out ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
MPrime . prototype . imulK = function imulK ( num ) {
return num . imul ( this . k ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
function K256 ( ) {
MPrime . call (
this ,
'k256' ,
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f' ) ;
}
inherits ( K256 , MPrime ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
K256 . prototype . split = function split ( input , output ) {
// 256 = 9 * 26 + 22
var mask = 0x3fffff ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var outLen = Math . min ( input . length , 9 ) ;
for ( var i = 0 ; i < outLen ; i ++ ) {
output . words [ i ] = input . words [ i ] ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
output . length = outLen ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
if ( input . length <= 9 ) {
input . words [ 0 ] = 0 ;
input . length = 1 ;
return ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Shift by 9 limbs
var prev = input . words [ 9 ] ;
output . words [ output . length ++ ] = prev & mask ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
for ( i = 10 ; i < input . length ; i ++ ) {
var next = input . words [ i ] | 0 ;
input . words [ i - 10 ] = ( ( next & mask ) << 4 ) | ( prev >>> 22 ) ;
prev = next ;
}
prev >>>= 22 ;
input . words [ i - 10 ] = prev ;
if ( prev === 0 && input . length > 10 ) {
input . length -= 10 ;
} else {
input . length -= 9 ;
2017-02-27 08:09:47 +03:00
}
} ;
2017-04-05 23:53:29 +03:00
K256 . prototype . imulK = function imulK ( num ) {
// K = 0x1000003d1 = [ 0x40, 0x3d1 ]
num . words [ num . length ] = 0 ;
num . words [ num . length + 1 ] = 0 ;
num . length += 2 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
var lo = 0 ;
for ( var i = 0 ; i < num . length ; i ++ ) {
var w = num . words [ i ] | 0 ;
lo += w * 0x3d1 ;
num . words [ i ] = lo & 0x3ffffff ;
lo = w * 0x40 + ( ( lo / 0x4000000 ) | 0 ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
// Fast length reduction
if ( num . words [ num . length - 1 ] === 0 ) {
num . length -- ;
if ( num . words [ num . length - 1 ] === 0 ) {
num . length -- ;
2017-02-27 08:09:47 +03:00
}
}
2017-04-05 23:53:29 +03:00
return num ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
function P224 ( ) {
MPrime . call (
this ,
'p224' ,
'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001' ) ;
}
inherits ( P224 , MPrime ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
function P192 ( ) {
MPrime . call (
this ,
'p192' ,
'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff' ) ;
}
inherits ( P192 , MPrime ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
function P25519 ( ) {
// 2 ^ 255 - 19
MPrime . call (
this ,
'25519' ,
'7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed' ) ;
}
inherits ( P25519 , MPrime ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
P25519 . prototype . imulK = function imulK ( num ) {
// K = 0x13
var carry = 0 ;
for ( var i = 0 ; i < num . length ; i ++ ) {
var hi = ( num . words [ i ] | 0 ) * 0x13 + carry ;
var lo = hi & 0x3ffffff ;
hi >>>= 26 ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
num . words [ i ] = lo ;
carry = hi ;
}
if ( carry !== 0 ) {
num . words [ num . length ++ ] = carry ;
}
return num ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
// Exported mostly for testing purposes, use plain name instead
BN . _prime = function prime ( name ) {
// Cached version of prime
if ( primes [ name ] ) return primes [ name ] ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var prime ;
if ( name === 'k256' ) {
prime = new K256 ( ) ;
} else if ( name === 'p224' ) {
prime = new P224 ( ) ;
} else if ( name === 'p192' ) {
prime = new P192 ( ) ;
} else if ( name === 'p25519' ) {
prime = new P25519 ( ) ;
} else {
throw new Error ( 'Unknown prime ' + name ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
primes [ name ] = prime ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
return prime ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
//
// Base reduction engine
//
function Red ( m ) {
if ( typeof m === 'string' ) {
var prime = BN . _prime ( m ) ;
this . m = prime . p ;
this . prime = prime ;
} else {
assert ( m . gtn ( 1 ) , 'modulus must be greater than 1' ) ;
this . m = m ;
this . prime = null ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
Red . prototype . _verify1 = function _verify1 ( a ) {
assert ( a . negative === 0 , 'red works only with positives' ) ;
assert ( a . red , 'red works only with red numbers' ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
Red . prototype . _verify2 = function _verify2 ( a , b ) {
assert ( ( a . negative | b . negative ) === 0 , 'red works only with positives' ) ;
assert ( a . red && a . red === b . red ,
'red works only with red numbers' ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
Red . prototype . imod = function imod ( a ) {
if ( this . prime ) return this . prime . ireduce ( a ) . _forceRed ( this ) ;
return a . umod ( this . m ) . _forceRed ( this ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
Red . prototype . neg = function neg ( a ) {
if ( a . isZero ( ) ) {
return a . clone ( ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return this . m . sub ( a ) . _forceRed ( this ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
Red . prototype . add = function add ( a , b ) {
this . _verify2 ( a , b ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var res = a . add ( b ) ;
if ( res . cmp ( this . m ) >= 0 ) {
res . isub ( this . m ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return res . _forceRed ( this ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
Red . prototype . iadd = function iadd ( a , b ) {
this . _verify2 ( a , b ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var res = a . iadd ( b ) ;
if ( res . cmp ( this . m ) >= 0 ) {
res . isub ( this . m ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return res ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
Red . prototype . sub = function sub ( a , b ) {
this . _verify2 ( a , b ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var res = a . sub ( b ) ;
if ( res . cmpn ( 0 ) < 0 ) {
res . iadd ( this . m ) ;
}
return res . _forceRed ( this ) ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
Red . prototype . isub = function isub ( a , b ) {
this . _verify2 ( a , b ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var res = a . isub ( b ) ;
if ( res . cmpn ( 0 ) < 0 ) {
res . iadd ( this . m ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return res ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
Red . prototype . shl = function shl ( a , num ) {
this . _verify1 ( a ) ;
return this . imod ( a . ushln ( num ) ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
Red . prototype . imul = function imul ( a , b ) {
this . _verify2 ( a , b ) ;
return this . imod ( a . imul ( b ) ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
Red . prototype . mul = function mul ( a , b ) {
this . _verify2 ( a , b ) ;
return this . imod ( a . mul ( b ) ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
Red . prototype . isqr = function isqr ( a ) {
return this . imul ( a , a . clone ( ) ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
Red . prototype . sqr = function sqr ( a ) {
return this . mul ( a , a ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
Red . prototype . sqrt = function sqrt ( a ) {
if ( a . isZero ( ) ) return a . clone ( ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var mod3 = this . m . andln ( 3 ) ;
assert ( mod3 % 2 === 1 ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Fast case
if ( mod3 === 3 ) {
var pow = this . m . add ( new BN ( 1 ) ) . iushrn ( 2 ) ;
return this . pow ( a , pow ) ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Tonelli-Shanks algorithm (Totally unoptimized and slow)
//
// Find Q and S, that Q * 2 ^ S = (P - 1)
var q = this . m . subn ( 1 ) ;
var s = 0 ;
while ( ! q . isZero ( ) && q . andln ( 1 ) === 0 ) {
s ++ ;
q . iushrn ( 1 ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
assert ( ! q . isZero ( ) ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var one = new BN ( 1 ) . toRed ( this ) ;
var nOne = one . redNeg ( ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
// Find quadratic non-residue
// NOTE: Max is such because of generalized Riemann hypothesis.
var lpow = this . m . subn ( 1 ) . iushrn ( 1 ) ;
var z = this . m . bitLength ( ) ;
z = new BN ( 2 * z * z ) . toRed ( this ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
while ( this . pow ( z , lpow ) . cmp ( nOne ) !== 0 ) {
z . redIAdd ( nOne ) ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var c = this . pow ( z , q ) ;
var r = this . pow ( a , q . addn ( 1 ) . iushrn ( 1 ) ) ;
var t = this . pow ( a , q ) ;
var m = s ;
while ( t . cmp ( one ) !== 0 ) {
var tmp = t ;
for ( var i = 0 ; tmp . cmp ( one ) !== 0 ; i ++ ) {
tmp = tmp . redSqr ( ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
assert ( i < m ) ;
var b = this . pow ( c , new BN ( 1 ) . iushln ( m - i - 1 ) ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
r = r . redMul ( b ) ;
c = b . redSqr ( ) ;
t = t . redMul ( c ) ;
m = i ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return r ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
Red . prototype . invm = function invm ( a ) {
var inv = a . _invmp ( this . m ) ;
if ( inv . negative !== 0 ) {
inv . negative = 0 ;
return this . imod ( inv ) . redNeg ( ) ;
} else {
return this . imod ( inv ) ;
}
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
Red . prototype . pow = function pow ( a , num ) {
2017-11-10 03:54:28 +03:00
if ( num . isZero ( ) ) return new BN ( 1 ) . toRed ( this ) ;
2017-04-05 23:53:29 +03:00
if ( num . cmpn ( 1 ) === 0 ) return a . clone ( ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var windowSize = 4 ;
var wnd = new Array ( 1 << windowSize ) ;
wnd [ 0 ] = new BN ( 1 ) . toRed ( this ) ;
wnd [ 1 ] = a ;
for ( var i = 2 ; i < wnd . length ; i ++ ) {
wnd [ i ] = this . mul ( wnd [ i - 1 ] , a ) ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var res = wnd [ 0 ] ;
var current = 0 ;
var currentLen = 0 ;
var start = num . bitLength ( ) % 26 ;
if ( start === 0 ) {
start = 26 ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
for ( i = num . length - 1 ; i >= 0 ; i -- ) {
var word = num . words [ i ] ;
for ( var j = start - 1 ; j >= 0 ; j -- ) {
var bit = ( word >> j ) & 1 ;
if ( res !== wnd [ 0 ] ) {
res = this . sqr ( res ) ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
if ( bit === 0 && current === 0 ) {
currentLen = 0 ;
continue ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
current <<= 1 ;
current |= bit ;
currentLen ++ ;
if ( currentLen !== windowSize && ( i !== 0 || j !== 0 ) ) continue ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
res = this . mul ( res , wnd [ current ] ) ;
currentLen = 0 ;
current = 0 ;
}
start = 26 ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return res ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
Red . prototype . convertTo = function convertTo ( num ) {
var r = num . umod ( this . m ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
return r === num ? r . clone ( ) : r ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
Red . prototype . convertFrom = function convertFrom ( num ) {
var res = num . clone ( ) ;
res . red = null ;
return res ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
//
// Montgomery method engine
//
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
BN . mont = function mont ( num ) {
return new Mont ( num ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
function Mont ( m ) {
Red . call ( this , m ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
this . shift = this . m . bitLength ( ) ;
if ( this . shift % 26 !== 0 ) {
this . shift += 26 - ( this . shift % 26 ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
this . r = new BN ( 1 ) . iushln ( this . shift ) ;
this . r2 = this . imod ( this . r . sqr ( ) ) ;
this . rinv = this . r . _invmp ( this . m ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
this . minv = this . rinv . mul ( this . r ) . isubn ( 1 ) . div ( this . m ) ;
this . minv = this . minv . umod ( this . r ) ;
this . minv = this . r . sub ( this . minv ) ;
}
inherits ( Mont , Red ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
Mont . prototype . convertTo = function convertTo ( num ) {
return this . imod ( num . ushln ( this . shift ) ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
Mont . prototype . convertFrom = function convertFrom ( num ) {
var r = this . imod ( num . mul ( this . rinv ) ) ;
r . red = null ;
return r ;
2017-02-27 08:09:47 +03:00
} ;
2017-04-05 23:53:29 +03:00
Mont . prototype . imul = function imul ( a , b ) {
if ( a . isZero ( ) || b . isZero ( ) ) {
a . words [ 0 ] = 0 ;
a . length = 1 ;
return a ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var t = a . imul ( b ) ;
var c = t . maskn ( this . shift ) . mul ( this . minv ) . imaskn ( this . shift ) . mul ( this . m ) ;
var u = t . isub ( c ) . iushrn ( this . shift ) ;
var res = u ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
if ( u . cmp ( this . m ) >= 0 ) {
res = u . isub ( this . m ) ;
} else if ( u . cmpn ( 0 ) < 0 ) {
res = u . iadd ( this . m ) ;
2017-02-27 08:09:47 +03:00
}
2017-04-05 23:53:29 +03:00
return res . _forceRed ( this ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
Mont . prototype . mul = function mul ( a , b ) {
if ( a . isZero ( ) || b . isZero ( ) ) return new BN ( 0 ) . _forceRed ( this ) ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
var t = a . mul ( b ) ;
var c = t . maskn ( this . shift ) . mul ( this . minv ) . imaskn ( this . shift ) . mul ( this . m ) ;
var u = t . isub ( c ) . iushrn ( this . shift ) ;
var res = u ;
if ( u . cmp ( this . m ) >= 0 ) {
res = u . isub ( this . m ) ;
} else if ( u . cmpn ( 0 ) < 0 ) {
res = u . iadd ( this . m ) ;
}
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
return res . _forceRed ( this ) ;
} ;
2017-02-27 08:09:47 +03:00
2017-04-05 23:53:29 +03:00
Mont . prototype . invm = function invm ( a ) {
// (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
var res = this . imod ( a . _invmp ( this . m ) . mul ( this . r2 ) ) ;
return res . _forceRed ( this ) ;
} ;
} ) ( typeof module === 'undefined' || module , this ) ;
2017-02-27 08:09:47 +03:00
2017-11-10 03:54:28 +03:00
} , { "buffer" : 5 } ] , 5 : [ function ( require , module , exports ) {
} , { } ] , 6 : [ function ( require , module , exports ) {
2017-02-27 08:09:47 +03:00
( function ( process , global ) {
/ * *
* [ js - sha3 ] { @ link https : //github.com/emn178/js-sha3}
*
* @ version 0.5 . 7
* @ author Chen , Yi - Cyuan [ emn178 @ gmail . com ]
* @ copyright Chen , Yi - Cyuan 2015 - 2016
* @ license MIT
* /
/*jslint bitwise: true */
( function ( ) {
'use strict' ;
var root = typeof window === 'object' ? window : { } ;
var NODE _JS = ! root . JS _SHA3 _NO _NODE _JS && typeof process === 'object' && process . versions && process . versions . node ;
if ( NODE _JS ) {
root = global ;
}
var COMMON _JS = ! root . JS _SHA3 _NO _COMMON _JS && typeof module === 'object' && module . exports ;
var HEX _CHARS = '0123456789abcdef' . split ( '' ) ;
var SHAKE _PADDING = [ 31 , 7936 , 2031616 , 520093696 ] ;
var KECCAK _PADDING = [ 1 , 256 , 65536 , 16777216 ] ;
var PADDING = [ 6 , 1536 , 393216 , 100663296 ] ;
var SHIFT = [ 0 , 8 , 16 , 24 ] ;
var RC = [ 1 , 0 , 32898 , 0 , 32906 , 2147483648 , 2147516416 , 2147483648 , 32907 , 0 , 2147483649 ,
0 , 2147516545 , 2147483648 , 32777 , 2147483648 , 138 , 0 , 136 , 0 , 2147516425 , 0 ,
2147483658 , 0 , 2147516555 , 0 , 139 , 2147483648 , 32905 , 2147483648 , 32771 ,
2147483648 , 32770 , 2147483648 , 128 , 2147483648 , 32778 , 0 , 2147483658 , 2147483648 ,
2147516545 , 2147483648 , 32896 , 2147483648 , 2147483649 , 0 , 2147516424 , 2147483648 ] ;
var BITS = [ 224 , 256 , 384 , 512 ] ;
var SHAKE _BITS = [ 128 , 256 ] ;
var OUTPUT _TYPES = [ 'hex' , 'buffer' , 'arrayBuffer' , 'array' ] ;
var createOutputMethod = function ( bits , padding , outputType ) {
return function ( message ) {
return new Keccak ( bits , padding , bits ) . update ( message ) [ outputType ] ( ) ;
} ;
} ;
var createShakeOutputMethod = function ( bits , padding , outputType ) {
return function ( message , outputBits ) {
return new Keccak ( bits , padding , outputBits ) . update ( message ) [ outputType ] ( ) ;
} ;
} ;
var createMethod = function ( bits , padding ) {
var method = createOutputMethod ( bits , padding , 'hex' ) ;
method . create = function ( ) {
return new Keccak ( bits , padding , bits ) ;
} ;
method . update = function ( message ) {
return method . create ( ) . update ( message ) ;
} ;
for ( var i = 0 ; i < OUTPUT _TYPES . length ; ++ i ) {
var type = OUTPUT _TYPES [ i ] ;
method [ type ] = createOutputMethod ( bits , padding , type ) ;
}
return method ;
} ;
var createShakeMethod = function ( bits , padding ) {
var method = createShakeOutputMethod ( bits , padding , 'hex' ) ;
method . create = function ( outputBits ) {
return new Keccak ( bits , padding , outputBits ) ;
} ;
method . update = function ( message , outputBits ) {
return method . create ( outputBits ) . update ( message ) ;
} ;
for ( var i = 0 ; i < OUTPUT _TYPES . length ; ++ i ) {
var type = OUTPUT _TYPES [ i ] ;
method [ type ] = createShakeOutputMethod ( bits , padding , type ) ;
}
return method ;
} ;
var algorithms = [
{ name : 'keccak' , padding : KECCAK _PADDING , bits : BITS , createMethod : createMethod } ,
{ name : 'sha3' , padding : PADDING , bits : BITS , createMethod : createMethod } ,
{ name : 'shake' , padding : SHAKE _PADDING , bits : SHAKE _BITS , createMethod : createShakeMethod }
] ;
var methods = { } , methodNames = [ ] ;
for ( var i = 0 ; i < algorithms . length ; ++ i ) {
var algorithm = algorithms [ i ] ;
var bits = algorithm . bits ;
for ( var j = 0 ; j < bits . length ; ++ j ) {
var methodName = algorithm . name + '_' + bits [ j ] ;
methodNames . push ( methodName ) ;
methods [ methodName ] = algorithm . createMethod ( bits [ j ] , algorithm . padding ) ;
}
}
function Keccak ( bits , padding , outputBits ) {
this . blocks = [ ] ;
this . s = [ ] ;
this . padding = padding ;
this . outputBits = outputBits ;
this . reset = true ;
this . block = 0 ;
this . start = 0 ;
this . blockCount = ( 1600 - ( bits << 1 ) ) >> 5 ;
this . byteCount = this . blockCount << 2 ;
this . outputBlocks = outputBits >> 5 ;
this . extraBytes = ( outputBits & 31 ) >> 3 ;
for ( var i = 0 ; i < 50 ; ++ i ) {
this . s [ i ] = 0 ;
}
}
Keccak . prototype . update = function ( message ) {
var notString = typeof message !== 'string' ;
if ( notString && message . constructor === ArrayBuffer ) {
message = new Uint8Array ( message ) ;
}
var length = message . length , blocks = this . blocks , byteCount = this . byteCount ,
blockCount = this . blockCount , index = 0 , s = this . s , i , code ;
while ( index < length ) {
if ( this . reset ) {
this . reset = false ;
blocks [ 0 ] = this . block ;
for ( i = 1 ; i < blockCount + 1 ; ++ i ) {
blocks [ i ] = 0 ;
}
}
if ( notString ) {
for ( i = this . start ; index < length && i < byteCount ; ++ index ) {
blocks [ i >> 2 ] |= message [ index ] << SHIFT [ i ++ & 3 ] ;
}
} else {
for ( i = this . start ; index < length && i < byteCount ; ++ index ) {
code = message . charCodeAt ( index ) ;
if ( code < 0x80 ) {
blocks [ i >> 2 ] |= code << SHIFT [ i ++ & 3 ] ;
} else if ( code < 0x800 ) {
blocks [ i >> 2 ] |= ( 0xc0 | ( code >> 6 ) ) << SHIFT [ i ++ & 3 ] ;
blocks [ i >> 2 ] |= ( 0x80 | ( code & 0x3f ) ) << SHIFT [ i ++ & 3 ] ;
} else if ( code < 0xd800 || code >= 0xe000 ) {
blocks [ i >> 2 ] |= ( 0xe0 | ( code >> 12 ) ) << SHIFT [ i ++ & 3 ] ;
blocks [ i >> 2 ] |= ( 0x80 | ( ( code >> 6 ) & 0x3f ) ) << SHIFT [ i ++ & 3 ] ;
blocks [ i >> 2 ] |= ( 0x80 | ( code & 0x3f ) ) << SHIFT [ i ++ & 3 ] ;
} else {
code = 0x10000 + ( ( ( code & 0x3ff ) << 10 ) | ( message . charCodeAt ( ++ index ) & 0x3ff ) ) ;
blocks [ i >> 2 ] |= ( 0xf0 | ( code >> 18 ) ) << SHIFT [ i ++ & 3 ] ;
blocks [ i >> 2 ] |= ( 0x80 | ( ( code >> 12 ) & 0x3f ) ) << SHIFT [ i ++ & 3 ] ;
blocks [ i >> 2 ] |= ( 0x80 | ( ( code >> 6 ) & 0x3f ) ) << SHIFT [ i ++ & 3 ] ;
blocks [ i >> 2 ] |= ( 0x80 | ( code & 0x3f ) ) << SHIFT [ i ++ & 3 ] ;
}
}
}
this . lastByteIndex = i ;
if ( i >= byteCount ) {
this . start = i - byteCount ;
this . block = blocks [ blockCount ] ;
for ( i = 0 ; i < blockCount ; ++ i ) {
s [ i ] ^= blocks [ i ] ;
}
f ( s ) ;
this . reset = true ;
} else {
this . start = i ;
}
}
return this ;
} ;
Keccak . prototype . finalize = function ( ) {
var blocks = this . blocks , i = this . lastByteIndex , blockCount = this . blockCount , s = this . s ;
blocks [ i >> 2 ] |= this . padding [ i & 3 ] ;
if ( this . lastByteIndex === this . byteCount ) {
blocks [ 0 ] = blocks [ blockCount ] ;
for ( i = 1 ; i < blockCount + 1 ; ++ i ) {
blocks [ i ] = 0 ;
}
}
blocks [ blockCount - 1 ] |= 0x80000000 ;
for ( i = 0 ; i < blockCount ; ++ i ) {
s [ i ] ^= blocks [ i ] ;
}
f ( s ) ;
} ;
Keccak . prototype . toString = Keccak . prototype . hex = function ( ) {
this . finalize ( ) ;
var blockCount = this . blockCount , s = this . s , outputBlocks = this . outputBlocks ,
extraBytes = this . extraBytes , i = 0 , j = 0 ;
var hex = '' , block ;
while ( j < outputBlocks ) {
for ( i = 0 ; i < blockCount && j < outputBlocks ; ++ i , ++ j ) {
block = s [ i ] ;
hex += HEX _CHARS [ ( block >> 4 ) & 0x0F ] + HEX _CHARS [ block & 0x0F ] +
HEX _CHARS [ ( block >> 12 ) & 0x0F ] + HEX _CHARS [ ( block >> 8 ) & 0x0F ] +
HEX _CHARS [ ( block >> 20 ) & 0x0F ] + HEX _CHARS [ ( block >> 16 ) & 0x0F ] +
HEX _CHARS [ ( block >> 28 ) & 0x0F ] + HEX _CHARS [ ( block >> 24 ) & 0x0F ] ;
}
if ( j % blockCount === 0 ) {
f ( s ) ;
i = 0 ;
}
}
if ( extraBytes ) {
block = s [ i ] ;
if ( extraBytes > 0 ) {
hex += HEX _CHARS [ ( block >> 4 ) & 0x0F ] + HEX _CHARS [ block & 0x0F ] ;
}
if ( extraBytes > 1 ) {
hex += HEX _CHARS [ ( block >> 12 ) & 0x0F ] + HEX _CHARS [ ( block >> 8 ) & 0x0F ] ;
}
if ( extraBytes > 2 ) {
hex += HEX _CHARS [ ( block >> 20 ) & 0x0F ] + HEX _CHARS [ ( block >> 16 ) & 0x0F ] ;
}
}
return hex ;
} ;
Keccak . prototype . arrayBuffer = function ( ) {
this . finalize ( ) ;
var blockCount = this . blockCount , s = this . s , outputBlocks = this . outputBlocks ,
extraBytes = this . extraBytes , i = 0 , j = 0 ;
var bytes = this . outputBits >> 3 ;
var buffer ;
if ( extraBytes ) {
buffer = new ArrayBuffer ( ( outputBlocks + 1 ) << 2 ) ;
} else {
buffer = new ArrayBuffer ( bytes ) ;
}
var array = new Uint32Array ( buffer ) ;
while ( j < outputBlocks ) {
for ( i = 0 ; i < blockCount && j < outputBlocks ; ++ i , ++ j ) {
array [ j ] = s [ i ] ;
}
if ( j % blockCount === 0 ) {
f ( s ) ;
}
}
if ( extraBytes ) {
array [ i ] = s [ i ] ;
buffer = buffer . slice ( 0 , bytes ) ;
}
return buffer ;
} ;
Keccak . prototype . buffer = Keccak . prototype . arrayBuffer ;
Keccak . prototype . digest = Keccak . prototype . array = function ( ) {
this . finalize ( ) ;
var blockCount = this . blockCount , s = this . s , outputBlocks = this . outputBlocks ,
extraBytes = this . extraBytes , i = 0 , j = 0 ;
var array = [ ] , offset , block ;
while ( j < outputBlocks ) {
for ( i = 0 ; i < blockCount && j < outputBlocks ; ++ i , ++ j ) {
offset = j << 2 ;
block = s [ i ] ;
array [ offset ] = block & 0xFF ;
array [ offset + 1 ] = ( block >> 8 ) & 0xFF ;
array [ offset + 2 ] = ( block >> 16 ) & 0xFF ;
array [ offset + 3 ] = ( block >> 24 ) & 0xFF ;
}
if ( j % blockCount === 0 ) {
f ( s ) ;
}
}
if ( extraBytes ) {
offset = j << 2 ;
block = s [ i ] ;
if ( extraBytes > 0 ) {
array [ offset ] = block & 0xFF ;
}
if ( extraBytes > 1 ) {
array [ offset + 1 ] = ( block >> 8 ) & 0xFF ;
}
if ( extraBytes > 2 ) {
array [ offset + 2 ] = ( block >> 16 ) & 0xFF ;
}
}
return array ;
} ;
var f = function ( s ) {
var h , l , n , c0 , c1 , c2 , c3 , c4 , c5 , c6 , c7 , c8 , c9 ,
b0 , b1 , b2 , b3 , b4 , b5 , b6 , b7 , b8 , b9 , b10 , b11 , b12 , b13 , b14 , b15 , b16 , b17 ,
b18 , b19 , b20 , b21 , b22 , b23 , b24 , b25 , b26 , b27 , b28 , b29 , b30 , b31 , b32 , b33 ,
b34 , b35 , b36 , b37 , b38 , b39 , b40 , b41 , b42 , b43 , b44 , b45 , b46 , b47 , b48 , b49 ;
for ( n = 0 ; n < 48 ; n += 2 ) {
c0 = s [ 0 ] ^ s [ 10 ] ^ s [ 20 ] ^ s [ 30 ] ^ s [ 40 ] ;
c1 = s [ 1 ] ^ s [ 11 ] ^ s [ 21 ] ^ s [ 31 ] ^ s [ 41 ] ;
c2 = s [ 2 ] ^ s [ 12 ] ^ s [ 22 ] ^ s [ 32 ] ^ s [ 42 ] ;
c3 = s [ 3 ] ^ s [ 13 ] ^ s [ 23 ] ^ s [ 33 ] ^ s [ 43 ] ;
c4 = s [ 4 ] ^ s [ 14 ] ^ s [ 24 ] ^ s [ 34 ] ^ s [ 44 ] ;
c5 = s [ 5 ] ^ s [ 15 ] ^ s [ 25 ] ^ s [ 35 ] ^ s [ 45 ] ;
c6 = s [ 6 ] ^ s [ 16 ] ^ s [ 26 ] ^ s [ 36 ] ^ s [ 46 ] ;
c7 = s [ 7 ] ^ s [ 17 ] ^ s [ 27 ] ^ s [ 37 ] ^ s [ 47 ] ;
c8 = s [ 8 ] ^ s [ 18 ] ^ s [ 28 ] ^ s [ 38 ] ^ s [ 48 ] ;
c9 = s [ 9 ] ^ s [ 19 ] ^ s [ 29 ] ^ s [ 39 ] ^ s [ 49 ] ;
h = c8 ^ ( ( c2 << 1 ) | ( c3 >>> 31 ) ) ;
l = c9 ^ ( ( c3 << 1 ) | ( c2 >>> 31 ) ) ;
s [ 0 ] ^= h ;
s [ 1 ] ^= l ;
s [ 10 ] ^= h ;
s [ 11 ] ^= l ;
s [ 20 ] ^= h ;
s [ 21 ] ^= l ;
s [ 30 ] ^= h ;
s [ 31 ] ^= l ;
s [ 40 ] ^= h ;
s [ 41 ] ^= l ;
h = c0 ^ ( ( c4 << 1 ) | ( c5 >>> 31 ) ) ;
l = c1 ^ ( ( c5 << 1 ) | ( c4 >>> 31 ) ) ;
s [ 2 ] ^= h ;
s [ 3 ] ^= l ;
s [ 12 ] ^= h ;
s [ 13 ] ^= l ;
s [ 22 ] ^= h ;
s [ 23 ] ^= l ;
s [ 32 ] ^= h ;
s [ 33 ] ^= l ;
s [ 42 ] ^= h ;
s [ 43 ] ^= l ;
h = c2 ^ ( ( c6 << 1 ) | ( c7 >>> 31 ) ) ;
l = c3 ^ ( ( c7 << 1 ) | ( c6 >>> 31 ) ) ;
s [ 4 ] ^= h ;
s [ 5 ] ^= l ;
s [ 14 ] ^= h ;
s [ 15 ] ^= l ;
s [ 24 ] ^= h ;
s [ 25 ] ^= l ;
s [ 34 ] ^= h ;
s [ 35 ] ^= l ;
s [ 44 ] ^= h ;
s [ 45 ] ^= l ;
h = c4 ^ ( ( c8 << 1 ) | ( c9 >>> 31 ) ) ;
l = c5 ^ ( ( c9 << 1 ) | ( c8 >>> 31 ) ) ;
s [ 6 ] ^= h ;
s [ 7 ] ^= l ;
s [ 16 ] ^= h ;
s [ 17 ] ^= l ;
s [ 26 ] ^= h ;
s [ 27 ] ^= l ;
s [ 36 ] ^= h ;
s [ 37 ] ^= l ;
s [ 46 ] ^= h ;
s [ 47 ] ^= l ;
h = c6 ^ ( ( c0 << 1 ) | ( c1 >>> 31 ) ) ;
l = c7 ^ ( ( c1 << 1 ) | ( c0 >>> 31 ) ) ;
s [ 8 ] ^= h ;
s [ 9 ] ^= l ;
s [ 18 ] ^= h ;
s [ 19 ] ^= l ;
s [ 28 ] ^= h ;
s [ 29 ] ^= l ;
s [ 38 ] ^= h ;
s [ 39 ] ^= l ;
s [ 48 ] ^= h ;
s [ 49 ] ^= l ;
b0 = s [ 0 ] ;
b1 = s [ 1 ] ;
b32 = ( s [ 11 ] << 4 ) | ( s [ 10 ] >>> 28 ) ;
b33 = ( s [ 10 ] << 4 ) | ( s [ 11 ] >>> 28 ) ;
b14 = ( s [ 20 ] << 3 ) | ( s [ 21 ] >>> 29 ) ;
b15 = ( s [ 21 ] << 3 ) | ( s [ 20 ] >>> 29 ) ;
b46 = ( s [ 31 ] << 9 ) | ( s [ 30 ] >>> 23 ) ;
b47 = ( s [ 30 ] << 9 ) | ( s [ 31 ] >>> 23 ) ;
b28 = ( s [ 40 ] << 18 ) | ( s [ 41 ] >>> 14 ) ;
b29 = ( s [ 41 ] << 18 ) | ( s [ 40 ] >>> 14 ) ;
b20 = ( s [ 2 ] << 1 ) | ( s [ 3 ] >>> 31 ) ;
b21 = ( s [ 3 ] << 1 ) | ( s [ 2 ] >>> 31 ) ;
b2 = ( s [ 13 ] << 12 ) | ( s [ 12 ] >>> 20 ) ;
b3 = ( s [ 12 ] << 12 ) | ( s [ 13 ] >>> 20 ) ;
b34 = ( s [ 22 ] << 10 ) | ( s [ 23 ] >>> 22 ) ;
b35 = ( s [ 23 ] << 10 ) | ( s [ 22 ] >>> 22 ) ;
b16 = ( s [ 33 ] << 13 ) | ( s [ 32 ] >>> 19 ) ;
b17 = ( s [ 32 ] << 13 ) | ( s [ 33 ] >>> 19 ) ;
b48 = ( s [ 42 ] << 2 ) | ( s [ 43 ] >>> 30 ) ;
b49 = ( s [ 43 ] << 2 ) | ( s [ 42 ] >>> 30 ) ;
b40 = ( s [ 5 ] << 30 ) | ( s [ 4 ] >>> 2 ) ;
b41 = ( s [ 4 ] << 30 ) | ( s [ 5 ] >>> 2 ) ;
b22 = ( s [ 14 ] << 6 ) | ( s [ 15 ] >>> 26 ) ;
b23 = ( s [ 15 ] << 6 ) | ( s [ 14 ] >>> 26 ) ;
b4 = ( s [ 25 ] << 11 ) | ( s [ 24 ] >>> 21 ) ;
b5 = ( s [ 24 ] << 11 ) | ( s [ 25 ] >>> 21 ) ;
b36 = ( s [ 34 ] << 15 ) | ( s [ 35 ] >>> 17 ) ;
b37 = ( s [ 35 ] << 15 ) | ( s [ 34 ] >>> 17 ) ;
b18 = ( s [ 45 ] << 29 ) | ( s [ 44 ] >>> 3 ) ;
b19 = ( s [ 44 ] << 29 ) | ( s [ 45 ] >>> 3 ) ;
b10 = ( s [ 6 ] << 28 ) | ( s [ 7 ] >>> 4 ) ;
b11 = ( s [ 7 ] << 28 ) | ( s [ 6 ] >>> 4 ) ;
b42 = ( s [ 17 ] << 23 ) | ( s [ 16 ] >>> 9 ) ;
b43 = ( s [ 16 ] << 23 ) | ( s [ 17 ] >>> 9 ) ;
b24 = ( s [ 26 ] << 25 ) | ( s [ 27 ] >>> 7 ) ;
b25 = ( s [ 27 ] << 25 ) | ( s [ 26 ] >>> 7 ) ;
b6 = ( s [ 36 ] << 21 ) | ( s [ 37 ] >>> 11 ) ;
b7 = ( s [ 37 ] << 21 ) | ( s [ 36 ] >>> 11 ) ;
b38 = ( s [ 47 ] << 24 ) | ( s [ 46 ] >>> 8 ) ;
b39 = ( s [ 46 ] << 24 ) | ( s [ 47 ] >>> 8 ) ;
b30 = ( s [ 8 ] << 27 ) | ( s [ 9 ] >>> 5 ) ;
b31 = ( s [ 9 ] << 27 ) | ( s [ 8 ] >>> 5 ) ;
b12 = ( s [ 18 ] << 20 ) | ( s [ 19 ] >>> 12 ) ;
b13 = ( s [ 19 ] << 20 ) | ( s [ 18 ] >>> 12 ) ;
b44 = ( s [ 29 ] << 7 ) | ( s [ 28 ] >>> 25 ) ;
b45 = ( s [ 28 ] << 7 ) | ( s [ 29 ] >>> 25 ) ;
b26 = ( s [ 38 ] << 8 ) | ( s [ 39 ] >>> 24 ) ;
b27 = ( s [ 39 ] << 8 ) | ( s [ 38 ] >>> 24 ) ;
b8 = ( s [ 48 ] << 14 ) | ( s [ 49 ] >>> 18 ) ;
b9 = ( s [ 49 ] << 14 ) | ( s [ 48 ] >>> 18 ) ;
s [ 0 ] = b0 ^ ( ~ b2 & b4 ) ;
s [ 1 ] = b1 ^ ( ~ b3 & b5 ) ;
s [ 10 ] = b10 ^ ( ~ b12 & b14 ) ;
s [ 11 ] = b11 ^ ( ~ b13 & b15 ) ;
s [ 20 ] = b20 ^ ( ~ b22 & b24 ) ;
s [ 21 ] = b21 ^ ( ~ b23 & b25 ) ;
s [ 30 ] = b30 ^ ( ~ b32 & b34 ) ;
s [ 31 ] = b31 ^ ( ~ b33 & b35 ) ;
s [ 40 ] = b40 ^ ( ~ b42 & b44 ) ;
s [ 41 ] = b41 ^ ( ~ b43 & b45 ) ;
s [ 2 ] = b2 ^ ( ~ b4 & b6 ) ;
s [ 3 ] = b3 ^ ( ~ b5 & b7 ) ;
s [ 12 ] = b12 ^ ( ~ b14 & b16 ) ;
s [ 13 ] = b13 ^ ( ~ b15 & b17 ) ;
s [ 22 ] = b22 ^ ( ~ b24 & b26 ) ;
s [ 23 ] = b23 ^ ( ~ b25 & b27 ) ;
s [ 32 ] = b32 ^ ( ~ b34 & b36 ) ;
s [ 33 ] = b33 ^ ( ~ b35 & b37 ) ;
s [ 42 ] = b42 ^ ( ~ b44 & b46 ) ;
s [ 43 ] = b43 ^ ( ~ b45 & b47 ) ;
s [ 4 ] = b4 ^ ( ~ b6 & b8 ) ;
s [ 5 ] = b5 ^ ( ~ b7 & b9 ) ;
s [ 14 ] = b14 ^ ( ~ b16 & b18 ) ;
s [ 15 ] = b15 ^ ( ~ b17 & b19 ) ;
s [ 24 ] = b24 ^ ( ~ b26 & b28 ) ;
s [ 25 ] = b25 ^ ( ~ b27 & b29 ) ;
s [ 34 ] = b34 ^ ( ~ b36 & b38 ) ;
s [ 35 ] = b35 ^ ( ~ b37 & b39 ) ;
s [ 44 ] = b44 ^ ( ~ b46 & b48 ) ;
s [ 45 ] = b45 ^ ( ~ b47 & b49 ) ;
s [ 6 ] = b6 ^ ( ~ b8 & b0 ) ;
s [ 7 ] = b7 ^ ( ~ b9 & b1 ) ;
s [ 16 ] = b16 ^ ( ~ b18 & b10 ) ;
s [ 17 ] = b17 ^ ( ~ b19 & b11 ) ;
s [ 26 ] = b26 ^ ( ~ b28 & b20 ) ;
s [ 27 ] = b27 ^ ( ~ b29 & b21 ) ;
s [ 36 ] = b36 ^ ( ~ b38 & b30 ) ;
s [ 37 ] = b37 ^ ( ~ b39 & b31 ) ;
s [ 46 ] = b46 ^ ( ~ b48 & b40 ) ;
s [ 47 ] = b47 ^ ( ~ b49 & b41 ) ;
s [ 8 ] = b8 ^ ( ~ b0 & b2 ) ;
s [ 9 ] = b9 ^ ( ~ b1 & b3 ) ;
s [ 18 ] = b18 ^ ( ~ b10 & b12 ) ;
s [ 19 ] = b19 ^ ( ~ b11 & b13 ) ;
s [ 28 ] = b28 ^ ( ~ b20 & b22 ) ;
s [ 29 ] = b29 ^ ( ~ b21 & b23 ) ;
s [ 38 ] = b38 ^ ( ~ b30 & b32 ) ;
s [ 39 ] = b39 ^ ( ~ b31 & b33 ) ;
s [ 48 ] = b48 ^ ( ~ b40 & b42 ) ;
s [ 49 ] = b49 ^ ( ~ b41 & b43 ) ;
s [ 0 ] ^= RC [ n ] ;
s [ 1 ] ^= RC [ n + 1 ] ;
}
} ;
if ( COMMON _JS ) {
module . exports = methods ;
} else {
for ( var i = 0 ; i < methodNames . length ; ++ i ) {
root [ methodNames [ i ] ] = methods [ methodNames [ i ] ] ;
}
}
} ) ( ) ;
2018-03-05 03:31:09 +03:00
} ) . call ( this , require ( '_process' ) , typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : { } )
} , { "_process" : 7 } ] , 7 : [ function ( require , module , exports ) {
2018-06-04 03:50:21 +03:00
// shim for using process in browser
var process = module . exports = { } ;
// cached from whatever global is present so that test runners that stub it
// don't break things. But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals. It's inside a
// function because try/catches deoptimize in certain engines.
var cachedSetTimeout ;
var cachedClearTimeout ;
function defaultSetTimout ( ) {
throw new Error ( 'setTimeout has not been defined' ) ;
}
function defaultClearTimeout ( ) {
throw new Error ( 'clearTimeout has not been defined' ) ;
}
( function ( ) {
try {
if ( typeof setTimeout === 'function' ) {
cachedSetTimeout = setTimeout ;
} else {
cachedSetTimeout = defaultSetTimout ;
}
} catch ( e ) {
cachedSetTimeout = defaultSetTimout ;
}
try {
if ( typeof clearTimeout === 'function' ) {
cachedClearTimeout = clearTimeout ;
} else {
cachedClearTimeout = defaultClearTimeout ;
}
} catch ( e ) {
cachedClearTimeout = defaultClearTimeout ;
}
} ( ) )
function runTimeout ( fun ) {
if ( cachedSetTimeout === setTimeout ) {
//normal enviroments in sane situations
return setTimeout ( fun , 0 ) ;
}
// if setTimeout wasn't available but was latter defined
if ( ( cachedSetTimeout === defaultSetTimout || ! cachedSetTimeout ) && setTimeout ) {
cachedSetTimeout = setTimeout ;
return setTimeout ( fun , 0 ) ;
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedSetTimeout ( fun , 0 ) ;
} catch ( e ) {
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedSetTimeout . call ( null , fun , 0 ) ;
} catch ( e ) {
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
return cachedSetTimeout . call ( this , fun , 0 ) ;
}
}
}
function runClearTimeout ( marker ) {
if ( cachedClearTimeout === clearTimeout ) {
//normal enviroments in sane situations
return clearTimeout ( marker ) ;
}
// if clearTimeout wasn't available but was latter defined
if ( ( cachedClearTimeout === defaultClearTimeout || ! cachedClearTimeout ) && clearTimeout ) {
cachedClearTimeout = clearTimeout ;
return clearTimeout ( marker ) ;
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedClearTimeout ( marker ) ;
} catch ( e ) {
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedClearTimeout . call ( null , marker ) ;
} catch ( e ) {
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
return cachedClearTimeout . call ( this , marker ) ;
}
}
}
var queue = [ ] ;
var draining = false ;
var currentQueue ;
var queueIndex = - 1 ;
function cleanUpNextTick ( ) {
if ( ! draining || ! currentQueue ) {
return ;
}
draining = false ;
if ( currentQueue . length ) {
queue = currentQueue . concat ( queue ) ;
} else {
queueIndex = - 1 ;
}
if ( queue . length ) {
drainQueue ( ) ;
}
}
function drainQueue ( ) {
if ( draining ) {
return ;
}
var timeout = runTimeout ( cleanUpNextTick ) ;
draining = true ;
var len = queue . length ;
while ( len ) {
currentQueue = queue ;
queue = [ ] ;
while ( ++ queueIndex < len ) {
if ( currentQueue ) {
currentQueue [ queueIndex ] . run ( ) ;
}
}
queueIndex = - 1 ;
len = queue . length ;
}
currentQueue = null ;
draining = false ;
runClearTimeout ( timeout ) ;
}
process . nextTick = function ( fun ) {
var args = new Array ( arguments . length - 1 ) ;
if ( arguments . length > 1 ) {
for ( var i = 1 ; i < arguments . length ; i ++ ) {
args [ i - 1 ] = arguments [ i ] ;
}
}
queue . push ( new Item ( fun , args ) ) ;
if ( queue . length === 1 && ! draining ) {
runTimeout ( drainQueue ) ;
}
} ;
// v8 likes predictible objects
function Item ( fun , array ) {
this . fun = fun ;
this . array = array ;
}
Item . prototype . run = function ( ) {
this . fun . apply ( null , this . array ) ;
} ;
process . title = 'browser' ;
process . browser = true ;
process . env = { } ;
process . argv = [ ] ;
process . version = '' ; // empty string to avoid regexp issues
process . versions = { } ;
function noop ( ) { }
process . on = noop ;
process . addListener = noop ;
process . once = noop ;
process . off = noop ;
process . removeListener = noop ;
process . removeAllListeners = noop ;
process . emit = noop ;
process . prependListener = noop ;
process . prependOnceListener = noop ;
process . listeners = function ( name ) { return [ ] }
process . binding = function ( name ) {
throw new Error ( 'process.binding is not supported' ) ;
} ;
process . cwd = function ( ) { return '/' } ;
process . chdir = function ( dir ) {
throw new Error ( 'process.chdir is not supported' ) ;
} ;
process . umask = function ( ) { return 0 ; } ;
2018-03-05 03:31:09 +03:00
} , { } ] , 8 : [ function ( require , module , exports ) {
'use strict' ;
// See: https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI
var utils = ( function ( ) {
var convert = require ( '../utils/convert.js' ) ;
var utf8 = require ( '../utils/utf8.js' ) ;
return {
defineProperty : require ( '../utils/properties.js' ) . defineProperty ,
arrayify : convert . arrayify ,
padZeros : convert . padZeros ,
bigNumberify : require ( '../utils/bignumber.js' ) . bigNumberify ,
getAddress : require ( '../utils/address' ) . getAddress ,
concat : convert . concat ,
toUtf8Bytes : utf8 . toUtf8Bytes ,
toUtf8String : utf8 . toUtf8String ,
hexlify : convert . hexlify ,
} ;
} ) ( ) ;
2018-04-17 04:42:17 +03:00
var errors = require ( './errors' ) ;
2018-03-05 03:31:09 +03:00
var paramTypeBytes = new RegExp ( /^bytes([0-9]*)$/ ) ;
var paramTypeNumber = new RegExp ( /^(u?int)([0-9]*)$/ ) ;
var paramTypeArray = new RegExp ( /^(.*)\[([0-9]*)\]$/ ) ;
var defaultCoerceFunc = function ( type , value ) {
var match = type . match ( paramTypeNumber )
if ( match && parseInt ( match [ 2 ] ) <= 48 ) { return value . toNumber ( ) ; }
return value ;
}
2018-06-21 05:06:05 +03:00
// Shallow copy object (will move to utils/properties in v4)
2018-06-14 23:55:54 +03:00
function shallowCopy ( object ) {
var result = { } ;
for ( var key in object ) { result [ key ] = object [ key ] ; }
return result ;
}
2018-06-04 03:50:21 +03:00
///////////////////////////////////
// Parsing for Solidity Signatures
var regexParen = new RegExp ( "^([^)(]*)\\((.*)\\)([^)(]*)$" ) ;
var regexIdentifier = new RegExp ( "^[A-Za-z_][A-Za-z0-9_]*$" ) ;
var close = { "(" : ")" , "[" : "]" } ;
2018-06-07 03:48:45 +03:00
function verifyType ( type ) {
// These need to be transformed to their full description
if ( type . match ( /^uint($|[^1-9])/ ) ) {
type = 'uint256' + type . substring ( 4 ) ;
} else if ( type . match ( /^int($|[^1-9])/ ) ) {
type = 'int256' + type . substring ( 3 ) ;
}
return type ;
}
2018-06-04 03:50:21 +03:00
function parseParam ( param , allowIndexed ) {
function throwError ( i ) {
throw new Error ( 'unexpected character "' + param [ i ] + '" at position ' + i + ' in "' + param + '"' ) ;
}
var parent = { type : '' , name : '' , state : { allowType : true } } ;
var node = parent ;
for ( var i = 0 ; i < param . length ; i ++ ) {
var c = param [ i ] ;
switch ( c ) {
case '(' :
if ( ! node . state . allowParams ) { throwError ( i ) ; }
delete node . state . allowType ;
2018-06-07 03:48:45 +03:00
node . type = verifyType ( node . type ) ;
2018-06-04 03:50:21 +03:00
node . components = [ { type : '' , name : '' , parent : node , state : { allowType : true } } ] ;
node = node . components [ 0 ] ;
break ;
case ')' :
delete node . state ;
2018-06-07 03:48:45 +03:00
node . type = verifyType ( node . type ) ;
2018-06-04 03:50:21 +03:00
var child = node ;
node = node . parent ;
2018-06-06 02:40:28 +03:00
if ( ! node ) { throwError ( i ) ; }
2018-06-04 03:50:21 +03:00
delete child . parent ;
delete node . state . allowParams ;
node . state . allowName = true ;
node . state . allowArray = true ;
break ;
case ',' :
delete node . state ;
2018-06-07 03:48:45 +03:00
node . type = verifyType ( node . type ) ;
2018-06-04 03:50:21 +03:00
var sibling = { type : '' , name : '' , parent : node . parent , state : { allowType : true } } ;
node . parent . components . push ( sibling ) ;
delete node . parent ;
node = sibling ;
break ;
// Hit a space...
case ' ' :
// If reading type, the type is done and may read a param or name
if ( node . state . allowType ) {
if ( node . type !== '' ) {
2018-06-07 03:48:45 +03:00
node . type = verifyType ( node . type ) ;
2018-06-04 03:50:21 +03:00
delete node . state . allowType ;
node . state . allowName = true ;
node . state . allowParams = true ;
}
}
// If reading name, the name is done
if ( node . state . allowName ) {
if ( node . name !== '' ) {
if ( allowIndexed && node . name === 'indexed' ) {
node . indexed = true ;
node . name = '' ;
} else {
delete node . state . allowName ;
}
}
}
break ;
case '[' :
if ( ! node . state . allowArray ) { throwError ( i ) ; }
//if (!node.array) { node.array = ''; }
//node.array += c;
node . type += c ;
delete node . state . allowArray ;
delete node . state . allowName ;
node . state . readArray = true ;
break ;
case ']' :
if ( ! node . state . readArray ) { throwError ( i ) ; }
//node.array += c;
node . type += c ;
delete node . state . readArray ;
node . state . allowArray = true ;
node . state . allowName = true ;
break ;
default :
if ( node . state . allowType ) {
node . type += c ;
node . state . allowParams = true ;
node . state . allowArray = true ;
} else if ( node . state . allowName ) {
node . name += c ;
delete node . state . allowArray ;
} else if ( node . state . readArray ) {
//node.array += c;
node . type += c ;
} else {
throwError ( i ) ;
}
}
}
2018-06-06 02:40:28 +03:00
if ( node . parent ) { throw new Error ( "unexpected eof" ) ; }
2018-06-04 03:50:21 +03:00
delete parent . state ;
2018-06-07 03:48:45 +03:00
parent . type = verifyType ( parent . type ) ;
//verifyType(parent);
2018-06-04 03:50:21 +03:00
return parent ;
}
function parseSignatureEvent ( fragment ) {
var abi = {
anonymous : false ,
inputs : [ ] ,
type : 'event'
}
var match = fragment . match ( regexParen ) ;
if ( ! match ) { throw new Error ( 'invalid event: ' + fragment ) ; }
abi . name = match [ 1 ] . trim ( ) ;
splitNesting ( match [ 2 ] ) . forEach ( function ( param ) {
param = parseParam ( param , true ) ;
param . indexed = ! ! param . indexed ;
abi . inputs . push ( param ) ;
} ) ;
match [ 3 ] . split ( ' ' ) . forEach ( function ( modifier ) {
switch ( modifier ) {
case 'anonymous' :
abi . anonymous = true ;
break ;
case '' :
break ;
default :
console . log ( 'unknown modifier: ' + mdifier ) ;
}
} ) ;
if ( abi . name && ! abi . name . match ( regexIdentifier ) ) {
throw new Error ( 'invalid identifier: "' + result . name + '"' ) ;
}
return abi ;
}
function parseSignatureFunction ( fragment ) {
var abi = {
constant : false ,
inputs : [ ] ,
outputs : [ ] ,
payable : false ,
type : 'function'
} ;
var comps = fragment . split ( ' returns ' ) ;
var left = comps [ 0 ] . match ( regexParen ) ;
if ( ! left ) { throw new Error ( 'invalid signature' ) ; }
abi . name = left [ 1 ] . trim ( ) ;
if ( ! abi . name . match ( regexIdentifier ) ) {
throw new Error ( 'invalid identifier: "' + left [ 1 ] + '"' ) ;
}
splitNesting ( left [ 2 ] ) . forEach ( function ( param ) {
abi . inputs . push ( parseParam ( param ) ) ;
} ) ;
left [ 3 ] . split ( ' ' ) . forEach ( function ( modifier ) {
switch ( modifier ) {
case 'constant' :
abi . constant = true ;
break ;
case 'payable' :
abi . payable = true ;
break ;
case 'pure' :
abi . constant = true ;
abi . stateMutability = 'pure' ;
break ;
case 'view' :
abi . constant = true ;
abi . stateMutability = 'view' ;
break ;
case '' :
break ;
default :
console . log ( 'unknown modifier: ' + modifier ) ;
}
} ) ;
// We have outputs
if ( comps . length > 1 ) {
var right = comps [ 1 ] . match ( regexParen ) ;
if ( right [ 1 ] . trim ( ) != '' || right [ 3 ] . trim ( ) != '' ) {
throw new Error ( 'unexpected tokens' ) ;
}
splitNesting ( right [ 2 ] ) . forEach ( function ( param ) {
abi . outputs . push ( parseParam ( param ) ) ;
} ) ;
}
return abi ;
}
function parseSignature ( fragment ) {
if ( typeof ( fragment ) === 'string' ) {
// Make sure the "returns" is surrounded by a space and all whitespace is exactly one space
fragment = fragment . replace ( /\(/g , ' (' ) . replace ( /\)/g , ') ' ) . replace ( /\s+/g , ' ' ) ;
fragment = fragment . trim ( ) ;
if ( fragment . substring ( 0 , 6 ) === 'event ' ) {
return parseSignatureEvent ( fragment . substring ( 6 ) . trim ( ) ) ;
} else {
if ( fragment . substring ( 0 , 9 ) === 'function ' ) {
fragment = fragment . substring ( 9 ) ;
}
return parseSignatureFunction ( fragment . trim ( ) ) ;
}
}
throw new Error ( 'unknown fragment' ) ;
}
///////////////////////////////////
// Coders
2018-03-05 03:31:09 +03:00
var coderNull = function ( coerceFunc ) {
return {
name : 'null' ,
type : '' ,
encode : function ( value ) {
return utils . arrayify ( [ ] ) ;
} ,
decode : function ( data , offset ) {
if ( offset > data . length ) { throw new Error ( 'invalid null' ) ; }
return {
consumed : 0 ,
value : coerceFunc ( 'null' , undefined )
}
} ,
dynamic : false
} ;
}
var coderNumber = function ( coerceFunc , size , signed , localName ) {
var name = ( ( signed ? 'int' : 'uint' ) + ( size * 8 ) ) ;
return {
localName : localName ,
name : name ,
type : name ,
encode : function ( value ) {
2018-04-17 04:42:17 +03:00
try {
value = utils . bigNumberify ( value )
} catch ( error ) {
errors . throwError ( 'invalid number value' , errors . INVALID _ARGUMENT , {
arg : localName ,
type : typeof ( value ) ,
value : value
} ) ;
}
value = value . toTwos ( size * 8 ) . maskn ( size * 8 ) ;
2018-03-05 03:31:09 +03:00
//value = value.toTwos(size * 8).maskn(size * 8);
if ( signed ) {
value = value . fromTwos ( size * 8 ) . toTwos ( 256 ) ;
}
return utils . padZeros ( utils . arrayify ( value ) , 32 ) ;
} ,
decode : function ( data , offset ) {
2018-04-17 04:42:17 +03:00
if ( data . length < offset + 32 ) {
errors . throwError ( 'insufficient data for ' + name + ' type' , errors . INVALID _ARGUMENT , {
arg : localName ,
coderType : name ,
value : utils . hexlify ( data . slice ( offset , offset + 32 ) )
} ) ;
}
2018-03-05 03:31:09 +03:00
var junkLength = 32 - size ;
var value = utils . bigNumberify ( data . slice ( offset + junkLength , offset + 32 ) ) ;
if ( signed ) {
value = value . fromTwos ( size * 8 ) ;
} else {
value = value . maskn ( size * 8 ) ;
}
//if (size <= 6) { value = value.toNumber(); }
return {
consumed : 32 ,
value : coerceFunc ( name , value ) ,
}
}
} ;
}
var uint256Coder = coderNumber ( function ( type , value ) { return value ; } , 32 , false ) ;
var coderBoolean = function ( coerceFunc , localName ) {
return {
localName : localName ,
2018-06-07 03:48:45 +03:00
name : 'bool' ,
type : 'bool' ,
2018-03-05 03:31:09 +03:00
encode : function ( value ) {
2018-04-17 04:42:17 +03:00
return uint256Coder . encode ( ! ! value ? 1 : 0 ) ;
2018-03-05 03:31:09 +03:00
} ,
2018-06-21 05:06:05 +03:00
decode : function ( data , offset ) {
2018-04-05 22:48:46 +03:00
try {
var result = uint256Coder . decode ( data , offset ) ;
} catch ( error ) {
2018-04-17 04:42:17 +03:00
if ( error . reason === 'insufficient data for uint256 type' ) {
errors . throwError ( 'insufficient data for boolean type' , errors . INVALID _ARGUMENT , {
arg : localName ,
coderType : 'boolean' ,
value : error . value
} ) ;
2018-04-05 22:48:46 +03:00
}
throw error ;
}
2018-03-05 03:31:09 +03:00
return {
consumed : result . consumed ,
value : coerceFunc ( 'boolean' , ! result . value . isZero ( ) )
}
}
}
}
var coderFixedBytes = function ( coerceFunc , length , localName ) {
var name = ( 'bytes' + length ) ;
return {
localName : localName ,
name : name ,
type : name ,
encode : function ( value ) {
2018-04-17 04:42:17 +03:00
try {
value = utils . arrayify ( value ) ;
} catch ( error ) {
errors . throwError ( 'invalid ' + name + ' value' , errors . INVALID _ARGUMENT , {
arg : localName ,
type : typeof ( value ) ,
value : error . value
} ) ;
}
2018-03-05 03:31:09 +03:00
if ( length === 32 ) { return value ; }
var result = new Uint8Array ( 32 ) ;
result . set ( value ) ;
return result ;
} ,
decode : function ( data , offset ) {
2018-04-17 04:42:17 +03:00
if ( data . length < offset + 32 ) {
errors . throwError ( 'insufficient data for ' + name + ' type' , errors . INVALID _ARGUMENT , {
arg : localName ,
coderType : name ,
value : utils . hexlify ( data . slice ( offset , offset + 32 ) )
} ) ;
}
2018-03-05 03:31:09 +03:00
return {
consumed : 32 ,
value : coerceFunc ( name , utils . hexlify ( data . slice ( offset , offset + length ) ) )
}
}
} ;
}
var coderAddress = function ( coerceFunc , localName ) {
return {
localName : localName ,
name : 'address' ,
type : 'address' ,
encode : function ( value ) {
2018-04-17 04:42:17 +03:00
try {
value = utils . arrayify ( utils . getAddress ( value ) ) ;
} catch ( error ) {
errors . throwError ( 'invalid address' , errors . INVALID _ARGUMENT , {
arg : localName ,
type : typeof ( value ) ,
value : value
} ) ;
}
2018-03-05 03:31:09 +03:00
var result = new Uint8Array ( 32 ) ;
result . set ( value , 12 ) ;
return result ;
} ,
decode : function ( data , offset ) {
2018-04-17 04:42:17 +03:00
if ( data . length < offset + 32 ) {
errors . throwError ( 'insufficuent data for address type' , errors . INVALID _ARGUMENT , {
arg : localName ,
coderType : 'address' ,
value : utils . hexlify ( data . slice ( offset , offset + 32 ) )
} ) ;
}
2018-03-05 03:31:09 +03:00
return {
consumed : 32 ,
value : coerceFunc ( 'address' , utils . getAddress ( utils . hexlify ( data . slice ( offset + 12 , offset + 32 ) ) ) )
}
}
}
}
function _encodeDynamicBytes ( value ) {
var dataLength = parseInt ( 32 * Math . ceil ( value . length / 32 ) ) ;
var padding = new Uint8Array ( dataLength - value . length ) ;
return utils . concat ( [
uint256Coder . encode ( value . length ) ,
value ,
padding
] ) ;
}
2018-04-17 04:42:17 +03:00
function _decodeDynamicBytes ( data , offset , localName ) {
if ( data . length < offset + 32 ) {
errors . throwError ( 'insufficient data for dynamicBytes length' , errors . INVALID _ARGUMENT , {
arg : localName ,
coderType : 'dynamicBytes' ,
value : utils . hexlify ( data . slice ( offset , offset + 32 ) )
} ) ;
}
2018-03-05 03:31:09 +03:00
var length = uint256Coder . decode ( data , offset ) . value ;
2018-04-17 04:42:17 +03:00
try {
length = length . toNumber ( ) ;
} catch ( error ) {
errors . throwError ( 'dynamic bytes count too large' , errors . INVALID _ARGUMENT , {
arg : localName ,
coderType : 'dynamicBytes' ,
value : length . toString ( )
} ) ;
}
if ( data . length < offset + 32 + length ) {
errors . throwError ( 'insufficient data for dynamicBytes type' , errors . INVALID _ARGUMENT , {
arg : localName ,
coderType : 'dynamicBytes' ,
value : utils . hexlify ( data . slice ( offset , offset + 32 + length ) )
} ) ;
}
2018-03-05 03:31:09 +03:00
return {
consumed : parseInt ( 32 + 32 * Math . ceil ( length / 32 ) ) ,
value : data . slice ( offset + 32 , offset + 32 + length ) ,
}
}
var coderDynamicBytes = function ( coerceFunc , localName ) {
return {
localName : localName ,
name : 'bytes' ,
type : 'bytes' ,
encode : function ( value ) {
2018-04-17 04:42:17 +03:00
try {
value = utils . arrayify ( value ) ;
} catch ( error ) {
errors . throwError ( 'invalid bytes value' , errors . INVALID _ARGUMENT , {
arg : localName ,
type : typeof ( value ) ,
value : error . value
} ) ;
}
return _encodeDynamicBytes ( value ) ;
2018-03-05 03:31:09 +03:00
} ,
decode : function ( data , offset ) {
2018-04-17 04:42:17 +03:00
var result = _decodeDynamicBytes ( data , offset , localName ) ;
2018-03-05 03:31:09 +03:00
result . value = coerceFunc ( 'bytes' , utils . hexlify ( result . value ) ) ;
return result ;
} ,
dynamic : true
} ;
}
var coderString = function ( coerceFunc , localName ) {
return {
localName : localName ,
name : 'string' ,
type : 'string' ,
encode : function ( value ) {
2018-04-17 04:42:17 +03:00
if ( typeof ( value ) !== 'string' ) {
errors . throwError ( 'invalid string value' , errors . INVALID _ARGUMENT , {
arg : localName ,
type : typeof ( value ) ,
value : value
} ) ;
}
2018-03-05 03:31:09 +03:00
return _encodeDynamicBytes ( utils . toUtf8Bytes ( value ) ) ;
} ,
decode : function ( data , offset ) {
2018-04-17 04:42:17 +03:00
var result = _decodeDynamicBytes ( data , offset , localName ) ;
2018-03-05 03:31:09 +03:00
result . value = coerceFunc ( 'string' , utils . toUtf8String ( result . value ) ) ;
return result ;
} ,
dynamic : true
} ;
}
function alignSize ( size ) {
return parseInt ( 32 * Math . ceil ( size / 32 ) ) ;
}
function pack ( coders , values ) {
2018-04-17 04:42:17 +03:00
2018-03-05 03:31:09 +03:00
if ( Array . isArray ( values ) ) {
2018-04-17 04:42:17 +03:00
// do nothing
2018-03-05 03:31:09 +03:00
} else if ( values && typeof ( values ) === 'object' ) {
var arrayValues = [ ] ;
coders . forEach ( function ( coder ) {
arrayValues . push ( values [ coder . localName ] ) ;
} ) ;
values = arrayValues ;
} else {
2018-04-17 04:42:17 +03:00
errors . throwError ( 'invalid tuple value' , errors . INVALID _ARGUMENT , {
coderType : 'tuple' ,
type : typeof ( values ) ,
value : values
} ) ;
}
if ( coders . length !== values . length ) {
errors . throwError ( 'types/value length mismatch' , errors . INVALID _ARGUMENT , {
coderType : 'tuple' ,
value : values
} ) ;
2018-03-05 03:31:09 +03:00
}
var parts = [ ] ;
coders . forEach ( function ( coder , index ) {
parts . push ( { dynamic : coder . dynamic , value : coder . encode ( values [ index ] ) } ) ;
} ) ;
var staticSize = 0 , dynamicSize = 0 ;
parts . forEach ( function ( part , index ) {
if ( part . dynamic ) {
staticSize += 32 ;
dynamicSize += alignSize ( part . value . length ) ;
} else {
staticSize += alignSize ( part . value . length ) ;
}
} ) ;
var offset = 0 , dynamicOffset = staticSize ;
var data = new Uint8Array ( staticSize + dynamicSize ) ;
parts . forEach ( function ( part , index ) {
if ( part . dynamic ) {
//uint256Coder.encode(dynamicOffset).copy(data, offset);
data . set ( uint256Coder . encode ( dynamicOffset ) , offset ) ;
offset += 32 ;
//part.value.copy(data, dynamicOffset); @TODO
data . set ( part . value , dynamicOffset ) ;
dynamicOffset += alignSize ( part . value . length ) ;
} else {
//part.value.copy(data, offset); @TODO
data . set ( part . value , offset ) ;
offset += alignSize ( part . value . length ) ;
}
} ) ;
return data ;
}
function unpack ( coders , data , offset ) {
var baseOffset = offset ;
var consumed = 0 ;
var value = [ ] ;
coders . forEach ( function ( coder ) {
if ( coder . dynamic ) {
var dynamicOffset = uint256Coder . decode ( data , offset ) ;
var result = coder . decode ( data , baseOffset + dynamicOffset . value . toNumber ( ) ) ;
// The dynamic part is leap-frogged somewhere else; doesn't count towards size
result . consumed = dynamicOffset . consumed ;
} else {
var result = coder . decode ( data , offset ) ;
}
if ( result . value != undefined ) {
value . push ( result . value ) ;
}
offset += result . consumed ;
consumed += result . consumed ;
} ) ;
coders . forEach ( function ( coder , index ) {
var name = coder . localName ;
if ( ! name ) { return ; }
if ( typeof ( name ) === 'object' ) { name = name . name ; }
if ( ! name ) { return ; }
if ( name === 'length' ) { name = '_length' ; }
if ( value [ name ] != null ) { return ; }
value [ name ] = value [ index ] ;
} ) ;
return {
value : value ,
consumed : consumed
}
return result ;
}
function coderArray ( coerceFunc , coder , length , localName ) {
var type = ( coder . type + '[' + ( length >= 0 ? length : '' ) + ']' ) ;
return {
coder : coder ,
localName : localName ,
length : length ,
name : 'array' ,
type : type ,
encode : function ( value ) {
2018-04-17 04:42:17 +03:00
if ( ! Array . isArray ( value ) ) {
errors . throwError ( 'expected array value' , errors . INVALID _ARGUMENT , {
arg : localName ,
coderType : 'array' ,
type : typeof ( value ) ,
value : value
} ) ;
}
2018-03-05 03:31:09 +03:00
var count = length ;
var result = new Uint8Array ( 0 ) ;
if ( count === - 1 ) {
count = value . length ;
result = uint256Coder . encode ( count ) ;
}
2018-04-17 04:42:17 +03:00
if ( count !== value . length ) {
error . throwError ( 'array value length mismatch' , errors . INVALID _ARGUMENT , {
arg : localName ,
coderType : 'array' ,
count : value . length ,
expectedCount : count ,
value : value
} ) ;
}
2018-03-05 03:31:09 +03:00
var coders = [ ] ;
value . forEach ( function ( value ) { coders . push ( coder ) ; } ) ;
return utils . concat ( [ result , pack ( coders , value ) ] ) ;
} ,
decode : function ( data , offset ) {
// @TODO:
//if (data.length < offset + length * 32) { throw new Error('invalid array'); }
var consumed = 0 ;
var count = length ;
if ( count === - 1 ) {
2018-04-17 04:42:17 +03:00
try {
var decodedLength = uint256Coder . decode ( data , offset ) ;
} catch ( error ) {
errors . throwError ( 'insufficient data for dynamic array length' , errors . INVALID _ARGUMENT , {
arg : localName ,
coderType : 'array' ,
value : error . value
} ) ;
}
try {
count = decodedLength . value . toNumber ( ) ;
} catch ( error ) {
errors . throwError ( 'array count too large' , errors . INVALID _ARGUMENT , {
arg : localName ,
coderType : 'array' ,
value : decodedLength . value . toString ( )
} ) ;
}
2018-03-05 03:31:09 +03:00
consumed += decodedLength . consumed ;
offset += decodedLength . consumed ;
}
2018-06-21 05:06:05 +03:00
// We don't want the children to have a localName
var subCoder = {
name : coder . name ,
type : coder . type ,
encode : coder . encode ,
decode : coder . decode ,
dynamic : coder . dynamic
} ;
2018-03-05 03:31:09 +03:00
var coders = [ ] ;
2018-06-21 05:06:05 +03:00
for ( var i = 0 ; i < count ; i ++ ) { coders . push ( subCoder ) ; }
2018-03-05 03:31:09 +03:00
var result = unpack ( coders , data , offset ) ;
result . consumed += consumed ;
result . value = coerceFunc ( type , result . value ) ;
return result ;
} ,
dynamic : ( length === - 1 || coder . dynamic )
}
}
function coderTuple ( coerceFunc , coders , localName ) {
2018-06-06 02:40:28 +03:00
2018-03-05 03:31:09 +03:00
var dynamic = false ;
var types = [ ] ;
coders . forEach ( function ( coder ) {
if ( coder . dynamic ) { dynamic = true ; }
types . push ( coder . type ) ;
} ) ;
var type = ( 'tuple(' + types . join ( ',' ) + ')' ) ;
return {
coders : coders ,
localName : localName ,
name : 'tuple' ,
type : type ,
encode : function ( value ) {
return pack ( coders , value ) ;
} ,
decode : function ( data , offset ) {
var result = unpack ( coders , data , offset ) ;
result . value = coerceFunc ( type , result . value ) ;
return result ;
} ,
dynamic : dynamic
} ;
}
/ *
function getTypes ( coders ) {
var type = coderTuple ( coders ) . type ;
return type . substring ( 6 , type . length - 1 ) ;
}
* /
function splitNesting ( value ) {
var result = [ ] ;
var accum = '' ;
var depth = 0 ;
for ( var offset = 0 ; offset < value . length ; offset ++ ) {
var c = value [ offset ] ;
if ( c === ',' && depth === 0 ) {
result . push ( accum ) ;
accum = '' ;
} else {
accum += c ;
if ( c === '(' ) {
depth ++ ;
} else if ( c === ')' ) {
depth -- ;
if ( depth === - 1 ) {
throw new Error ( 'unbalanced parenthsis' ) ;
}
}
}
}
result . push ( accum ) ;
return result ;
}
var paramTypeSimple = {
address : coderAddress ,
bool : coderBoolean ,
string : coderString ,
bytes : coderDynamicBytes ,
} ;
2018-06-04 03:50:21 +03:00
function getTupleParamCoder ( coerceFunc , components , localName ) {
2018-06-07 03:48:45 +03:00
if ( ! components ) { components = [ ] ; }
2018-06-04 03:50:21 +03:00
var coders = [ ] ;
components . forEach ( function ( component ) {
coders . push ( getParamCoder ( coerceFunc , component ) ) ;
} ) ;
2018-06-06 02:40:28 +03:00
2018-06-04 03:50:21 +03:00
return coderTuple ( coerceFunc , coders , localName ) ;
}
2018-06-06 02:40:28 +03:00
function getParamCoder ( coerceFunc , param ) {
var coder = paramTypeSimple [ param . type ] ;
if ( coder ) { return coder ( coerceFunc , param . name ) ; }
2018-03-05 03:31:09 +03:00
2018-06-06 02:40:28 +03:00
var match = param . type . match ( paramTypeNumber ) ;
2018-03-05 03:31:09 +03:00
if ( match ) {
var size = parseInt ( match [ 2 ] || 256 ) ;
if ( size === 0 || size > 256 || ( size % 8 ) !== 0 ) {
2018-04-17 04:42:17 +03:00
errors . throwError ( 'invalid ' + match [ 1 ] + ' bit length' , errors . INVALID _ARGUMENT , {
2018-06-06 02:40:28 +03:00
arg : 'param' ,
value : param
2018-04-17 04:42:17 +03:00
} ) ;
2018-03-05 03:31:09 +03:00
}
2018-06-06 02:40:28 +03:00
return coderNumber ( coerceFunc , size / 8 , ( match [ 1 ] === 'int' ) , param . name ) ;
2018-03-05 03:31:09 +03:00
}
2018-06-06 02:40:28 +03:00
var match = param . type . match ( paramTypeBytes ) ;
2018-03-05 03:31:09 +03:00
if ( match ) {
var size = parseInt ( match [ 1 ] ) ;
if ( size === 0 || size > 32 ) {
2018-04-17 04:42:17 +03:00
errors . throwError ( 'invalid bytes length' , errors . INVALID _ARGUMENT , {
2018-06-06 02:40:28 +03:00
arg : 'param' ,
value : param
2018-04-17 04:42:17 +03:00
} ) ;
2018-03-05 03:31:09 +03:00
}
2018-06-06 02:40:28 +03:00
return coderFixedBytes ( coerceFunc , size , param . name ) ;
2018-03-05 03:31:09 +03:00
}
2018-06-06 02:40:28 +03:00
var match = param . type . match ( paramTypeArray ) ;
2018-03-05 03:31:09 +03:00
if ( match ) {
2018-06-14 23:55:54 +03:00
param = shallowCopy ( param ) ;
2018-03-05 03:31:09 +03:00
var size = parseInt ( match [ 2 ] || - 1 ) ;
2018-06-06 02:40:28 +03:00
param . type = match [ 1 ] ;
return coderArray ( coerceFunc , getParamCoder ( coerceFunc , param ) , size , param . name ) ;
2018-03-05 03:31:09 +03:00
}
2018-06-06 02:40:28 +03:00
if ( param . type . substring ( 0 , 5 ) === 'tuple' ) {
return getTupleParamCoder ( coerceFunc , param . components , param . name ) ;
2018-03-05 03:31:09 +03:00
}
if ( type === '' ) {
return coderNull ( coerceFunc ) ;
}
2018-04-17 04:42:17 +03:00
errors . throwError ( 'invalid type' , errors . INVALID _ARGUMENT , {
arg : 'type' ,
value : type
} ) ;
2018-03-05 03:31:09 +03:00
}
function Coder ( coerceFunc ) {
if ( ! ( this instanceof Coder ) ) { throw new Error ( 'missing new' ) ; }
if ( ! coerceFunc ) { coerceFunc = defaultCoerceFunc ; }
utils . defineProperty ( this , 'coerceFunc' , coerceFunc ) ;
}
2018-06-06 02:40:28 +03:00
// Legacy name support
// @TODO: In the next major version, remove names from decode/encode and don't do this
function populateNames ( type , name ) {
if ( ! name ) { return ; }
if ( type . type . substring ( 0 , 5 ) === 'tuple' && typeof ( name ) !== 'string' ) {
if ( type . components . length != name . names . length ) {
errors . throwError ( 'names/types length mismatch' , errors . INVALID _ARGUMENT , {
count : { names : name . names . length , types : type . components . length } ,
value : { names : name . names , types : type . components }
} ) ;
}
name . names . forEach ( function ( name , index ) {
populateNames ( type . components [ index ] , name ) ;
} ) ;
name = ( name . name || '' ) ;
}
if ( ! type . name && typeof ( name ) === 'string' ) {
type . name = name ;
}
}
2018-03-05 03:31:09 +03:00
utils . defineProperty ( Coder . prototype , 'encode' , function ( names , types , values ) {
// Names is optional, so shift over all the parameters if not provided
if ( arguments . length < 3 ) {
values = types ;
types = names ;
2018-06-06 02:40:28 +03:00
names = [ ] ;
2018-03-05 03:31:09 +03:00
}
2018-04-17 04:42:17 +03:00
if ( types . length !== values . length ) {
errors . throwError ( 'types/values length mismatch' , errors . INVALID _ARGUMENT , {
count : { types : types . length , values : values . length } ,
value : { types : types , values : values }
} ) ;
}
2018-03-05 03:31:09 +03:00
var coders = [ ] ;
types . forEach ( function ( type , index ) {
2018-06-06 02:40:28 +03:00
// Convert types to type objects
// - "uint foo" => { type: "uint", name: "foo" }
// - "tuple(uint, uint)" => { type: "tuple", components: [ { type: "uint" }, { type: "uint" }, ] }
if ( typeof ( type ) === 'string' ) {
type = parseParam ( type ) ;
}
// Legacy support for passing in names (this is going away in the next major version)
populateNames ( type , names [ index ] ) ;
coders . push ( getParamCoder ( this . coerceFunc , type ) ) ;
2018-03-05 03:31:09 +03:00
} , this ) ;
return utils . hexlify ( coderTuple ( this . coerceFunc , coders ) . encode ( values ) ) ;
} ) ;
utils . defineProperty ( Coder . prototype , 'decode' , function ( names , types , data ) {
// Names is optional, so shift over all the parameters if not provided
if ( arguments . length < 3 ) {
data = types ;
types = names ;
2018-06-06 02:40:28 +03:00
names = [ ] ;
2018-03-05 03:31:09 +03:00
}
data = utils . arrayify ( data ) ;
var coders = [ ] ;
types . forEach ( function ( type , index ) {
2018-06-06 02:40:28 +03:00
// See encode for details
if ( typeof ( type ) === 'string' ) {
type = parseParam ( type ) ;
}
// Legacy; going away in the next major version
populateNames ( type , names [ index ] ) ;
coders . push ( getParamCoder ( this . coerceFunc , type ) ) ;
2018-03-05 03:31:09 +03:00
} , this ) ;
return coderTuple ( this . coerceFunc , coders ) . decode ( data , 0 ) . value ;
} ) ;
utils . defineProperty ( Coder , 'defaultCoder' , new Coder ( ) ) ;
2018-06-04 03:50:21 +03:00
utils . defineProperty ( Coder , 'parseSignature' , parseSignature ) ;
2018-03-05 03:31:09 +03:00
module . exports = Coder
2018-04-17 04:42:17 +03:00
} , { "../utils/address" : 9 , "../utils/bignumber.js" : 10 , "../utils/convert.js" : 11 , "../utils/properties.js" : 14 , "../utils/utf8.js" : 16 , "./errors" : 12 } ] , 9 : [ function ( require , module , exports ) {
2018-03-05 03:31:09 +03:00
var BN = require ( 'bn.js' ) ;
var convert = require ( './convert' ) ;
var throwError = require ( './throw-error' ) ;
var keccak256 = require ( './keccak256' ) ;
function getChecksumAddress ( address ) {
if ( typeof ( address ) !== 'string' || ! address . match ( /^0x[0-9A-Fa-f]{40}$/ ) ) {
throwError ( 'invalid address' , { input : address } ) ;
}
address = address . toLowerCase ( ) ;
var hashed = address . substring ( 2 ) . split ( '' ) ;
for ( var i = 0 ; i < hashed . length ; i ++ ) {
hashed [ i ] = hashed [ i ] . charCodeAt ( 0 ) ;
}
hashed = convert . arrayify ( keccak256 ( hashed ) ) ;
address = address . substring ( 2 ) . split ( '' ) ;
for ( var i = 0 ; i < 40 ; i += 2 ) {
if ( ( hashed [ i >> 1 ] >> 4 ) >= 8 ) {
address [ i ] = address [ i ] . toUpperCase ( ) ;
}
if ( ( hashed [ i >> 1 ] & 0x0f ) >= 8 ) {
address [ i + 1 ] = address [ i + 1 ] . toUpperCase ( ) ;
}
}
return '0x' + address . join ( '' ) ;
}
// Shims for environments that are missing some required constants and functions
var MAX _SAFE _INTEGER = 0x1fffffffffffff ;
function log10 ( x ) {
if ( Math . log10 ) { return Math . log10 ( x ) ; }
return Math . log ( x ) / Math . LN10 ;
}
// See: https://en.wikipedia.org/wiki/International_Bank_Account_Number
var ibanChecksum = ( function ( ) {
// Create lookup table
var ibanLookup = { } ;
for ( var i = 0 ; i < 10 ; i ++ ) { ibanLookup [ String ( i ) ] = String ( i ) ; }
for ( var i = 0 ; i < 26 ; i ++ ) { ibanLookup [ String . fromCharCode ( 65 + i ) ] = String ( 10 + i ) ; }
// How many decimal digits can we process? (for 64-bit float, this is 15)
var safeDigits = Math . floor ( log10 ( MAX _SAFE _INTEGER ) ) ;
return function ( address ) {
address = address . toUpperCase ( ) ;
address = address . substring ( 4 ) + address . substring ( 0 , 2 ) + '00' ;
var expanded = address . split ( '' ) ;
for ( var i = 0 ; i < expanded . length ; i ++ ) {
expanded [ i ] = ibanLookup [ expanded [ i ] ] ;
}
expanded = expanded . join ( '' ) ;
// Javascript can handle integers safely up to 15 (decimal) digits
while ( expanded . length >= safeDigits ) {
var block = expanded . substring ( 0 , safeDigits ) ;
expanded = parseInt ( block , 10 ) % 97 + expanded . substring ( block . length ) ;
}
var checksum = String ( 98 - ( parseInt ( expanded , 10 ) % 97 ) ) ;
while ( checksum . length < 2 ) { checksum = '0' + checksum ; }
return checksum ;
} ;
} ) ( ) ;
function getAddress ( address , icapFormat ) {
var result = null ;
if ( typeof ( address ) !== 'string' ) {
throwError ( 'invalid address' , { input : address } ) ;
}
if ( address . match ( /^(0x)?[0-9a-fA-F]{40}$/ ) ) {
// Missing the 0x prefix
if ( address . substring ( 0 , 2 ) !== '0x' ) { address = '0x' + address ; }
result = getChecksumAddress ( address ) ;
// It is a checksummed address with a bad checksum
if ( address . match ( /([A-F].*[a-f])|([a-f].*[A-F])/ ) && result !== address ) {
throwError ( 'invalid address checksum' , { input : address , expected : result } ) ;
}
// Maybe ICAP? (we only support direct mode)
} else if ( address . match ( /^XE[0-9]{2}[0-9A-Za-z]{30,31}$/ ) ) {
// It is an ICAP address with a bad checksum
if ( address . substring ( 2 , 4 ) !== ibanChecksum ( address ) ) {
throwError ( 'invalid address icap checksum' , { input : address } ) ;
}
result = ( new BN ( address . substring ( 4 ) , 36 ) ) . toString ( 16 ) ;
while ( result . length < 40 ) { result = '0' + result ; }
result = getChecksumAddress ( '0x' + result ) ;
} else {
throwError ( 'invalid address' , { input : address } ) ;
}
if ( icapFormat ) {
var base36 = ( new BN ( result . substring ( 2 ) , 16 ) ) . toString ( 36 ) . toUpperCase ( ) ;
while ( base36 . length < 30 ) { base36 = '0' + base36 ; }
return 'XE' + ibanChecksum ( 'XE00' + base36 ) + base36 ;
}
return result ;
}
module . exports = {
getAddress : getAddress ,
}
2018-04-13 01:31:02 +03:00
} , { "./convert" : 11 , "./keccak256" : 13 , "./throw-error" : 15 , "bn.js" : 4 } ] , 10 : [ function ( require , module , exports ) {
2018-03-05 03:31:09 +03:00
/ * *
* BigNumber
*
* A wrapper around the BN . js object . In the future we can swap out
* the underlying BN . js library for something smaller .
* /
var BN = require ( 'bn.js' ) ;
var defineProperty = require ( './properties' ) . defineProperty ;
var convert = require ( './convert' ) ;
var throwError = require ( './throw-error' ) ;
function BigNumber ( value ) {
if ( ! ( this instanceof BigNumber ) ) { throw new Error ( 'missing new' ) ; }
if ( convert . isHexString ( value ) ) {
if ( value == '0x' ) { value = '0x0' ; }
value = new BN ( value . substring ( 2 ) , 16 ) ;
} else if ( typeof ( value ) === 'string' && value [ 0 ] === '-' && convert . isHexString ( value . substring ( 1 ) ) ) {
value = ( new BN ( value . substring ( 3 ) , 16 ) ) . mul ( BigNumber . constantNegativeOne . _bn ) ;
} else if ( typeof ( value ) === 'string' && value . match ( /^-?[0-9]*$/ ) ) {
if ( value == '' ) { value = '0' ; }
value = new BN ( value ) ;
} else if ( typeof ( value ) === 'number' && parseInt ( value ) == value ) {
value = new BN ( value ) ;
} else if ( BN . isBN ( value ) ) {
//value = value
} else if ( isBigNumber ( value ) ) {
value = value . _bn ;
} else if ( convert . isArrayish ( value ) ) {
value = new BN ( convert . hexlify ( value ) . substring ( 2 ) , 16 ) ;
} else {
throwError ( 'invalid BigNumber value' , { input : value } ) ;
}
defineProperty ( this , '_bn' , value ) ;
}
defineProperty ( BigNumber , 'constantNegativeOne' , bigNumberify ( - 1 ) ) ;
defineProperty ( BigNumber , 'constantZero' , bigNumberify ( 0 ) ) ;
defineProperty ( BigNumber , 'constantOne' , bigNumberify ( 1 ) ) ;
defineProperty ( BigNumber , 'constantTwo' , bigNumberify ( 2 ) ) ;
defineProperty ( BigNumber , 'constantWeiPerEther' , bigNumberify ( new BN ( '1000000000000000000' ) ) ) ;
defineProperty ( BigNumber . prototype , 'fromTwos' , function ( value ) {
return new BigNumber ( this . _bn . fromTwos ( value ) ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'toTwos' , function ( value ) {
return new BigNumber ( this . _bn . toTwos ( value ) ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'add' , function ( other ) {
return new BigNumber ( this . _bn . add ( bigNumberify ( other ) . _bn ) ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'sub' , function ( other ) {
return new BigNumber ( this . _bn . sub ( bigNumberify ( other ) . _bn ) ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'div' , function ( other ) {
return new BigNumber ( this . _bn . div ( bigNumberify ( other ) . _bn ) ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'mul' , function ( other ) {
return new BigNumber ( this . _bn . mul ( bigNumberify ( other ) . _bn ) ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'mod' , function ( other ) {
return new BigNumber ( this . _bn . mod ( bigNumberify ( other ) . _bn ) ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'pow' , function ( other ) {
return new BigNumber ( this . _bn . pow ( bigNumberify ( other ) . _bn ) ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'maskn' , function ( value ) {
return new BigNumber ( this . _bn . maskn ( value ) ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'eq' , function ( other ) {
return this . _bn . eq ( bigNumberify ( other ) . _bn ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'lt' , function ( other ) {
return this . _bn . lt ( bigNumberify ( other ) . _bn ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'lte' , function ( other ) {
return this . _bn . lte ( bigNumberify ( other ) . _bn ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'gt' , function ( other ) {
return this . _bn . gt ( bigNumberify ( other ) . _bn ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'gte' , function ( other ) {
return this . _bn . gte ( bigNumberify ( other ) . _bn ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'isZero' , function ( ) {
return this . _bn . isZero ( ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'toNumber' , function ( base ) {
return this . _bn . toNumber ( ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'toString' , function ( ) {
//return this._bn.toString(base || 10);
return this . _bn . toString ( 10 ) ;
} ) ;
defineProperty ( BigNumber . prototype , 'toHexString' , function ( ) {
var hex = this . _bn . toString ( 16 ) ;
if ( hex . length % 2 ) { hex = '0' + hex ; }
return '0x' + hex ;
} ) ;
function isBigNumber ( value ) {
return ( value . _bn && value . _bn . mod ) ;
}
function bigNumberify ( value ) {
if ( isBigNumber ( value ) ) { return value ; }
return new BigNumber ( value ) ;
}
module . exports = {
isBigNumber : isBigNumber ,
bigNumberify : bigNumberify ,
BigNumber : BigNumber
} ;
2018-04-13 01:31:02 +03:00
} , { "./convert" : 11 , "./properties" : 14 , "./throw-error" : 15 , "bn.js" : 4 } ] , 11 : [ function ( require , module , exports ) {
2018-03-05 03:31:09 +03:00
/ * *
* Conversion Utilities
*
* /
var defineProperty = require ( './properties.js' ) . defineProperty ;
2018-04-13 01:31:02 +03:00
var errors = require ( './errors' ) ;
2018-03-05 03:31:09 +03:00
function addSlice ( array ) {
if ( array . slice ) { return array ; }
array . slice = function ( ) {
var args = Array . prototype . slice . call ( arguments ) ;
return new Uint8Array ( Array . prototype . slice . apply ( array , args ) ) ;
}
return array ;
}
function isArrayish ( value ) {
if ( ! value || parseInt ( value . length ) != value . length || typeof ( value ) === 'string' ) {
return false ;
}
for ( var i = 0 ; i < value . length ; i ++ ) {
var v = value [ i ] ;
if ( v < 0 || v >= 256 || parseInt ( v ) != v ) {
return false ;
}
}
return true ;
}
2018-04-13 01:31:02 +03:00
function arrayify ( value ) {
if ( value == null ) {
errors . throwError ( 'cannot convert null value to array' , errors . INVALID _ARGUMENT , { arg : 'value' , value : value } ) ;
}
2018-03-05 03:31:09 +03:00
if ( value && value . toHexString ) {
value = value . toHexString ( ) ;
}
if ( isHexString ( value ) ) {
value = value . substring ( 2 ) ;
if ( value . length % 2 ) { value = '0' + value ; }
var result = [ ] ;
for ( var i = 0 ; i < value . length ; i += 2 ) {
result . push ( parseInt ( value . substr ( i , 2 ) , 16 ) ) ;
}
return addSlice ( new Uint8Array ( result ) ) ;
2018-04-13 01:31:02 +03:00
} else if ( typeof ( value ) === 'string' ) {
if ( value . match ( /^[0-9a-fA-F]*$/ ) ) {
errors . throwError ( 'hex string must have 0x prefix' , errors . INVALID _ARGUMENT , { arg : 'value' , value : value } ) ;
}
errors . throwError ( 'invalid hexidecimal string' , errors . INVALID _ARGUMENT , { arg : 'value' , value : value } ) ;
2018-03-05 03:31:09 +03:00
}
if ( isArrayish ( value ) ) {
return addSlice ( new Uint8Array ( value ) ) ;
}
2018-04-13 01:31:02 +03:00
errors . throwError ( 'invalid arrayify value' , { arg : 'value' , value : value , type : typeof ( value ) } ) ;
2018-03-05 03:31:09 +03:00
}
function concat ( objects ) {
var arrays = [ ] ;
var length = 0 ;
for ( var i = 0 ; i < objects . length ; i ++ ) {
var object = arrayify ( objects [ i ] )
arrays . push ( object ) ;
length += object . length ;
}
var result = new Uint8Array ( length ) ;
var offset = 0 ;
for ( var i = 0 ; i < arrays . length ; i ++ ) {
result . set ( arrays [ i ] , offset ) ;
offset += arrays [ i ] . length ;
}
return addSlice ( result ) ;
}
function stripZeros ( value ) {
value = arrayify ( value ) ;
if ( value . length === 0 ) { return value ; }
// Find the first non-zero entry
var start = 0 ;
while ( value [ start ] === 0 ) { start ++ }
// If we started with zeros, strip them
if ( start ) {
value = value . slice ( start ) ;
}
return value ;
}
function padZeros ( value , length ) {
value = arrayify ( value ) ;
if ( length < value . length ) { throw new Error ( 'cannot pad' ) ; }
var result = new Uint8Array ( length ) ;
result . set ( value , length - value . length ) ;
return addSlice ( result ) ;
}
function isHexString ( value , length ) {
if ( typeof ( value ) !== 'string' || ! value . match ( /^0x[0-9A-Fa-f]*$/ ) ) {
return false
}
if ( length && value . length !== 2 + 2 * length ) { return false ; }
return true ;
}
var HexCharacters = '0123456789abcdef' ;
2018-04-13 01:31:02 +03:00
function hexlify ( value ) {
2018-03-05 03:31:09 +03:00
if ( value && value . toHexString ) {
return value . toHexString ( ) ;
}
if ( typeof ( value ) === 'number' ) {
if ( value < 0 ) {
2018-04-13 01:31:02 +03:00
errors . throwError ( 'cannot hexlify negative value' , errors . INVALID _ARG , { arg : 'value' , value : value } ) ;
2018-03-05 03:31:09 +03:00
}
var hex = '' ;
while ( value ) {
hex = HexCharacters [ value & 0x0f ] + hex ;
value = parseInt ( value / 16 ) ;
}
if ( hex . length ) {
if ( hex . length % 2 ) { hex = '0' + hex ; }
return '0x' + hex ;
}
return '0x00' ;
}
if ( isHexString ( value ) ) {
if ( value . length % 2 ) {
value = '0x0' + value . substring ( 2 ) ;
}
return value ;
}
if ( isArrayish ( value ) ) {
var result = [ ] ;
for ( var i = 0 ; i < value . length ; i ++ ) {
var v = value [ i ] ;
result . push ( HexCharacters [ ( v & 0xf0 ) >> 4 ] + HexCharacters [ v & 0x0f ] ) ;
}
return '0x' + result . join ( '' ) ;
}
2018-04-13 01:31:02 +03:00
errors . throwError ( 'invalid hexlify value' , { arg : 'value' , value : value } ) ;
2018-03-05 03:31:09 +03:00
}
function hexStripZeros ( value ) {
while ( value . length > 3 && value . substring ( 0 , 3 ) === '0x0' ) {
value = '0x' + value . substring ( 3 ) ;
}
return value ;
}
function hexZeroPad ( value , length ) {
while ( value . length < 2 * length + 2 ) {
value = '0x0' + value . substring ( 2 ) ;
}
return value ;
}
2018-04-13 01:31:02 +03:00
/ * @ T O D O : A d d s o m e t h i n g l i k e t h i s t o m a k e s l i c i n g c o d e e a s i e r t o u n d e r s t a n d
function hexSlice ( hex , start , end ) {
hex = hexlify ( hex ) ;
return '0x' + hex . substring ( 2 + start * 2 , 2 + end * 2 ) ;
}
* /
function splitSignature ( signature ) {
signature = arrayify ( signature ) ;
if ( signature . length !== 65 ) {
throw new Error ( 'invalid signature' ) ;
}
var v = signature [ 64 ] ;
if ( v !== 27 && v !== 28 ) {
v = 27 + ( v % 2 ) ;
}
return {
r : hexlify ( signature . slice ( 0 , 32 ) ) ,
s : hexlify ( signature . slice ( 32 , 64 ) ) ,
v : v
}
}
2018-03-05 03:31:09 +03:00
module . exports = {
arrayify : arrayify ,
isArrayish : isArrayish ,
concat : concat ,
padZeros : padZeros ,
stripZeros : stripZeros ,
2018-04-13 01:31:02 +03:00
splitSignature : splitSignature ,
2018-03-05 03:31:09 +03:00
hexlify : hexlify ,
isHexString : isHexString ,
hexStripZeros : hexStripZeros ,
hexZeroPad : hexZeroPad ,
} ;
2018-04-13 01:31:02 +03:00
} , { "./errors" : 12 , "./properties.js" : 14 } ] , 12 : [ function ( require , module , exports ) {
'use strict' ;
var defineProperty = require ( './properties' ) . defineProperty ;
var codes = { } ;
[
// Unknown Error
'UNKNOWN_ERROR' ,
2018-04-14 01:21:48 +03:00
// Not implemented
'NOT_IMPLEMENTED' ,
2018-04-13 01:31:02 +03:00
// Missing new operator to an object
// - name: The name of the class
'MISSING_NEW' ,
2018-04-14 01:21:48 +03:00
2018-04-17 04:42:17 +03:00
// Call exception
'CALL_EXCEPTION' ,
// Response from a server was invalid
// - response: The body of the response
//'BAD_RESPONSE',
2018-04-14 01:21:48 +03:00
// Invalid argument (e.g. type) to a function:
2018-04-13 01:31:02 +03:00
// - arg: The argument name that was invalid
2018-04-17 04:42:17 +03:00
// - value: The value of the argument
// - type: The type of the argument
// - expected: What was expected
2018-04-14 01:21:48 +03:00
'INVALID_ARGUMENT' ,
// Missing argument to a function:
// - arg: The argument name that is required
2018-04-17 04:42:17 +03:00
// - count: The number of arguments received
// - expectedCount: The number of arguments expected
2018-04-14 01:21:48 +03:00
'MISSING_ARGUMENT' ,
// Too many arguments
2018-04-17 04:42:17 +03:00
// - count: The number of arguments received
// - expectedCount: The number of arguments expected
2018-04-14 01:21:48 +03:00
'UNEXPECTED_ARGUMENT' ,
// Unsupported operation
// - operation
'UNSUPPORTED_OPERATION' ,
2018-04-13 01:31:02 +03:00
] . forEach ( function ( code ) {
defineProperty ( codes , code , code ) ;
} ) ;
defineProperty ( codes , 'throwError' , function ( message , code , params ) {
if ( ! code ) { code = codes . UNKNOWN _ERROR ; }
if ( ! params ) { params = { } ; }
var messageDetails = [ ] ;
Object . keys ( params ) . forEach ( function ( key ) {
2018-04-17 04:42:17 +03:00
try {
messageDetails . push ( key + '=' + JSON . stringify ( params [ key ] ) ) ;
} catch ( error ) {
messageDetails . push ( key + '=' + JSON . stringify ( params [ key ] . toString ( ) ) ) ;
}
2018-04-13 01:31:02 +03:00
} ) ;
var reason = message ;
if ( messageDetails . length ) {
message += ' (' + messageDetails . join ( ', ' ) + ')' ;
}
var error = new Error ( message ) ;
error . reason = reason ;
error . code = code
Object . keys ( params ) . forEach ( function ( key ) {
error [ key ] = params [ key ] ;
} ) ;
throw error ;
} ) ;
defineProperty ( codes , 'checkNew' , function ( self , kind ) {
if ( ! ( self instanceof kind ) ) {
codes . throwError ( 'missing new' , codes . MISSING _NEW , { name : kind . name } ) ;
}
} ) ;
module . exports = codes ;
} , { "./properties" : 14 } ] , 13 : [ function ( require , module , exports ) {
2018-03-05 03:31:09 +03:00
'use strict' ;
var sha3 = require ( 'js-sha3' ) ;
var convert = require ( './convert.js' ) ;
function keccak256 ( data ) {
data = convert . arrayify ( data ) ;
return '0x' + sha3 . keccak _256 ( data ) ;
}
module . exports = keccak256 ;
2018-04-13 01:31:02 +03:00
} , { "./convert.js" : 11 , "js-sha3" : 6 } ] , 14 : [ function ( require , module , exports ) {
2018-03-05 03:31:09 +03:00
'use strict' ;
function defineProperty ( object , name , value ) {
Object . defineProperty ( object , name , {
enumerable : true ,
value : value ,
writable : false ,
} ) ;
}
function defineFrozen ( object , name , value ) {
var frozen = JSON . stringify ( value ) ;
Object . defineProperty ( object , name , {
enumerable : true ,
get : function ( ) { return JSON . parse ( frozen ) ; }
} ) ;
}
module . exports = {
defineFrozen : defineFrozen ,
defineProperty : defineProperty ,
} ;
2018-04-13 01:31:02 +03:00
} , { } ] , 15 : [ function ( require , module , exports ) {
2018-03-05 03:31:09 +03:00
'use strict' ;
function throwError ( message , params ) {
var error = new Error ( message ) ;
for ( var key in params ) {
error [ key ] = params [ key ] ;
}
throw error ;
}
module . exports = throwError ;
2018-04-13 01:31:02 +03:00
} , { } ] , 16 : [ function ( require , module , exports ) {
2018-03-05 03:31:09 +03:00
var convert = require ( './convert.js' ) ;
// http://stackoverflow.com/questions/18729405/how-to-convert-utf8-string-to-byte-array
function utf8ToBytes ( str ) {
var result = [ ] ;
var offset = 0 ;
for ( var i = 0 ; i < str . length ; i ++ ) {
var c = str . charCodeAt ( i ) ;
if ( c < 128 ) {
result [ offset ++ ] = c ;
} else if ( c < 2048 ) {
result [ offset ++ ] = ( c >> 6 ) | 192 ;
result [ offset ++ ] = ( c & 63 ) | 128 ;
} else if ( ( ( c & 0xFC00 ) == 0xD800 ) && ( i + 1 ) < str . length && ( ( str . charCodeAt ( i + 1 ) & 0xFC00 ) == 0xDC00 ) ) {
// Surrogate Pair
c = 0x10000 + ( ( c & 0x03FF ) << 10 ) + ( str . charCodeAt ( ++ i ) & 0x03FF ) ;
result [ offset ++ ] = ( c >> 18 ) | 240 ;
result [ offset ++ ] = ( ( c >> 12 ) & 63 ) | 128 ;
result [ offset ++ ] = ( ( c >> 6 ) & 63 ) | 128 ;
result [ offset ++ ] = ( c & 63 ) | 128 ;
} else {
result [ offset ++ ] = ( c >> 12 ) | 224 ;
result [ offset ++ ] = ( ( c >> 6 ) & 63 ) | 128 ;
result [ offset ++ ] = ( c & 63 ) | 128 ;
}
}
return convert . arrayify ( result ) ;
} ;
// http://stackoverflow.com/questions/13356493/decode-utf-8-with-javascript#13691499
function bytesToUtf8 ( bytes ) {
bytes = convert . arrayify ( bytes ) ;
var result = '' ;
var i = 0 ;
// Invalid bytes are ignored
while ( i < bytes . length ) {
var c = bytes [ i ++ ] ;
if ( c >> 7 == 0 ) {
// 0xxx xxxx
result += String . fromCharCode ( c ) ;
continue ;
}
// Invalid starting byte
if ( c >> 6 == 0x02 ) { continue ; }
// Multibyte; how many bytes left for thus character?
var extraLength = null ;
if ( c >> 5 == 0x06 ) {
extraLength = 1 ;
} else if ( c >> 4 == 0x0e ) {
extraLength = 2 ;
} else if ( c >> 3 == 0x1e ) {
extraLength = 3 ;
} else if ( c >> 2 == 0x3e ) {
extraLength = 4 ;
} else if ( c >> 1 == 0x7e ) {
extraLength = 5 ;
} else {
continue ;
}
// Do we have enough bytes in our data?
if ( i + extraLength > bytes . length ) {
// If there is an invalid unprocessed byte, try to continue
for ( ; i < bytes . length ; i ++ ) {
if ( bytes [ i ] >> 6 != 0x02 ) { break ; }
}
if ( i != bytes . length ) continue ;
// All leftover bytes are valid.
return result ;
}
// Remove the UTF-8 prefix from the char (res)
var res = c & ( ( 1 << ( 8 - extraLength - 1 ) ) - 1 ) ;
var count ;
for ( count = 0 ; count < extraLength ; count ++ ) {
var nextChar = bytes [ i ++ ] ;
// Is the char valid multibyte part?
if ( nextChar >> 6 != 0x02 ) { break ; } ;
res = ( res << 6 ) | ( nextChar & 0x3f ) ;
}
if ( count != extraLength ) {
i -- ;
continue ;
}
if ( res <= 0xffff ) {
result += String . fromCharCode ( res ) ;
continue ;
}
res -= 0x10000 ;
result += String . fromCharCode ( ( ( res >> 10 ) & 0x3ff ) + 0xd800 , ( res & 0x3ff ) + 0xdc00 ) ;
}
return result ;
}
module . exports = {
toUtf8Bytes : utf8ToBytes ,
toUtf8String : bytesToUtf8 ,
} ;
} , { "./convert.js" : 11 } ] } , { } , [ 2 ] ) ( 2 )
2018-06-04 03:50:21 +03:00
} ) ;