mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-20 12:15:51 +00:00
181 lines
5.3 KiB
JavaScript
181 lines
5.3 KiB
JavaScript
'use strict';
|
|
const BigNumber = require('bignumber.js');
|
|
const Transaction = require('./transaction').Transaction;
|
|
const SHAMap = require('./shamap').SHAMap;
|
|
const SHAMapTreeNode = require('./shamap').SHAMapTreeNode;
|
|
const SerializedObject = require('./serializedobject').SerializedObject;
|
|
const stypes = require('./serializedtypes');
|
|
const UInt160 = require('./uint160').UInt160;
|
|
const Currency = require('./currency').Currency;
|
|
|
|
function Ledger() {
|
|
this.ledger_json = {};
|
|
}
|
|
|
|
Ledger.from_json = function(v) {
|
|
const ledger = new Ledger();
|
|
ledger.parse_json(v);
|
|
return ledger;
|
|
};
|
|
|
|
Ledger.space = require('./ledgerspaces');
|
|
|
|
/**
|
|
* Generate the key for an AccountRoot entry.
|
|
*
|
|
* @param {String|UInt160} accountArg - Ripple Account
|
|
* @return {UInt256}
|
|
*/
|
|
Ledger.calcAccountRootEntryHash =
|
|
Ledger.prototype.calcAccountRootEntryHash = function(accountArg) {
|
|
const account = UInt160.from_json(accountArg);
|
|
const index = new SerializedObject();
|
|
|
|
index.append([0, Ledger.space.account.charCodeAt(0)]);
|
|
index.append(account.to_bytes());
|
|
|
|
return index.hash();
|
|
};
|
|
|
|
/**
|
|
* 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(accountArg, sequence) {
|
|
const account = UInt160.from_json(accountArg);
|
|
const index = new SerializedObject();
|
|
|
|
index.append([0, Ledger.space.offer.charCodeAt(0)]);
|
|
index.append(account.to_bytes());
|
|
stypes.Int32.serialize(index, sequence);
|
|
|
|
return index.hash();
|
|
};
|
|
|
|
/**
|
|
* 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(
|
|
_account1, _account2, _currency) {
|
|
const currency = Currency.from_json(_currency);
|
|
const account1 = UInt160.from_json(_account1);
|
|
const account2 = UInt160.from_json(_account2);
|
|
|
|
if (!account1.is_valid()) {
|
|
throw new Error('Invalid first account');
|
|
}
|
|
if (!account2.is_valid()) {
|
|
throw new Error('Invalid second account');
|
|
}
|
|
if (!currency.is_valid()) {
|
|
throw new Error('Invalid currency');
|
|
}
|
|
|
|
const swap = account1.greater_than(account2);
|
|
const lowAccount = swap ? account2 : account1;
|
|
const highAccount = swap ? account1 : account2;
|
|
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) {
|
|
this.ledger_json = v;
|
|
};
|
|
|
|
Ledger.prototype.calc_tx_hash = function() {
|
|
const tx_map = new SHAMap();
|
|
|
|
this.ledger_json.transactions.forEach(function(tx_json) {
|
|
const tx = Transaction.from_json(tx_json);
|
|
const meta = SerializedObject.from_json(tx_json.metaData);
|
|
|
|
const data = new SerializedObject();
|
|
stypes.VariableLength.serialize(data, tx.serialize());
|
|
stypes.VariableLength.serialize(data, meta.to_hex());
|
|
tx_map.add_item(tx.hash(), 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(options) {
|
|
const account_map = new SHAMap();
|
|
let erred;
|
|
|
|
this.ledger_json.accountState.forEach(function(le) {
|
|
let data = SerializedObject.from_json(le);
|
|
|
|
let json;
|
|
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();
|
|
};
|
|
|
|
// see rippled Ledger::updateHash()
|
|
Ledger.calculateLedgerHash =
|
|
Ledger.prototype.calculateLedgerHash = function(ledgerHeader) {
|
|
const so = new SerializedObject();
|
|
const prefix = 0x4C575200;
|
|
const totalCoins = (new BigNumber(ledgerHeader.total_coins)).toString(16);
|
|
|
|
stypes.Int32.serialize(so, Number(ledgerHeader.ledger_index));
|
|
stypes.Int64.serialize(so, totalCoins);
|
|
stypes.Hash256.serialize(so, ledgerHeader.parent_hash);
|
|
stypes.Hash256.serialize(so, ledgerHeader.transaction_hash);
|
|
stypes.Hash256.serialize(so, ledgerHeader.account_hash);
|
|
stypes.Int32.serialize(so, ledgerHeader.parent_close_time);
|
|
stypes.Int32.serialize(so, ledgerHeader.close_time);
|
|
stypes.Int8.serialize(so, ledgerHeader.close_time_resolution);
|
|
stypes.Int8.serialize(so, ledgerHeader.close_flags);
|
|
|
|
return so.hash(prefix).to_hex();
|
|
};
|
|
|
|
exports.Ledger = Ledger;
|