[FEATURE] Add ability to calculate ledger entry keys.

This commit is contained in:
Stefan Thomas
2014-05-24 09:17:38 +02:00
parent fb213e5818
commit 9100e8ecc0
4 changed files with 173 additions and 8 deletions

View File

@@ -5,6 +5,11 @@ var SHAMap = require('./shamap').SHAMap;
var SHAMapTreeNode = require('./shamap').SHAMapTreeNode;
var SerializedObject = require('./serializedobject').SerializedObject;
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()
{
@@ -17,6 +22,91 @@ Ledger.from_json = function (v) {
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) {
this.ledger_json = v;
};

View 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'
};

View File

@@ -3,6 +3,7 @@ var extend = require('extend');
var binformat = require('./binformat');
var stypes = require('./serializedtypes');
var UInt256 = require('./uint256').UInt256;
var Crypt = require('./crypt').Crypt;
var utils = require('./utils');
var sjcl = utils.sjcl;
@@ -247,20 +248,23 @@ SerializedObject.prototype.serialize = function(typedef, obj) {
SerializedObject.prototype.hash = function(prefix) {
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);
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
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) {
var name = spec[0];
var presence = spec[1];