You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
229 lines
5.9 KiB
229 lines
5.9 KiB
11 years ago
|
// BigInteger monkey patching
|
||
|
BigInteger.valueOf = nbv;
|
||
|
|
||
|
/**
|
||
|
* Returns a byte array representation of the big integer.
|
||
|
*
|
||
|
* This returns the absolute of the contained value in big endian
|
||
|
* form. A value of zero results in an empty array.
|
||
|
*/
|
||
|
BigInteger.prototype.toByteArrayUnsigned = function () {
|
||
|
var ba = this.abs().toByteArray();
|
||
|
if (ba.length) {
|
||
|
if (ba[0] == 0) {
|
||
|
ba = ba.slice(1);
|
||
|
}
|
||
|
return ba.map(function (v) {
|
||
|
return (v < 0) ? v + 256 : v;
|
||
|
});
|
||
|
} else {
|
||
|
// Empty array, nothing to do
|
||
|
return ba;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Turns a byte array into a big integer.
|
||
|
*
|
||
|
* This function will interpret a byte array as a big integer in big
|
||
|
* endian notation and ignore leading zeros.
|
||
|
*/
|
||
|
BigInteger.fromByteArrayUnsigned = function (ba) {
|
||
|
if (!ba.length) {
|
||
|
return ba.valueOf(0);
|
||
|
} else if (ba[0] & 0x80) {
|
||
|
// Prepend a zero so the BigInteger class doesn't mistake this
|
||
|
// for a negative integer.
|
||
|
return new BigInteger([0].concat(ba));
|
||
|
} else {
|
||
|
return new BigInteger(ba);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Converts big integer to signed byte representation.
|
||
|
*
|
||
|
* The format for this value uses a the most significant bit as a sign
|
||
|
* bit. If the most significant bit is already occupied by the
|
||
|
* absolute value, an extra byte is prepended and the sign bit is set
|
||
|
* there.
|
||
|
*
|
||
|
* Examples:
|
||
|
*
|
||
|
* 0 => 0x00
|
||
|
* 1 => 0x01
|
||
|
* -1 => 0x81
|
||
|
* 127 => 0x7f
|
||
|
* -127 => 0xff
|
||
|
* 128 => 0x0080
|
||
|
* -128 => 0x8080
|
||
|
* 255 => 0x00ff
|
||
|
* -255 => 0x80ff
|
||
|
* 16300 => 0x3fac
|
||
|
* -16300 => 0xbfac
|
||
|
* 62300 => 0x00f35c
|
||
|
* -62300 => 0x80f35c
|
||
|
*/
|
||
|
BigInteger.prototype.toByteArraySigned = function () {
|
||
|
var val = this.abs().toByteArrayUnsigned();
|
||
|
var neg = this.compareTo(BigInteger.ZERO) < 0;
|
||
|
|
||
|
if (neg) {
|
||
|
if (val[0] & 0x80) {
|
||
|
val.unshift(0x80);
|
||
|
} else {
|
||
|
val[0] |= 0x80;
|
||
|
}
|
||
|
} else {
|
||
|
if (val[0] & 0x80) {
|
||
|
val.unshift(0x00);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return val;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Parse a signed big integer byte representation.
|
||
|
*
|
||
|
* For details on the format please see BigInteger.toByteArraySigned.
|
||
|
*/
|
||
|
BigInteger.fromByteArraySigned = function (ba) {
|
||
|
// Check for negative value
|
||
|
if (ba[0] & 0x80) {
|
||
|
// Remove sign bit
|
||
|
ba[0] &= 0x7f;
|
||
|
|
||
|
return BigInteger.fromByteArrayUnsigned(ba).negate();
|
||
|
} else {
|
||
|
return BigInteger.fromByteArrayUnsigned(ba);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Console ignore
|
||
|
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
|
||
|
"dirxml", "group", "groupEnd", "time", "timeEnd", "count",
|
||
|
"trace", "profile", "profileEnd"];
|
||
|
|
||
|
if ("undefined" == typeof window.console) window.console = {};
|
||
|
for (var i = 0; i < names.length; ++i)
|
||
|
if ("undefined" == typeof window.console[names[i]])
|
||
|
window.console[names[i]] = function() {};
|
||
|
|
||
|
// Bitcoin utility functions
|
||
|
Bitcoin.Util = {
|
||
|
/**
|
||
|
* Cross-browser compatibility version of Array.isArray.
|
||
|
*/
|
||
|
isArray: Array.isArray || function(o)
|
||
|
{
|
||
|
return Object.prototype.toString.call(o) === '[object Array]';
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Create an array of a certain length filled with a specific value.
|
||
|
*/
|
||
|
makeFilledArray: function (len, val)
|
||
|
{
|
||
|
var array = [];
|
||
|
var i = 0;
|
||
|
while (i < len) {
|
||
|
array[i++] = val;
|
||
|
}
|
||
|
return array;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Turn an integer into a "var_int".
|
||
|
*
|
||
|
* "var_int" is a variable length integer used by Bitcoin's binary format.
|
||
|
*
|
||
|
* Returns a byte array.
|
||
|
*/
|
||
|
numToVarInt: function (i)
|
||
|
{
|
||
|
if (i < 0xfd) {
|
||
|
// unsigned char
|
||
|
return [i];
|
||
|
} else if (i <= 1<<16) {
|
||
|
// unsigned short (LE)
|
||
|
return [0xfd, i >>> 8, i & 255];
|
||
|
} else if (i <= 1<<32) {
|
||
|
// unsigned int (LE)
|
||
|
return [0xfe].concat(Crypto.util.wordsToBytes([i]));
|
||
|
} else {
|
||
|
// unsigned long long (LE)
|
||
|
return [0xff].concat(Crypto.util.wordsToBytes([i >>> 32, i]));
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Parse a Bitcoin value byte array, returning a BigInteger.
|
||
|
*/
|
||
|
valueToBigInt: function (valueBuffer)
|
||
|
{
|
||
|
if (valueBuffer instanceof BigInteger) return valueBuffer;
|
||
|
|
||
|
// Prepend zero byte to prevent interpretation as negative integer
|
||
|
return BigInteger.fromByteArrayUnsigned(valueBuffer);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Format a Bitcoin value as a string.
|
||
|
*
|
||
|
* Takes a BigInteger or byte-array and returns that amount of Bitcoins in a
|
||
|
* nice standard formatting.
|
||
|
*
|
||
|
* Examples:
|
||
|
* 12.3555
|
||
|
* 0.1234
|
||
|
* 900.99998888
|
||
|
* 34.00
|
||
|
*/
|
||
|
formatValue: function (valueBuffer) {
|
||
|
var value = this.valueToBigInt(valueBuffer).toString();
|
||
|
var integerPart = value.length > 8 ? value.substr(0, value.length-8) : '0';
|
||
|
var decimalPart = value.length > 8 ? value.substr(value.length-8) : value;
|
||
|
while (decimalPart.length < 8) decimalPart = "0"+decimalPart;
|
||
|
decimalPart = decimalPart.replace(/0*$/, '');
|
||
|
while (decimalPart.length < 2) decimalPart += "0";
|
||
|
return integerPart+"."+decimalPart;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Parse a floating point string as a Bitcoin value.
|
||
|
*
|
||
|
* Keep in mind that parsing user input is messy. You should always display
|
||
|
* the parsed value back to the user to make sure we understood his input
|
||
|
* correctly.
|
||
|
*/
|
||
|
parseValue: function (valueString) {
|
||
|
// TODO: Detect other number formats (e.g. comma as decimal separator)
|
||
|
var valueComp = valueString.split('.');
|
||
|
var integralPart = valueComp[0];
|
||
|
var fractionalPart = valueComp[1] || "0";
|
||
|
while (fractionalPart.length < 8) fractionalPart += "0";
|
||
|
fractionalPart = fractionalPart.replace(/^0+/g, '');
|
||
|
var value = BigInteger.valueOf(parseInt(integralPart));
|
||
|
value = value.multiply(BigInteger.valueOf(100000000));
|
||
|
value = value.add(BigInteger.valueOf(parseInt(fractionalPart)));
|
||
|
return value;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Calculate RIPEMD160(SHA256(data)).
|
||
|
*
|
||
|
* Takes an arbitrary byte array as inputs and returns the hash as a byte
|
||
|
* array.
|
||
|
*/
|
||
|
sha256ripe160: function (data) {
|
||
|
return Crypto.RIPEMD160(Crypto.SHA256(data, {asBytes: true}), {asBytes: true});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
for (var i in Crypto.util) {
|
||
|
if (Crypto.util.hasOwnProperty(i)) {
|
||
|
Bitcoin.Util[i] = Crypto.util[i];
|
||
|
}
|
||
|
}
|