From 0dc000839bbf24da99dd73f80737be9122a2b9eb Mon Sep 17 00:00:00 2001 From: Chris Clark Date: Wed, 14 Oct 2015 15:45:01 -0700 Subject: [PATCH] Use ripple-hashes --- npm-shrinkwrap.json | 28 +++++ package.json | 1 + src/api/offline/ledgerhash.js | 13 ++- src/core/hashprefixes.js | 38 ------- src/core/index.js | 2 - src/core/ledger.js | 186 ---------------------------------- src/core/ledgerspaces.js | 22 ---- src/core/shamap.js | 175 -------------------------------- src/core/transaction.js | 24 ++--- test/ledger-test.js | 93 ----------------- test/transaction-test.js | 26 +---- 11 files changed, 46 insertions(+), 562 deletions(-) delete mode 100644 src/core/hashprefixes.js delete mode 100644 src/core/ledger.js delete mode 100644 src/core/ledgerspaces.js delete mode 100644 src/core/shamap.js delete mode 100644 test/ledger-test.js diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index feef4bfb..a3b095d6 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -168,6 +168,34 @@ } } }, + "ripple-hashes": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/ripple-hashes/-/ripple-hashes-0.0.1.tgz", + "dependencies": { + "create-hash": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.2.tgz", + "dependencies": { + "cipher-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.1.tgz" + }, + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + }, + "ripemd160": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-1.0.1.tgz" + }, + "sha.js": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.4.tgz" + } + } + } + } + }, "ripple-keypairs": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/ripple-keypairs/-/ripple-keypairs-0.10.0.tgz", diff --git a/package.json b/package.json index ad98ce1a..ae0dea1d 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "lru-cache": "~2.5.0", "ripple-address-codec": "^2.0.1", "ripple-binary-codec": "^0.0.6", + "ripple-hashes": "^0.0.1", "ripple-keypairs": "^0.10.0", "ripple-lib-transactionparser": "^0.5.1", "ripple-lib-value": "0.1.0", diff --git a/src/api/offline/ledgerhash.js b/src/api/offline/ledgerhash.js index 474188d4..69b60365 100644 --- a/src/api/offline/ledgerhash.js +++ b/src/api/offline/ledgerhash.js @@ -2,6 +2,7 @@ 'use strict'; const _ = require('lodash'); const common = require('../common'); +const hashes = require('ripple-hashes'); function convertLedgerHeader(header) { return { @@ -25,7 +26,7 @@ function convertLedgerHeader(header) { function hashLedgerHeader(ledgerHeader) { const header = convertLedgerHeader(ledgerHeader); - return common.core.Ledger.calculateLedgerHash(header); + return hashes.computeLedgerHash(header); } function computeTransactionHash(ledger) { @@ -39,8 +40,7 @@ function computeTransactionHash(ledger) { tx.meta ? {metaData: tx.meta} : {}); return renameMeta; }); - const ledgerObject = common.core.Ledger.from_json({transactions: txs}); - const transactionHash = ledgerObject.calc_tx_hash(); + const transactionHash = hashes.computeTransactionTreeHash(txs); if (ledger.transactionHash !== undefined && ledger.transactionHash !== transactionHash) { throw new common.errors.ValidationError('transactionHash in header' @@ -54,8 +54,7 @@ function computeStateHash(ledger) { return ledger.stateHash; } const state = JSON.parse(ledger.rawState); - const ledgerObject = common.core.Ledger.from_json({accountState: state}); - const stateHash = ledgerObject.calc_account_hash(); + const stateHash = hashes.computeStateTreeHash(state); if (ledger.stateHash !== undefined && ledger.stateHash !== stateHash) { throw new common.errors.ValidationError('stateHash in header' + ' does not match computed hash of state'); @@ -64,11 +63,11 @@ function computeStateHash(ledger) { } function computeLedgerHash(ledger: Object): string { - const hashes = { + const subhashes = { transactionHash: computeTransactionHash(ledger), stateHash: computeStateHash(ledger) }; - return hashLedgerHeader(_.assign({}, ledger, hashes)); + return hashLedgerHeader(_.assign({}, ledger, subhashes)); } module.exports = computeLedgerHash; diff --git a/src/core/hashprefixes.js b/src/core/hashprefixes.js deleted file mode 100644 index d55a6a9b..00000000 --- a/src/core/hashprefixes.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -// TODO: move in helpers from serializedtypes to utils -function toBytes(n) { - return [n >>> 24, (n >>> 16) & 0xff, (n >>> 8) & 0xff, n & 0xff]; -} - -/** - * Prefix for hashing functions. - * - * These prefixes are inserted before the source material used to - * generate various hashes. This is done to put each hash in its own - * "space." This way, two different types of objects with the - * same binary data will produce different hashes. - * - * Each prefix is a 4-byte value with the last byte set to zero - * and the first three bytes formed from the ASCII equivalent of - * some arbitrary string. For example "TXN". - */ - -// transaction plus signature to give transaction ID -exports.HASH_TX_ID = 0x54584E00; // 'TXN' -// transaction plus metadata -exports.HASH_TX_NODE = 0x534E4400; // 'TND' -// inner node in tree -exports.HASH_INNER_NODE = 0x4D494E00; // 'MIN' -// leaf node in tree -exports.HASH_LEAF_NODE = 0x4D4C4E00; // 'MLN' -// inner transaction to sign -exports.HASH_TX_SIGN = 0x53545800; // 'STX' -// inner transaction to sign (TESTNET) -exports.HASH_TX_SIGN_TESTNET = 0x73747800; // 'stx' -// inner transaction to multisign -exports.HASH_TX_MULTISIGN = 0x534D5400; // 'SMT' - -Object.keys(exports).forEach(function(k) { - exports[k + '_BYTES'] = toBytes(exports[k]); -}); diff --git a/src/core/index.js b/src/core/index.js index 5495bfb7..2fc17dde 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -9,7 +9,6 @@ exports.Meta = require('./meta').Meta; exports.RippleError = require('./rippleerror').RippleError; exports.utils = require('./utils'); exports.Server = require('./server').Server; -exports.Ledger = require('./ledger').Ledger; exports._test = { Log: require('./log'), @@ -17,7 +16,6 @@ exports._test = { TransactionManager: require('./transactionmanager').TransactionManager, TransactionQueue: require('./transactionqueue').TransactionQueue, RangeSet: require('./rangeset').RangeSet, - HashPrefixes: require('./hashprefixes'), OrderbookUtils: require('./orderbookutils'), constants: require('./constants') }; diff --git a/src/core/ledger.js b/src/core/ledger.js deleted file mode 100644 index 35e5a334..00000000 --- a/src/core/ledger.js +++ /dev/null @@ -1,186 +0,0 @@ -'use strict'; -const sha512half = require('./utils').sha512half; -const BigNumber = require('bignumber.js'); -const hashprefixes = require('./hashprefixes'); -const SHAMap = require('./shamap').SHAMap; -const SHAMapTreeNode = require('./shamap').SHAMapTreeNode; -const {decodeAddress} = require('ripple-address-codec'); -const binary = require('ripple-binary-codec'); - -function Ledger() { - this.ledger_json = {}; -} - -Ledger.from_json = function(v) { - const ledger = new Ledger(); - ledger.parse_json(v); - return ledger; -}; - -Ledger.space = require('./ledgerspaces'); - -function hash(hex) { - return sha512half(new Buffer(hex, 'hex')); -} - -function hashTransaction(txBlobHex) { - const prefix = hashprefixes.HASH_TX_ID.toString(16).toUpperCase(); - return hash(prefix + txBlobHex); -} - -function padLeftZero(string, length) { - return Array(length - string.length + 1).join('0') + string; -} - -function intToHex(integer, byteLength) { - return padLeftZero(Number(integer).toString(16), byteLength * 2); -} - -function bytesToHex(bytes) { - return (new Buffer(bytes)).toString('hex'); -} - -function bigintToHex(integerString, byteLength) { - const hex = (new BigNumber(integerString)).toString(16); - return padLeftZero(hex, byteLength * 2); -} - -function addressToHex(address) { - return (new Buffer(decodeAddress(address))).toString('hex'); -} - -function currencyToHex(currency) { - if (currency.length === 3) { - const bytes = new Array(20 + 1).join('0').split('').map(parseFloat); - bytes[12] = currency.charCodeAt(0) & 0xff; - bytes[13] = currency.charCodeAt(1) & 0xff; - bytes[14] = currency.charCodeAt(2) & 0xff; - return bytesToHex(bytes); - } - return currency; -} - -/** - * Generate the key for an AccountRoot entry. - * - * @param {String|UInt160} accountArg - Ripple Account - * @return {UInt256} - */ -Ledger.calcAccountRootEntryHash = -Ledger.prototype.calcAccountRootEntryHash = function(address) { - const prefix = '00' + intToHex(Ledger.space.account.charCodeAt(0), 1); - return hash(prefix + addressToHex(address)); -}; - -/** - * Generate the key for an Offer entry. - * - * @param {String|UInt160} accountArg - Ripple Account - * @param {Number} sequence - Sequence number of the OfferCreate transaction - * that instantiated this offer. - * @return {UInt256} - */ -Ledger.calcOfferEntryHash = -Ledger.prototype.calcOfferEntryHash = function(address, sequence) { - const prefix = '00' + intToHex(Ledger.space.offer.charCodeAt(0), 1); - return hash(prefix + addressToHex(address) + intToHex(sequence, 4)); -}; - -/** - * Generate the key for a RippleState entry. - * - * The ordering of the two account parameters does not matter. - * - * @param {String|UInt160} _account1 - First Ripple Account - * @param {String|UInt160} _account2 - Second Ripple Account - * @param {String|Currency} _currency - The currency code - * @return {UInt256} - */ -Ledger.calcRippleStateEntryHash = -Ledger.prototype.calcRippleStateEntryHash = function( - address1, address2, currency) { - const address1Hex = addressToHex(address1); - const address2Hex = addressToHex(address2); - - const swap = (new BigNumber(address1Hex, 16)).greaterThan( - new BigNumber(address2Hex, 16)); - const lowAddressHex = swap ? address2Hex : address1Hex; - const highAddressHex = swap ? address1Hex : address2Hex; - - const prefix = '00' + intToHex(Ledger.space.rippleState.charCodeAt(0), 1); - return hash(prefix + lowAddressHex + highAddressHex + - currencyToHex(currency)); -}; - -Ledger.prototype.parse_json = function(v) { - this.ledger_json = v; -}; - -function addLengthPrefix(hex) { - const length = hex.length / 2; - if (length <= 192) { - return bytesToHex([length]) + hex; - } else if (length <= 12480) { - const x = length - 193; - return bytesToHex([193 + (x >>> 8), x & 0xff]) + hex; - } else if (length <= 918744) { - const x = length - 12481; - return bytesToHex([241 + (x >>> 16), x >>> 8 & 0xff, x & 0xff]) + hex; - } - throw new Error('Variable integer overflow.'); -} - -Ledger.prototype.calc_tx_hash = function() { - const tx_map = new SHAMap(); - - this.ledger_json.transactions.forEach(function(tx_json) { - const txBlobHex = binary.encode(tx_json); - const metaHex = binary.encode(tx_json.metaData); - const txHash = hashTransaction(txBlobHex); - const data = addLengthPrefix(txBlobHex) + addLengthPrefix(metaHex); - tx_map.add_item(txHash, data, SHAMapTreeNode.TYPE_TRANSACTION_MD); - }); - - return tx_map.hash(); -}; - -/** -* @param {Object} options - object -* -* @param {Boolean} [options.sanity_test=false] - If `true`, will serialize each -* accountState item to binary and then back to json before finally -* serializing for hashing. This is mostly to expose any issues with -* ripple-lib's binary <--> json codecs. -* -* @return {UInt256} - hash of shamap -*/ -Ledger.prototype.calc_account_hash = function() { - const account_map = new SHAMap(); - - this.ledger_json.accountState.forEach(function(ledgerEntry) { - const data = binary.encode(ledgerEntry); - account_map.add_item(ledgerEntry.index, data, - SHAMapTreeNode.TYPE_ACCOUNT_STATE); - }); - - return account_map.hash(); -}; - -// see rippled Ledger::updateHash() -Ledger.calculateLedgerHash = -Ledger.prototype.calculateLedgerHash = function(ledgerHeader) { - const prefix = '4C575200'; - return hash(prefix + - intToHex(ledgerHeader.ledger_index, 4) + - bigintToHex(ledgerHeader.total_coins, 8) + - ledgerHeader.parent_hash + - ledgerHeader.transaction_hash + - ledgerHeader.account_hash + - intToHex(ledgerHeader.parent_close_time, 4) + - intToHex(ledgerHeader.close_time, 4) + - intToHex(ledgerHeader.close_time_resolution, 1) + - intToHex(ledgerHeader.close_flags, 1) - ); -}; - -exports.Ledger = Ledger; diff --git a/src/core/ledgerspaces.js b/src/core/ledgerspaces.js deleted file mode 100644 index 57fbc22f..00000000 --- a/src/core/ledgerspaces.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Ripple ledger namespace prefixes. - * - * The Ripple ledger is a key-value store. In order to avoid name collisions, - * names are partitioned into namespaces. - * - * Each namespace is just a single character prefix. - */ -module.exports = { - account : 'a', - dirNode : 'd', - generatorMap : 'g', - nickname : 'n', - rippleState : 'r', - offer : 'o', // Entry for an offer. - ownerDir : 'O', // Directory of things owned by an account. - bookDir : 'B', // Directory of order books. - contract : 'c', - skipList : 's', - amendment : 'f', - feeSettings : 'e' -}; \ No newline at end of file diff --git a/src/core/shamap.js b/src/core/shamap.js deleted file mode 100644 index 0db5d9c5..00000000 --- a/src/core/shamap.js +++ /dev/null @@ -1,175 +0,0 @@ -'use strict'; - -const util = require('util'); -const hashprefixes = require('./hashprefixes'); -const sha512half = require('./utils').sha512half; -const HEX_ZERO = '00000000000000000000000000000000' + - '00000000000000000000000000000000'; - -/** - * Abstract class representing a node in a SHAMap tree. - * - * Can be either SHAMapTreeNodeInner or SHAMapTreeNodeLeaf. - * - * @class - */ -function SHAMapTreeNode() { } - -SHAMapTreeNode.TYPE_INNER = 1; -SHAMapTreeNode.TYPE_TRANSACTION_NM = 2; -SHAMapTreeNode.TYPE_TRANSACTION_MD = 3; -SHAMapTreeNode.TYPE_ACCOUNT_STATE = 4; - -function hash(hex) { - return sha512half(new Buffer(hex, 'hex')); -} - -/** -* @param {String} tag (64 hexadecimal characters) -* @param {SHAMapTreeNode} node -* @return {void} -* @virtual -*/ -/* eslint-disable no-unused-vars*/ -SHAMapTreeNode.prototype.add_item = function(tag, node) { - throw new Error( - 'Called unimplemented virtual method SHAMapTreeNode#add_item.'); -}; -/* eslint-enable no-unused-vars*/ - -SHAMapTreeNode.prototype.hash = function() { - throw new Error('Called unimplemented virtual method SHAMapTreeNode#hash.'); -}; - -/** - * Inner (non-leaf) node in a SHAMap tree. - * @param {Number} depth (i.e. how many parent inner nodes) - * @class - */ -function SHAMapTreeNodeInner(depth) { - SHAMapTreeNode.call(this); - this.leaves = {}; - this.type = SHAMapTreeNode.INNER; - this.depth = depth === undefined ? 0 : depth; - this.empty = true; -} - -util.inherits(SHAMapTreeNodeInner, SHAMapTreeNode); - -/** - * @param {String} tag (equates to a ledger entry `index`) - * @param {SHAMapTreeNode} node (to add) - * @return {void} - */ -SHAMapTreeNodeInner.prototype.add_item = function(tag, node) { - const depth = this.depth; - const existing_node = this.get_node(tag[depth]); - - if (existing_node) { - // A node already exists in this slot - if (existing_node instanceof SHAMapTreeNodeInner) { - // There is an inner node, so we need to go deeper - existing_node.add_item(tag, node); - } else if (existing_node.tag === tag) { - // Collision - throw new Error( - 'Tried to add a node to a SHAMap that was already in there.'); - } else { - // Turn it into an inner node - const new_inner_node = new SHAMapTreeNodeInner(depth + 1); - - // Parent new and existing node - new_inner_node.add_item(existing_node.tag, existing_node); - new_inner_node.add_item(tag, node); - - // And place the newly created inner node in the slot - this.set_node(tag[depth], new_inner_node); - } - } else { - // Neat, we have a nice open spot for the new node - this.set_node(tag[depth], node); - } -}; - -/** - * Overwrite the node that is currently in a given slot. - * @param {String} slot (a character 0-F) - * @param {SHAMapTreeNode} node (to place) - * @return {void} - */ -SHAMapTreeNodeInner.prototype.set_node = function(slot, node) { - this.leaves[slot] = node; - this.empty = false; -}; - -SHAMapTreeNodeInner.prototype.get_node = function(slot) { - return this.leaves[slot]; -}; - -SHAMapTreeNodeInner.prototype.hash = function() { - if (this.empty) { - return HEX_ZERO; - } - - let hex = ''; - for (let i = 0; i < 16; i++) { - const slot = i.toString(16).toUpperCase(); - hex += this.leaves[slot] ? this.leaves[slot].hash() : HEX_ZERO; - } - - const prefix = hashprefixes.HASH_INNER_NODE.toString(16); - return hash(prefix + hex); -}; - -/** - * Leaf node in a SHAMap tree. - * @param {String} tag (equates to a ledger entry `index`) - * @param {String} data (hex of account state, transaction etc) - * @param {Number} type (one of TYPE_ACCOUNT_STATE, TYPE_TRANSACTION_MD etc) - * @class - */ -function SHAMapTreeNodeLeaf(tag, data, type) { - SHAMapTreeNode.call(this); - - if (typeof tag !== 'string') { - throw new Error('Tag is unexpected type.'); - } - - this.tag = tag; - this.type = type; - this.data = data; -} - -util.inherits(SHAMapTreeNodeLeaf, SHAMapTreeNode); - -SHAMapTreeNodeLeaf.prototype.hash = function() { - switch (this.type) { - case SHAMapTreeNode.TYPE_ACCOUNT_STATE: - const leafPrefix = hashprefixes.HASH_LEAF_NODE.toString(16); - return hash(leafPrefix + this.data + this.tag); - case SHAMapTreeNode.TYPE_TRANSACTION_NM: - return this.tag; - case SHAMapTreeNode.TYPE_TRANSACTION_MD: - const txPrefix = hashprefixes.HASH_TX_NODE.toString(16); - return hash(txPrefix + this.data + this.tag); - default: - throw new Error('Tried to hash a SHAMap node of unknown type.'); - } -}; - -function SHAMap() { - this.root = new SHAMapTreeNodeInner(0); -} - -SHAMap.prototype.add_item = function(tag, data, type) { - this.root.add_item(tag, new SHAMapTreeNodeLeaf(tag, data, type)); -}; - -SHAMap.prototype.hash = function() { - return this.root.hash(); -}; - -exports.SHAMap = SHAMap; -exports.SHAMapTreeNode = SHAMapTreeNode; -exports.SHAMapTreeNodeInner = SHAMapTreeNodeInner; -exports.SHAMapTreeNodeLeaf = SHAMapTreeNodeLeaf; diff --git a/src/core/transaction.js b/src/core/transaction.js index caedcd0e..e4cfe405 100644 --- a/src/core/transaction.js +++ b/src/core/transaction.js @@ -10,10 +10,11 @@ const sjclcodec = require('sjcl-codec'); const Amount = require('./amount').Amount; const Currency = require('./currency').Currency; const RippleError = require('./rippleerror').RippleError; -const hashprefixes = require('./hashprefixes'); const log = require('./log').internal.sub('transaction'); const {isValidAddress, decodeAddress} = require('ripple-address-codec'); const binary = require('ripple-binary-codec'); +const {computeTransactionHash, computeTransactionSigningHash} + = require('ripple-hashes'); /** * @constructor Transaction @@ -462,8 +463,8 @@ Transaction.prototype.serialize = function() { return binary.encode(this.tx_json); }; -Transaction.prototype.signingHash = function(testnet) { - return this.hash(testnet ? 'HASH_TX_SIGN_TESTNET' : 'HASH_TX_SIGN'); +Transaction.prototype.signingHash = function() { + return computeTransactionSigningHash(this.tx_json); }; Transaction.prototype.signingData = function() { @@ -474,21 +475,8 @@ Transaction.prototype.multiSigningData = function(account) { return binary.encodeForMultisigning(this.tx_json, account); }; -Transaction.prototype.hash = function(prefix_, serialized_) { - let prefix; - assert(serialized_ === undefined || _.isString(serialized_)); - - if (typeof prefix_ !== 'string') { - prefix = hashprefixes.HASH_TX_ID; - } else if (!hashprefixes.hasOwnProperty(prefix_)) { - throw new Error('Unknown hashing prefix requested: ' + prefix_); - } else { - prefix = hashprefixes[prefix_]; - } - - const hexPrefix = prefix.toString(16).toUpperCase(); - const serialized = serialized_ || this.serialize(); - return utils.sha512half(new Buffer(hexPrefix + serialized, 'hex')); +Transaction.prototype.hash = function() { + return computeTransactionHash(this.tx_json); }; Transaction.prototype.sign = function(secret) { diff --git a/test/ledger-test.js b/test/ledger-test.js deleted file mode 100644 index f768737f..00000000 --- a/test/ledger-test.js +++ /dev/null @@ -1,93 +0,0 @@ -/* eslint-disable max-len, valid-jsdoc */ -'use strict'; - -const assert = require('assert'); -const fs = require('fs'); - -const Ledger = require('ripple-lib').Ledger; - -/** -* @param ledger_index {Number} -* Expects a corresponding ledger dump in $repo/test/fixtures/ folder -*/ -function create_ledger_test(ledger_index) { - describe(String(ledger_index), function() { - const path = __dirname + '/fixtures/ledger-full-' + ledger_index + '.json'; - - const ledger_raw = fs.readFileSync(path); - const ledger_json = JSON.parse(ledger_raw); - const ledger = Ledger.from_json(ledger_json); - - const hasAccounts = Array.isArray(ledger_json.accountState) - && ledger_json.accountState.length > 0; - - if (hasAccounts) { - it('has account_hash of ' + ledger_json.account_hash, function() { - assert.equal(ledger_json.account_hash, ledger.calc_account_hash()); - }); - } - it('has transaction_hash of ' + ledger_json.transaction_hash, function() { - assert.equal(ledger_json.transaction_hash, - ledger.calc_tx_hash()); - }); - }); -} -describe('Ledger', function() { - // This is the first recorded ledger with a non empty transaction set - create_ledger_test(38129); - // Because, why not. - create_ledger_test(40000); - // 1311 AffectedNodes, no accounts - create_ledger_test(7501326); - - describe('#calcAccountRootEntryHash', function() { - it('will calculate the AccountRoot entry hash for rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', function() { - const account = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'; - const expectedEntryHash = '2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8'; - const actualEntryHash = Ledger.calcAccountRootEntryHash(account); - - assert.equal(actualEntryHash, expectedEntryHash); - }); - }); - - describe('#calcRippleStateEntryHash', function() { - it('will calculate the RippleState entry hash for rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh and rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY in USD', function() { - const account1 = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'; - const account2 = 'rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY'; - const currency = 'USD'; - - const expectedEntryHash = 'C683B5BB928F025F1E860D9D69D6C554C2202DE0D45877ADB3077DA4CB9E125C'; - const actualEntryHash1 = Ledger.calcRippleStateEntryHash(account1, account2, currency); - const actualEntryHash2 = Ledger.calcRippleStateEntryHash(account2, account1, currency); - - assert.equal(actualEntryHash1, expectedEntryHash); - assert.equal(actualEntryHash2, expectedEntryHash); - }); - - it('will calculate the RippleState entry hash for r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV and rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj in UAM', function() { - const account1 = 'r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV'; - const account2 = 'rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj'; - const currency = 'UAM'; - - const expectedEntryHash = 'AE9ADDC584358E5847ADFC971834E471436FC3E9DE6EA1773DF49F419DC0F65E'; - const actualEntryHash1 = Ledger.calcRippleStateEntryHash(account1, account2, currency); - const actualEntryHash2 = Ledger.calcRippleStateEntryHash(account2, account1, currency); - - assert.equal(actualEntryHash1, expectedEntryHash); - assert.equal(actualEntryHash2, expectedEntryHash); - }); - }); - - describe('#calcOfferEntryHash', function() { - it('will calculate the Offer entry hash for r32UufnaCGL82HubijgJGDmdE5hac7ZvLw, sequence 137', function() { - const account = 'r32UufnaCGL82HubijgJGDmdE5hac7ZvLw'; - const sequence = 137; - const expectedEntryHash = '03F0AED09DEEE74CEF85CD57A0429D6113507CF759C597BABB4ADB752F734CE3'; - const actualEntryHash = Ledger.calcOfferEntryHash(account, sequence); - - assert.equal(actualEntryHash, expectedEntryHash); - }); - }); -}); - -// vim:sw=2:sts=2:ts=8:et diff --git a/test/transaction-test.js b/test/transaction-test.js index 2774abcd..fe83fd3c 100644 --- a/test/transaction-test.js +++ b/test/transaction-test.js @@ -637,25 +637,8 @@ describe('Transaction', function() { transaction.tx_json.Sequence = 1; transaction.tx_json.TransactionType = 'AccountSet'; - assert.strictEqual(transaction.hash('HASH_TX_SIGN'), 'D1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE'); - assert.strictEqual(transaction.hash('HASH_TX_SIGN_TESTNET'), '9FE7D27FC5B9891076B66591F99A683E01E0912986A629235459A3BD1961F341'); - - done(); - }); - - it('Get hash - invalid prefix', function(done) { - const transaction = new Transaction(); - transaction._secret = 'sh2pTicynUEG46jjR4EoexHcQEoij'; - transaction.tx_json.SigningPubKey = '021FED5FD081CE5C4356431267D04C6E2167E4112C897D5E10335D4E22B4DA49ED'; - transaction.tx_json.Account = 'rMWwx3Ma16HnqSd4H6saPisihX9aKpXxHJ'; - transaction.tx_json.Flags = 0; - transaction.tx_json.Fee = '10'; - transaction.tx_json.Sequence = 1; - transaction.tx_json.TransactionType = 'AccountSet'; - - assert.throws(function() { - transaction.hash('HASH_TX_SIGNZ'); - }); + assert.strictEqual(transaction.signingHash(), + 'D1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE'); done(); }); @@ -2258,10 +2241,11 @@ describe('Transaction', function() { const txHex = binary.encode( lodash.merge(transaction.tx_json, {SigningPubKey: ''})); const abytes = decodeAddress(a1); - const prefix = require('ripple-lib')._test.HashPrefixes.HASH_TX_MULTISIGN_BYTES; + const prefix = 0x534D5400; + const prefixHex = prefix.toString(16); assert.deepEqual(new Buffer(d1, 'hex'), - Buffer.concat([new Buffer(prefix), new Buffer(txHex, 'hex'), + Buffer.concat([new Buffer(prefixHex, 'hex'), new Buffer(txHex, 'hex'), new Buffer(abytes)])); });