blocktrail-sdk
Version:
BlockTrail's Developer Friendly API binding for NodeJS
180 lines (157 loc) • 6.21 kB
JavaScript
/* ----------------------------------------------------------------------
* Copyright (c) 2014 Artem S Vybornov
*
* Copyright (c) 2012 Yves-Marie K. Rinquin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* ----------------------------------------------------------------------
*
* ISAAC is a cryptographically secure pseudo-random number generator
* (or CSPRNG for short) designed by Robert J. Jenkins Jr. in 1996 and
* based on RC4. It is designed for speed and security.
*
* ISAAC's informations & analysis:
* http://burtleburtle.net/bob/rand/isaac.html
* ISAAC's implementation details:
* http://burtleburtle.net/bob/rand/isaacafa.html
*
* ISAAC succesfully passed TestU01
*/
var ISAAC = ( function () {
var m = new Uint32Array(256), // internal memory
r = new Uint32Array(256), // result array
acc = 0, // accumulator
brs = 0, // last result
cnt = 0, // counter
gnt = 0; // generation counter
/* private: randinit function, same as ISAAC reference implementation */
function randinit() {
var a, b, c, d, e, f, g, h;
/* private mixing function */
function mix () {
a ^= b << 11; d = (d + a)|0; b = (b + c)|0;
b ^= c >>> 2; e = (e + b)|0; c = (c + d)|0;
c ^= d << 8; f = (f + c)|0; d = (d + e)|0;
d ^= e >>> 16; g = (g + d)|0; e = (e + f)|0;
e ^= f << 10; h = (h + e)|0; f = (f + g)|0;
f ^= g >>> 4; a = (a + f)|0; g = (g + h)|0;
g ^= h << 8; b = (b + g)|0; h = (h + a)|0;
h ^= a >>> 9; c = (c + h)|0; a = (a + b)|0;
}
acc = brs = cnt = 0;
// the golden ratio
a = b = c = d = e = f = g = h = 0x9e3779b9;
// scramble it
for ( var i = 0; i < 4; i++ )
mix();
// mix it and combine with the internal state
for ( var i = 0; i < 256; i += 8 ) {
a = (a + r[i|0])|0; b = (b + r[i|1])|0;
c = (c + r[i|2])|0; d = (d + r[i|3])|0;
e = (e + r[i|4])|0; f = (f + r[i|5])|0;
g = (g + r[i|6])|0; h = (h + r[i|7])|0;
mix();
m.set([a, b, c, d, e, f, g, h], i);
}
// mix it again
for ( var i = 0; i < 256; i += 8 ) {
a = (a + m[i|0])|0; b = (b + m[i|1])|0;
c = (c + m[i|2])|0; d = (d + m[i|3])|0;
e = (e + m[i|4])|0; f = (f + m[i|5])|0;
g = (g + m[i|6])|0; h = (h + m[i|7])|0;
mix();
m.set([a, b, c, d, e, f, g, h], i);
}
// fill in the first set of results
prng(1), gnt = 256;
}
/* public: seeding function */
function seed ( s ) {
var i, j, k, n, l;
if ( !is_typed_array(s) ) {
if ( is_number(s) ) {
n = new FloatArray(1), n[0] = s;
s = new Uint8Array(n.buffer);
}
else if ( is_string(s) ) {
s = string_to_bytes(s);
}
else if ( is_buffer(s) ) {
s = new Uint8Array(s);
}
else {
throw new TypeError("bad seed type");
}
}
else {
s = new Uint8Array(s.buffer);
}
// preprocess the seed
l = s.length;
for ( j = 0; j < l; j += 1024 )
{
// xor each chunk of 1024 bytes with r, for randinit() to mix in
for ( k = j, i = 0; ( i < 1024 ) && ( k < l ); k = j | (++i) ) {
r[i >> 2] ^= ( s[k] << ( (i & 3) << 3 ) );
}
randinit();
}
}
/* public: isaac generator, n = number of run */
function prng ( n ) {
n = n || 1;
var i, x, y;
while ( n-- ) {
cnt = (cnt + 1)|0;
brs = (brs + cnt)|0;
for ( i = 0; i < 256; i += 4 ) {
acc ^= acc << 13;
acc = m[(i + 128) & 0xff] + acc | 0; x = m[i|0];
m[i|0] = y = m[(x>>>2) & 0xff] + ( acc + brs | 0 ) | 0;
r[i|0] = brs = m[(y>>>10) & 0xff] + x | 0;
acc ^= acc >>> 6;
acc = m[(i + 129) & 0xff] + acc | 0; x = m[i|1];
m[i|1] = y = m[(x >>> 2) & 0xff] + ( acc + brs | 0 ) | 0;
r[i|1] = brs = m[(y >>> 10) & 0xff] + x | 0;
acc ^= acc << 2;
acc = m[(i + 130) & 0xff] + acc | 0; x = m[i|2];
m[i|2] = y = m[(x >>> 2) & 0xff] + ( acc + brs | 0 ) | 0;
r[i|2] = brs = m[(y >>> 10) & 0xff] + x | 0;
acc ^= acc >>> 16;
acc = m[(i + 131) & 0xff] + acc | 0; x = m[i|3];
m[i|3] = y = m[(x >>> 2) & 0xff] + (acc + brs | 0 ) | 0;
r[i|3] = brs = m[(y >>> 10) & 0xff] + x | 0;
}
}
}
/* public: return a random number */
function rand() {
if ( !gnt-- )
prng(1), gnt = 255;
return r[gnt];
}
/* return class object */
return {
'seed': seed,
'prng': prng,
'rand': rand
};
})();