mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-20 20:25:48 +00:00
[FEATURE] Add ability to calculate ledger entry keys.
This commit is contained in:
@@ -5,6 +5,11 @@ var SHAMap = require('./shamap').SHAMap;
|
|||||||
var SHAMapTreeNode = require('./shamap').SHAMapTreeNode;
|
var SHAMapTreeNode = require('./shamap').SHAMapTreeNode;
|
||||||
var SerializedObject = require('./serializedobject').SerializedObject;
|
var SerializedObject = require('./serializedobject').SerializedObject;
|
||||||
var stypes = require('./serializedtypes');
|
var stypes = require('./serializedtypes');
|
||||||
|
var UInt160 = require('./uint160').UInt160;
|
||||||
|
var Currency = require('./currency').Currency;
|
||||||
|
var stypes = require('./serializedtypes');
|
||||||
|
var sjcl = require('./utils').sjcl;
|
||||||
|
var Crypt = require('./crypt').Crypt;
|
||||||
|
|
||||||
function Ledger()
|
function Ledger()
|
||||||
{
|
{
|
||||||
@@ -17,6 +22,91 @@ Ledger.from_json = function (v) {
|
|||||||
return ledger;
|
return ledger;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Ledger.space = require('./ledgerspaces');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the key for an AccountRoot entry.
|
||||||
|
*
|
||||||
|
* @param {String|UInt160} account Ripple Account
|
||||||
|
* @return {UInt256}
|
||||||
|
*/
|
||||||
|
Ledger.calcAccountRootEntryHash =
|
||||||
|
Ledger.prototype.calcAccountRootEntryHash = function (account) {
|
||||||
|
account = UInt160.from_json(account);
|
||||||
|
|
||||||
|
var 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} account Ripple Account
|
||||||
|
* @param {Number} sequence Sequence number of the OfferCreate transaction
|
||||||
|
* that instantiated this offer.
|
||||||
|
* @return {UInt256}
|
||||||
|
*/
|
||||||
|
Ledger.calcOfferEntryHash =
|
||||||
|
Ledger.prototype.calcOfferEntryHash = function (account, sequence) {
|
||||||
|
account = UInt160.from_json(account);
|
||||||
|
sequence = parseInt(sequence);
|
||||||
|
|
||||||
|
var 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) {
|
||||||
|
currency = Currency.from_json(currency);
|
||||||
|
account1 = UInt160.from_json(account1);
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The lower ID has to come first
|
||||||
|
if (account1.to_bn().greaterEquals(account2.to_bn())) {
|
||||||
|
var tmp = account2;
|
||||||
|
account2 = account1;
|
||||||
|
account1 = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
var index = new SerializedObject();
|
||||||
|
|
||||||
|
index.append([0, Ledger.space.rippleState.charCodeAt(0)]);
|
||||||
|
index.append(account1.to_bytes());
|
||||||
|
index.append(account2.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;
|
||||||
};
|
};
|
||||||
|
|||||||
22
src/js/ripple/ledgerspaces.js
Normal file
22
src/js/ripple/ledgerspaces.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* 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'
|
||||||
|
};
|
||||||
@@ -3,6 +3,7 @@ var extend = require('extend');
|
|||||||
var binformat = require('./binformat');
|
var binformat = require('./binformat');
|
||||||
var stypes = require('./serializedtypes');
|
var stypes = require('./serializedtypes');
|
||||||
var UInt256 = require('./uint256').UInt256;
|
var UInt256 = require('./uint256').UInt256;
|
||||||
|
var Crypt = require('./crypt').Crypt;
|
||||||
var utils = require('./utils');
|
var utils = require('./utils');
|
||||||
|
|
||||||
var sjcl = utils.sjcl;
|
var sjcl = utils.sjcl;
|
||||||
@@ -247,20 +248,23 @@ SerializedObject.prototype.serialize = function(typedef, obj) {
|
|||||||
|
|
||||||
SerializedObject.prototype.hash = function(prefix) {
|
SerializedObject.prototype.hash = function(prefix) {
|
||||||
var sign_buffer = new SerializedObject();
|
var sign_buffer = new SerializedObject();
|
||||||
stypes.Int32.serialize(sign_buffer, prefix);
|
|
||||||
|
// Add hashing prefix
|
||||||
|
if ("undefined" !== typeof prefix) {
|
||||||
|
stypes.Int32.serialize(sign_buffer, prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy buffer to temporary buffer
|
||||||
sign_buffer.append(this.buffer);
|
sign_buffer.append(this.buffer);
|
||||||
return sign_buffer.hash_sha512_half();
|
|
||||||
|
// XXX We need a proper Buffer class then Crypt could accept that
|
||||||
|
var bits = sjcl.codec.bytes.toBits(sign_buffer.buffer);
|
||||||
|
return Crypt.hashSha512Half(bits);
|
||||||
};
|
};
|
||||||
|
|
||||||
// DEPRECATED
|
// DEPRECATED
|
||||||
SerializedObject.prototype.signing_hash = SerializedObject.prototype.hash;
|
SerializedObject.prototype.signing_hash = SerializedObject.prototype.hash;
|
||||||
|
|
||||||
SerializedObject.prototype.hash_sha512_half = function() {
|
|
||||||
var bits = sjcl.codec.bytes.toBits(this.buffer);
|
|
||||||
var hash = sjcl.bitArray.bitSlice(sjcl.hash.sha512.hash(bits), 0, 256);
|
|
||||||
return UInt256.from_hex(sjcl.codec.hex.fromBits(hash));
|
|
||||||
};
|
|
||||||
|
|
||||||
SerializedObject.prototype.serialize_field = function(spec, obj) {
|
SerializedObject.prototype.serialize_field = function(spec, obj) {
|
||||||
var name = spec[0];
|
var name = spec[0];
|
||||||
var presence = spec[1];
|
var presence = spec[1];
|
||||||
|
|||||||
@@ -34,6 +34,55 @@ describe('Ledger', function() {
|
|||||||
create_ledger_test(38129);
|
create_ledger_test(38129);
|
||||||
// Because, why not.
|
// Because, why not.
|
||||||
create_ledger_test(40000);
|
create_ledger_test(40000);
|
||||||
|
|
||||||
|
describe('#calcAccountRootEntryHash', function () {
|
||||||
|
it('will calculate the AccountRoot entry hash for rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', function () {
|
||||||
|
var account = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh';
|
||||||
|
var expectedEntryHash = '2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8';
|
||||||
|
var actualEntryHash = Ledger.calcAccountRootEntryHash(account);
|
||||||
|
|
||||||
|
assert.equal(actualEntryHash.to_hex(), expectedEntryHash);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#calcRippleStateEntryHash', function () {
|
||||||
|
it('will calculate the RippleState entry hash for rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh and rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY in USD', function () {
|
||||||
|
var account1 = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh';
|
||||||
|
var account2 = 'rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY';
|
||||||
|
var currency = 'USD';
|
||||||
|
|
||||||
|
var expectedEntryHash = 'C683B5BB928F025F1E860D9D69D6C554C2202DE0D45877ADB3077DA4CB9E125C';
|
||||||
|
var actualEntryHash1 = Ledger.calcRippleStateEntryHash(account1, account2, currency);
|
||||||
|
var actualEntryHash2 = Ledger.calcRippleStateEntryHash(account2, account1, currency);
|
||||||
|
|
||||||
|
assert.equal(actualEntryHash1.to_hex(), expectedEntryHash);
|
||||||
|
assert.equal(actualEntryHash2.to_hex(), expectedEntryHash);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('will calculate the RippleState entry hash for r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV and rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj in UAM', function () {
|
||||||
|
var account1 = 'r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV';
|
||||||
|
var account2 = 'rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj';
|
||||||
|
var currency = 'UAM';
|
||||||
|
|
||||||
|
var expectedEntryHash = 'AE9ADDC584358E5847ADFC971834E471436FC3E9DE6EA1773DF49F419DC0F65E';
|
||||||
|
var actualEntryHash1 = Ledger.calcRippleStateEntryHash(account1, account2, currency);
|
||||||
|
var actualEntryHash2 = Ledger.calcRippleStateEntryHash(account2, account1, currency);
|
||||||
|
|
||||||
|
assert.equal(actualEntryHash1.to_hex(), expectedEntryHash);
|
||||||
|
assert.equal(actualEntryHash2.to_hex(), expectedEntryHash);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#calcOfferEntryHash', function () {
|
||||||
|
it('will calculate the Offer entry hash for r32UufnaCGL82HubijgJGDmdE5hac7ZvLw, sequence 137', function () {
|
||||||
|
var account = 'r32UufnaCGL82HubijgJGDmdE5hac7ZvLw';
|
||||||
|
var sequence = 137
|
||||||
|
var expectedEntryHash = '03F0AED09DEEE74CEF85CD57A0429D6113507CF759C597BABB4ADB752F734CE3';
|
||||||
|
var actualEntryHash = Ledger.calcOfferEntryHash(account, sequence);
|
||||||
|
|
||||||
|
assert.equal(actualEntryHash.to_hex(), expectedEntryHash);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// vim:sw=2:sts=2:ts=8:et
|
// vim:sw=2:sts=2:ts=8:et
|
||||||
|
|||||||
Reference in New Issue
Block a user