Beta 7 with some repo names changed.
This commit is contained in:
1 parent
0f7b40cca7
commit
963c19493a
3408 files changed
+462217
-15516
No files matched your search
+57
@@ -0,0 +1,57 @@
|
||||
// type Var = {
|
||||
// name: String
|
||||
// type: "uint256" | "bytes32" | ...
|
||||
// }
|
||||
//
|
||||
// type Method = {
|
||||
// name: String
|
||||
// inputs: [Var]
|
||||
// output: [Var]
|
||||
// constant: Bool
|
||||
// payable: Bool
|
||||
// }
|
||||
|
||||
const Bytes = require("./bytes");
|
||||
const Nat = require("./nat");
|
||||
const keccak256s = require("./hash").keccak256s;
|
||||
|
||||
// (type : String), JSType(type) -> {data: Bytes, dynamic: Bool}
|
||||
// ABI-encodes a single term.
|
||||
const encode = (type, value) => {
|
||||
if (type === "bytes") {
|
||||
const length = Bytes.length(value);
|
||||
const nextMul32 = (((length - 1) / 32 | 0) + 1) * 32;
|
||||
const lengthEncoded = encode("uint256", Nat.fromNumber(length)).data;
|
||||
const bytesEncoded = Bytes.padRight(nextMul32, value);
|
||||
return { data: Bytes.concat(lengthEncoded, bytesEncoded), dynamic: true };
|
||||
} else if (type === "uint256" || type === "bytes32" || type === "address") {
|
||||
return { data: Bytes.pad(32, value), dynamic: false };
|
||||
} else {
|
||||
throw "Eth-lib can't encode ABI type " + type + " yet.";
|
||||
}
|
||||
};
|
||||
|
||||
// (method : Method), [JSType(method.inputs[i].type)] -> Bytes
|
||||
// ABI-encodes the transaction data to call a method.
|
||||
const methodData = (method, params) => {
|
||||
const methodSig = method.name + "(" + method.inputs.map(i => i.type).join(",") + ")";
|
||||
const methodHash = keccak256s(methodSig).slice(0, 10);
|
||||
let encodedParams = params.map((param, i) => encode(method.inputs[i].type, param));
|
||||
var headBlock = "0x";
|
||||
let dataBlock = "0x";
|
||||
for (var i = 0; i < encodedParams.length; ++i) {
|
||||
if (encodedParams[i].dynamic) {
|
||||
var dataLoc = encodedParams.length * 32 + Bytes.length(dataBlock);
|
||||
headBlock = Bytes.concat(headBlock, Bytes.pad(32, Nat.fromNumber(dataLoc)));
|
||||
dataBlock = Bytes.concat(dataBlock, encodedParams[i].data);
|
||||
} else {
|
||||
headBlock = Bytes.concat(headBlock, encodedParams[i].data);
|
||||
}
|
||||
}
|
||||
return Bytes.flatten([methodHash, headBlock, dataBlock]);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
encode,
|
||||
methodData
|
||||
};
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
const Bytes = require("./bytes");
|
||||
const Nat = require("./nat");
|
||||
const elliptic = require("elliptic");
|
||||
const rlp = require("./rlp");
|
||||
const secp256k1 = new elliptic.ec("secp256k1"); // eslint-disable-line
|
||||
const { keccak256, keccak256s } = require("./hash");
|
||||
|
||||
const create = entropy => {
|
||||
const innerHex = keccak256(Bytes.concat(Bytes.random(32), entropy || Bytes.random(32)));
|
||||
const middleHex = Bytes.concat(Bytes.concat(Bytes.random(32), innerHex), Bytes.random(32));
|
||||
const outerHex = keccak256(middleHex);
|
||||
return fromPrivate(outerHex);
|
||||
};
|
||||
|
||||
const toChecksum = address => {
|
||||
const addressHash = keccak256s(address.slice(2));
|
||||
let checksumAddress = "0x";
|
||||
for (let i = 0; i < 40; i++) checksumAddress += parseInt(addressHash[i + 2], 16) > 7 ? address[i + 2].toUpperCase() : address[i + 2];
|
||||
return checksumAddress;
|
||||
};
|
||||
|
||||
const fromPrivate = privateKey => {
|
||||
const buffer = new Buffer(privateKey.slice(2), "hex");
|
||||
const ecKey = secp256k1.keyFromPrivate(buffer);
|
||||
const publicKey = "0x" + ecKey.getPublic(false, 'hex').slice(2);
|
||||
const publicHash = keccak256(publicKey);
|
||||
const address = toChecksum("0x" + publicHash.slice(-40));
|
||||
return {
|
||||
address: address,
|
||||
privateKey: privateKey
|
||||
};
|
||||
};
|
||||
|
||||
const encodeSignature = ([v, r, s]) => Bytes.flatten([r, s, v]);
|
||||
|
||||
const decodeSignature = hex => [Bytes.slice(64, Bytes.length(hex), hex), Bytes.slice(0, 32, hex), Bytes.slice(32, 64, hex)];
|
||||
|
||||
const makeSigner = addToV => (hash, privateKey) => {
|
||||
const signature = secp256k1.keyFromPrivate(new Buffer(privateKey.slice(2), "hex")).sign(new Buffer(hash.slice(2), "hex"), { canonical: true });
|
||||
return encodeSignature([Nat.fromString(Bytes.fromNumber(addToV + signature.recoveryParam)), Bytes.pad(32, Bytes.fromNat("0x" + signature.r.toString(16))), Bytes.pad(32, Bytes.fromNat("0x" + signature.s.toString(16)))]);
|
||||
};
|
||||
|
||||
const sign = makeSigner(27); // v=27|28 instead of 0|1...
|
||||
|
||||
const recover = (hash, signature) => {
|
||||
const vals = decodeSignature(signature);
|
||||
const vrs = { v: Bytes.toNumber(vals[0]), r: vals[1].slice(2), s: vals[2].slice(2) };
|
||||
const ecPublicKey = secp256k1.recoverPubKey(new Buffer(hash.slice(2), "hex"), vrs, vrs.v < 2 ? vrs.v : 1 - vrs.v % 2); // because odd vals mean v=0... sadly that means v=0 means v=1... I hate that
|
||||
const publicKey = "0x" + ecPublicKey.encode("hex", false).slice(2);
|
||||
const publicHash = keccak256(publicKey);
|
||||
const address = toChecksum("0x" + publicHash.slice(-40));
|
||||
return address;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
create,
|
||||
toChecksum,
|
||||
fromPrivate,
|
||||
sign,
|
||||
makeSigner,
|
||||
recover,
|
||||
encodeSignature,
|
||||
decodeSignature
|
||||
};
|
||||
+241
@@ -0,0 +1,241 @@
|
||||
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
||||
|
||||
var Api = function Api(provider) {
|
||||
var Nat = require("./nat");
|
||||
var Map = require("./map");
|
||||
var Bytes = require("./bytes");
|
||||
var keccak256s = require("./hash").keccak256s;
|
||||
var send = function send(method) {
|
||||
return function () {
|
||||
for (var _len = arguments.length, params = Array(_len), _key = 0; _key < _len; _key++) {
|
||||
params[_key] = arguments[_key];
|
||||
}
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
return provider.send(method, params, function (err, result) {
|
||||
return err ? reject(err) : resolve(result);
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
// TODO check inputs
|
||||
// TODO move to proper file
|
||||
var encodeABI = function encodeABI(type, value) {
|
||||
if (type === "bytes") {
|
||||
var length = Bytes.length(value);
|
||||
var nextMul32 = (((length - 1) / 32 | 0) + 1) * 32;
|
||||
var lengthEncoded = encodeABI("uint256", Nat.fromNumber(length)).data;
|
||||
var bytesEncoded = Bytes.padRight(nextMul32, value);
|
||||
return { data: Bytes.concat(lengthEncoded, bytesEncoded), dynamic: true };
|
||||
} else if (type === "uint256" || type === "bytes32" || type === "address") {
|
||||
return { data: Bytes.pad(32, value), dynamic: false };
|
||||
} else {
|
||||
throw "Eth-lib can't encode ABI type " + type + " yet.";
|
||||
}
|
||||
};
|
||||
|
||||
var sendTransaction = send("eth_sendTransaction");
|
||||
var sendRawTransaction = send("eth_sendRawTransaction");
|
||||
var getTransactionReceipt = send("eth_getTransactionReceipt");
|
||||
var compileSolidity = send("eth_compileSolidity");
|
||||
var call = send("eth_call");
|
||||
var getBalance = send("eth_getBalance");
|
||||
var accounts = send("eth_accounts");
|
||||
|
||||
var removeEmptyTo = function removeEmptyTo(tx) {
|
||||
return tx.to === "" || tx.to === "0x" ? Map.remove("to")(tx) : tx;
|
||||
};
|
||||
|
||||
var waitTransactionReceipt = getTransactionReceipt; // TODO: implement correctly
|
||||
|
||||
var addTransactionDefaults = async function addTransactionDefaults(tx) {
|
||||
var baseDefaults = [tx.chainId || send("net_version")(), tx.gasPrice || send("eth_gasPrice")(), tx.nonce || send("eth_getTransactionCount")(tx.from, "latest"), tx.value || "0x0", tx.data || "0x"];
|
||||
|
||||
var _ref = await Promise.all(baseDefaults),
|
||||
_ref2 = _slicedToArray(_ref, 5),
|
||||
chainIdNum = _ref2[0],
|
||||
gasPrice = _ref2[1],
|
||||
nonce = _ref2[2],
|
||||
value = _ref2[3],
|
||||
data = _ref2[4];
|
||||
|
||||
var chainId = Nat.fromNumber(chainIdNum);
|
||||
var from = tx.from;
|
||||
var to = tx.to === "" || tx.to === "0x" ? null : tx.to;
|
||||
var gas = tx.gas ? tx.gas : Nat.div(Nat.mul((await send("eth_estimateGas")({
|
||||
from: tx.from,
|
||||
to: tx.to,
|
||||
value: tx.value,
|
||||
nonce: tx.nonce,
|
||||
data: tx.data
|
||||
})), "0x6"), "0x5");
|
||||
|
||||
return {
|
||||
chainId: chainId,
|
||||
from: from.toLowerCase(),
|
||||
to: to.toLowerCase(),
|
||||
gasPrice: gasPrice,
|
||||
gas: gas,
|
||||
nonce: nonce,
|
||||
value: value,
|
||||
data: data.toLowerCase()
|
||||
};
|
||||
};
|
||||
|
||||
var sendTransactionWithDefaults = async function sendTransactionWithDefaults(tx) {
|
||||
return sendTransaction(removeEmptyTo((await addTransactionDefaults(tx))));
|
||||
};
|
||||
|
||||
var callWithDefaults = function callWithDefaults(tx, block) {
|
||||
return addTransactionDefaults(tx).then(function (tx) {
|
||||
return call(removeEmptyTo(tx), block || "latest");
|
||||
});
|
||||
};
|
||||
|
||||
var callMethodData = function callMethodData(method) {
|
||||
return function () {
|
||||
for (var _len2 = arguments.length, params = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
||||
params[_key2] = arguments[_key2];
|
||||
}
|
||||
|
||||
var methodSig = method.name + "(" + method.inputs.map(function (i) {
|
||||
return i.type;
|
||||
}).join(",") + ")";
|
||||
var methodHash = keccak256s(methodSig).slice(0, 10);
|
||||
var encodedParams = params.map(function (param, i) {
|
||||
return encodeABI(method.inputs[i].type, param);
|
||||
});
|
||||
var headBlock = "0x";
|
||||
var dataBlock = "0x";
|
||||
for (var i = 0; i < encodedParams.length; ++i) {
|
||||
if (encodedParams[i].dynamic) {
|
||||
var dataLoc = encodedParams.length * 32 + Bytes.length(dataBlock);
|
||||
headBlock = Bytes.concat(headBlock, Bytes.pad(32, Nat.fromNumber(dataLoc)));
|
||||
dataBlock = Bytes.concat(dataBlock, encodedParams[i].data);
|
||||
} else {
|
||||
headBlock = Bytes.concat(headBlock, encodedParams[i].data);
|
||||
}
|
||||
}
|
||||
return Bytes.flatten([methodHash, headBlock, dataBlock]);
|
||||
};
|
||||
};
|
||||
|
||||
// Address, Address, ContractInterface -> Contract
|
||||
var contract = function contract(from, address, contractInterface) {
|
||||
var contract = {};
|
||||
contract._address = address;
|
||||
contract._from = from;
|
||||
contract.broadcast = {};
|
||||
contractInterface.forEach(function (method) {
|
||||
if (method && method.name) {
|
||||
var _call = function _call(type, value) {
|
||||
return function () {
|
||||
var transaction = {
|
||||
from: from,
|
||||
to: address,
|
||||
value: value,
|
||||
data: callMethodData(method).apply(undefined, arguments)
|
||||
};
|
||||
return type === "data" ? Promise.resolve(transaction) : method.constant ? callWithDefaults(transaction) : sendTransactionWithDefaults(transaction).then(type === "receipt" ? waitTransactionReceipt : function (x) {
|
||||
return x;
|
||||
});
|
||||
};
|
||||
};
|
||||
contract[method.name] = _call("receipt", "0x0");
|
||||
if (!method.constant) {
|
||||
contract[method.name + "_data"] = _call("data", "0x0");
|
||||
contract[method.name + "_pay"] = function (value) {
|
||||
return function () {
|
||||
return _call("receipt", value).apply(undefined, arguments);
|
||||
};
|
||||
};
|
||||
contract[method.name + "_pay_txHash"] = function (value) {
|
||||
return function () {
|
||||
return _call("txHash", value).apply(undefined, arguments);
|
||||
};
|
||||
};
|
||||
contract[method.name + "_txHash"] = _call("txHash", "0x0");
|
||||
}
|
||||
}
|
||||
});
|
||||
return contract;
|
||||
};
|
||||
|
||||
// Address, Bytecode -> TxHash
|
||||
var deployBytecode_txHash = function deployBytecode_txHash(from, code) {
|
||||
return sendTransactionWithDefaults({ from: from, data: code, to: "" });
|
||||
};
|
||||
|
||||
// Address, Bytecode -> Receipt
|
||||
var deployBytecode = function deployBytecode(from, code) {
|
||||
return deployBytecode_txHash(from, code).then(waitTransactionReceipt);
|
||||
};
|
||||
|
||||
// Address, Bytecode, ContractInterface
|
||||
var deployBytecodeContract = function deployBytecodeContract(from, code, contractInterface) {
|
||||
return deployBytecode(from, code).then(function (receipt) {
|
||||
return contract(from, receipt.contractAddress, contractInterface);
|
||||
});
|
||||
};
|
||||
|
||||
// Address, String, Address -> Contract
|
||||
var solidityContract = function solidityContract(from, source, at) {
|
||||
return compileSolidity(source).then(function (_ref3) {
|
||||
var abiDefinition = _ref3.info.abiDefinition;
|
||||
return contract(from, at, abiDefinition);
|
||||
});
|
||||
};
|
||||
|
||||
// Address, String -> TxHash
|
||||
var deploySolidity_txHash = function deploySolidity_txHash(from, source) {
|
||||
return compileSolidity(source).then(function (_ref4) {
|
||||
var code = _ref4.code;
|
||||
return deployBytecode_txHash(from, code);
|
||||
});
|
||||
};
|
||||
|
||||
// Address, String -> Receipt
|
||||
var deploySolidity = function deploySolidity(from, source) {
|
||||
return deploySolidity_txHash(from, source).then(waitTransactionReceipt);
|
||||
};
|
||||
|
||||
// Address, String -> Contract
|
||||
var deploySolidityContract = function deploySolidityContract(from, source) {
|
||||
return compileSolidity(source).then(function (_ref5) {
|
||||
var code = _ref5.code,
|
||||
abiDefinition = _ref5.info.abiDefinition;
|
||||
return deployBytecodeContract(from, code, abiDefinition);
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
send: send,
|
||||
|
||||
sendTransaction: sendTransaction,
|
||||
sendRawTransaction: sendRawTransaction,
|
||||
getTransactionReceipt: getTransactionReceipt,
|
||||
call: call,
|
||||
getBalance: getBalance,
|
||||
accounts: accounts,
|
||||
|
||||
waitTransactionReceipt: waitTransactionReceipt,
|
||||
addTransactionDefaults: addTransactionDefaults,
|
||||
sendTransactionWithDefaults: sendTransactionWithDefaults,
|
||||
callWithDefaults: callWithDefaults,
|
||||
callMethodData: callMethodData,
|
||||
|
||||
contract: contract,
|
||||
deployBytecode_txHash: deployBytecode_txHash,
|
||||
deployBytecode: deployBytecode,
|
||||
deployBytecodeContract: deployBytecodeContract,
|
||||
|
||||
compileSolidity: compileSolidity,
|
||||
solidityContract: solidityContract,
|
||||
deploySolidity_txHash: deploySolidity_txHash,
|
||||
deploySolidity: deploySolidity,
|
||||
deploySolidityContract: deploySolidityContract
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = Api;
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
const generate = (num, fn) => {
|
||||
let a = [];
|
||||
for (var i = 0; i < num; ++i) a.push(fn(i));
|
||||
return a;
|
||||
};
|
||||
|
||||
const replicate = (num, val) => generate(num, () => val);
|
||||
|
||||
const concat = (a, b) => a.concat(b);
|
||||
|
||||
const flatten = a => {
|
||||
let r = [];
|
||||
for (let j = 0, J = a.length; j < J; ++j) for (let i = 0, I = a[j].length; i < I; ++i) r.push(a[j][i]);
|
||||
return r;
|
||||
};
|
||||
|
||||
const chunksOf = (n, a) => {
|
||||
let b = [];
|
||||
for (let i = 0, l = a.length; i < l; i += n) b.push(a.slice(i, i + n));
|
||||
return b;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
generate,
|
||||
replicate,
|
||||
concat,
|
||||
flatten,
|
||||
chunksOf
|
||||
};
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
const A = require("./array.js");
|
||||
|
||||
const at = (bytes, index) => parseInt(bytes.slice(index * 2 + 2, index * 2 + 4), 16);
|
||||
|
||||
const random = bytes => {
|
||||
let rnd;
|
||||
if (typeof window !== "undefined" && window.crypto && window.crypto.getRandomValues) rnd = window.crypto.getRandomValues(new Uint8Array(bytes));else if (typeof require !== "undefined") rnd = require("c" + "rypto").randomBytes(bytes);else throw "Safe random numbers not available.";
|
||||
let hex = "0x";
|
||||
for (let i = 0; i < bytes; ++i) hex += ("00" + rnd[i].toString(16)).slice(-2);
|
||||
return hex;
|
||||
};
|
||||
|
||||
const length = a => (a.length - 2) / 2;
|
||||
|
||||
const flatten = a => "0x" + a.reduce((r, s) => r + s.slice(2), "");
|
||||
|
||||
const slice = (i, j, bs) => "0x" + bs.slice(i * 2 + 2, j * 2 + 2);
|
||||
|
||||
const reverse = hex => {
|
||||
let rev = "0x";
|
||||
for (let i = 0, l = length(hex); i < l; ++i) {
|
||||
rev += hex.slice((l - i) * 2, (l - i + 1) * 2);
|
||||
}
|
||||
return rev;
|
||||
};
|
||||
|
||||
const pad = (l, hex) => hex.length === l * 2 + 2 ? hex : pad(l, "0x" + "0" + hex.slice(2));
|
||||
|
||||
const padRight = (l, hex) => hex.length === l * 2 + 2 ? hex : padRight(l, hex + "0");
|
||||
|
||||
const toArray = hex => {
|
||||
let arr = [];
|
||||
for (let i = 2, l = hex.length; i < l; i += 2) arr.push(parseInt(hex.slice(i, i + 2), 16));
|
||||
return arr;
|
||||
};
|
||||
|
||||
const fromArray = arr => {
|
||||
let hex = "0x";
|
||||
for (let i = 0, l = arr.length; i < l; ++i) {
|
||||
let b = arr[i];
|
||||
hex += (b < 16 ? "0" : "") + b.toString(16);
|
||||
}
|
||||
return hex;
|
||||
};
|
||||
|
||||
const toUint8Array = hex => new Uint8Array(toArray(hex));
|
||||
|
||||
const fromUint8Array = arr => fromArray([].slice.call(arr, 0));
|
||||
|
||||
const fromNumber = num => {
|
||||
let hex = num.toString(16);
|
||||
return hex.length % 2 === 0 ? "0x" + hex : "0x0" + hex;
|
||||
};
|
||||
|
||||
const toNumber = hex => parseInt(hex.slice(2), 16);
|
||||
|
||||
const concat = (a, b) => a.concat(b.slice(2));
|
||||
|
||||
const fromNat = bn => bn === "0x0" ? "0x" : bn.length % 2 === 0 ? bn : "0x0" + bn.slice(2);
|
||||
|
||||
const toNat = bn => bn[2] === "0" ? "0x" + bn.slice(3) : bn;
|
||||
|
||||
const fromAscii = ascii => {
|
||||
let hex = "0x";
|
||||
for (let i = 0; i < ascii.length; ++i) hex += ("00" + ascii.charCodeAt(i).toString(16)).slice(-2);
|
||||
return hex;
|
||||
};
|
||||
|
||||
const toAscii = hex => {
|
||||
let ascii = "";
|
||||
for (let i = 2; i < hex.length; i += 2) ascii += String.fromCharCode(parseInt(hex.slice(i, i + 2), 16));
|
||||
return ascii;
|
||||
};
|
||||
|
||||
// From https://gist.github.com/pascaldekloe/62546103a1576803dade9269ccf76330
|
||||
const fromString = s => {
|
||||
const makeByte = uint8 => {
|
||||
const b = uint8.toString(16);
|
||||
return b.length < 2 ? "0" + b : b;
|
||||
};
|
||||
let bytes = "0x";
|
||||
for (let ci = 0; ci != s.length; ci++) {
|
||||
let c = s.charCodeAt(ci);
|
||||
if (c < 128) {
|
||||
bytes += makeByte(c);
|
||||
continue;
|
||||
}
|
||||
if (c < 2048) {
|
||||
bytes += makeByte(c >> 6 | 192);
|
||||
} else {
|
||||
if (c > 0xd7ff && c < 0xdc00) {
|
||||
if (++ci == s.length) return null;
|
||||
let c2 = s.charCodeAt(ci);
|
||||
if (c2 < 0xdc00 || c2 > 0xdfff) return null;
|
||||
c = 0x10000 + ((c & 0x03ff) << 10) + (c2 & 0x03ff);
|
||||
bytes += makeByte(c >> 18 | 240);
|
||||
bytes += makeByte(c >> 12 & 63 | 128);
|
||||
} else {
|
||||
// c <= 0xffff
|
||||
bytes += makeByte(c >> 12 | 224);
|
||||
}
|
||||
bytes += makeByte(c >> 6 & 63 | 128);
|
||||
}
|
||||
bytes += makeByte(c & 63 | 128);
|
||||
}
|
||||
return bytes;
|
||||
};
|
||||
|
||||
const toString = bytes => {
|
||||
let s = '';
|
||||
let i = 0;
|
||||
let l = length(bytes);
|
||||
while (i < l) {
|
||||
let c = at(bytes, i++);
|
||||
if (c > 127) {
|
||||
if (c > 191 && c < 224) {
|
||||
if (i >= l) return null;
|
||||
c = (c & 31) << 6 | at(bytes, i) & 63;
|
||||
} else if (c > 223 && c < 240) {
|
||||
if (i + 1 >= l) return null;
|
||||
c = (c & 15) << 12 | (at(bytes, i) & 63) << 6 | at(bytes, ++i) & 63;
|
||||
} else if (c > 239 && c < 248) {
|
||||
if (i + 2 >= l) return null;
|
||||
c = (c & 7) << 18 | (at(bytes, i) & 63) << 12 | (at(bytes, ++i) & 63) << 6 | at(bytes, ++i) & 63;
|
||||
} else return null;
|
||||
++i;
|
||||
}
|
||||
if (c <= 0xffff) s += String.fromCharCode(c);else if (c <= 0x10ffff) {
|
||||
c -= 0x10000;
|
||||
s += String.fromCharCode(c >> 10 | 0xd800);
|
||||
s += String.fromCharCode(c & 0x3FF | 0xdc00);
|
||||
} else return null;
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
random,
|
||||
length,
|
||||
concat,
|
||||
flatten,
|
||||
slice,
|
||||
reverse,
|
||||
pad,
|
||||
padRight,
|
||||
fromAscii,
|
||||
toAscii,
|
||||
fromString,
|
||||
toString,
|
||||
fromNumber,
|
||||
toNumber,
|
||||
fromNat,
|
||||
toNat,
|
||||
fromArray,
|
||||
toArray,
|
||||
fromUint8Array,
|
||||
toUint8Array
|
||||
};
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
const Bytes = require("./bytes");
|
||||
|
||||
const inis = "pbtdkgxjfvlrmnsz".split("");
|
||||
|
||||
const mids = "auie".split("");
|
||||
|
||||
const back = [inis, mids].map(chars => {
|
||||
let map = {};
|
||||
for (let i = 0; i < chars.length; ++i) map[chars[i]] = i;
|
||||
return map;
|
||||
});
|
||||
|
||||
const syllableFromB64 = b64 => {
|
||||
const ini = b64 >>> 2 & 15;
|
||||
const mid = b64 >>> 0 & 3;
|
||||
return inis[ini] + mids[mid];
|
||||
};
|
||||
|
||||
const syllableToB64 = syllable => {
|
||||
const ini = back[0][syllable[0]];
|
||||
const mid = back[1][syllable[1]];
|
||||
return ini * 4 + mid;
|
||||
};
|
||||
|
||||
const b64sFromBytes = bytes => {
|
||||
//BoooooBoooooBoooooBooooo
|
||||
//BoooooooBoooooooBooooooo
|
||||
let b64s = [],
|
||||
b64;
|
||||
for (let i = 0, l = Math.ceil(bytes.length * 8 / 6); i < l; ++i) {
|
||||
let j = i / 8 * 6 | 0;
|
||||
b64s.push(i % 4 === 0 ? bytes[j + 0] / 4 | 0 : i % 4 === 1 ? bytes[j + 0] % 4 * 16 + (bytes[j + 1] / 16 | 0) : i % 4 === 2 ? bytes[j + 0] % 16 * 4 + (bytes[j + 1] / 64 | 0) : bytes[j + 0] % 64 * 1);
|
||||
}
|
||||
return b64s;
|
||||
};
|
||||
|
||||
const b64sToBytes = b64s => {
|
||||
let bytes = [];
|
||||
for (let i = 0, l = Math.floor(b64s.length * 6 / 8); i < l; ++i) {
|
||||
let j = i / 6 * 8 | 0;
|
||||
bytes.push(i % 3 === 0 ? b64s[j + 0] % 64 * 4 + (b64s[j + 1] / 16 | 0) : i % 3 === 1 ? b64s[j + 0] % 16 * 16 + (b64s[j + 1] / 4 | 0) : b64s[j + 0] % 4 * 64 + (b64s[j + 1] / 1 | 0));
|
||||
}
|
||||
return bytes;
|
||||
};
|
||||
|
||||
const fromBytes = bytes => b64sFromBytes(Bytes.toArray(bytes)).map(syllableFromB64).join("");
|
||||
|
||||
const toBytes = syllables => Bytes.fromArray(b64sToBytes(syllables.match(/\w\w/g).map(syllableToB64)));
|
||||
|
||||
module.exports = {
|
||||
fromBytes,
|
||||
toBytes
|
||||
};
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
const times = (n, f, x) => {
|
||||
for (let i = 0; i < n; ++i) {
|
||||
x = f(x);
|
||||
}
|
||||
return x;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
times
|
||||
};
|
||||
+331
@@ -0,0 +1,331 @@
|
||||
// This was ported from https://github.com/emn178/js-sha3, with some minor
|
||||
// modifications and pruning. It is licensed under MIT:
|
||||
//
|
||||
// Copyright 2015-2016 Chen, Yi-Cyuan
|
||||
//
|
||||
// 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.
|
||||
|
||||
const HEX_CHARS = '0123456789abcdef'.split('');
|
||||
const KECCAK_PADDING = [1, 256, 65536, 16777216];
|
||||
const SHIFT = [0, 8, 16, 24];
|
||||
const 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];
|
||||
|
||||
const Keccak = bits => ({
|
||||
blocks: [],
|
||||
reset: true,
|
||||
block: 0,
|
||||
start: 0,
|
||||
blockCount: 1600 - (bits << 1) >> 5,
|
||||
outputBlocks: bits >> 5,
|
||||
s: (s => [].concat(s, s, s, s, s))([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
||||
});
|
||||
|
||||
const update = (state, message) => {
|
||||
var length = message.length,
|
||||
blocks = state.blocks,
|
||||
byteCount = state.blockCount << 2,
|
||||
blockCount = state.blockCount,
|
||||
outputBlocks = state.outputBlocks,
|
||||
s = state.s,
|
||||
index = 0,
|
||||
i,
|
||||
code;
|
||||
|
||||
// update
|
||||
while (index < length) {
|
||||
if (state.reset) {
|
||||
state.reset = false;
|
||||
blocks[0] = state.block;
|
||||
for (i = 1; i < blockCount + 1; ++i) {
|
||||
blocks[i] = 0;
|
||||
}
|
||||
}
|
||||
if (typeof message !== "string") {
|
||||
for (i = state.start; index < length && i < byteCount; ++index) {
|
||||
blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
|
||||
}
|
||||
} else {
|
||||
for (i = state.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];
|
||||
}
|
||||
}
|
||||
}
|
||||
state.lastByteIndex = i;
|
||||
if (i >= byteCount) {
|
||||
state.start = i - byteCount;
|
||||
state.block = blocks[blockCount];
|
||||
for (i = 0; i < blockCount; ++i) {
|
||||
s[i] ^= blocks[i];
|
||||
}
|
||||
f(s);
|
||||
state.reset = true;
|
||||
} else {
|
||||
state.start = i;
|
||||
}
|
||||
}
|
||||
|
||||
// finalize
|
||||
i = state.lastByteIndex;
|
||||
blocks[i >> 2] |= KECCAK_PADDING[i & 3];
|
||||
if (state.lastByteIndex === 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);
|
||||
|
||||
// toString
|
||||
var hex = '',
|
||||
i = 0,
|
||||
j = 0,
|
||||
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;
|
||||
}
|
||||
}
|
||||
return "0x" + hex;
|
||||
};
|
||||
|
||||
const f = 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];
|
||||
}
|
||||
};
|
||||
|
||||
const keccak = bits => str => {
|
||||
var msg;
|
||||
if (str.slice(0, 2) === "0x") {
|
||||
msg = [];
|
||||
for (var i = 2, l = str.length; i < l; i += 2) msg.push(parseInt(str.slice(i, i + 2), 16));
|
||||
} else {
|
||||
msg = str;
|
||||
}
|
||||
return update(Keccak(bits, bits), msg);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
keccak256: keccak(256),
|
||||
keccak512: keccak(512),
|
||||
keccak256s: keccak(256),
|
||||
keccak512s: keccak(512)
|
||||
};
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
account: require("./account.js"),
|
||||
nat: require("./nat.js"),
|
||||
bytes: require("./bytes.js"),
|
||||
hash: require("./hash.js"),
|
||||
RLP: require("./rlp.js"),
|
||||
abi: require("./abi.js"),
|
||||
transaction: require("./transaction.js"),
|
||||
rpc: require("./rpc.js"),
|
||||
desubits: require("./desubits.js"),
|
||||
passphrase: require("./passphrase.js")
|
||||
};
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
const merge = a => b => {
|
||||
let c = {};
|
||||
for (let key in a) c[key] = a[key];
|
||||
for (let key in b) c[key] = b[key];
|
||||
return c;
|
||||
};
|
||||
|
||||
const remove = removeKey => a => {
|
||||
let b = {};
|
||||
for (let key in a) if (key !== removeKey) b[key] = a[key];
|
||||
return b;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
merge,
|
||||
remove
|
||||
};
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
const BN = require("bn.js");
|
||||
const Bytes = require("./bytes");
|
||||
|
||||
const fromBN = bn => "0x" + bn.toString("hex");
|
||||
|
||||
const toBN = str => new BN(str.slice(2), 16);
|
||||
|
||||
const fromString = str => {
|
||||
const bn = "0x" + (str.slice(0, 2) === "0x" ? new BN(str.slice(2), 16) : new BN(str, 10)).toString("hex");
|
||||
return bn === "0x0" ? "0x" : bn;
|
||||
};
|
||||
|
||||
const toEther = wei => toNumber(div(wei, fromString("10000000000"))) / 100000000;
|
||||
|
||||
const fromEther = eth => mul(fromNumber(Math.floor(eth * 100000000)), fromString("10000000000"));
|
||||
|
||||
const toString = a => toBN(a).toString(10);
|
||||
|
||||
const fromNumber = a => typeof a === "string" ? /^0x/.test(a) ? a : "0x" + a : "0x" + new BN(a).toString("hex");
|
||||
|
||||
const toNumber = a => toBN(a).toNumber();
|
||||
|
||||
const toUint256 = a => Bytes.pad(32, a);
|
||||
|
||||
const bin = method => (a, b) => fromBN(toBN(a)[method](toBN(b)));
|
||||
|
||||
const add = bin("add");
|
||||
const mul = bin("mul");
|
||||
const div = bin("div");
|
||||
const sub = bin("sub");
|
||||
|
||||
module.exports = {
|
||||
toString,
|
||||
fromString,
|
||||
toNumber,
|
||||
fromNumber,
|
||||
toEther,
|
||||
fromEther,
|
||||
toUint256,
|
||||
add,
|
||||
mul,
|
||||
div,
|
||||
sub
|
||||
};
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
const Hash = require("./hash");
|
||||
const Bytes = require("./bytes");
|
||||
const Desubits = require("./desubits");
|
||||
|
||||
// Bytes -> Bytes
|
||||
const bytesAddChecksum = bytes => {
|
||||
const hash = Hash.keccak256(bytes);
|
||||
const sum = Bytes.slice(0, 1, hash);
|
||||
return Bytes.concat(bytes, sum);
|
||||
};
|
||||
|
||||
// Bytes -> Bool
|
||||
const bytesChecksum = bytes => {
|
||||
const length = Bytes.length(bytes);
|
||||
const prefix = Bytes.slice(0, length - 1, bytes);
|
||||
return bytesAddChecksum(prefix) === bytes;
|
||||
};
|
||||
|
||||
// () ~> Passphrase
|
||||
const create = () => {
|
||||
const bytes = bytesAddChecksum(Bytes.random(11));
|
||||
const seed = Desubits.fromBytes(bytes);
|
||||
const passphrase = seed.replace(/([a-z]{8})/g, "$1 ");
|
||||
return passphrase;
|
||||
};
|
||||
|
||||
// Passphrase -> Bytes
|
||||
const toBytes = passphrase => {
|
||||
const seed = passphrase.replace(/ /g, "");
|
||||
const bytes = Desubits.toBytes(passphrase);
|
||||
return bytes;
|
||||
};
|
||||
|
||||
// Passphrase -> Bool
|
||||
const checksum = passphrase => bytesChecksum(toBytes(passphrase));
|
||||
|
||||
// Passphrase -> Bytes
|
||||
const toMasterKey = passphrase => {
|
||||
let hash = Hash.keccak256;
|
||||
let bytes = toBytes(passphrase);
|
||||
for (let i = 0, l = Math.pow(2, 12); i < l; ++i) bytes = hash(bytes);
|
||||
return bytes;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
create,
|
||||
checksum,
|
||||
toMasterKey
|
||||
};
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
var njsp = require("nano-json-stream-parser");
|
||||
var request = require("xhr-request-promise");
|
||||
|
||||
var EthereumProvider = function EthereumProvider(url) {
|
||||
var api = {};
|
||||
var onResponse = {};
|
||||
var callbacks = {};
|
||||
var nextId = 0;
|
||||
var send = void 0;
|
||||
|
||||
var parseResponse = njsp(function (json) {
|
||||
onResponse[json.id] && onResponse[json.id](null, json.result);
|
||||
});
|
||||
|
||||
var genPayload = function genPayload(method, params) {
|
||||
return {
|
||||
jsonrpc: "2.0",
|
||||
id: ++nextId,
|
||||
method: method,
|
||||
params: params
|
||||
};
|
||||
};
|
||||
|
||||
if (/^http/.test(url)) {
|
||||
api.send = async function (method, params) {
|
||||
try {
|
||||
var answer = await request(url, {
|
||||
method: "POST",
|
||||
contentType: "application/json-rpc",
|
||||
body: JSON.stringify(genPayload(method, params)) });
|
||||
var resp = JSON.parse(answer);
|
||||
if (resp.error) {
|
||||
return resp.error.message;
|
||||
} else {
|
||||
throw resp.result;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
return api;
|
||||
};
|
||||
|
||||
module.exports = EthereumProvider;
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
// The RLP format
|
||||
// Serialization and deserialization for the BytesTree type, under the following grammar:
|
||||
// | First byte | Meaning |
|
||||
// | ---------- | -------------------------------------------------------------------------- |
|
||||
// | 0 to 127 | HEX(leaf) |
|
||||
// | 128 to 183 | HEX(length_of_leaf + 128) + HEX(leaf) |
|
||||
// | 184 to 191 | HEX(length_of_length_of_leaf + 128 + 55) + HEX(length_of_leaf) + HEX(leaf) |
|
||||
// | 192 to 247 | HEX(length_of_node + 192) + HEX(node) |
|
||||
// | 248 to 255 | HEX(length_of_length_of_node + 128 + 55) + HEX(length_of_node) + HEX(node) |
|
||||
|
||||
const encode = tree => {
|
||||
const padEven = str => str.length % 2 === 0 ? str : "0" + str;
|
||||
|
||||
const uint = num => padEven(num.toString(16));
|
||||
|
||||
const length = (len, add) => len < 56 ? uint(add + len) : uint(add + uint(len).length / 2 + 55) + uint(len);
|
||||
|
||||
const dataTree = tree => {
|
||||
if (typeof tree === "string") {
|
||||
const hex = tree.slice(2);
|
||||
const pre = hex.length != 2 || hex >= "80" ? length(hex.length / 2, 128) : "";
|
||||
return pre + hex;
|
||||
} else {
|
||||
const hex = tree.map(dataTree).join("");
|
||||
const pre = length(hex.length / 2, 192);
|
||||
return pre + hex;
|
||||
}
|
||||
};
|
||||
|
||||
return "0x" + dataTree(tree);
|
||||
};
|
||||
|
||||
const decode = hex => {
|
||||
let i = 2;
|
||||
|
||||
const parseTree = () => {
|
||||
if (i >= hex.length) throw "";
|
||||
const head = hex.slice(i, i + 2);
|
||||
return head < "80" ? (i += 2, "0x" + head) : head < "c0" ? parseHex() : parseList();
|
||||
};
|
||||
|
||||
const parseLength = () => {
|
||||
const len = parseInt(hex.slice(i, i += 2), 16) % 64;
|
||||
return len < 56 ? len : parseInt(hex.slice(i, i += (len - 55) * 2), 16);
|
||||
};
|
||||
|
||||
const parseHex = () => {
|
||||
const len = parseLength();
|
||||
return "0x" + hex.slice(i, i += len * 2);
|
||||
};
|
||||
|
||||
const parseList = () => {
|
||||
const lim = parseLength() * 2 + i;
|
||||
let list = [];
|
||||
while (i < lim) list.push(parseTree());
|
||||
return list;
|
||||
};
|
||||
|
||||
try {
|
||||
return parseTree();
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { encode, decode };
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
const request = require("xhr-request-promise");
|
||||
|
||||
const genPayload = (() => {
|
||||
let nextId = 0;
|
||||
return (method, params) => ({
|
||||
jsonrpc: "2.0",
|
||||
id: ++nextId,
|
||||
method: method,
|
||||
params: params
|
||||
});
|
||||
})();
|
||||
|
||||
const send = url => (method, params) => {
|
||||
return request(url, {
|
||||
method: "POST",
|
||||
contentType: "application/json-rpc",
|
||||
body: JSON.stringify(genPayload(method, params))
|
||||
}).then(answer => {
|
||||
var resp = JSON.parse(answer); // todo: use njsp?
|
||||
if (resp.error) {
|
||||
throw new Error(resp.error.message);
|
||||
} else {
|
||||
return resp.result;
|
||||
}
|
||||
}).catch(e => {
|
||||
return { error: e.toString() };
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = send;
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
const Account = require("./account");
|
||||
const Nat = require("./nat");
|
||||
const Bytes = require("./bytes");
|
||||
const RLP = require("./rlp");
|
||||
const keccak256 = require("./hash").keccak256;
|
||||
|
||||
// EthereumRPC, IncompleteTransaction -> Promise Transaction
|
||||
const addDefaults = (rpc, tx) => {
|
||||
var baseDefaults = [tx.chainId || rpc("net_version", []), tx.gasPrice || rpc("eth_gasPrice", []), tx.nonce || rpc("eth_getTransactionCount", [tx.from, "latest"]), tx.value || "0x0", tx.data || "0x"];
|
||||
const noAddress = address => !address || address === "" || address === "0x";
|
||||
return Promise.all(baseDefaults).then(([chainIdNum, gasPrice, nonce, value, data]) => {
|
||||
var chainId = Nat.fromNumber(chainIdNum);
|
||||
var gasEstimator = tx.gas ? Promise.resolve(null) : rpc("eth_estimateGas", [{
|
||||
from: noAddress(tx.from) ? null : tx.from,
|
||||
to: noAddress(tx.to) ? null : tx.to,
|
||||
value: tx.value,
|
||||
nonce: tx.nonce,
|
||||
data: tx.data
|
||||
}]);
|
||||
return gasEstimator.then(gasEstimate => {
|
||||
if (gasEstimate.error) {
|
||||
throw gasEstimate.error;
|
||||
}
|
||||
return {
|
||||
chainId: chainId,
|
||||
from: noAddress(tx.from) ? "0x" : tx.from.toLowerCase(),
|
||||
to: noAddress(tx.to) ? "0x" : tx.to.toLowerCase(),
|
||||
gasPrice: gasPrice,
|
||||
gas: tx.gas ? tx.gas : Nat.div(Nat.mul(gasEstimate, "0x6"), "0x5"),
|
||||
nonce: nonce,
|
||||
value: value,
|
||||
data: data ? data.toLowerCase() : null
|
||||
};
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Transaction -> Bytes
|
||||
const signingData = tx => {
|
||||
return RLP.encode([Bytes.fromNat(tx.nonce), Bytes.fromNat(tx.gasPrice), Bytes.fromNat(tx.gas), tx.to ? tx.to.toLowerCase() : "0x", Bytes.fromNat(tx.value), tx.data, Bytes.fromNat(tx.chainId || "0x1"), "0x", "0x"]);
|
||||
};
|
||||
|
||||
// Transaction, Account -> Bytes
|
||||
const sign = (tx, account) => {
|
||||
const data = signingData(tx);
|
||||
const signature = Account.makeSigner(Nat.toNumber(tx.chainId || "0x1") * 2 + 35)(keccak256(data), account.privateKey);
|
||||
const rawTransaction = RLP.decode(data).slice(0, 6).concat(Account.decodeSignature(signature));
|
||||
return RLP.encode(rawTransaction);
|
||||
};
|
||||
|
||||
// Bytes -> Address
|
||||
const recover = rawTransaction => {
|
||||
const values = RLP.decode(rawTransaction);
|
||||
const signature = Account.encodeSignature(values.slice(6, 9));
|
||||
const recovery = Bytes.toNumber(values[6]);
|
||||
const extraData = recovery < 35 ? [] : [Bytes.fromNumber(recovery - 35 >> 1), "0x", "0x"];
|
||||
const data = values.slice(0, 6).concat(extraData);
|
||||
const dataHex = RLP.encode(data);
|
||||
return Account.recover(keccak256(dataHex), signature);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
addDefaults,
|
||||
signingData,
|
||||
sign,
|
||||
recover
|
||||
};
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
var F = require("forall");
|
||||
var A = require("./array");
|
||||
var B = require("./bytes");
|
||||
var Account = require("./account");
|
||||
|
||||
F.Bytes = F(F.Type, {
|
||||
form: "a JavaScript String starting with a `0x`, followed by an even number of low-case hex chars (i.e., `0123456789abcdef`)",
|
||||
rand: function rand() {
|
||||
return "0x" + A.generate((Math.random() * 16 | 0) * 2, function () {
|
||||
return (Math.random() * 16 | 0).toString(16);
|
||||
}).join("");
|
||||
},
|
||||
test: function test(value) {
|
||||
return typeof value === "string" && /^0x([0-9a-f][0-9a-f])*$/.test(value);
|
||||
}
|
||||
}).__name("Bytes").__desc("any arbitrary data");
|
||||
|
||||
F.NBytes = function (bytes) {
|
||||
return F(F.Type, {
|
||||
form: "a JavaScript String starting with a `0x`, followed by " + bytes * 2 + " low-case hex chars (i.e., `0123456789abcdef`)",
|
||||
test: function test(value) {
|
||||
return F.Bytes.test(value) && value.length === bytes * 2 + 2;
|
||||
},
|
||||
rand: function rand() {
|
||||
return "0x" + A.generate(bytes * 2, function () {
|
||||
return (Math.random() * 16 | 0).toString(16);
|
||||
}).join("");
|
||||
}
|
||||
}).__name("NBytes(" + bytes + ")").__desc("any arbitrary data of exactly " + bytes + "-byte" + (bytes > 1 ? "s" : ""));
|
||||
};
|
||||
|
||||
F.Nat = F(F.Type, {
|
||||
form: "a JavaScript String starting with a `0x`, followed by at least one low-case hex char different from 0, followed by any number of low-case hex chars (i.e., `0123456789abcdef`)",
|
||||
test: function test(value) {
|
||||
return typeof value === "string" && /^0x[1-9a-f]([0-9a-f])*$/.test(value);
|
||||
},
|
||||
rand: function rand() {
|
||||
return "0x" + (Math.random() * Math.pow(2, 50) | 0).toString(16);
|
||||
}
|
||||
}).__name("Nat").__desc("an arbitrarily long non-negative integer number");
|
||||
|
||||
F.Address = F(F.Type, {
|
||||
form: "a JavaScript String starting with a `0x`, followed by 40 hex chars (i.e., `0123456789abcdefABCDEF`), with the nth hex being uppercase iff the nth hex of the keccak256 of the lowercase address in ASCII is > 7",
|
||||
test: function test(address) {
|
||||
return (/^(0x)?[0-9a-f]{40}$/i.test(address) && Account.toChecksum(address.toLowerCase()) === address
|
||||
);
|
||||
},
|
||||
rand: function rand() {
|
||||
return F.Account.rand().address;
|
||||
}
|
||||
}).__name("Address").__desc("an Ethereum public address");
|
||||
|
||||
F.Hash = F(F.Type, {
|
||||
form: F.NBytes(32).form,
|
||||
test: F.NBytes(32).test,
|
||||
rand: F.NBytes(32).rand
|
||||
}).__name("Hash").__desc("a Keccak-256 hash");
|
||||
|
||||
F.PrivateKey = F(F.Type, {
|
||||
form: F.NBytes(32).form,
|
||||
test: F.NBytes(32).test,
|
||||
rand: F.NBytes(32).rand
|
||||
}).__name("PrivateKey").__desc("an Ethereum private key");
|
||||
|
||||
F.Account = function () {
|
||||
var base = F.Struct({
|
||||
address: F.Address,
|
||||
privateKey: F.PrivateKey
|
||||
});
|
||||
return F(F.Type, {
|
||||
form: base.form,
|
||||
test: base.test,
|
||||
rand: function rand() {
|
||||
return Account.create("");
|
||||
}
|
||||
});
|
||||
}().__name("Account").__desc("an Ethereum account");
|
||||
|
||||
F.BytesTree = F(F.Type, {
|
||||
form: "either " + F.Bytes.form + ", or a tree of nested JavaScript Arrays of BytesTrees",
|
||||
test: function test(value) {
|
||||
return F.Bytes.test(value) || value instanceof Array && value.reduce(function (r, v) {
|
||||
return F.BytesTree.test(v) && r;
|
||||
}, true);
|
||||
},
|
||||
rand: function rand() {
|
||||
var list = [];
|
||||
while (Math.random() < 0.8) {
|
||||
if (Math.random() < 0.8) list.push(F.Bytes.rand());else list.push(F.BytesTree.rand());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}).__name("BytesTree").__desc("a tree of arbitrary binary data");
|
||||
|
||||
module.exports = F;
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"_from": "eth-lib@0.2.8",
|
||||
"_id": "eth-lib@0.2.8",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==",
|
||||
"_location": "/web3-eth-accounts/eth-lib",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "eth-lib@0.2.8",
|
||||
"name": "eth-lib",
|
||||
"escapedName": "eth-lib",
|
||||
"rawSpec": "0.2.8",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "0.2.8"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/web3-eth-accounts"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz",
|
||||
"_shasum": "b194058bef4b220ad12ea497431d6cb6aa0623c8",
|
||||
"_spec": "eth-lib@0.2.8",
|
||||
"_where": "C:\\Users\\Luis\\source\\repos\\AAMasters\\BackendServers\\node_modules\\web3-eth-accounts",
|
||||
"author": {
|
||||
"name": "Victor Maia"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/maiavictor/eth-lib/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"bn.js": "^4.11.6",
|
||||
"elliptic": "^6.4.0",
|
||||
"xhr-request-promise": "^0.1.2"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "Lightweight Ethereum libraries",
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.24.1",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"ethjs-account": "^0.1.1",
|
||||
"ethjs-signer": "^0.1.1",
|
||||
"rlp": "^2.0.0"
|
||||
},
|
||||
"homepage": "https://github.com/maiavictor/eth-lib#readme",
|
||||
"keywords": [
|
||||
"ethereum"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"name": "eth-lib",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/maiavictor/eth-lib.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "babel src --out-dir=lib",
|
||||
"test": "mocha test/test.js"
|
||||
},
|
||||
"version": "0.2.8"
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
// type Var = {
|
||||
// name: String
|
||||
// type: "uint256" | "bytes32" | ...
|
||||
// }
|
||||
//
|
||||
// type Method = {
|
||||
// name: String
|
||||
// inputs: [Var]
|
||||
// output: [Var]
|
||||
// constant: Bool
|
||||
// payable: Bool
|
||||
// }
|
||||
|
||||
const Bytes = require("./bytes");
|
||||
const Nat = require("./nat");
|
||||
const keccak256s = require("./hash").keccak256s;
|
||||
|
||||
// (type : String), JSType(type) -> {data: Bytes, dynamic: Bool}
|
||||
// ABI-encodes a single term.
|
||||
const encode = (type, value) => {
|
||||
if (type === "bytes") {
|
||||
const length = Bytes.length(value);
|
||||
const nextMul32 = (((length - 1) / 32 | 0) + 1) * 32;
|
||||
const lengthEncoded = encode("uint256", Nat.fromNumber(length)).data;
|
||||
const bytesEncoded = Bytes.padRight(nextMul32, value);
|
||||
return {data: Bytes.concat(lengthEncoded, bytesEncoded), dynamic: true};
|
||||
} else if (type === "uint256" || type === "bytes32" || type === "address") {
|
||||
return {data: Bytes.pad(32, value), dynamic: false};
|
||||
} else {
|
||||
throw "Eth-lib can't encode ABI type " + type + " yet.";
|
||||
}
|
||||
}
|
||||
|
||||
// (method : Method), [JSType(method.inputs[i].type)] -> Bytes
|
||||
// ABI-encodes the transaction data to call a method.
|
||||
const methodData = (method, params) => {
|
||||
const methodSig = method.name + "(" + method.inputs.map(i => i.type).join(",") + ")";
|
||||
const methodHash = keccak256s(methodSig).slice(0,10);
|
||||
let encodedParams = params.map((param,i) => encode(method.inputs[i].type, param));
|
||||
var headBlock = "0x";
|
||||
let dataBlock = "0x";
|
||||
for (var i = 0; i < encodedParams.length; ++i) {
|
||||
if (encodedParams[i].dynamic) {
|
||||
var dataLoc = encodedParams.length * 32 + Bytes.length(dataBlock);
|
||||
headBlock = Bytes.concat(headBlock, Bytes.pad(32, Nat.fromNumber(dataLoc)));
|
||||
dataBlock = Bytes.concat(dataBlock, encodedParams[i].data);
|
||||
} else {
|
||||
headBlock = Bytes.concat(headBlock, encodedParams[i].data);
|
||||
}
|
||||
}
|
||||
return Bytes.flatten([methodHash, headBlock, dataBlock]);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
encode,
|
||||
methodData
|
||||
};
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
const Bytes = require("./bytes");
|
||||
const Nat = require("./nat");
|
||||
const elliptic = require("elliptic");
|
||||
const rlp = require("./rlp");
|
||||
const secp256k1 = new (elliptic.ec)("secp256k1"); // eslint-disable-line
|
||||
const {keccak256, keccak256s} = require("./hash");
|
||||
|
||||
const create = entropy => {
|
||||
const innerHex = keccak256(Bytes.concat(Bytes.random(32), entropy || Bytes.random(32)));
|
||||
const middleHex = Bytes.concat(Bytes.concat(Bytes.random(32), innerHex), Bytes.random(32));
|
||||
const outerHex = keccak256(middleHex);
|
||||
return fromPrivate(outerHex);
|
||||
}
|
||||
|
||||
const toChecksum = address => {
|
||||
const addressHash = keccak256s(address.slice(2));
|
||||
let checksumAddress = "0x";
|
||||
for (let i = 0; i < 40; i++)
|
||||
checksumAddress += parseInt(addressHash[i + 2], 16) > 7
|
||||
? address[i + 2].toUpperCase()
|
||||
: address[i + 2];
|
||||
return checksumAddress;
|
||||
}
|
||||
|
||||
const fromPrivate = privateKey => {
|
||||
const buffer = new Buffer(privateKey.slice(2), "hex");
|
||||
const ecKey = secp256k1.keyFromPrivate(buffer);
|
||||
const publicKey = "0x" + ecKey.getPublic(false, 'hex').slice(2);
|
||||
const publicHash = keccak256(publicKey);
|
||||
const address = toChecksum("0x" + publicHash.slice(-40));
|
||||
return {
|
||||
address: address,
|
||||
privateKey: privateKey
|
||||
}
|
||||
}
|
||||
|
||||
const encodeSignature = ([v, r, s]) =>
|
||||
Bytes.flatten([r,s,v]);
|
||||
|
||||
const decodeSignature = (hex) => [
|
||||
Bytes.slice(64, Bytes.length(hex), hex),
|
||||
Bytes.slice(0, 32, hex),
|
||||
Bytes.slice(32, 64, hex)];
|
||||
|
||||
const makeSigner = addToV => (hash, privateKey) => {
|
||||
const signature = secp256k1
|
||||
.keyFromPrivate(new Buffer(privateKey.slice(2), "hex"))
|
||||
.sign(new Buffer(hash.slice(2), "hex"), {canonical: true});
|
||||
return encodeSignature([
|
||||
Nat.fromString(Bytes.fromNumber(addToV + signature.recoveryParam)),
|
||||
Bytes.pad(32, Bytes.fromNat("0x" + signature.r.toString(16))),
|
||||
Bytes.pad(32, Bytes.fromNat("0x" + signature.s.toString(16)))]);
|
||||
}
|
||||
|
||||
const sign = makeSigner(27); // v=27|28 instead of 0|1...
|
||||
|
||||
const recover = (hash, signature) => {
|
||||
const vals = decodeSignature(signature);
|
||||
const vrs = {v: Bytes.toNumber(vals[0]), r:vals[1].slice(2), s:vals[2].slice(2)};
|
||||
const ecPublicKey = secp256k1.recoverPubKey(new Buffer(hash.slice(2), "hex"), vrs, vrs.v < 2 ? vrs.v : 1 - (vrs.v % 2)); // because odd vals mean v=0... sadly that means v=0 means v=1... I hate that
|
||||
const publicKey = "0x" + ecPublicKey.encode("hex", false).slice(2);
|
||||
const publicHash = keccak256(publicKey);
|
||||
const address = toChecksum("0x" + publicHash.slice(-40));
|
||||
return address;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
create,
|
||||
toChecksum,
|
||||
fromPrivate,
|
||||
sign,
|
||||
makeSigner,
|
||||
recover,
|
||||
encodeSignature,
|
||||
decodeSignature
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
const generate = (num, fn) => {
|
||||
let a = [];
|
||||
for (var i = 0; i < num; ++i)
|
||||
a.push(fn(i));
|
||||
return a;
|
||||
};
|
||||
|
||||
const replicate = (num, val) =>
|
||||
generate(num, () => val);
|
||||
|
||||
const concat = (a, b) =>
|
||||
a.concat(b);
|
||||
|
||||
const flatten = (a) => {
|
||||
let r = [];
|
||||
for (let j = 0, J = a.length; j < J; ++j)
|
||||
for (let i = 0, I = a[j].length; i < I; ++i)
|
||||
r.push(a[j][i]);
|
||||
return r;
|
||||
}
|
||||
|
||||
const chunksOf = (n,a) => {
|
||||
let b = [];
|
||||
for (let i = 0, l = a.length; i < l; i += n)
|
||||
b.push(a.slice(i, i + n));
|
||||
return b;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
generate,
|
||||
replicate,
|
||||
concat,
|
||||
flatten,
|
||||
chunksOf
|
||||
}
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
const A = require("./array.js");
|
||||
|
||||
const at = (bytes, index) =>
|
||||
parseInt(bytes.slice(index * 2 + 2, index * 2 + 4), 16);
|
||||
|
||||
const random = bytes => {
|
||||
let rnd;
|
||||
if (typeof window !== "undefined" && window.crypto && window.crypto.getRandomValues)
|
||||
rnd = window.crypto.getRandomValues(new Uint8Array(bytes));
|
||||
else if (typeof require !== "undefined")
|
||||
rnd = require("c" + "rypto").randomBytes(bytes);
|
||||
else
|
||||
throw "Safe random numbers not available.";
|
||||
let hex = "0x";
|
||||
for (let i = 0; i < bytes; ++i)
|
||||
hex += ("00" + rnd[i].toString(16)).slice(-2);
|
||||
return hex;
|
||||
};
|
||||
|
||||
const length = a =>
|
||||
(a.length - 2) / 2;
|
||||
|
||||
const flatten = (a) =>
|
||||
"0x" + a.reduce((r,s) => r + s.slice(2), "");
|
||||
|
||||
const slice = (i,j,bs) =>
|
||||
"0x" + bs.slice(i*2+2,j*2+2);
|
||||
|
||||
const reverse = hex => {
|
||||
let rev = "0x";
|
||||
for (let i = 0, l = length(hex); i < l; ++i) {
|
||||
rev += hex.slice((l-i)*2, (l-i+1)*2);
|
||||
}
|
||||
return rev;
|
||||
}
|
||||
|
||||
const pad = (l,hex) =>
|
||||
hex.length === l*2+2 ? hex : pad(l,"0x"+"0"+hex.slice(2));
|
||||
|
||||
const padRight = (l,hex) =>
|
||||
hex.length === l*2+2 ? hex : padRight(l,hex+"0");
|
||||
|
||||
const toArray = hex => {
|
||||
let arr = [];
|
||||
for (let i = 2, l = hex.length; i < l; i += 2)
|
||||
arr.push(parseInt(hex.slice(i, i + 2), 16));
|
||||
return arr;
|
||||
}
|
||||
|
||||
const fromArray = arr => {
|
||||
let hex = "0x";
|
||||
for (let i = 0, l = arr.length; i < l; ++i) {
|
||||
let b = arr[i];
|
||||
hex += (b < 16 ? "0" : "") + b.toString(16);
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
|
||||
const toUint8Array = hex =>
|
||||
new Uint8Array(toArray(hex));
|
||||
|
||||
const fromUint8Array = arr =>
|
||||
fromArray([].slice.call(arr, 0));
|
||||
|
||||
const fromNumber = num => {
|
||||
let hex = num.toString(16);
|
||||
return hex.length % 2 === 0 ? "0x" + hex : "0x0" + hex ;
|
||||
};
|
||||
|
||||
const toNumber = hex =>
|
||||
parseInt(hex.slice(2), 16);
|
||||
|
||||
const concat = (a, b) =>
|
||||
a.concat(b.slice(2));
|
||||
|
||||
const fromNat = bn =>
|
||||
bn === "0x0" ? "0x" : bn.length % 2 === 0 ? bn : "0x0" + bn.slice(2);
|
||||
|
||||
const toNat = bn =>
|
||||
bn[2] === "0" ? "0x" + bn.slice(3) : bn;
|
||||
|
||||
const fromAscii = ascii => {
|
||||
let hex = "0x";
|
||||
for (let i = 0; i < ascii.length; ++i)
|
||||
hex += ("00" + ascii.charCodeAt(i).toString(16)).slice(-2);
|
||||
return hex;
|
||||
};
|
||||
|
||||
const toAscii = hex => {
|
||||
let ascii = "";
|
||||
for (let i = 2; i < hex.length; i += 2)
|
||||
ascii += String.fromCharCode(parseInt(hex.slice(i, i + 2), 16));
|
||||
return ascii;
|
||||
};
|
||||
|
||||
// From https://gist.github.com/pascaldekloe/62546103a1576803dade9269ccf76330
|
||||
const fromString = s => {
|
||||
const makeByte = uint8 => {
|
||||
const b = uint8.toString(16);
|
||||
return b.length < 2 ? "0" + b : b;
|
||||
};
|
||||
let bytes = "0x";
|
||||
for (let ci = 0; ci != s.length; ci++) {
|
||||
let c = s.charCodeAt(ci);
|
||||
if (c < 128) {
|
||||
bytes += makeByte(c);
|
||||
continue;
|
||||
}
|
||||
if (c < 2048) {
|
||||
bytes += makeByte(c >> 6 | 192);
|
||||
} else {
|
||||
if (c > 0xd7ff && c < 0xdc00) {
|
||||
if (++ci == s.length) return null;
|
||||
let c2 = s.charCodeAt(ci);
|
||||
if (c2 < 0xdc00 || c2 > 0xdfff) return null;
|
||||
c = 0x10000 + ((c & 0x03ff) << 10) + (c2 & 0x03ff);
|
||||
bytes += makeByte(c >> 18 | 240);
|
||||
bytes += makeByte(c>> 12 & 63 | 128);
|
||||
} else { // c <= 0xffff
|
||||
bytes += makeByte(c >> 12 | 224);
|
||||
}
|
||||
bytes += makeByte(c >> 6 & 63 | 128);
|
||||
}
|
||||
bytes += makeByte(c & 63 | 128);
|
||||
}
|
||||
return bytes;
|
||||
};
|
||||
|
||||
const toString = (bytes) => {
|
||||
let s = '';
|
||||
let i = 0;
|
||||
let l = length(bytes);
|
||||
while (i < l) {
|
||||
let c = at(bytes, i++);
|
||||
if (c > 127) {
|
||||
if (c > 191 && c < 224) {
|
||||
if (i >= l) return null;
|
||||
c = (c & 31) << 6 | at(bytes, i) & 63;
|
||||
} else if (c > 223 && c < 240) {
|
||||
if (i + 1 >= l) return null;
|
||||
c = (c & 15) << 12 | (at(bytes, i) & 63) << 6 | at(bytes, ++i) & 63;
|
||||
} else if (c > 239 && c < 248) {
|
||||
if (i+2 >= l) return null;
|
||||
c = (c & 7) << 18 | (at(bytes, i) & 63) << 12 | (at(bytes, ++i) & 63) << 6 | at(bytes, ++i) & 63;
|
||||
} else return null;
|
||||
++i;
|
||||
}
|
||||
if (c <= 0xffff) s += String.fromCharCode(c);
|
||||
else if (c <= 0x10ffff) {
|
||||
c -= 0x10000;
|
||||
s += String.fromCharCode(c >> 10 | 0xd800)
|
||||
s += String.fromCharCode(c & 0x3FF | 0xdc00)
|
||||
} else return null;
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
random,
|
||||
length,
|
||||
concat,
|
||||
flatten,
|
||||
slice,
|
||||
reverse,
|
||||
pad,
|
||||
padRight,
|
||||
fromAscii,
|
||||
toAscii,
|
||||
fromString,
|
||||
toString,
|
||||
fromNumber,
|
||||
toNumber,
|
||||
fromNat,
|
||||
toNat,
|
||||
fromArray,
|
||||
toArray,
|
||||
fromUint8Array,
|
||||
toUint8Array
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
const Bytes = require("./bytes");
|
||||
|
||||
const inis = "pbtdkgxjfvlrmnsz".split("");
|
||||
|
||||
const mids = "auie".split("");
|
||||
|
||||
const back = [inis,mids].map(chars => {
|
||||
let map = {};
|
||||
for (let i = 0; i < chars.length; ++i)
|
||||
map[chars[i]] = i;
|
||||
return map;
|
||||
});
|
||||
|
||||
const syllableFromB64 = b64 => {
|
||||
const ini = (b64 >>> 2) & 15;
|
||||
const mid = (b64 >>> 0) & 3;
|
||||
return inis[ini] + mids[mid];
|
||||
}
|
||||
|
||||
const syllableToB64 = syllable => {
|
||||
const ini = back[0][syllable[0]];
|
||||
const mid = back[1][syllable[1]];
|
||||
return ini * 4 + mid;
|
||||
}
|
||||
|
||||
const b64sFromBytes = bytes => {
|
||||
//BoooooBoooooBoooooBooooo
|
||||
//BoooooooBoooooooBooooooo
|
||||
let b64s = [], b64;
|
||||
for (let i = 0, l = Math.ceil(bytes.length * 8 / 6); i < l; ++i) {
|
||||
let j = i / 8 * 6 | 0;
|
||||
b64s.push
|
||||
( i % 4 === 0 ? (bytes[j+0] / 4 | 0)
|
||||
: i % 4 === 1 ? bytes[j+0] % 4 * 16 + (bytes[j+1] / 16 | 0)
|
||||
: i % 4 === 2 ? bytes[j+0] % 16 * 4 + (bytes[j+1] / 64 | 0)
|
||||
: bytes[j+0] % 64 * 1);
|
||||
}
|
||||
return b64s;
|
||||
}
|
||||
|
||||
const b64sToBytes = b64s => {
|
||||
let bytes = [];
|
||||
for (let i = 0, l = Math.floor(b64s.length * 6 / 8); i < l; ++i) {
|
||||
let j = i / 6 * 8 | 0;
|
||||
bytes.push
|
||||
( i % 3 === 0 ? b64s[j+0] % 64 * 4 + (b64s[j+1] / 16 | 0)
|
||||
: i % 3 === 1 ? b64s[j+0] % 16 * 16 + (b64s[j+1] / 4 | 0)
|
||||
: b64s[j+0] % 4 * 64 + (b64s[j+1] / 1 | 0));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
const fromBytes = bytes =>
|
||||
b64sFromBytes(Bytes.toArray(bytes)).map(syllableFromB64).join("");
|
||||
|
||||
const toBytes = syllables =>
|
||||
Bytes.fromArray(b64sToBytes(syllables.match(/\w\w/g).map(syllableToB64)));
|
||||
|
||||
module.exports = {
|
||||
fromBytes,
|
||||
toBytes
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
const times = (n, f, x) => {
|
||||
for (let i = 0; i < n; ++i) {
|
||||
x = f(x);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
times
|
||||
}
|
||||
+340
@@ -0,0 +1,340 @@
|
||||
// This was ported from https://github.com/emn178/js-sha3, with some minor
|
||||
// modifications and pruning. It is licensed under MIT:
|
||||
//
|
||||
// Copyright 2015-2016 Chen, Yi-Cyuan
|
||||
//
|
||||
// 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.
|
||||
|
||||
const HEX_CHARS = '0123456789abcdef'.split('');
|
||||
const KECCAK_PADDING = [1, 256, 65536, 16777216];
|
||||
const SHIFT = [0, 8, 16, 24];
|
||||
const 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];
|
||||
|
||||
const Keccak = (bits) => ({
|
||||
blocks: [],
|
||||
reset: true,
|
||||
block: 0,
|
||||
start: 0,
|
||||
blockCount: (1600 - (bits << 1)) >> 5,
|
||||
outputBlocks: bits >> 5,
|
||||
s: (s=>[].concat(s,s,s,s,s))([0,0,0,0,0,0,0,0,0,0])
|
||||
});
|
||||
|
||||
const update = (state, message) => {
|
||||
var length = message.length,
|
||||
blocks = state.blocks,
|
||||
byteCount = state.blockCount << 2,
|
||||
blockCount = state.blockCount,
|
||||
outputBlocks = state.outputBlocks,
|
||||
s = state.s,
|
||||
index = 0,
|
||||
i,
|
||||
code;
|
||||
|
||||
// update
|
||||
while (index < length) {
|
||||
if (state.reset) {
|
||||
state.reset = false;
|
||||
blocks[0] = state.block;
|
||||
for (i = 1; i < blockCount + 1; ++i) {
|
||||
blocks[i] = 0;
|
||||
}
|
||||
}
|
||||
if (typeof message !== "string") {
|
||||
for (i = state.start; index < length && i < byteCount; ++index) {
|
||||
blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
|
||||
}
|
||||
} else {
|
||||
for (i = state.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];
|
||||
}
|
||||
}
|
||||
}
|
||||
state.lastByteIndex = i;
|
||||
if (i >= byteCount) {
|
||||
state.start = i - byteCount;
|
||||
state.block = blocks[blockCount];
|
||||
for (i = 0; i < blockCount; ++i) {
|
||||
s[i] ^= blocks[i];
|
||||
}
|
||||
f(s);
|
||||
state.reset = true;
|
||||
} else {
|
||||
state.start = i;
|
||||
}
|
||||
}
|
||||
|
||||
// finalize
|
||||
i = state.lastByteIndex;
|
||||
blocks[i >> 2] |= KECCAK_PADDING[i & 3];
|
||||
if (state.lastByteIndex === 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);
|
||||
|
||||
// toString
|
||||
var hex = '', i = 0, j = 0, 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;
|
||||
}
|
||||
}
|
||||
return "0x" + hex;
|
||||
}
|
||||
|
||||
const f = 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];
|
||||
}
|
||||
}
|
||||
|
||||
const keccak = bits => str => {
|
||||
var msg;
|
||||
if (str.slice(0,2) === "0x") {
|
||||
msg = [];
|
||||
for (var i = 2, l = str.length; i < l; i += 2)
|
||||
msg.push(parseInt(str.slice(i,i+2), 16));
|
||||
} else {
|
||||
msg = str;
|
||||
}
|
||||
return update(Keccak(bits, bits), msg);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
keccak256: keccak(256),
|
||||
keccak512: keccak(512),
|
||||
keccak256s: keccak(256),
|
||||
keccak512s: keccak(512),
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
account: require("./account.js"),
|
||||
nat: require("./nat.js"),
|
||||
bytes: require("./bytes.js"),
|
||||
hash: require("./hash.js"),
|
||||
RLP: require("./rlp.js"),
|
||||
abi: require("./abi.js"),
|
||||
transaction: require("./transaction.js"),
|
||||
rpc: require("./rpc.js"),
|
||||
desubits: require("./desubits.js"),
|
||||
passphrase: require("./passphrase.js")
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
const merge = a => b => {
|
||||
let c = {};
|
||||
for (let key in a)
|
||||
c[key] = a[key];
|
||||
for (let key in b)
|
||||
c[key] = b[key];
|
||||
return c;
|
||||
}
|
||||
|
||||
const remove = removeKey => a => {
|
||||
let b = {};
|
||||
for (let key in a)
|
||||
if (key !== removeKey)
|
||||
b[key] = a[key];
|
||||
return b;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
merge,
|
||||
remove
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
const BN = require("bn.js");
|
||||
const Bytes = require("./bytes");
|
||||
|
||||
const fromBN = bn =>
|
||||
"0x" + bn.toString("hex");
|
||||
|
||||
const toBN = str =>
|
||||
new BN(str.slice(2), 16);
|
||||
|
||||
const fromString = str => {
|
||||
const bn = "0x" + (str.slice(0,2) === "0x"
|
||||
? new BN(str.slice(2), 16)
|
||||
: new BN(str, 10)).toString("hex");
|
||||
return bn === "0x0" ? "0x" : bn;
|
||||
}
|
||||
|
||||
const toEther = wei =>
|
||||
toNumber(div(wei, fromString("10000000000"))) / 100000000;
|
||||
|
||||
const fromEther = eth =>
|
||||
mul(fromNumber(Math.floor(eth * 100000000)), fromString("10000000000"));
|
||||
|
||||
const toString = a =>
|
||||
toBN(a).toString(10);
|
||||
|
||||
const fromNumber = a =>
|
||||
typeof a === "string"
|
||||
? (/^0x/.test(a) ? a : "0x" + a)
|
||||
: "0x" + new BN(a).toString("hex");
|
||||
|
||||
const toNumber = a =>
|
||||
toBN(a).toNumber();
|
||||
|
||||
const toUint256 = a =>
|
||||
Bytes.pad(32, a);
|
||||
|
||||
const bin = method => (a, b) =>
|
||||
fromBN(toBN(a)[method](toBN(b)));
|
||||
|
||||
const add = bin("add");
|
||||
const mul = bin("mul");
|
||||
const div = bin("div");
|
||||
const sub = bin("sub");
|
||||
|
||||
module.exports = {
|
||||
toString,
|
||||
fromString,
|
||||
toNumber,
|
||||
fromNumber,
|
||||
toEther,
|
||||
fromEther,
|
||||
toUint256,
|
||||
add,
|
||||
mul,
|
||||
div,
|
||||
sub
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
const Hash = require("./hash");
|
||||
const Bytes = require("./bytes");
|
||||
const Desubits = require("./desubits");
|
||||
|
||||
// Bytes -> Bytes
|
||||
const bytesAddChecksum = (bytes) => {
|
||||
const hash = Hash.keccak256(bytes);
|
||||
const sum = Bytes.slice(0, 1, hash);
|
||||
return Bytes.concat(bytes, sum);
|
||||
};
|
||||
|
||||
// Bytes -> Bool
|
||||
const bytesChecksum = (bytes) => {
|
||||
const length = Bytes.length(bytes);
|
||||
const prefix = Bytes.slice(0, length - 1, bytes);
|
||||
return bytesAddChecksum(prefix) === bytes;
|
||||
};
|
||||
|
||||
// () ~> Passphrase
|
||||
const create = () => {
|
||||
const bytes = bytesAddChecksum(Bytes.random(11));
|
||||
const seed = Desubits.fromBytes(bytes);
|
||||
const passphrase = seed.replace(/([a-z]{8})/g, "$1 ");
|
||||
return passphrase;
|
||||
};
|
||||
|
||||
// Passphrase -> Bytes
|
||||
const toBytes = (passphrase) => {
|
||||
const seed = passphrase.replace(/ /g, "");
|
||||
const bytes = Desubits.toBytes(passphrase);
|
||||
return bytes;
|
||||
};
|
||||
|
||||
// Passphrase -> Bool
|
||||
const checksum = (passphrase) =>
|
||||
bytesChecksum(toBytes(passphrase));
|
||||
|
||||
// Passphrase -> Bytes
|
||||
const toMasterKey = (passphrase) => {
|
||||
let hash = Hash.keccak256;
|
||||
let bytes = toBytes(passphrase);
|
||||
for (let i = 0, l = Math.pow(2,12); i < l; ++i)
|
||||
bytes = hash(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
create,
|
||||
checksum,
|
||||
toMasterKey
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
// The RLP format
|
||||
// Serialization and deserialization for the BytesTree type, under the following grammar:
|
||||
// | First byte | Meaning |
|
||||
// | ---------- | -------------------------------------------------------------------------- |
|
||||
// | 0 to 127 | HEX(leaf) |
|
||||
// | 128 to 183 | HEX(length_of_leaf + 128) + HEX(leaf) |
|
||||
// | 184 to 191 | HEX(length_of_length_of_leaf + 128 + 55) + HEX(length_of_leaf) + HEX(leaf) |
|
||||
// | 192 to 247 | HEX(length_of_node + 192) + HEX(node) |
|
||||
// | 248 to 255 | HEX(length_of_length_of_node + 128 + 55) + HEX(length_of_node) + HEX(node) |
|
||||
|
||||
const encode = tree => {
|
||||
const padEven = str =>
|
||||
str.length % 2 === 0 ? str : "0" + str;
|
||||
|
||||
const uint = num =>
|
||||
padEven(num.toString(16))
|
||||
|
||||
const length = (len, add) =>
|
||||
len < 56 ? uint(add + len) : uint(add + uint(len).length / 2 + 55) + uint(len);
|
||||
|
||||
const dataTree = tree => {
|
||||
if (typeof tree === "string") {
|
||||
const hex = tree.slice(2);
|
||||
const pre = hex.length != 2 || hex >= "80" ? length(hex.length / 2, 128) : "";
|
||||
return pre + hex;
|
||||
} else {
|
||||
const hex = tree.map(dataTree).join("");
|
||||
const pre = length(hex.length / 2, 192)
|
||||
return pre + hex;
|
||||
}
|
||||
}
|
||||
|
||||
return "0x" + dataTree(tree);
|
||||
};
|
||||
|
||||
const decode = hex => {
|
||||
let i = 2;
|
||||
|
||||
const parseTree = () => {
|
||||
if (i >= hex.length) throw "";
|
||||
const head = hex.slice(i,i+2);
|
||||
return head < "80" ? (i+=2, "0x" + head)
|
||||
: head < "c0" ? parseHex()
|
||||
: parseList();
|
||||
}
|
||||
|
||||
const parseLength = () => {
|
||||
const len = parseInt(hex.slice(i,i+=2), 16) % 64;
|
||||
return len < 56 ? len : parseInt(hex.slice(i, i += (len - 55) * 2), 16);
|
||||
}
|
||||
|
||||
const parseHex = () => {
|
||||
const len = parseLength();
|
||||
return "0x" + hex.slice(i, i += len * 2);
|
||||
}
|
||||
|
||||
const parseList = () => {
|
||||
const lim = parseLength() * 2 + i;
|
||||
let list = [];
|
||||
while (i < lim)
|
||||
list.push(parseTree());
|
||||
return list;
|
||||
}
|
||||
|
||||
try {
|
||||
return parseTree();
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {encode, decode};
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
const request = require("xhr-request-promise");
|
||||
|
||||
const genPayload = (() => {
|
||||
let nextId = 0;
|
||||
return (method, params) => ({
|
||||
jsonrpc: "2.0",
|
||||
id: ++nextId,
|
||||
method: method,
|
||||
params: params
|
||||
});
|
||||
})();
|
||||
|
||||
const send = url => (method, params) => {
|
||||
return request(url, {
|
||||
method: "POST",
|
||||
contentType: "application/json-rpc",
|
||||
body: JSON.stringify(genPayload(method,params))
|
||||
}).then(answer => {
|
||||
var resp = JSON.parse(answer); // todo: use njsp?
|
||||
if (resp.error) {
|
||||
throw new Error(resp.error.message);
|
||||
} else {
|
||||
return resp.result;
|
||||
}
|
||||
}).catch(e => {
|
||||
return {error: e.toString()};
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = send;
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
const Account = require("./account");
|
||||
const Nat = require("./nat");
|
||||
const Bytes = require("./bytes");
|
||||
const RLP = require("./rlp");
|
||||
const keccak256 = require("./hash").keccak256;
|
||||
|
||||
// EthereumRPC, IncompleteTransaction -> Promise Transaction
|
||||
const addDefaults = (rpc, tx) => {
|
||||
var baseDefaults = [
|
||||
tx.chainId || rpc("net_version", []),
|
||||
tx.gasPrice || rpc("eth_gasPrice", []),
|
||||
tx.nonce || rpc("eth_getTransactionCount", [tx.from,"latest"]),
|
||||
tx.value || "0x0",
|
||||
tx.data || "0x"
|
||||
];
|
||||
const noAddress = address => !address || address === "" || address === "0x";
|
||||
return Promise.all(baseDefaults).then(([chainIdNum, gasPrice, nonce, value, data]) => {
|
||||
var chainId = Nat.fromNumber(chainIdNum);
|
||||
var gasEstimator = tx.gas
|
||||
? Promise.resolve(null)
|
||||
: rpc("eth_estimateGas", [{
|
||||
from: noAddress(tx.from) ? null : tx.from,
|
||||
to: noAddress(tx.to) ? null : tx.to,
|
||||
value: tx.value,
|
||||
nonce: tx.nonce,
|
||||
data: tx.data
|
||||
}]);
|
||||
return gasEstimator.then(gasEstimate => {
|
||||
if (gasEstimate.error) {
|
||||
throw gasEstimate.error;
|
||||
}
|
||||
return {
|
||||
chainId: chainId,
|
||||
from: noAddress(tx.from) ? "0x" : tx.from.toLowerCase(),
|
||||
to: noAddress(tx.to) ? "0x" : tx.to.toLowerCase(),
|
||||
gasPrice: gasPrice,
|
||||
gas: tx.gas ? tx.gas : Nat.div(Nat.mul(gasEstimate, "0x6"), "0x5"),
|
||||
nonce: nonce,
|
||||
value: value,
|
||||
data: data ? data.toLowerCase() : null
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Transaction -> Bytes
|
||||
const signingData = tx => {
|
||||
return RLP.encode([
|
||||
Bytes.fromNat(tx.nonce),
|
||||
Bytes.fromNat(tx.gasPrice),
|
||||
Bytes.fromNat(tx.gas),
|
||||
tx.to ? tx.to.toLowerCase() : "0x",
|
||||
Bytes.fromNat(tx.value),
|
||||
tx.data,
|
||||
Bytes.fromNat(tx.chainId || "0x1"),
|
||||
"0x",
|
||||
"0x"
|
||||
]);
|
||||
};
|
||||
|
||||
// Transaction, Account -> Bytes
|
||||
const sign = (tx, account) => {
|
||||
const data = signingData(tx);
|
||||
const signature = Account.makeSigner(Nat.toNumber(tx.chainId || "0x1") * 2 + 35)(keccak256(data), account.privateKey);
|
||||
const rawTransaction = RLP.decode(data).slice(0,6).concat(Account.decodeSignature(signature));
|
||||
return RLP.encode(rawTransaction);
|
||||
};
|
||||
|
||||
// Bytes -> Address
|
||||
const recover = (rawTransaction) => {
|
||||
const values = RLP.decode(rawTransaction);
|
||||
const signature = Account.encodeSignature(values.slice(6,9));
|
||||
const recovery = Bytes.toNumber(values[6]);
|
||||
const extraData = recovery < 35 ? [] : [Bytes.fromNumber((recovery - 35) >> 1), "0x", "0x"]
|
||||
const data = values.slice(0,6).concat(extraData);
|
||||
const dataHex = RLP.encode(data);
|
||||
return Account.recover(keccak256(dataHex), signature);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
addDefaults,
|
||||
signingData,
|
||||
sign,
|
||||
recover
|
||||
};
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
const rnd = require("./randomData.js");
|
||||
const rlp = require("./../../src/rlp.js");
|
||||
const ref = {rlp: require("rlp")};
|
||||
const cps = f => {
|
||||
for (var t = Date.now(), i = 0; Date.now() - t < 1000; ++i)
|
||||
f();
|
||||
return i;
|
||||
};
|
||||
|
||||
let dataTrees = [];
|
||||
for (let i = 0; i < 64; ++i)
|
||||
dataTrees.push(rnd.dataTree());
|
||||
console.log("Benchmarking Eth-Lib's RLP implementation vs the one on NPM.");
|
||||
const liteCps = cps(() => dataTrees.map((dt) => rlp.decode(rlp.encode(dt))));
|
||||
const npmCps = cps(() => dataTrees.map((dt) => ref.rlp.decode(ref.rlp.encode(dt))));
|
||||
console.log("- Eth-Lib: " + liteCps + " calls per second.");
|
||||
console.log("- Reference: " + npmCps + " calls per second.");
|
||||
console.log("- Eth-Lib is: " + (liteCps / npmCps).toFixed(2) + " " + (liteCps > npmCps ? "faster" : "slower") + " than reference.");
|
||||
Generated
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
// () ~> HexString
|
||||
const hexString = () => {
|
||||
let str = "";
|
||||
while (Math.random() < 0.95)
|
||||
str = str + ("00" + (Math.random() * 256 | 0).toString(16)).slice(-2);
|
||||
return "0x" + str;
|
||||
}
|
||||
|
||||
// () ~> DataTree
|
||||
const dataTree = () => {
|
||||
let list = [];
|
||||
while (Math.random() < 0.8) {
|
||||
if (Math.random() < 0.8)
|
||||
list.push(hexString());
|
||||
else
|
||||
list.push(dataTree());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
hexString,
|
||||
dataTree
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
const assert = require("assert");
|
||||
const rnd = require("./lib/randomData.js");
|
||||
const rlp = require("./../src/rlp.js");
|
||||
const ref = {rlp: require("rlp")};
|
||||
// const F = require("./../src/types.js");
|
||||
const Nat = require("./../src/Nat.js");
|
||||
const Account = require("./../src/account.js");
|
||||
const keccak256 = require("./../src/hash.js").keccak256;
|
||||
const ethjs = {
|
||||
signer: require("ethjs-signer"),
|
||||
account: require("ethjs-account")};
|
||||
|
||||
describe("RLP", () => {
|
||||
it("Must operate identically to reference implementation", () => {
|
||||
// Builds a test set of 256 random dataTrees + 2 default
|
||||
let dataTrees = [];
|
||||
dataTrees.push(["0x00112233", "0x00", "0x44", "0x55", "0xf0", "0xff", ["0x66"], ["0x77", "0x88"], "0x", "0x", "0x99aabb"]);
|
||||
dataTrees.push("0x00112233445566778899aabbccddeeff");
|
||||
for (let i = 0; i < 256; ++i)
|
||||
dataTrees.push(rnd.dataTree());
|
||||
|
||||
// Tests if they encode and decode identically to the reference implementation
|
||||
dataTrees.forEach(dataTree => {
|
||||
const refEnc = "0x" + ref.rlp.encode(dataTree).toString("hex");
|
||||
const impEnc = rlp.encode(dataTree);
|
||||
const impDec = rlp.decode(impEnc);
|
||||
try {
|
||||
assert(refEnc === impEnc);
|
||||
assert(JSON.stringify(impDec) === JSON.stringify(dataTree));
|
||||
} catch (e) {
|
||||
console.log(JSON.stringify(dataTree, null, 2));
|
||||
}
|
||||
});
|
||||
});
|
||||
it("Obeys law: `decode(encode(tree)) == tree`", () => {
|
||||
F.forall([F.BytesTree], tree => JSON.stringify(rlp.decode(rlp.encode(tree))) === JSON.stringify(tree));
|
||||
});
|
||||
});
|
||||
|
||||
describe("account", function () {
|
||||
it("must recover the same address that signed", () => {
|
||||
F.forall([F.Account, F.Bytes], (acc, msg) =>
|
||||
Account.recover(keccak256(msg), Account.sign(keccak256(msg), acc.privateKey, 0)) === acc.address,
|
||||
32);
|
||||
});
|
||||
|
||||
it("must match the generated address with EthJS-account", () => {
|
||||
F.forall([F.NBytes(32)], pvt => {
|
||||
const ethfpAcc = Account.fromPrivate(pvt);
|
||||
const ethjsAcc = ethjs.account.privateToAccount(pvt);
|
||||
return ethfpAcc.address === ethjsAcc.address;
|
||||
}, 128);
|
||||
});
|
||||
|
||||
it("must match expected values for complex pre-determined tests", () => {
|
||||
const accounts = [
|
||||
{
|
||||
"address": '0x9d8A62f656a8d1615C1294fd71e9CFb3E4855A4F',
|
||||
"publicKey": '0x4bc2a31265153f07e70e0bab08724e6b85e217f8cd628ceb62974247bb493382ce28cab79ad7119ee1ad3ebcdb98a16805211530ecc6cfefa1b88e6dff99232a',
|
||||
"privateKey": '0x4646464646464646464646464646464646464646464646464646464646464646',
|
||||
"transactions": [
|
||||
{
|
||||
"object": {
|
||||
"nonce": Nat.fromString("9"),
|
||||
"gasPrice": Nat.fromString("20000000000"),
|
||||
"gas": Nat.fromString("21000"),
|
||||
"to": '0x3535353535353535353535353535353535353535',
|
||||
"value": Nat.fromString("1000000000000000000"),
|
||||
"data": "0x"
|
||||
},
|
||||
"signature": "0xf86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"address": '0xFCAd0B19bB29D4674531d6f115237E16AfCE377c',
|
||||
"publicKey": '0x4646ae5047316b4230d0086c8acec687f00b1cd9d1dc634f6cb358ac0a9a8ffffe77b4dd0a4bfb95851f3b7355c781dd60f8418fc8a65d14907aff47c903a559',
|
||||
"privateKey": '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
|
||||
"transactions": [
|
||||
{
|
||||
"object": {
|
||||
"nonce": Nat.fromString("0"),
|
||||
"gasPrice": Nat.fromString("230000000000"),
|
||||
"gas": Nat.fromString("21000"),
|
||||
"to": '0xFCAd0B19bB29D4674531d6f115237E16AfCE377c',
|
||||
"value": Nat.fromString("1000000000000000000"),
|
||||
"data": "0x0123abcd"
|
||||
},
|
||||
"signature": "0xf8708085358d117c0082520894fcad0b19bb29d4674531d6f115237e16afce377c880de0b6b3a7640000840123abcd25a032dbcf46a64b9892df24d8b961d2a52fd66b1dabd3a0d96940fd6795c01d8711a01b86df9475de7451554557d87b69456e3fa95aa5375584bf63d1ffd647a225d9",
|
||||
"oldSignature": "0xf8708085358d117c0082520894fcad0b19bb29d4674531d6f115237e16afce377c880de0b6b3a7640000840123abcd1ba04e289b471dd4469d5080ce3726b8359d5b0c649e012bbbdde53f9b6580ad21a2a0333663ea96846c112f3878705c8c24a763d1fbf8f97c174d26e350c7ef0d7263"
|
||||
},
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// For each account
|
||||
accounts.forEach(function (correctAccount, i) {
|
||||
|
||||
// Generates an address from this account's private key
|
||||
const testAccount = Account.fromPrivate(correctAccount.privateKey);
|
||||
|
||||
// Generated address must match
|
||||
assert(testAccount.address === correctAccount.address);
|
||||
|
||||
// For each transaction on this account
|
||||
correctAccount.transactions.forEach(function (transaction) {
|
||||
|
||||
// Signs it, uing post-EIP 155 scheme
|
||||
const signature = Account.signTransaction(
|
||||
transaction.object,
|
||||
correctAccount.privateKey);
|
||||
|
||||
// Checks if the signature is as expected
|
||||
assert(transaction.signature === signature);
|
||||
|
||||
//// Checks if we can recover the right address
|
||||
const recoveredAddress = Account.recoverTransaction(signature);
|
||||
assert(recoveredAddress === testAccount.address);
|
||||
|
||||
//// If the test also provides a pre-EIP 155 signature
|
||||
if (transaction.oldSignature) {
|
||||
|
||||
let txObj = {};
|
||||
for (let key in transaction.object)
|
||||
txObj[key] = transaction.object[key].replace(/^0x$/,"0x0");
|
||||
|
||||
//Signs it, using pre-EIP 155 scheme (using the ethjs-signer lib)
|
||||
const oldSignature = ethjs.signer.sign(txObj, correctAccount.privateKey);
|
||||
|
||||
//// Checks if the signature is as expected
|
||||
assert(transaction.oldSignature === oldSignature);
|
||||
|
||||
//// Checks if we can recover the right address from old sigs (using web3)
|
||||
const recoveredAddress = Account.recoverTransaction(oldSignature);
|
||||
assert(recoveredAddress === testAccount.address);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"root": true,
|
||||
"env": {
|
||||
"browser": true,
|
||||
"commonjs": true,
|
||||
"node": true,
|
||||
"mocha": true
|
||||
},
|
||||
"extends": ["eslint:recommended"],
|
||||
"rules": {
|
||||
"array-bracket-spacing": ["warn", "never"],
|
||||
"arrow-body-style": ["warn", "as-needed"],
|
||||
"arrow-parens": ["warn", "as-needed"],
|
||||
"arrow-spacing": "warn",
|
||||
"brace-style": ["warn", "1tbs"],
|
||||
"camelcase": "warn",
|
||||
"comma-spacing": ["warn", {"after": true}],
|
||||
"dot-notation": "warn",
|
||||
"eqeqeq": ["warn", "smart"],
|
||||
"indent": ["warn", 2, {
|
||||
"SwitchCase": 1,
|
||||
"FunctionDeclaration": {"parameters": 1},
|
||||
"MemberExpression": 1,
|
||||
"CallExpression": {"arguments": 1}
|
||||
}],
|
||||
"key-spacing": ["warn", {"beforeColon": false, "afterColon": true, "mode": "minimum"}],
|
||||
"keyword-spacing": "warn",
|
||||
"no-console": "off",
|
||||
"no-empty": "off",
|
||||
"no-multi-spaces": "warn",
|
||||
"no-redeclare": "off",
|
||||
"no-restricted-globals": ["warn", "Promise"],
|
||||
"no-trailing-spaces": "warn",
|
||||
"no-undef": "error",
|
||||
"no-unused-vars": ["warn", {"args": "none"}],
|
||||
"one-var": ["warn", "never"],
|
||||
"padded-blocks": ["warn", "never"],
|
||||
"object-curly-spacing": ["warn", "never"],
|
||||
"quotes": ["warn", "single"],
|
||||
"react/prop-types": "off",
|
||||
"react/jsx-no-bind": "off",
|
||||
"semi": ["warn", "always"],
|
||||
"space-before-blocks": ["warn", "always"],
|
||||
"space-before-function-paren": ["warn", "never"],
|
||||
"space-in-parens": ["warn", "never"]
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
var v1 = require('./v1');
|
||||
var v4 = require('./v4');
|
||||
|
||||
var uuid = v4;
|
||||
uuid.v1 = v1;
|
||||
uuid.v4 = v4;
|
||||
|
||||
module.exports = uuid;
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Convert array of 16 byte values to UUID string format of the form:
|
||||
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||
*/
|
||||
var byteToHex = [];
|
||||
for (var i = 0; i < 256; ++i) {
|
||||
byteToHex[i] = (i + 0x100).toString(16).substr(1);
|
||||
}
|
||||
|
||||
function bytesToUuid(buf, offset) {
|
||||
var i = offset || 0;
|
||||
var bth = byteToHex;
|
||||
// join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
|
||||
return ([bth[buf[i++]], bth[buf[i++]],
|
||||
bth[buf[i++]], bth[buf[i++]], '-',
|
||||
bth[buf[i++]], bth[buf[i++]], '-',
|
||||
bth[buf[i++]], bth[buf[i++]], '-',
|
||||
bth[buf[i++]], bth[buf[i++]], '-',
|
||||
bth[buf[i++]], bth[buf[i++]],
|
||||
bth[buf[i++]], bth[buf[i++]],
|
||||
bth[buf[i++]], bth[buf[i++]]]).join('');
|
||||
}
|
||||
|
||||
module.exports = bytesToUuid;
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Browser-compatible JavaScript MD5
|
||||
*
|
||||
* Modification of JavaScript MD5
|
||||
* https://github.com/blueimp/JavaScript-MD5
|
||||
*
|
||||
* Copyright 2011, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
* Based on
|
||||
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
||||
* Digest Algorithm, as defined in RFC 1321.
|
||||
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
|
||||
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
||||
* Distributed under the BSD License
|
||||
* See http://pajhome.org.uk/crypt/md5 for more info.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
function md5(bytes) {
|
||||
if (typeof(bytes) == 'string') {
|
||||
var msg = unescape(encodeURIComponent(bytes)); // UTF8 escape
|
||||
bytes = new Array(msg.length);
|
||||
for (var i = 0; i < msg.length; i++) bytes[i] = msg.charCodeAt(i);
|
||||
}
|
||||
|
||||
return md5ToHexEncodedArray(
|
||||
wordsToMd5(
|
||||
bytesToWords(bytes)
|
||||
, bytes.length * 8)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert an array of little-endian words to an array of bytes
|
||||
*/
|
||||
function md5ToHexEncodedArray(input) {
|
||||
var i;
|
||||
var x;
|
||||
var output = [];
|
||||
var length32 = input.length * 32;
|
||||
var hexTab = '0123456789abcdef';
|
||||
var hex;
|
||||
|
||||
for (i = 0; i < length32; i += 8) {
|
||||
x = (input[i >> 5] >>> (i % 32)) & 0xFF;
|
||||
|
||||
hex = parseInt(hexTab.charAt((x >>> 4) & 0x0F) + hexTab.charAt(x & 0x0F), 16);
|
||||
|
||||
output.push(hex);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the MD5 of an array of little-endian words, and a bit length.
|
||||
*/
|
||||
function wordsToMd5(x, len) {
|
||||
/* append padding */
|
||||
x[len >> 5] |= 0x80 << (len % 32);
|
||||
x[(((len + 64) >>> 9) << 4) + 14] = len;
|
||||
|
||||
var i;
|
||||
var olda;
|
||||
var oldb;
|
||||
var oldc;
|
||||
var oldd;
|
||||
var a = 1732584193;
|
||||
var b = -271733879;
|
||||
var c = -1732584194;
|
||||
|
||||
var d = 271733878;
|
||||
|
||||
for (i = 0; i < x.length; i += 16) {
|
||||
olda = a;
|
||||
oldb = b;
|
||||
oldc = c;
|
||||
oldd = d;
|
||||
|
||||
a = md5ff(a, b, c, d, x[i], 7, -680876936);
|
||||
d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);
|
||||
c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);
|
||||
b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);
|
||||
a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);
|
||||
d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);
|
||||
c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);
|
||||
b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);
|
||||
a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);
|
||||
d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);
|
||||
c = md5ff(c, d, a, b, x[i + 10], 17, -42063);
|
||||
b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);
|
||||
a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);
|
||||
d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);
|
||||
c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);
|
||||
b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);
|
||||
|
||||
a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);
|
||||
d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);
|
||||
c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);
|
||||
b = md5gg(b, c, d, a, x[i], 20, -373897302);
|
||||
a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);
|
||||
d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);
|
||||
c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);
|
||||
b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);
|
||||
a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);
|
||||
d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);
|
||||
c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);
|
||||
b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);
|
||||
a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);
|
||||
d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);
|
||||
c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);
|
||||
b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);
|
||||
|
||||
a = md5hh(a, b, c, d, x[i + 5], 4, -378558);
|
||||
d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);
|
||||
c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);
|
||||
b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);
|
||||
a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);
|
||||
d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);
|
||||
c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);
|
||||
b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);
|
||||
a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);
|
||||
d = md5hh(d, a, b, c, x[i], 11, -358537222);
|
||||
c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);
|
||||
b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);
|
||||
a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);
|
||||
d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);
|
||||
c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);
|
||||
b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);
|
||||
|
||||
a = md5ii(a, b, c, d, x[i], 6, -198630844);
|
||||
d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);
|
||||
c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);
|
||||
b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);
|
||||
a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);
|
||||
d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);
|
||||
c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);
|
||||
b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);
|
||||
a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);
|
||||
d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);
|
||||
c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);
|
||||
b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);
|
||||
a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);
|
||||
d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);
|
||||
c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);
|
||||
b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);
|
||||
|
||||
a = safeAdd(a, olda);
|
||||
b = safeAdd(b, oldb);
|
||||
c = safeAdd(c, oldc);
|
||||
d = safeAdd(d, oldd);
|
||||
}
|
||||
return [a, b, c, d];
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array bytes to an array of little-endian words
|
||||
* Characters >255 have their high-byte silently ignored.
|
||||
*/
|
||||
function bytesToWords(input) {
|
||||
var i;
|
||||
var output = [];
|
||||
output[(input.length >> 2) - 1] = undefined;
|
||||
for (i = 0; i < output.length; i += 1) {
|
||||
output[i] = 0;
|
||||
}
|
||||
var length8 = input.length * 8;
|
||||
for (i = 0; i < length8; i += 8) {
|
||||
output[i >> 5] |= (input[(i / 8)] & 0xFF) << (i % 32);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
|
||||
* to work around bugs in some JS interpreters.
|
||||
*/
|
||||
function safeAdd(x, y) {
|
||||
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
||||
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
||||
return (msw << 16) | (lsw & 0xFFFF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bitwise rotate a 32-bit number to the left.
|
||||
*/
|
||||
function bitRotateLeft(num, cnt) {
|
||||
return (num << cnt) | (num >>> (32 - cnt));
|
||||
}
|
||||
|
||||
/*
|
||||
* These functions implement the four basic operations the algorithm uses.
|
||||
*/
|
||||
function md5cmn(q, a, b, x, s, t) {
|
||||
return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);
|
||||
}
|
||||
function md5ff(a, b, c, d, x, s, t) {
|
||||
return md5cmn((b & c) | ((~b) & d), a, b, x, s, t);
|
||||
}
|
||||
function md5gg(a, b, c, d, x, s, t) {
|
||||
return md5cmn((b & d) | (c & (~d)), a, b, x, s, t);
|
||||
}
|
||||
function md5hh(a, b, c, d, x, s, t) {
|
||||
return md5cmn(b ^ c ^ d, a, b, x, s, t);
|
||||
}
|
||||
function md5ii(a, b, c, d, x, s, t) {
|
||||
return md5cmn(c ^ (b | (~d)), a, b, x, s, t);
|
||||
}
|
||||
|
||||
module.exports = md5;
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
var crypto = require('crypto');
|
||||
|
||||
function md5(bytes) {
|
||||
if (typeof Buffer.from === 'function') {
|
||||
// Modern Buffer API
|
||||
if (Array.isArray(bytes)) {
|
||||
bytes = Buffer.from(bytes);
|
||||
} else if (typeof bytes === 'string') {
|
||||
bytes = Buffer.from(bytes, 'utf8');
|
||||
}
|
||||
} else {
|
||||
// Pre-v4 Buffer API
|
||||
if (Array.isArray(bytes)) {
|
||||
bytes = new Buffer(bytes);
|
||||
} else if (typeof bytes === 'string') {
|
||||
bytes = new Buffer(bytes, 'utf8');
|
||||
}
|
||||
}
|
||||
|
||||
return crypto.createHash('md5').update(bytes).digest();
|
||||
}
|
||||
|
||||
module.exports = md5;
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// Unique ID creation requires a high quality random # generator. In the
|
||||
// browser this is a little complicated due to unknown quality of Math.random()
|
||||
// and inconsistent support for the `crypto` API. We do the best we can via
|
||||
// feature-detection
|
||||
|
||||
// getRandomValues needs to be invoked in a context where "this" is a Crypto
|
||||
// implementation. Also, find the complete implementation of crypto on IE11.
|
||||
var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||
|
||||
(typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));
|
||||
|
||||
if (getRandomValues) {
|
||||
// WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
|
||||
var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef
|
||||
|
||||
module.exports = function whatwgRNG() {
|
||||
getRandomValues(rnds8);
|
||||
return rnds8;
|
||||
};
|
||||
} else {
|
||||
// Math.random()-based (RNG)
|
||||
//
|
||||
// If all else fails, use Math.random(). It's fast, but is of unspecified
|
||||
// quality.
|
||||
var rnds = new Array(16);
|
||||
|
||||
module.exports = function mathRNG() {
|
||||
for (var i = 0, r; i < 16; i++) {
|
||||
if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
|
||||
rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
|
||||
}
|
||||
|
||||
return rnds;
|
||||
};
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// Unique ID creation requires a high quality random # generator. In node.js
|
||||
// this is pretty straight-forward - we use the crypto API.
|
||||
|
||||
var crypto = require('crypto');
|
||||
|
||||
module.exports = function nodeRNG() {
|
||||
return crypto.randomBytes(16);
|
||||
};
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
// Adapted from Chris Veness' SHA1 code at
|
||||
// http://www.movable-type.co.uk/scripts/sha1.html
|
||||
'use strict';
|
||||
|
||||
function f(s, x, y, z) {
|
||||
switch (s) {
|
||||
case 0: return (x & y) ^ (~x & z);
|
||||
case 1: return x ^ y ^ z;
|
||||
case 2: return (x & y) ^ (x & z) ^ (y & z);
|
||||
case 3: return x ^ y ^ z;
|
||||
}
|
||||
}
|
||||
|
||||
function ROTL(x, n) {
|
||||
return (x << n) | (x>>> (32 - n));
|
||||
}
|
||||
|
||||
function sha1(bytes) {
|
||||
var K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6];
|
||||
var H = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
|
||||
|
||||
if (typeof(bytes) == 'string') {
|
||||
var msg = unescape(encodeURIComponent(bytes)); // UTF8 escape
|
||||
bytes = new Array(msg.length);
|
||||
for (var i = 0; i < msg.length; i++) bytes[i] = msg.charCodeAt(i);
|
||||
}
|
||||
|
||||
bytes.push(0x80);
|
||||
|
||||
var l = bytes.length/4 + 2;
|
||||
var N = Math.ceil(l/16);
|
||||
var M = new Array(N);
|
||||
|
||||
for (var i=0; i<N; i++) {
|
||||
M[i] = new Array(16);
|
||||
for (var j=0; j<16; j++) {
|
||||
M[i][j] =
|
||||
bytes[i * 64 + j * 4] << 24 |
|
||||
bytes[i * 64 + j * 4 + 1] << 16 |
|
||||
bytes[i * 64 + j * 4 + 2] << 8 |
|
||||
bytes[i * 64 + j * 4 + 3];
|
||||
}
|
||||
}
|
||||
|
||||
M[N - 1][14] = ((bytes.length - 1) * 8) /
|
||||
Math.pow(2, 32); M[N - 1][14] = Math.floor(M[N - 1][14]);
|
||||
M[N - 1][15] = ((bytes.length - 1) * 8) & 0xffffffff;
|
||||
|
||||
for (var i=0; i<N; i++) {
|
||||
var W = new Array(80);
|
||||
|
||||
for (var t=0; t<16; t++) W[t] = M[i][t];
|
||||
for (var t=16; t<80; t++) {
|
||||
W[t] = ROTL(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1);
|
||||
}
|
||||
|
||||
var a = H[0];
|
||||
var b = H[1];
|
||||
var c = H[2];
|
||||
var d = H[3];
|
||||
var e = H[4];
|
||||
|
||||
for (var t=0; t<80; t++) {
|
||||
var s = Math.floor(t/20);
|
||||
var T = ROTL(a, 5) + f(s, b, c, d) + e + K[s] + W[t] >>> 0;
|
||||
e = d;
|
||||
d = c;
|
||||
c = ROTL(b, 30) >>> 0;
|
||||
b = a;
|
||||
a = T;
|
||||
}
|
||||
|
||||
H[0] = (H[0] + a) >>> 0;
|
||||
H[1] = (H[1] + b) >>> 0;
|
||||
H[2] = (H[2] + c) >>> 0;
|
||||
H[3] = (H[3] + d) >>> 0;
|
||||
H[4] = (H[4] + e) >>> 0;
|
||||
}
|
||||
|
||||
return [
|
||||
H[0] >> 24 & 0xff, H[0] >> 16 & 0xff, H[0] >> 8 & 0xff, H[0] & 0xff,
|
||||
H[1] >> 24 & 0xff, H[1] >> 16 & 0xff, H[1] >> 8 & 0xff, H[1] & 0xff,
|
||||
H[2] >> 24 & 0xff, H[2] >> 16 & 0xff, H[2] >> 8 & 0xff, H[2] & 0xff,
|
||||
H[3] >> 24 & 0xff, H[3] >> 16 & 0xff, H[3] >> 8 & 0xff, H[3] & 0xff,
|
||||
H[4] >> 24 & 0xff, H[4] >> 16 & 0xff, H[4] >> 8 & 0xff, H[4] & 0xff
|
||||
];
|
||||
}
|
||||
|
||||
module.exports = sha1;
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
var crypto = require('crypto');
|
||||
|
||||
function sha1(bytes) {
|
||||
if (typeof Buffer.from === 'function') {
|
||||
// Modern Buffer API
|
||||
if (Array.isArray(bytes)) {
|
||||
bytes = Buffer.from(bytes);
|
||||
} else if (typeof bytes === 'string') {
|
||||
bytes = Buffer.from(bytes, 'utf8');
|
||||
}
|
||||
} else {
|
||||
// Pre-v4 Buffer API
|
||||
if (Array.isArray(bytes)) {
|
||||
bytes = new Buffer(bytes);
|
||||
} else if (typeof bytes === 'string') {
|
||||
bytes = new Buffer(bytes, 'utf8');
|
||||
}
|
||||
}
|
||||
|
||||
return crypto.createHash('sha1').update(bytes).digest();
|
||||
}
|
||||
|
||||
module.exports = sha1;
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
var bytesToUuid = require('./bytesToUuid');
|
||||
|
||||
function uuidToBytes(uuid) {
|
||||
// Note: We assume we're being passed a valid uuid string
|
||||
var bytes = [];
|
||||
uuid.replace(/[a-fA-F0-9]{2}/g, function(hex) {
|
||||
bytes.push(parseInt(hex, 16));
|
||||
});
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function stringToBytes(str) {
|
||||
str = unescape(encodeURIComponent(str)); // UTF8 escape
|
||||
var bytes = new Array(str.length);
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
bytes[i] = str.charCodeAt(i);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
module.exports = function(name, version, hashfunc) {
|
||||
var generateUUID = function(value, namespace, buf, offset) {
|
||||
var off = buf && offset || 0;
|
||||
|
||||
if (typeof(value) == 'string') value = stringToBytes(value);
|
||||
if (typeof(namespace) == 'string') namespace = uuidToBytes(namespace);
|
||||
|
||||
if (!Array.isArray(value)) throw TypeError('value must be an array of bytes');
|
||||
if (!Array.isArray(namespace) || namespace.length !== 16) throw TypeError('namespace must be uuid string or an Array of 16 byte values');
|
||||
|
||||
// Per 4.3
|
||||
var bytes = hashfunc(namespace.concat(value));
|
||||
bytes[6] = (bytes[6] & 0x0f) | version;
|
||||
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
||||
|
||||
if (buf) {
|
||||
for (var idx = 0; idx < 16; ++idx) {
|
||||
buf[off+idx] = bytes[idx];
|
||||
}
|
||||
}
|
||||
|
||||
return buf || bytesToUuid(bytes);
|
||||
};
|
||||
|
||||
// Function#name is not settable on some platforms (#270)
|
||||
try {
|
||||
generateUUID.name = name;
|
||||
} catch (err) {
|
||||
}
|
||||
|
||||
// Pre-defined namespaces, per Appendix C
|
||||
generateUUID.DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
|
||||
generateUUID.URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';
|
||||
|
||||
return generateUUID;
|
||||
};
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
{
|
||||
"_from": "uuid@3.3.2",
|
||||
"_id": "uuid@3.3.2",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
|
||||
"_location": "/web3-eth-accounts/uuid",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "uuid@3.3.2",
|
||||
"name": "uuid",
|
||||
"escapedName": "uuid",
|
||||
"rawSpec": "3.3.2",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "3.3.2"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/web3-eth-accounts"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
|
||||
"_shasum": "1b4af4955eb3077c501c23872fc6513811587131",
|
||||
"_spec": "uuid@3.3.2",
|
||||
"_where": "C:\\Users\\Luis\\source\\repos\\AAMasters\\BackendServers\\node_modules\\web3-eth-accounts",
|
||||
"bin": {
|
||||
"uuid": "bin/uuid"
|
||||
},
|
||||
"browser": {
|
||||
"./lib/rng.js": "./lib/rng-browser.js",
|
||||
"./lib/sha1.js": "./lib/sha1-browser.js",
|
||||
"./lib/md5.js": "./lib/md5-browser.js"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/kelektiv/node-uuid/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"commitlint": {
|
||||
"extends": [
|
||||
"@commitlint/config-conventional"
|
||||
]
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Robert Kieffer",
|
||||
"email": "robert@broofa.com"
|
||||
},
|
||||
{
|
||||
"name": "Christoph Tavan",
|
||||
"email": "dev@tavan.de"
|
||||
},
|
||||
{
|
||||
"name": "AJ ONeal",
|
||||
"email": "coolaj86@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Vincent Voyer",
|
||||
"email": "vincent@zeroload.net"
|
||||
},
|
||||
{
|
||||
"name": "Roman Shtylman",
|
||||
"email": "shtylman@gmail.com"
|
||||
}
|
||||
],
|
||||
"deprecated": false,
|
||||
"description": "RFC4122 (v1, v4, and v5) UUIDs",
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "7.0.0",
|
||||
"@commitlint/config-conventional": "7.0.1",
|
||||
"eslint": "4.19.1",
|
||||
"husky": "0.14.3",
|
||||
"mocha": "5.2.0",
|
||||
"runmd": "1.0.1",
|
||||
"standard-version": "4.4.0"
|
||||
},
|
||||
"homepage": "https://github.com/kelektiv/node-uuid#readme",
|
||||
"keywords": [
|
||||
"uuid",
|
||||
"guid",
|
||||
"rfc4122"
|
||||
],
|
||||
"license": "MIT",
|
||||
"name": "uuid",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/kelektiv/node-uuid.git"
|
||||
},
|
||||
"scripts": {
|
||||
"commitmsg": "commitlint -E GIT_PARAMS",
|
||||
"md": "runmd --watch --output=README.md README_js.md",
|
||||
"prepare": "runmd --output=README.md README_js.md",
|
||||
"release": "standard-version",
|
||||
"test": "mocha test/test.js"
|
||||
},
|
||||
"version": "3.3.2"
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
var rng = require('./lib/rng');
|
||||
var bytesToUuid = require('./lib/bytesToUuid');
|
||||
|
||||
// **`v1()` - Generate time-based UUID**
|
||||
//
|
||||
// Inspired by https://github.com/LiosK/UUID.js
|
||||
// and http://docs.python.org/library/uuid.html
|
||||
|
||||
var _nodeId;
|
||||
var _clockseq;
|
||||
|
||||
// Previous uuid creation time
|
||||
var _lastMSecs = 0;
|
||||
var _lastNSecs = 0;
|
||||
|
||||
// See https://github.com/broofa/node-uuid for API details
|
||||
function v1(options, buf, offset) {
|
||||
var i = buf && offset || 0;
|
||||
var b = buf || [];
|
||||
|
||||
options = options || {};
|
||||
var node = options.node || _nodeId;
|
||||
var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;
|
||||
|
||||
// node and clockseq need to be initialized to random values if they're not
|
||||
// specified. We do this lazily to minimize issues related to insufficient
|
||||
// system entropy. See #189
|
||||
if (node == null || clockseq == null) {
|
||||
var seedBytes = rng();
|
||||
if (node == null) {
|
||||
// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
|
||||
node = _nodeId = [
|
||||
seedBytes[0] | 0x01,
|
||||
seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]
|
||||
];
|
||||
}
|
||||
if (clockseq == null) {
|
||||
// Per 4.2.2, randomize (14 bit) clockseq
|
||||
clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
|
||||
}
|
||||
}
|
||||
|
||||
// UUID timestamps are 100 nano-second units since the Gregorian epoch,
|
||||
// (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
|
||||
// time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
|
||||
// (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
|
||||
var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();
|
||||
|
||||
// Per 4.2.1.2, use count of uuid's generated during the current clock
|
||||
// cycle to simulate higher resolution clock
|
||||
var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;
|
||||
|
||||
// Time since last uuid creation (in msecs)
|
||||
var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
|
||||
|
||||
// Per 4.2.1.2, Bump clockseq on clock regression
|
||||
if (dt < 0 && options.clockseq === undefined) {
|
||||
clockseq = clockseq + 1 & 0x3fff;
|
||||
}
|
||||
|
||||
// Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
|
||||
// time interval
|
||||
if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
|
||||
nsecs = 0;
|
||||
}
|
||||
|
||||
// Per 4.2.1.2 Throw error if too many uuids are requested
|
||||
if (nsecs >= 10000) {
|
||||
throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
|
||||
}
|
||||
|
||||
_lastMSecs = msecs;
|
||||
_lastNSecs = nsecs;
|
||||
_clockseq = clockseq;
|
||||
|
||||
// Per 4.1.4 - Convert from unix epoch to Gregorian epoch
|
||||
msecs += 12219292800000;
|
||||
|
||||
// `time_low`
|
||||
var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
|
||||
b[i++] = tl >>> 24 & 0xff;
|
||||
b[i++] = tl >>> 16 & 0xff;
|
||||
b[i++] = tl >>> 8 & 0xff;
|
||||
b[i++] = tl & 0xff;
|
||||
|
||||
// `time_mid`
|
||||
var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
|
||||
b[i++] = tmh >>> 8 & 0xff;
|
||||
b[i++] = tmh & 0xff;
|
||||
|
||||
// `time_high_and_version`
|
||||
b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
|
||||
b[i++] = tmh >>> 16 & 0xff;
|
||||
|
||||
// `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
|
||||
b[i++] = clockseq >>> 8 | 0x80;
|
||||
|
||||
// `clock_seq_low`
|
||||
b[i++] = clockseq & 0xff;
|
||||
|
||||
// `node`
|
||||
for (var n = 0; n < 6; ++n) {
|
||||
b[i + n] = node[n];
|
||||
}
|
||||
|
||||
return buf ? buf : bytesToUuid(b);
|
||||
}
|
||||
|
||||
module.exports = v1;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
var v35 = require('./lib/v35.js');
|
||||
var md5 = require('./lib/md5');
|
||||
|
||||
module.exports = v35('v3', 0x30, md5);
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
var rng = require('./lib/rng');
|
||||
var bytesToUuid = require('./lib/bytesToUuid');
|
||||
|
||||
function v4(options, buf, offset) {
|
||||
var i = buf && offset || 0;
|
||||
|
||||
if (typeof(options) == 'string') {
|
||||
buf = options === 'binary' ? new Array(16) : null;
|
||||
options = null;
|
||||
}
|
||||
options = options || {};
|
||||
|
||||
var rnds = options.random || (options.rng || rng)();
|
||||
|
||||
// Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
|
||||
rnds[6] = (rnds[6] & 0x0f) | 0x40;
|
||||
rnds[8] = (rnds[8] & 0x3f) | 0x80;
|
||||
|
||||
// Copy bytes to buffer, if provided
|
||||
if (buf) {
|
||||
for (var ii = 0; ii < 16; ++ii) {
|
||||
buf[i + ii] = rnds[ii];
|
||||
}
|
||||
}
|
||||
|
||||
return buf || bytesToUuid(rnds);
|
||||
}
|
||||
|
||||
module.exports = v4;
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
var v35 = require('./lib/v35.js');
|
||||
var sha1 = require('./lib/sha1');
|
||||
module.exports = v35('v5', 0x50, sha1);
|
||||
Reference in new issue
Block a user