mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-21 20:55:48 +00:00
Merge pull request #591 from clark800/ledger-hashes
Decouple ledger.js and serialization code
This commit is contained in:
@@ -40,7 +40,7 @@ function computeTransactionHash(ledger) {
|
|||||||
return renameMeta;
|
return renameMeta;
|
||||||
});
|
});
|
||||||
const ledgerObject = common.core.Ledger.from_json({transactions: txs});
|
const ledgerObject = common.core.Ledger.from_json({transactions: txs});
|
||||||
const transactionHash = ledgerObject.calc_tx_hash().to_hex();
|
const transactionHash = ledgerObject.calc_tx_hash();
|
||||||
if (ledger.transactionHash !== undefined
|
if (ledger.transactionHash !== undefined
|
||||||
&& ledger.transactionHash !== transactionHash) {
|
&& ledger.transactionHash !== transactionHash) {
|
||||||
throw new common.errors.ValidationError('transactionHash in header'
|
throw new common.errors.ValidationError('transactionHash in header'
|
||||||
@@ -55,7 +55,7 @@ function computeStateHash(ledger) {
|
|||||||
}
|
}
|
||||||
const state = JSON.parse(ledger.rawState);
|
const state = JSON.parse(ledger.rawState);
|
||||||
const ledgerObject = common.core.Ledger.from_json({accountState: state});
|
const ledgerObject = common.core.Ledger.from_json({accountState: state});
|
||||||
const stateHash = ledgerObject.calc_account_hash().to_hex();
|
const stateHash = ledgerObject.calc_account_hash();
|
||||||
if (ledger.stateHash !== undefined && ledger.stateHash !== stateHash) {
|
if (ledger.stateHash !== undefined && ledger.stateHash !== stateHash) {
|
||||||
throw new common.errors.ValidationError('stateHash in header'
|
throw new common.errors.ValidationError('stateHash in header'
|
||||||
+ ' does not match computed hash of state');
|
+ ' does not match computed hash of state');
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
const sha512half = require('./utils').sha512half;
|
||||||
const BigNumber = require('bignumber.js');
|
const BigNumber = require('bignumber.js');
|
||||||
const Transaction = require('./transaction').Transaction;
|
const hashprefixes = require('./hashprefixes');
|
||||||
const SHAMap = require('./shamap').SHAMap;
|
const SHAMap = require('./shamap').SHAMap;
|
||||||
const SHAMapTreeNode = require('./shamap').SHAMapTreeNode;
|
const SHAMapTreeNode = require('./shamap').SHAMapTreeNode;
|
||||||
const SerializedObject = require('./serializedobject').SerializedObject;
|
const {decodeAddress} = require('ripple-address-codec');
|
||||||
const stypes = require('./serializedtypes');
|
const binary = require('ripple-binary-codec');
|
||||||
const UInt160 = require('./uint160').UInt160;
|
|
||||||
const Currency = require('./currency').Currency;
|
|
||||||
|
|
||||||
function Ledger() {
|
function Ledger() {
|
||||||
this.ledger_json = {};
|
this.ledger_json = {};
|
||||||
@@ -20,6 +19,47 @@ Ledger.from_json = function(v) {
|
|||||||
|
|
||||||
Ledger.space = require('./ledgerspaces');
|
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.
|
* Generate the key for an AccountRoot entry.
|
||||||
*
|
*
|
||||||
@@ -27,14 +67,9 @@ Ledger.space = require('./ledgerspaces');
|
|||||||
* @return {UInt256}
|
* @return {UInt256}
|
||||||
*/
|
*/
|
||||||
Ledger.calcAccountRootEntryHash =
|
Ledger.calcAccountRootEntryHash =
|
||||||
Ledger.prototype.calcAccountRootEntryHash = function(accountArg) {
|
Ledger.prototype.calcAccountRootEntryHash = function(address) {
|
||||||
const account = UInt160.from_json(accountArg);
|
const prefix = '00' + intToHex(Ledger.space.account.charCodeAt(0), 1);
|
||||||
const index = new SerializedObject();
|
return hash(prefix + addressToHex(address));
|
||||||
|
|
||||||
index.append([0, Ledger.space.account.charCodeAt(0)]);
|
|
||||||
index.append(account.to_bytes());
|
|
||||||
|
|
||||||
return index.hash();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,15 +81,9 @@ Ledger.prototype.calcAccountRootEntryHash = function(accountArg) {
|
|||||||
* @return {UInt256}
|
* @return {UInt256}
|
||||||
*/
|
*/
|
||||||
Ledger.calcOfferEntryHash =
|
Ledger.calcOfferEntryHash =
|
||||||
Ledger.prototype.calcOfferEntryHash = function(accountArg, sequence) {
|
Ledger.prototype.calcOfferEntryHash = function(address, sequence) {
|
||||||
const account = UInt160.from_json(accountArg);
|
const prefix = '00' + intToHex(Ledger.space.offer.charCodeAt(0), 1);
|
||||||
const index = new SerializedObject();
|
return hash(prefix + addressToHex(address) + intToHex(sequence, 4));
|
||||||
|
|
||||||
index.append([0, Ledger.space.offer.charCodeAt(0)]);
|
|
||||||
index.append(account.to_bytes());
|
|
||||||
stypes.Int32.serialize(index, sequence);
|
|
||||||
|
|
||||||
return index.hash();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,49 +98,47 @@ Ledger.prototype.calcOfferEntryHash = function(accountArg, sequence) {
|
|||||||
*/
|
*/
|
||||||
Ledger.calcRippleStateEntryHash =
|
Ledger.calcRippleStateEntryHash =
|
||||||
Ledger.prototype.calcRippleStateEntryHash = function(
|
Ledger.prototype.calcRippleStateEntryHash = function(
|
||||||
_account1, _account2, _currency) {
|
address1, address2, currency) {
|
||||||
const currency = Currency.from_json(_currency);
|
const address1Hex = addressToHex(address1);
|
||||||
const account1 = UInt160.from_json(_account1);
|
const address2Hex = addressToHex(address2);
|
||||||
const account2 = UInt160.from_json(_account2);
|
|
||||||
|
|
||||||
if (!account1.is_valid()) {
|
const swap = (new BigNumber(address1Hex, 16)).greaterThan(
|
||||||
throw new Error('Invalid first account');
|
new BigNumber(address2Hex, 16));
|
||||||
}
|
const lowAddressHex = swap ? address2Hex : address1Hex;
|
||||||
if (!account2.is_valid()) {
|
const highAddressHex = swap ? address1Hex : address2Hex;
|
||||||
throw new Error('Invalid second account');
|
|
||||||
}
|
|
||||||
if (!currency.is_valid()) {
|
|
||||||
throw new Error('Invalid currency');
|
|
||||||
}
|
|
||||||
|
|
||||||
const swap = account1.greater_than(account2);
|
const prefix = '00' + intToHex(Ledger.space.rippleState.charCodeAt(0), 1);
|
||||||
const lowAccount = swap ? account2 : account1;
|
return hash(prefix + lowAddressHex + highAddressHex +
|
||||||
const highAccount = swap ? account1 : account2;
|
currencyToHex(currency));
|
||||||
const index = new SerializedObject();
|
|
||||||
|
|
||||||
index.append([0, Ledger.space.rippleState.charCodeAt(0)]);
|
|
||||||
index.append(lowAccount.to_bytes());
|
|
||||||
index.append(highAccount.to_bytes());
|
|
||||||
index.append(currency.to_bytes());
|
|
||||||
|
|
||||||
return index.hash();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ledger.prototype.parse_json = function(v) {
|
Ledger.prototype.parse_json = function(v) {
|
||||||
this.ledger_json = 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() {
|
Ledger.prototype.calc_tx_hash = function() {
|
||||||
const tx_map = new SHAMap();
|
const tx_map = new SHAMap();
|
||||||
|
|
||||||
this.ledger_json.transactions.forEach(function(tx_json) {
|
this.ledger_json.transactions.forEach(function(tx_json) {
|
||||||
const tx = Transaction.from_json(tx_json);
|
const txBlobHex = binary.encode(tx_json);
|
||||||
const meta = SerializedObject.from_json(tx_json.metaData);
|
const metaHex = binary.encode(tx_json.metaData);
|
||||||
|
const txHash = hashTransaction(txBlobHex);
|
||||||
const data = new SerializedObject();
|
const data = addLengthPrefix(txBlobHex) + addLengthPrefix(metaHex);
|
||||||
stypes.VariableLength.serialize(data, tx.serialize());
|
tx_map.add_item(txHash, data, SHAMapTreeNode.TYPE_TRANSACTION_MD);
|
||||||
stypes.VariableLength.serialize(data, meta.to_hex());
|
|
||||||
tx_map.add_item(tx.hash(), data, SHAMapTreeNode.TYPE_TRANSACTION_MD);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return tx_map.hash();
|
return tx_map.hash();
|
||||||
@@ -127,54 +154,33 @@ Ledger.prototype.calc_tx_hash = function() {
|
|||||||
*
|
*
|
||||||
* @return {UInt256} - hash of shamap
|
* @return {UInt256} - hash of shamap
|
||||||
*/
|
*/
|
||||||
Ledger.prototype.calc_account_hash = function(options) {
|
Ledger.prototype.calc_account_hash = function() {
|
||||||
const account_map = new SHAMap();
|
const account_map = new SHAMap();
|
||||||
let erred;
|
|
||||||
|
|
||||||
this.ledger_json.accountState.forEach(function(le) {
|
this.ledger_json.accountState.forEach(function(ledgerEntry) {
|
||||||
let data = SerializedObject.from_json(le);
|
const data = binary.encode(ledgerEntry);
|
||||||
|
account_map.add_item(ledgerEntry.index, data,
|
||||||
let json;
|
SHAMapTreeNode.TYPE_ACCOUNT_STATE);
|
||||||
if (options && options.sanity_test) {
|
|
||||||
try {
|
|
||||||
json = data.to_json();
|
|
||||||
data = SerializedObject.from_json(json);
|
|
||||||
} catch (e) {
|
|
||||||
console.log('account state item: ', le);
|
|
||||||
console.log('to_json() ', json);
|
|
||||||
console.log('exception: ', e);
|
|
||||||
erred = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
account_map.add_item(le.index, data, SHAMapTreeNode.TYPE_ACCOUNT_STATE);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (erred) {
|
|
||||||
throw new Error('There were errors with sanity_test'); // all logged above
|
|
||||||
}
|
|
||||||
|
|
||||||
return account_map.hash();
|
return account_map.hash();
|
||||||
};
|
};
|
||||||
|
|
||||||
// see rippled Ledger::updateHash()
|
// see rippled Ledger::updateHash()
|
||||||
Ledger.calculateLedgerHash =
|
Ledger.calculateLedgerHash =
|
||||||
Ledger.prototype.calculateLedgerHash = function(ledgerHeader) {
|
Ledger.prototype.calculateLedgerHash = function(ledgerHeader) {
|
||||||
const so = new SerializedObject();
|
const prefix = '4C575200';
|
||||||
const prefix = 0x4C575200;
|
return hash(prefix +
|
||||||
const totalCoins = (new BigNumber(ledgerHeader.total_coins)).toString(16);
|
intToHex(ledgerHeader.ledger_index, 4) +
|
||||||
|
bigintToHex(ledgerHeader.total_coins, 8) +
|
||||||
stypes.Int32.serialize(so, Number(ledgerHeader.ledger_index));
|
ledgerHeader.parent_hash +
|
||||||
stypes.Int64.serialize(so, totalCoins);
|
ledgerHeader.transaction_hash +
|
||||||
stypes.Hash256.serialize(so, ledgerHeader.parent_hash);
|
ledgerHeader.account_hash +
|
||||||
stypes.Hash256.serialize(so, ledgerHeader.transaction_hash);
|
intToHex(ledgerHeader.parent_close_time, 4) +
|
||||||
stypes.Hash256.serialize(so, ledgerHeader.account_hash);
|
intToHex(ledgerHeader.close_time, 4) +
|
||||||
stypes.Int32.serialize(so, ledgerHeader.parent_close_time);
|
intToHex(ledgerHeader.close_time_resolution, 1) +
|
||||||
stypes.Int32.serialize(so, ledgerHeader.close_time);
|
intToHex(ledgerHeader.close_flags, 1)
|
||||||
stypes.Int8.serialize(so, ledgerHeader.close_time_resolution);
|
);
|
||||||
stypes.Int8.serialize(so, ledgerHeader.close_flags);
|
|
||||||
|
|
||||||
return so.hash(prefix).to_hex();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.Ledger = Ledger;
|
exports.Ledger = Ledger;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var util = require('util');
|
const util = require('util');
|
||||||
var hashprefixes = require('./hashprefixes');
|
const hashprefixes = require('./hashprefixes');
|
||||||
|
const sha512half = require('./utils').sha512half;
|
||||||
var UInt256 = require('./uint256').UInt256;
|
const HEX_ZERO = '00000000000000000000000000000000' +
|
||||||
var SerializedObject = require('./serializedobject').SerializedObject;
|
'00000000000000000000000000000000';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class representing a node in a SHAMap tree.
|
* Abstract class representing a node in a SHAMap tree.
|
||||||
@@ -20,18 +20,22 @@ SHAMapTreeNode.TYPE_TRANSACTION_NM = 2;
|
|||||||
SHAMapTreeNode.TYPE_TRANSACTION_MD = 3;
|
SHAMapTreeNode.TYPE_TRANSACTION_MD = 3;
|
||||||
SHAMapTreeNode.TYPE_ACCOUNT_STATE = 4;
|
SHAMapTreeNode.TYPE_ACCOUNT_STATE = 4;
|
||||||
|
|
||||||
|
function hash(hex) {
|
||||||
|
return sha512half(new Buffer(hex, 'hex'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {String} tag (64 hexadecimal characters)
|
* @param {String} tag (64 hexadecimal characters)
|
||||||
* @param {SHAMapTreeNode} node
|
* @param {SHAMapTreeNode} node
|
||||||
* @return {void}
|
* @return {void}
|
||||||
* @virtual
|
* @virtual
|
||||||
*/
|
*/
|
||||||
/*eslint-disable no-unused-vars*/
|
/* eslint-disable no-unused-vars*/
|
||||||
SHAMapTreeNode.prototype.add_item = function(tag, node) {
|
SHAMapTreeNode.prototype.add_item = function(tag, node) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Called unimplemented virtual method SHAMapTreeNode#add_item.');
|
'Called unimplemented virtual method SHAMapTreeNode#add_item.');
|
||||||
};
|
};
|
||||||
/*eslint-enable no-unused-vars*/
|
/* eslint-enable no-unused-vars*/
|
||||||
|
|
||||||
SHAMapTreeNode.prototype.hash = function() {
|
SHAMapTreeNode.prototype.hash = function() {
|
||||||
throw new Error('Called unimplemented virtual method SHAMapTreeNode#hash.');
|
throw new Error('Called unimplemented virtual method SHAMapTreeNode#hash.');
|
||||||
@@ -44,12 +48,9 @@ SHAMapTreeNode.prototype.hash = function() {
|
|||||||
*/
|
*/
|
||||||
function SHAMapTreeNodeInner(depth) {
|
function SHAMapTreeNodeInner(depth) {
|
||||||
SHAMapTreeNode.call(this);
|
SHAMapTreeNode.call(this);
|
||||||
|
|
||||||
this.leaves = {};
|
this.leaves = {};
|
||||||
|
|
||||||
this.type = SHAMapTreeNode.INNER;
|
this.type = SHAMapTreeNode.INNER;
|
||||||
this.depth = depth === undefined ? 0 : depth;
|
this.depth = depth === undefined ? 0 : depth;
|
||||||
|
|
||||||
this.empty = true;
|
this.empty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,8 +62,8 @@ util.inherits(SHAMapTreeNodeInner, SHAMapTreeNode);
|
|||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
SHAMapTreeNodeInner.prototype.add_item = function(tag, node) {
|
SHAMapTreeNodeInner.prototype.add_item = function(tag, node) {
|
||||||
var depth = this.depth;
|
const depth = this.depth;
|
||||||
var existing_node = this.get_node(tag[depth]);
|
const existing_node = this.get_node(tag[depth]);
|
||||||
|
|
||||||
if (existing_node) {
|
if (existing_node) {
|
||||||
// A node already exists in this slot
|
// A node already exists in this slot
|
||||||
@@ -75,7 +76,7 @@ SHAMapTreeNodeInner.prototype.add_item = function(tag, node) {
|
|||||||
'Tried to add a node to a SHAMap that was already in there.');
|
'Tried to add a node to a SHAMap that was already in there.');
|
||||||
} else {
|
} else {
|
||||||
// Turn it into an inner node
|
// Turn it into an inner node
|
||||||
var new_inner_node = new SHAMapTreeNodeInner(depth + 1);
|
const new_inner_node = new SHAMapTreeNodeInner(depth + 1);
|
||||||
|
|
||||||
// Parent new and existing node
|
// Parent new and existing node
|
||||||
new_inner_node.add_item(existing_node.tag, existing_node);
|
new_inner_node.add_item(existing_node.tag, existing_node);
|
||||||
@@ -107,35 +108,27 @@ SHAMapTreeNodeInner.prototype.get_node = function(slot) {
|
|||||||
|
|
||||||
SHAMapTreeNodeInner.prototype.hash = function() {
|
SHAMapTreeNodeInner.prototype.hash = function() {
|
||||||
if (this.empty) {
|
if (this.empty) {
|
||||||
return UInt256.from_hex(UInt256.HEX_ZERO);
|
return HEX_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
var hash_buffer = new SerializedObject();
|
let hex = '';
|
||||||
|
for (let i = 0; i < 16; i++) {
|
||||||
for (var i = 0; i < 16; i++) {
|
const slot = i.toString(16).toUpperCase();
|
||||||
var leafHash = UInt256.from_hex(UInt256.HEX_ZERO);
|
hex += this.leaves[slot] ? this.leaves[slot].hash() : HEX_ZERO;
|
||||||
var slot = i.toString(16).toUpperCase();
|
|
||||||
|
|
||||||
if (typeof this.leaves[slot] === 'object') {
|
|
||||||
leafHash = this.leaves[slot].hash();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_buffer.append(leafHash.to_bytes());
|
const prefix = hashprefixes.HASH_INNER_NODE.toString(16);
|
||||||
}
|
return hash(prefix + hex);
|
||||||
|
|
||||||
var hash = hash_buffer.hash(hashprefixes.HASH_INNER_NODE);
|
|
||||||
|
|
||||||
return UInt256.from_bits(hash);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Leaf node in a SHAMap tree.
|
* Leaf node in a SHAMap tree.
|
||||||
* @param {String} tag (equates to a ledger entry `index`)
|
* @param {String} tag (equates to a ledger entry `index`)
|
||||||
* @param {SerializedObject} node (bytes of account state, transaction etc)
|
* @param {String} data (hex of account state, transaction etc)
|
||||||
* @param {Number} type (one of TYPE_ACCOUNT_STATE, TYPE_TRANSACTION_MD etc)
|
* @param {Number} type (one of TYPE_ACCOUNT_STATE, TYPE_TRANSACTION_MD etc)
|
||||||
* @class
|
* @class
|
||||||
*/
|
*/
|
||||||
function SHAMapTreeNodeLeaf(tag, node, type) {
|
function SHAMapTreeNodeLeaf(tag, data, type) {
|
||||||
SHAMapTreeNode.call(this);
|
SHAMapTreeNode.call(this);
|
||||||
|
|
||||||
if (typeof tag !== 'string') {
|
if (typeof tag !== 'string') {
|
||||||
@@ -143,26 +136,22 @@ function SHAMapTreeNodeLeaf(tag, node, type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
this.tag_bytes = UInt256.from_hex(this.tag).to_bytes();
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.node = node;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
util.inherits(SHAMapTreeNodeLeaf, SHAMapTreeNode);
|
util.inherits(SHAMapTreeNodeLeaf, SHAMapTreeNode);
|
||||||
|
|
||||||
SHAMapTreeNodeLeaf.prototype.hash = function() {
|
SHAMapTreeNodeLeaf.prototype.hash = function() {
|
||||||
var buffer = new SerializedObject();
|
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case SHAMapTreeNode.TYPE_ACCOUNT_STATE:
|
case SHAMapTreeNode.TYPE_ACCOUNT_STATE:
|
||||||
buffer.append(this.node);
|
const leafPrefix = hashprefixes.HASH_LEAF_NODE.toString(16);
|
||||||
buffer.append(this.tag_bytes);
|
return hash(leafPrefix + this.data + this.tag);
|
||||||
return buffer.hash(hashprefixes.HASH_LEAF_NODE);
|
|
||||||
case SHAMapTreeNode.TYPE_TRANSACTION_NM:
|
case SHAMapTreeNode.TYPE_TRANSACTION_NM:
|
||||||
return this.tag_bytes;
|
return this.tag;
|
||||||
case SHAMapTreeNode.TYPE_TRANSACTION_MD:
|
case SHAMapTreeNode.TYPE_TRANSACTION_MD:
|
||||||
buffer.append(this.node);
|
const txPrefix = hashprefixes.HASH_TX_NODE.toString(16);
|
||||||
buffer.append(this.tag_bytes);
|
return hash(txPrefix + this.data + this.tag);
|
||||||
return buffer.hash(hashprefixes.HASH_TX_NODE);
|
|
||||||
default:
|
default:
|
||||||
throw new Error('Tried to hash a SHAMap node of unknown type.');
|
throw new Error('Tried to hash a SHAMap node of unknown type.');
|
||||||
}
|
}
|
||||||
@@ -172,9 +161,8 @@ function SHAMap() {
|
|||||||
this.root = new SHAMapTreeNodeInner(0);
|
this.root = new SHAMapTreeNodeInner(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAMap.prototype.add_item = function(tag, node, type) {
|
SHAMap.prototype.add_item = function(tag, data, type) {
|
||||||
node = new SHAMapTreeNodeLeaf(tag, node, type);
|
this.root.add_item(tag, new SHAMapTreeNodeLeaf(tag, data, type));
|
||||||
this.root.add_item(tag, node);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SHAMap.prototype.hash = function() {
|
SHAMap.prototype.hash = function() {
|
||||||
|
|||||||
@@ -23,13 +23,12 @@ function create_ledger_test(ledger_index) {
|
|||||||
|
|
||||||
if (hasAccounts) {
|
if (hasAccounts) {
|
||||||
it('has account_hash of ' + ledger_json.account_hash, function() {
|
it('has account_hash of ' + ledger_json.account_hash, function() {
|
||||||
assert.equal(ledger_json.account_hash,
|
assert.equal(ledger_json.account_hash, ledger.calc_account_hash());
|
||||||
ledger.calc_account_hash({sanity_test: true}).to_hex());
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
it('has transaction_hash of ' + ledger_json.transaction_hash, function() {
|
it('has transaction_hash of ' + ledger_json.transaction_hash, function() {
|
||||||
assert.equal(ledger_json.transaction_hash,
|
assert.equal(ledger_json.transaction_hash,
|
||||||
ledger.calc_tx_hash().to_hex());
|
ledger.calc_tx_hash());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -47,7 +46,7 @@ describe('Ledger', function() {
|
|||||||
const expectedEntryHash = '2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8';
|
const expectedEntryHash = '2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8';
|
||||||
const actualEntryHash = Ledger.calcAccountRootEntryHash(account);
|
const actualEntryHash = Ledger.calcAccountRootEntryHash(account);
|
||||||
|
|
||||||
assert.equal(actualEntryHash.to_hex(), expectedEntryHash);
|
assert.equal(actualEntryHash, expectedEntryHash);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -61,8 +60,8 @@ describe('Ledger', function() {
|
|||||||
const actualEntryHash1 = Ledger.calcRippleStateEntryHash(account1, account2, currency);
|
const actualEntryHash1 = Ledger.calcRippleStateEntryHash(account1, account2, currency);
|
||||||
const actualEntryHash2 = Ledger.calcRippleStateEntryHash(account2, account1, currency);
|
const actualEntryHash2 = Ledger.calcRippleStateEntryHash(account2, account1, currency);
|
||||||
|
|
||||||
assert.equal(actualEntryHash1.to_hex(), expectedEntryHash);
|
assert.equal(actualEntryHash1, expectedEntryHash);
|
||||||
assert.equal(actualEntryHash2.to_hex(), expectedEntryHash);
|
assert.equal(actualEntryHash2, expectedEntryHash);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('will calculate the RippleState entry hash for r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV and rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj in UAM', function() {
|
it('will calculate the RippleState entry hash for r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV and rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj in UAM', function() {
|
||||||
@@ -74,8 +73,8 @@ describe('Ledger', function() {
|
|||||||
const actualEntryHash1 = Ledger.calcRippleStateEntryHash(account1, account2, currency);
|
const actualEntryHash1 = Ledger.calcRippleStateEntryHash(account1, account2, currency);
|
||||||
const actualEntryHash2 = Ledger.calcRippleStateEntryHash(account2, account1, currency);
|
const actualEntryHash2 = Ledger.calcRippleStateEntryHash(account2, account1, currency);
|
||||||
|
|
||||||
assert.equal(actualEntryHash1.to_hex(), expectedEntryHash);
|
assert.equal(actualEntryHash1, expectedEntryHash);
|
||||||
assert.equal(actualEntryHash2.to_hex(), expectedEntryHash);
|
assert.equal(actualEntryHash2, expectedEntryHash);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -86,7 +85,7 @@ describe('Ledger', function() {
|
|||||||
const expectedEntryHash = '03F0AED09DEEE74CEF85CD57A0429D6113507CF759C597BABB4ADB752F734CE3';
|
const expectedEntryHash = '03F0AED09DEEE74CEF85CD57A0429D6113507CF759C597BABB4ADB752F734CE3';
|
||||||
const actualEntryHash = Ledger.calcOfferEntryHash(account, sequence);
|
const actualEntryHash = Ledger.calcOfferEntryHash(account, sequence);
|
||||||
|
|
||||||
assert.equal(actualEntryHash.to_hex(), expectedEntryHash);
|
assert.equal(actualEntryHash, expectedEntryHash);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user