UNPKG

bitcore-lib-doge

Version:

A pure and powerful JavaScript Dogecoin library.

1,628 lines (1,450 loc) 1.83 MB
require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ (function (Buffer){(function (){ 'use strict'; var _ = require('lodash'); var $ = require('./util/preconditions'); var errors = require('./errors'); var Base58Check = require('./encoding/base58check'); var Networks = require('./networks'); var Hash = require('./crypto/hash'); var JSUtil = require('./util/js'); var PublicKey = require('./publickey'); /** * Instantiate an address from an address String or Buffer, a public key or script hash Buffer, * or an instance of {@link PublicKey} or {@link Script}. * * This is an immutable class, and if the first parameter provided to this constructor is an * `Address` instance, the same argument will be returned. * * An address has two key properties: `network` and `type`. The type is either * `Address.PayToPublicKeyHash` (value is the `'pubkeyhash'` string) * or `Address.PayToScriptHash` (the string `'scripthash'`). The network is an instance of {@link Network}. * You can quickly check whether an address is of a given kind by using the methods * `isPayToPublicKeyHash` and `isPayToScriptHash` * * @example * ```javascript * // validate that an input field is valid * var error = Address.getValidationError(input, 'testnet'); * if (!error) { * var address = Address(input, 'testnet'); * } else { * // invalid network or checksum (typo?) * var message = error.messsage; * } * * // get an address from a public key * var address = Address(publicKey, 'testnet').toString(); * ``` * * @param {*} data - The encoded data in various formats * @param {Network|String|number=} network - The network: 'livenet' or 'testnet' * @param {string=} type - The type of address: 'script' or 'pubkey' * @returns {Address} A new valid and frozen instance of an Address * @constructor */ function Address(data, network, type) { /* jshint maxcomplexity: 12 */ /* jshint maxstatements: 20 */ if (!(this instanceof Address)) { return new Address(data, network, type); } if (_.isArray(data) && _.isNumber(network)) { return Address.createMultisig(data, network, type); } if (data instanceof Address) { // Immutable instance return data; } $.checkArgument(data, 'First argument is required, please include address data.', 'guide/address.html'); if (network && !Networks.get(network)) { throw new TypeError('Second argument must be "livenet" or "testnet".'); } if (type && (type !== Address.PayToPublicKeyHash && type !== Address.PayToScriptHash)) { throw new TypeError('Third argument must be "pubkeyhash" or "scripthash".'); } var info = this._classifyArguments(data, network, type); // set defaults if not set info.network = info.network || Networks.get(network) || Networks.defaultNetwork; info.type = info.type || type || Address.PayToPublicKeyHash; JSUtil.defineImmutable(this, { hashBuffer: info.hashBuffer, network: info.network, type: info.type }); return this; } /** * Internal function used to split different kinds of arguments of the constructor * @param {*} data - The encoded data in various formats * @param {Network|String|number=} network - The network: 'livenet' or 'testnet' * @param {string=} type - The type of address: 'script' or 'pubkey' * @returns {Object} An "info" object with "type", "network", and "hashBuffer" */ Address.prototype._classifyArguments = function(data, network, type) { /* jshint maxcomplexity: 10 */ // transform and validate input data if ((data instanceof Buffer || data instanceof Uint8Array) && data.length === 20) { return Address._transformHash(data); } else if ((data instanceof Buffer || data instanceof Uint8Array) && data.length === 21) { return Address._transformBuffer(data, network, type); } else if (data instanceof PublicKey) { return Address._transformPublicKey(data); } else if (data instanceof Script) { return Address._transformScript(data, network); } else if (typeof(data) === 'string') { return Address._transformString(data, network, type); } else if (_.isObject(data)) { return Address._transformObject(data); } else { throw new TypeError('First argument is an unrecognized data format.'); } }; /** @static */ Address.PayToPublicKeyHash = 'pubkeyhash'; /** @static */ Address.PayToScriptHash = 'scripthash'; /** * @param {Buffer} hash - An instance of a hash Buffer * @returns {Object} An object with keys: hashBuffer * @private */ Address._transformHash = function(hash) { var info = {}; if (!(hash instanceof Buffer) && !(hash instanceof Uint8Array)) { throw new TypeError('Address supplied is not a buffer.'); } if (hash.length !== 20) { throw new TypeError('Address hashbuffers must be exactly 20 bytes.'); } info.hashBuffer = hash; return info; }; /** * Deserializes an address serialized through `Address#toObject()` * @param {Object} data * @param {string} data.hash - the hash that this address encodes * @param {string} data.type - either 'pubkeyhash' or 'scripthash' * @param {Network=} data.network - the name of the network associated * @return {Address} */ Address._transformObject = function(data) { $.checkArgument(data.hash || data.hashBuffer, 'Must provide a `hash` or `hashBuffer` property'); $.checkArgument(data.type, 'Must provide a `type` property'); return { hashBuffer: data.hash ? Buffer.from(data.hash, 'hex') : data.hashBuffer, network: Networks.get(data.network) || Networks.defaultNetwork, type: data.type }; }; /** * Internal function to discover the network and type based on the first data byte * * @param {Buffer} buffer - An instance of a hex encoded address Buffer * @returns {Object} An object with keys: network and type * @private */ Address._classifyFromVersion = function(buffer) { var version = {}; var pubkeyhashNetwork = Networks.get(buffer[0], 'pubkeyhash'); var scripthashNetwork = Networks.get(buffer[0], 'scripthash'); if (pubkeyhashNetwork) { version.network = pubkeyhashNetwork; version.type = Address.PayToPublicKeyHash; } else if (scripthashNetwork) { version.network = scripthashNetwork; version.type = Address.PayToScriptHash; } return version; }; /** * Internal function to transform a bitcoin address buffer * * @param {Buffer} buffer - An instance of a hex encoded address Buffer * @param {string=} network - The network: 'livenet' or 'testnet' * @param {string=} type - The type: 'pubkeyhash' or 'scripthash' * @returns {Object} An object with keys: hashBuffer, network and type * @private */ Address._transformBuffer = function(buffer, network, type) { /* jshint maxcomplexity: 9 */ var info = {}; if (!(buffer instanceof Buffer) && !(buffer instanceof Uint8Array)) { throw new TypeError('Address supplied is not a buffer.'); } if (buffer.length !== 1 + 20) { throw new TypeError('Address buffers must be exactly 21 bytes.'); } network = Networks.get(network); var bufferVersion = Address._classifyFromVersion(buffer); if (!bufferVersion.network || (network && network !== bufferVersion.network)) { throw new TypeError('Address has mismatched network type.'); } if (!bufferVersion.type || (type && type !== bufferVersion.type)) { throw new TypeError('Address has mismatched type.'); } info.hashBuffer = buffer.slice(1); info.network = bufferVersion.network; info.type = bufferVersion.type; return info; }; /** * Internal function to transform a {@link PublicKey} * * @param {PublicKey} pubkey - An instance of PublicKey * @returns {Object} An object with keys: hashBuffer, type * @private */ Address._transformPublicKey = function(pubkey) { var info = {}; if (!(pubkey instanceof PublicKey)) { throw new TypeError('Address must be an instance of PublicKey.'); } info.hashBuffer = Hash.sha256ripemd160(pubkey.toBuffer()); info.type = Address.PayToPublicKeyHash; return info; }; /** * Internal function to transform a {@link Script} into a `info` object. * * @param {Script} script - An instance of Script * @returns {Object} An object with keys: hashBuffer, type * @private */ Address._transformScript = function(script, network) { $.checkArgument(script instanceof Script, 'script must be a Script instance'); var info = script.getAddressInfo(network); if (!info) { throw new errors.Script.CantDeriveAddress(script); } return info; }; /** * Creates a P2SH address from a set of public keys and a threshold. * * The addresses will be sorted lexicographically, as that is the trend in bitcoin. * To create an address from unsorted public keys, use the {@link Script#buildMultisigOut} * interface. * * @param {Array} publicKeys - a set of public keys to create an address * @param {number} threshold - the number of signatures needed to release the funds * @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' * @return {Address} */ Address.createMultisig = function(publicKeys, threshold, network) { network = network || publicKeys[0].network || Networks.defaultNetwork; return Address.payingTo(Script.buildMultisigOut(publicKeys, threshold), network); }; /** * Internal function to transform a bitcoin address string * * @param {string} data * @param {String|Network=} network - either a Network instance, 'livenet', or 'testnet' * @param {string=} type - The type: 'pubkeyhash' or 'scripthash' * @returns {Object} An object with keys: hashBuffer, network and type * @private */ Address._transformString = function(data, network, type) { if (typeof(data) !== 'string') { throw new TypeError('data parameter supplied is not a string.'); } data = data.trim(); var addressBuffer = Base58Check.decode(data); var info = Address._transformBuffer(addressBuffer, network, type); return info; }; /** * Instantiate an address from a PublicKey instance * * @param {PublicKey} data * @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' * @returns {Address} A new valid and frozen instance of an Address */ Address.fromPublicKey = function(data, network) { var info = Address._transformPublicKey(data); network = network || Networks.defaultNetwork; return new Address(info.hashBuffer, network, info.type); }; /** * Instantiate an address from a ripemd160 public key hash * * @param {Buffer} hash - An instance of buffer of the hash * @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' * @returns {Address} A new valid and frozen instance of an Address */ Address.fromPublicKeyHash = function(hash, network) { var info = Address._transformHash(hash); return new Address(info.hashBuffer, network, Address.PayToPublicKeyHash); }; /** * Instantiate an address from a ripemd160 script hash * * @param {Buffer} hash - An instance of buffer of the hash * @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' * @returns {Address} A new valid and frozen instance of an Address */ Address.fromScriptHash = function(hash, network) { $.checkArgument(hash, 'hash parameter is required'); var info = Address._transformHash(hash); return new Address(info.hashBuffer, network, Address.PayToScriptHash); }; /** * Builds a p2sh address paying to script. This will hash the script and * use that to create the address. * If you want to extract an address associated with a script instead, * see {{Address#fromScript}} * * @param {Script} script - An instance of Script * @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' * @returns {Address} A new valid and frozen instance of an Address */ Address.payingTo = function(script, network) { $.checkArgument(script, 'script is required'); $.checkArgument(script instanceof Script, 'script must be instance of Script'); return Address.fromScriptHash(Hash.sha256ripemd160(script.toBuffer()), network); }; /** * Extract address from a Script. The script must be of one * of the following types: p2pkh input, p2pkh output, p2sh input * or p2sh output. * This will analyze the script and extract address information from it. * If you want to transform any script to a p2sh Address paying * to that script's hash instead, use {{Address#payingTo}} * * @param {Script} script - An instance of Script * @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' * @returns {Address} A new valid and frozen instance of an Address */ Address.fromScript = function(script, network) { $.checkArgument(script instanceof Script, 'script must be a Script instance'); var info = Address._transformScript(script, network); return new Address(info.hashBuffer, network, info.type); }; /** * Instantiate an address from a buffer of the address * * @param {Buffer} buffer - An instance of buffer of the address * @param {String|Network=} network - either a Network instance, 'livenet', or 'testnet' * @param {string=} type - The type of address: 'script' or 'pubkey' * @returns {Address} A new valid and frozen instance of an Address */ Address.fromBuffer = function(buffer, network, type) { var info = Address._transformBuffer(buffer, network, type); return new Address(info.hashBuffer, info.network, info.type); }; /** * Instantiate an address from an address string * * @param {string} str - An string of the bitcoin address * @param {String|Network=} network - either a Network instance, 'livenet', or 'testnet' * @param {string=} type - The type of address: 'script' or 'pubkey' * @returns {Address} A new valid and frozen instance of an Address */ Address.fromString = function(str, network, type) { var info = Address._transformString(str, network, type); return new Address(info.hashBuffer, info.network, info.type); }; /** * Instantiate an address from an Object * * @param {string} json - An JSON string or Object with keys: hash, network and type * @returns {Address} A new valid instance of an Address */ Address.fromObject = function fromObject(obj) { $.checkState( JSUtil.isHexa(obj.hash), 'Unexpected hash property, "' + obj.hash + '", expected to be hex.' ); var hashBuffer = Buffer.from(obj.hash, 'hex'); return new Address(hashBuffer, obj.network, obj.type); }; /** * Will return a validation error if exists * * @example * ```javascript * // a network mismatch error * var error = Address.getValidationError('15vkcKf7gB23wLAnZLmbVuMiiVDc1Nm4a2', 'testnet'); * ``` * * @param {string} data - The encoded data * @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' * @param {string} type - The type of address: 'script' or 'pubkey' * @returns {null|Error} The corresponding error message */ Address.getValidationError = function(data, network, type) { var error; try { /* jshint nonew: false */ new Address(data, network, type); } catch (e) { error = e; } return error; }; /** * Will return a boolean if an address is valid * * @example * ```javascript * assert(Address.isValid('15vkcKf7gB23wLAnZLmbVuMiiVDc1Nm4a2', 'livenet')); * ``` * * @param {string} data - The encoded data * @param {String|Network} network - either a Network instance, 'livenet', or 'testnet' * @param {string} type - The type of address: 'script' or 'pubkey' * @returns {boolean} The corresponding error message */ Address.isValid = function(data, network, type) { return !Address.getValidationError(data, network, type); }; /** * Returns true if an address is of pay to public key hash type * @return boolean */ Address.prototype.isPayToPublicKeyHash = function() { return this.type === Address.PayToPublicKeyHash; }; /** * Returns true if an address is of pay to script hash type * @return boolean */ Address.prototype.isPayToScriptHash = function() { return this.type === Address.PayToScriptHash; }; /** * Will return a buffer representation of the address * * @returns {Buffer} Bitcoin address buffer */ Address.prototype.toBuffer = function() { var version = Buffer.from([this.network[this.type]]); var buf = Buffer.concat([version, this.hashBuffer]); return buf; }; /** * @returns {Object} A plain object with the address information */ Address.prototype.toObject = Address.prototype.toJSON = function toObject() { return { hash: this.hashBuffer.toString('hex'), type: this.type, network: this.network.toString() }; }; /** * Will return a the string representation of the address * * @returns {string} Bitcoin address */ Address.prototype.toString = function() { return Base58Check.encode(this.toBuffer()); }; /** * Will return a string formatted for the console * * @returns {string} Bitcoin address */ Address.prototype.inspect = function() { return '<Address: ' + this.toString() + ', type: ' + this.type + ', network: ' + this.network + '>'; }; module.exports = Address; var Script = require('./script'); }).call(this)}).call(this,require("buffer").Buffer) },{"./crypto/hash":9,"./encoding/base58check":14,"./errors":18,"./networks":23,"./publickey":26,"./script":27,"./util/js":46,"./util/preconditions":47,"buffer":119,"lodash":191}],2:[function(require,module,exports){ 'use strict'; const BufferReader = require('../encoding/bufferreader'); const BufferWriter = require('../encoding/bufferwriter'); const $ = require('../util/preconditions'); const BufferUtil = require('../util/buffer'); const Transaction = require('../transaction/transaction'); const BlockHeader = require('./blockheader'); /** * Parse the Aux Proof-of-Work block in the block header * Ref: https://en.bitcoin.it/wiki/Merged_mining_specification#Aux_proof-of-work_block * @param {BlockHeader} header - BlockHeader this is attached to * @param {BufferReader} br - BufferReader containing the header */ function AuxPow(header, data) { if (!(this instanceof AuxPow)) { return new AuxPow(header, data); } $.checkArgument(header && header.version, 'version is missing from header') if (!(header.version & (1 << 8))) { return; } const info = this._from(data); this.coinbaseTxn = info.coinbaseTxn; this.coinbaseBranch = info.coinbaseBranch; this.blockchainBranch = info.blockchainBranch; // Note: the blockhash is only used when re-serializing. Otherwise, use the parent block hash this._blockHash = info.blockHashBuf; this._parentBlock = info.parentBlockBuf; return this; }; Object.defineProperty(AuxPow.prototype, 'parentBlock', { enumerable: true, configurable: true, get: function() { return new BlockHeader(this._parentBlock); } }); Object.defineProperty(AuxPow.prototype, 'blockHash', { enumerable: true, configurable: false, get: function() { // Note that the blockhash taken from the header is not a reliable value, so use the parentBlock.hash instead. // See https://en.bitcoin.it/wiki/Merged_mining_specification#Aux_proof-of-work_block // "Note that the block_hash element is not needed as you have the full parent_block header element and can calculate the hash from that. [...]some AuxPOW blocks have it little-endian, and some have it big-endian." return this.parentBlock.hash; } }); /** * @param {*} - A Buffer or BufferReader * @returns {Object} - An object representing block header data * @throws {TypeError} - If the argument was not recognized * @private */ AuxPow.prototype._from = function(data) { let info = {}; if (data instanceof BufferReader || (BufferUtil.isBuffer(data.buf) && !isNaN(data.pos))) { info = this._fromBufferReader(data); } else if (BufferUtil.isBuffer(data)) { data = BufferReader(data); info = this._fromBufferReader(data); // TODO // } else if (_.isObject(data)) { // info = AuxPow._fromObject(data); } else { throw new TypeError('Unrecognized argument for AuxPow'); } return info; }; /** * @param {BufferReader} - A BufferReader of the auxpow block header * @returns {Object} - An object representing auxpow block header data * @private */ AuxPow.prototype._fromBufferReader = function(br) { $.checkArgument(br && br instanceof BufferReader, 'A bufferreader is required') const info = { coinbaseTxn : new Transaction().fromBufferReader(br), blockHashBuf : br.read(32), coinbaseBranch : this._getMerkleBranch(br), blockchainBranch : this._getMerkleBranch(br), parentBlockBuf : br.read(80) } return info; }; /** * @param {BufferReader} br * @returns */ AuxPow.prototype._getMerkleBranch = function(br) { const branchLen = br.readVarintNum(); const branchHashes = []; for (let j = 0; j < branchLen; j++) { branchHashes.push(br.readReverse(32)); } const branchSideMask = br.readInt32LE(); return { branchLen, branchHashes, branchSideMask }; }; /** * @returns {Buffer} - A Buffer of the AuxPow header */ AuxPow.prototype.toBuffer = function() { const bw = this.toBufferWriter(); return bw.concat(); }; /** * @param {BufferWriter} - (optional) An existing instance BufferWriter * @returns {BufferWriter} - An instance of BufferWriter representation of the BlockHeader */ AuxPow.prototype.toBufferWriter = function(bw) { if (!bw) { bw = new BufferWriter(); } // Coinbase Transaction this.coinbaseTxn.toBufferWriter(bw); // Block Hash bw.write(this._blockHash); // Coinbase Branch bw.writeVarintNum(this.coinbaseBranch.branchLen); for (let branchHash of this.coinbaseBranch.branchHashes) { bw.writeReverse(branchHash); } bw.writeInt32LE(this.coinbaseBranch.branchSideMask); // Blockchain Branch bw.writeVarintNum(this.blockchainBranch.branchLen); for (let branchHash of this.blockchainBranch.branchHashes) { bw.writeReverse(branchHash); } bw.writeInt32LE(this.blockchainBranch.branchSideMask); // ParentBlock bw.write(this._parentBlock); return bw; }; module.exports = AuxPow; },{"../encoding/bufferreader":15,"../encoding/bufferwriter":16,"../transaction/transaction":41,"../util/buffer":45,"../util/preconditions":47,"./blockheader":4}],3:[function(require,module,exports){ (function (Buffer){(function (){ 'use strict'; var _ = require('lodash'); var BlockHeader = require('./blockheader'); var BN = require('../crypto/bn'); var BufferUtil = require('../util/buffer'); var BufferReader = require('../encoding/bufferreader'); var BufferWriter = require('../encoding/bufferwriter'); var Hash = require('../crypto/hash'); var Transaction = require('../transaction'); var $ = require('../util/preconditions'); /** * Instantiate a Block from a Buffer, JSON object, or Object with * the properties of the Block * * @param {*} - A Buffer, JSON string, or Object * @returns {Block} * @constructor */ function Block(arg) { if (!(this instanceof Block)) { return new Block(arg); } _.extend(this, Block._from(arg)); return this; } // https://github.com/bitcoin/bitcoin/blob/b5fa132329f0377d787a4a21c1686609c2bfaece/src/primitives/block.h#L14 Block.MAX_BLOCK_SIZE = 1000000; /** * @param {*} - A Buffer, JSON string or Object * @returns {Object} - An object representing block data * @throws {TypeError} - If the argument was not recognized * @private */ Block._from = function _from(arg) { var info = {}; if (BufferUtil.isBuffer(arg)) { info = Block._fromBufferReader(BufferReader(arg)); } else if (_.isObject(arg)) { info = Block._fromObject(arg); } else { throw new TypeError('Unrecognized argument for Block'); } return info; }; /** * @param {Object} - A plain JavaScript object * @returns {Object} - An object representing block data * @private */ Block._fromObject = function _fromObject(data) { var transactions = []; data.transactions.forEach(function(tx) { if (tx instanceof Transaction) { transactions.push(tx); } else { transactions.push(Transaction().fromObject(tx)); } }); var info = { header: BlockHeader.fromObject(data.header), transactions: transactions }; return info; }; /** * @param {Object} - A plain JavaScript object * @returns {Block} - An instance of block */ Block.fromObject = function fromObject(obj) { var info = Block._fromObject(obj); return new Block(info); }; /** * @param {BufferReader} - Block data * @returns {Object} - An object representing the block data * @private */ Block._fromBufferReader = function _fromBufferReader(br) { var info = {}; $.checkState(!br.finished(), 'No block data received'); info.header = BlockHeader.fromBufferReader(br); var transactions = br.readVarintNum(); info.transactions = []; for (var i = 0; i < transactions; i++) { info.transactions.push(Transaction().fromBufferReader(br)); } return info; }; /** * @param {BufferReader} - A buffer reader of the block * @returns {Block} - An instance of block */ Block.fromBufferReader = function fromBufferReader(br) { $.checkArgument(br, 'br is required'); var info = Block._fromBufferReader(br); return new Block(info); }; /** * @param {Buffer} - A buffer of the block * @returns {Block} - An instance of block */ Block.fromBuffer = function fromBuffer(buf) { return Block.fromBufferReader(new BufferReader(buf)); }; /** * @param {string} - str - A hex encoded string of the block * @returns {Block} - A hex encoded string of the block */ Block.fromString = function fromString(str) { var buf = Buffer.from(str, 'hex'); return Block.fromBuffer(buf); }; /** * @param {Binary} - Raw block binary data or buffer * @returns {Block} - An instance of block */ Block.fromRawBlock = function fromRawBlock(data) { if (!BufferUtil.isBuffer(data)) { data = Buffer.from(data, 'binary'); } var br = BufferReader(data); br.pos = Block.Values.START_OF_BLOCK; var info = Block._fromBufferReader(br); return new Block(info); }; /** * @returns {Object} - A plain object with the block properties */ Block.prototype.toObject = Block.prototype.toJSON = function toObject() { var transactions = []; this.transactions.forEach(function(tx) { transactions.push(tx.toObject()); }); return { header: this.header.toObject(), transactions: transactions }; }; /** * @returns {Buffer} - A buffer of the block */ Block.prototype.toBuffer = function toBuffer() { return this.toBufferWriter().concat(); }; /** * @returns {string} - A hex encoded string of the block */ Block.prototype.toString = function toString() { return this.toBuffer().toString('hex'); }; /** * @param {BufferWriter} - An existing instance of BufferWriter * @returns {BufferWriter} - An instance of BufferWriter representation of the Block */ Block.prototype.toBufferWriter = function toBufferWriter(bw) { if (!bw) { bw = new BufferWriter(); } bw.write(this.header.toBuffer()); bw.writeVarintNum(this.transactions.length); for (var i = 0; i < this.transactions.length; i++) { this.transactions[i].toBufferWriter(bw); } return bw; }; /** * Will iterate through each transaction and return an array of hashes * @returns {Array} - An array with transaction hashes */ Block.prototype.getTransactionHashes = function getTransactionHashes() { var hashes = []; if (this.transactions.length === 0) { return [Block.Values.NULL_HASH]; } for (var t = 0; t < this.transactions.length; t++) { hashes.push(this.transactions[t]._getHash()); } return hashes; }; /** * Will build a merkle tree of all the transactions, ultimately arriving at * a single point, the merkle root. * @link https://en.bitcoin.it/wiki/Protocol_specification#Merkle_Trees * @returns {Array} - An array with each level of the tree after the other. */ Block.prototype.getMerkleTree = function getMerkleTree() { var tree = this.getTransactionHashes(); var j = 0; for (var size = this.transactions.length; size > 1; size = Math.floor((size + 1) / 2)) { for (var i = 0; i < size; i += 2) { var i2 = Math.min(i + 1, size - 1); var buf = Buffer.concat([tree[j + i], tree[j + i2]]); tree.push(Hash.sha256sha256(buf)); } j += size; } return tree; }; /** * Calculates the merkleRoot from the transactions. * @returns {Buffer} - A buffer of the merkle root hash */ Block.prototype.getMerkleRoot = function getMerkleRoot() { var tree = this.getMerkleTree(); return tree[tree.length - 1]; }; /** * Verifies that the transactions in the block match the header merkle root * @returns {Boolean} - If the merkle roots match */ Block.prototype.validMerkleRoot = function validMerkleRoot() { var h = new BN(this.header.merkleRoot.toString('hex'), 'hex'); var c = new BN(this.getMerkleRoot().toString('hex'), 'hex'); if (h.cmp(c) !== 0) { return false; } return true; }; /** * @returns {Buffer} - The little endian hash buffer of the header */ Block.prototype._getHash = function() { return this.header._getHash(); }; var idProperty = { configurable: false, enumerable: true, /** * @returns {string} - The big endian hash buffer of the header */ get: function() { if (!this._id) { this._id = this.header.id; } return this._id; }, set: _.noop }; Object.defineProperty(Block.prototype, 'id', idProperty); Object.defineProperty(Block.prototype, 'hash', idProperty); /** * @returns {string} - A string formatted for the console */ Block.prototype.inspect = function inspect() { return '<Block ' + this.id + '>'; }; Block.Values = { START_OF_BLOCK: 0, // Start of block in raw block data NULL_HASH: Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex') }; module.exports = Block; }).call(this)}).call(this,require("buffer").Buffer) },{"../crypto/bn":7,"../crypto/hash":9,"../encoding/bufferreader":15,"../encoding/bufferwriter":16,"../transaction":30,"../util/buffer":45,"../util/preconditions":47,"./blockheader":4,"buffer":119,"lodash":191}],4:[function(require,module,exports){ (function (Buffer){(function (){ 'use strict'; var _ = require('lodash'); var BN = require('../crypto/bn'); var BufferUtil = require('../util/buffer'); var BufferReader = require('../encoding/bufferreader'); var BufferWriter = require('../encoding/bufferwriter'); var Hash = require('../crypto/hash'); var $ = require('../util/preconditions'); var Script = require('../script'); var GENESIS_BITS = 0x1e0ffff0; // Regtest: 0x207fffff /** * Instantiate a BlockHeader from a Buffer, JSON object, or Object with * the properties of the BlockHeader * * @param {*} - A Buffer, JSON string, or Object * @returns {BlockHeader} - An instance of block header * @constructor */ var BlockHeader = function BlockHeader(arg) { if (!(this instanceof BlockHeader)) { return new BlockHeader(arg); } var info = BlockHeader._from(arg); this.version = info.version; this.prevHash = info.prevHash; this.merkleRoot = info.merkleRoot; this.time = info.time; this.timestamp = info.time; this.bits = info.bits; this.nonce = info.nonce; this._auxpow = info.auxpow; if (info.hash) { $.checkState( this.hash === info.hash, 'Argument object hash property does not match block hash.' ); } return this; }; /** * @param {*} - A Buffer, JSON string or Object * @returns {Object} - An object representing block header data * @throws {TypeError} - If the argument was not recognized * @private */ BlockHeader._from = function _from(arg) { var info = {}; if (BufferUtil.isBuffer(arg)) { info = BlockHeader._fromBufferReader(BufferReader(arg)); } else if (_.isObject(arg)) { info = BlockHeader._fromObject(arg); } else { throw new TypeError('Unrecognized argument for BlockHeader'); } return info; }; /** * @param {Object} - A JSON string * @returns {Object} - An object representing block header data * @private */ BlockHeader._fromObject = function _fromObject(data) { $.checkArgument(data, 'data is required'); var prevHash = data.prevHash; var merkleRoot = data.merkleRoot; if (_.isString(data.prevHash)) { prevHash = BufferUtil.reverse(Buffer.from(data.prevHash, 'hex')); } if (_.isString(data.merkleRoot)) { merkleRoot = BufferUtil.reverse(Buffer.from(data.merkleRoot, 'hex')); } var info = { hash: data.hash, version: data.version, prevHash: prevHash, merkleRoot: merkleRoot, time: data.time, timestamp: data.time, bits: data.bits, nonce: data.nonce, auxpow: data.auxpow }; return info; }; /** * @param {Object} - A plain JavaScript object * @returns {BlockHeader} - An instance of block header */ BlockHeader.fromObject = function fromObject(obj) { var info = BlockHeader._fromObject(obj); return new BlockHeader(info); }; /** * @param {Binary} - Raw block binary data or buffer * @returns {BlockHeader} - An instance of block header */ BlockHeader.fromRawBlock = function fromRawBlock(data) { if (!BufferUtil.isBuffer(data)) { data = Buffer.from(data, 'binary'); } var br = BufferReader(data); br.pos = BlockHeader.Constants.START_OF_HEADER; var info = BlockHeader._fromBufferReader(br); return new BlockHeader(info); }; /** * @param {Buffer} - A buffer of the block header * @returns {BlockHeader} - An instance of block header */ BlockHeader.fromBuffer = function fromBuffer(buf) { var info = BlockHeader._fromBufferReader(BufferReader(buf)); return new BlockHeader(info); }; /** * @param {string} - A hex encoded buffer of the block header * @returns {BlockHeader} - An instance of block header */ BlockHeader.fromString = function fromString(str) { var buf = Buffer.from(str, 'hex'); return BlockHeader.fromBuffer(buf); }; /** * @param {BufferReader} - A BufferReader of the block header * @returns {Object} - An object representing block header data * @private */ BlockHeader._fromBufferReader = function _fromBufferReader(br) { var info = {}; info.version = br.readInt32LE(); info.prevHash = br.read(32); info.merkleRoot = br.read(32); info.time = br.readUInt32LE(); info.bits = br.readUInt32LE(); info.nonce = br.readUInt32LE(); info.auxpow = new AuxPow(info, br); return info; }; /** * @param {BufferReader} - A BufferReader of the block header * @returns {BlockHeader} - An instance of block header */ BlockHeader.fromBufferReader = function fromBufferReader(br) { var info = BlockHeader._fromBufferReader(br); return new BlockHeader(info); }; /** * @returns {Object} - A plain object of the BlockHeader */ BlockHeader.prototype.toObject = BlockHeader.prototype.toJSON = function toObject() { return { hash: this.hash, version: this.version, prevHash: BufferUtil.reverse(this.prevHash).toString('hex'), merkleRoot: BufferUtil.reverse(this.merkleRoot).toString('hex'), time: this.time, bits: this.bits, nonce: this.nonce }; }; /** * @param {Boolean} - Include AuxPow header (default: true) * @returns {Buffer} - A Buffer of the BlockHeader */ BlockHeader.prototype.toBuffer = function toBuffer(includeAuxPow = true) { return this.toBufferWriter(null, includeAuxPow).concat(); }; /** * @returns {string} - A hex encoded string of the BlockHeader */ BlockHeader.prototype.toString = function toString() { return this.toBuffer().toString('hex'); }; /** * @param {BufferWriter} - An existing instance BufferWriter * @param {Boolean} - Include AuxPow header (default: true) * @returns {BufferWriter} - An instance of BufferWriter representation of the BlockHeader */ BlockHeader.prototype.toBufferWriter = function toBufferWriter(bw, includeAuxPow = true) { if (!bw) { bw = new BufferWriter(); } bw.writeInt32LE(this.version); bw.write(this.prevHash); bw.write(this.merkleRoot); bw.writeUInt32LE(this.time); bw.writeUInt32LE(this.bits); bw.writeUInt32LE(this.nonce); if (includeAuxPow && this.isAuxPow()) { this.auxpow.toBufferWriter(bw); } return bw; }; /** * Returns the target difficulty for this block * @param {Number} bits * @returns {BN} An instance of BN with the decoded difficulty bits */ BlockHeader.prototype.getTargetDifficulty = function getTargetDifficulty(bits) { bits = bits || this.bits; var target = new BN(bits & 0xffffff); var mov = 8 * ((bits >>> 24) - 3); while (mov-- > 0) { target = target.mul(new BN(2)); } return target; }; /** * @link https://github.com/dogecoin/dogecoin/blob/f80bfe9068ac1a0619d48dad0d268894d926941e/src/rpc/blockchain.cpp#L47 * @return {Number} */ BlockHeader.prototype.getDifficulty = function getDifficulty() { // minimum difficulty = 1.0. if (!this.bits) { return 1.0; } let decimalShift = (this.bits >> 24) & 0xff; let difficulty = 0x0000ffff / (this.bits & 0x00ffffff); while (decimalShift < 29) { difficulty *= 256.0; decimalShift++; } while (decimalShift > 29) { difficulty /= 256.0; decimalShift--; } return parseFloat(difficulty.toFixed(19)); }; /** * @returns {Buffer} - The little endian hash buffer of the header */ BlockHeader.prototype._getHash = function hash() { var buf = this.toBuffer(false); return Hash.sha256sha256(buf); }; var idProperty = { configurable: false, enumerable: true, /** * @returns {string} - The big endian hash buffer of the header */ get: function() { if (!this._id) { this._id = BufferReader(this._getHash()).readReverse().toString('hex'); } return this._id; }, set: _.noop }; Object.defineProperty(BlockHeader.prototype, 'id', idProperty); Object.defineProperty(BlockHeader.prototype, 'hash', idProperty); /** * @returns {Boolean} - If timestamp is not too far in the future */ BlockHeader.prototype.validTimestamp = function validTimestamp() { var currentTime = Math.round(new Date().getTime() / 1000); if (this.time > currentTime + BlockHeader.Constants.MAX_TIME_OFFSET) { return false; } return true; }; /** * @returns {Boolean} - If the proof-of-work hash satisfies the target difficulty */ BlockHeader.prototype.validProofOfWork = function validProofOfWork() { // For Litecoin, we use the scrypt hash to calculate proof of work let hashBuf; if (this.isAuxPow()) { hashBuf = this.auxpow.parentBlock.toBuffer(); } else { hashBuf = this.toBuffer() } var pow = new BN(Hash.scrypt(hashBuf)); var target = this.getTargetDifficulty(); if (pow.cmp(target) > 0) { return false; } return true; }; /** * @returns {string} - A string formatted for the console */ BlockHeader.prototype.inspect = function inspect() { return '<BlockHeader ' + this.id + '>'; }; /** * @returns {Boolean} - Whether block is part of an Aux Proof-of-Work */ BlockHeader.prototype.isAuxPow = function() { // Reference for AuxPoW bit: // https://github.com/dogecoin/dogecoin/blob/0b46a40ed125d7bf4b5a485b91350bc8bdc48fc8/src/primitives/pureheader.h#L131 return Boolean(this.version & (1 << 8)); } Object.defineProperty(BlockHeader.prototype, 'auxpow', { configurable: false, enumerable: true, /** * @returns {AuxPow} */ get: function() { if (this.isAuxPow()) { return this._auxpow; } return null; } }) BlockHeader.Constants = { START_OF_HEADER: 0, // Start buffer position in raw block data MAX_TIME_OFFSET: 2 * 60 * 60, // The max a timestamp can be in the future LARGEST_HASH: new BN('10000000000000000000000000000000000000000000000000000000000000000', 'hex') }; module.exports = BlockHeader; var AuxPow = require('./auxpow'); }).call(this)}).call(this,require("buffer").Buffer) },{"../crypto/bn":7,"../crypto/hash":9,"../encoding/bufferreader":15,"../encoding/bufferwriter":16,"../script":27,"../util/buffer":45,"../util/preconditions":47,"./auxpow":2,"buffer":119,"lodash":191}],5:[function(require,module,exports){ module.exports = require('./block'); module.exports.BlockHeader = require('./blockheader'); module.exports.MerkleBlock = require('./merkleblock'); },{"./block":3,"./blockheader":4,"./merkleblock":6}],6:[function(require,module,exports){ (function (Buffer){(function (){ 'use strict'; var _ = require('lodash'); var BlockHeader = require('./blockheader'); var BufferUtil = require('../util/buffer'); var BufferReader = require('../encoding/bufferreader'); var BufferWriter = require('../encoding/bufferwriter'); var Hash = require('../crypto/hash'); var JSUtil = require('../util/js'); var Transaction = require('../transaction'); var $ = require('../util/preconditions'); /** * Instantiate a MerkleBlock from a Buffer, JSON object, or Object with * the properties of the Block * * @param {*} - A Buffer, JSON string, or Object representing a MerkleBlock * @returns {MerkleBlock} * @constructor */ function MerkleBlock(arg) { /* jshint maxstatements: 18 */ if (!(this instanceof MerkleBlock)) { return new MerkleBlock(arg); } var info = {}; if (BufferUtil.isBuffer(arg)) { info = MerkleBlock._fromBufferReader(BufferReader(arg)); } else if (_.isObject(arg)) { var header; if(arg.header instanceof BlockHeader) { header = arg.header; } else { header = BlockHeader.fromObject(arg.header); } info = { /** * @name MerkleBlock#header * @type {BlockHeader} */ header: header, /** * @name MerkleBlock#numTransactions * @type {Number} */ numTransactions: arg.numTransactions, /** * @name MerkleBlock#hashes * @type {String[]} */ hashes: arg.hashes, /** * @name MerkleBlock#flags * @type {Number[]} */ flags: arg.flags }; } else { throw new TypeError('Unrecognized argument for MerkleBlock'); } _.extend(this,info); this._flagBitsUsed = 0; this._hashesUsed = 0; return this; } /** * @param {Buffer} - MerkleBlock data in a Buffer object * @returns {MerkleBlock} - A MerkleBlock object */ MerkleBlock.fromBuffer = function fromBuffer(buf) { return MerkleBlock.fromBufferReader(BufferReader(buf)); }; /** * @param {BufferReader} - MerkleBlock data in a BufferReader object * @returns {MerkleBlock} - A MerkleBlock object */ MerkleBlock.fromBufferReader = function fromBufferReader(br) { return new MerkleBlock(MerkleBlock._fromBufferReader(br)); }; /** * @returns {Buffer} - A buffer of the block */ MerkleBlock.prototype.toBuffer = function toBuffer() { return this.toBufferWriter().concat(); }; /** * @param {BufferWriter} - An existing instance of BufferWriter * @returns {BufferWriter} - An instance of BufferWriter representation of the MerkleBlock */ MerkleBlock.prototype.toBufferWriter = function toBufferWriter(bw) { if (!bw) { bw = new BufferWriter(); } bw.write(this.header.toBuffer()); bw.writeUInt32LE(this.numTransactions); bw.writeVarintNum(this.hashes.length); for (var i = 0; i < this.hashes.length; i++) { bw.write(new Buffer(this.hashes[i], 'hex')); } bw.writeVarintNum(this.flags.length); for (i = 0; i < this.flags.length; i++) { bw.writeUInt8(this.flags[i]); } return bw; }; /** * @returns {Object} - A plain object with the MerkleBlock properties */ MerkleBlock.prototype.toObject = MerkleBlock.prototype.toJSON = function toObject() { return { header: this.header.toObject(), numTransactions: this.numTransactions, hashes: this.hashes, flags: this.flags }; }; /** * Verify that the MerkleBlock is valid * @returns {Boolean} - True/False whether this MerkleBlock is Valid */ MerkleBlock.prototype.validMerkleTree = function validMerkleTree() { $.checkState(_.isArray(this.flags), 'MerkleBlock flags is not an array'); $.checkState(_.isArray(this.hashes), 'MerkleBlock hashes is not an array'); // Can't have more hashes than numTransactions if(this.hashes.length > this.numTransactions) { return false; } // Can't have more flag bits than num hashes if(this.flags.length * 8 < this.hashes.length) { return false; } var height = this._calcTreeHeight(); var opts = { hashesUsed: 0, flagBitsUsed: 0 }; var root = this._traverseMerkleTree(height, 0, opts); if(opts.hashesUsed !== this.hashes.length) { return false; } return BufferUtil.equals(root, this.header.merkleRoot); }; /** * Traverse a the tree in this MerkleBlock, validating it along the way * Modeled after Bitcoin Core merkleblock.cpp TraverseAndExtract() * @param {Number} - depth - Current height * @param {Number} - pos - Current position in the tree * @param {Object} - opts - Object with values that need to be mutated throughout the traversal * @param {Number} - opts.flagBitsUsed - Number of flag bits used, should start at 0 * @param {Number} - opts.hashesUsed - Number of hashes used, should start at 0 * @param {Array} - opts.txs - Will finish populated by transactions found during traversal * @returns {Buffer|null} - Buffer containing the Merkle Hash for that height * @private */ MerkleBlock.prototype._traverseMerkleTree = function traverseMerkleTree(depth, pos, opts) { /* jshint maxcomplexity: 12*/ /* jshint maxstatements: 20 */ opts = opts || {}; opts.txs = opts.txs || []; opts.flagBitsUsed = opts.flagBitsUsed || 0; opts.hashesUsed = opts.hashesUsed || 0; if(opts.flagBitsUsed > this.flags.length * 8) { return null; } var isParentOfMatch = (this.flags[opts.flagBitsUsed >> 3] >>> (opts.flagBitsUsed++ & 7)) & 1; if(depth === 0 || !isParentOfMatch) { if(opts.hashesUsed >= this.hashes.length) { return null; } var hash = this.hashes[opts.hashesUsed++]; if(depth === 0 && isParentOfMatch) { opts.txs.push(hash); } return new Buffer(hash, 'hex'); } else { var left = this._traverseMerkleTree(depth-1, pos*2, opts); var right = left; if(pos*2+1 < this._calcTreeWidth(depth-1)) { right = this._traverseMerkleTree(depth-1, pos*2+1, opts); } return Hash.sha256sha256(new Buffer.concat([left, right])); } }; /** Calculates the width of a merkle tree at a given height. * Modeled after Bitcoin Core merkleblock.h CalcTreeWidth() * @param {Number} - Height at which we want the tree width * @returns {Number} - Width of the tree at a given height * @private */ MerkleBlock.prototype._calcTreeWidth = function calcTreeWidth(height) { return (this.numTransactions + (1 << height) - 1) >> height; }; /** Calculates the height of the merkle tree in this MerkleBlock * @param {Number} - Height at which we want the tree width * @returns {Number} - Height of the merkle tree in this MerkleBlock * @private */ MerkleBlock.prototype._calcTreeHeight = function calcTreeHeight() { var height = 0; while (this._calcTreeWidth(height) > 1) { height++; } return height; }; /** * @param {Transaction|String} - Transaction or Transaction ID Hash * @returns {Boolean} - return true/false if this MerkleBlock has the TX or not * @private */ MerkleBlock.prototype.hasTransaction = function hasTransaction(tx) { $.checkArgument(!_.isUndefined(tx), 'tx cannot be undefined'); $.checkArgument(tx instanceof Transaction || typeof tx === 'string', 'Invalid tx given, tx must be a "string" or "Transaction"'); var hash = tx; if(tx instanceof Transaction) { // We need to reverse the id hash for the lookup hash = BufferUtil.reverse(new Buffer(tx.id, 'hex')).toString('hex'); } var txs = []; var height = this._calcTreeHeight(); this._traverseMerkleTree(height, 0, { txs: txs }); return txs.indexOf(hash) !== -1; }; /** * @param {Buffer} - MerkleBlock data * @returns {Object} - An Object representing merkleblock data * @private */ MerkleBlock._fromBufferReader = function _fromBufferReader(br) { $.checkState(!br.finished(), 'No merkleblock data received'); var info = {}; info.header = BlockHeader.fromBufferReader(br); info.numTransactions = br.readUInt32LE(); var numHashes = br.readVarintNum(); info.hashes = []; for (var i = 0; i < numHashes; i++) { info.hashes.push(br.read(32).toString('hex')); } var numFlags = br.readVarintNum(); info.flags = []; for (i = 0; i < numFlags; i++) { info.flags.push(br.readUInt8()); } return info; }; /** * @param {Object} - A plain JavaScript object * @returns {Block} - An instance of block */ MerkleBlock.fromObject = function fromObject(obj) { return new MerkleBlock(obj); }; module.exports = MerkleBlock; }).call(this)}).call(this,require("buffer").Buffer) },{"../crypto/hash":9,"../encoding/bufferreader":15,"../encoding/bufferwriter":16,"../transaction":30,"../util/buffer":45,"../util/js":46,"../util/preconditions":47,"./blockheader":4,"buffer":119,"lodash":191}],7:[function(require,module,exports){ (function (Buffer){(function (){ 'use strict'; var BN = require('bn.js'); var $ = require('../util/preconditions'); var _ = require('lodash'); var reversebuf = function(buf) { var buf2 = Buffer.alloc(buf.length); for (var i = 0; i < buf.length; i++) { buf2[i] = buf[buf.length - 1 - i]; } return buf2; }; BN.Zero = new BN(0); BN.One = new BN(1); BN.Minus1 = new BN(-1); BN.fromNumber = function(n) { $.checkArgument(_.isNumber(n)); return new BN(n); }; BN.fromString = function(str, base) { $.checkArgument(_.isString(str)); return new BN(str, base); }; BN.fromBuffer = function(buf, opts) { if (typeof opts !== 'undefined' && opts.endian === 'little') { buf = reversebuf(buf); } var hex = buf.toString('hex'); var bn = new BN(hex, 16); return bn; }; /** * Instantiate a BigNumber from a "signed magnitude buffer" * (a buffer where the most significant bit represents the sign