This commit is contained in:
wltsmrz
2013-10-05 15:06:55 -07:00
parent f24be618d8
commit 37b653eae6

View File

@@ -5,7 +5,7 @@ var stypes = require('./serializedtypes');
var UInt256 = require('./uint256').UInt256; var UInt256 = require('./uint256').UInt256;
var SerializedObject = function (buf) { function SerializedObject(buf) {
if (Array.isArray(buf) || (Buffer && Buffer.isBuffer(buf)) ) { if (Array.isArray(buf) || (Buffer && Buffer.isBuffer(buf)) ) {
this.buffer = buf; this.buffer = buf;
} else if (typeof buf === 'string') { } else if (typeof buf === 'string') {
@@ -13,35 +13,41 @@ var SerializedObject = function (buf) {
} else if (!buf) { } else if (!buf) {
this.buffer = []; this.buffer = [];
} else { } else {
throw new Error("Invalid buffer passed."); throw new Error('Invalid buffer passed.');
} }
this.pointer = 0; this.pointer = 0;
}; };
SerializedObject.from_json = function (obj) { SerializedObject.from_json = function (obj) {
var so = new SerializedObject();
var typedef;
// Create a copy of the object so we don't modify it // Create a copy of the object so we don't modify it
obj = extend({}, obj); var obj = extend({}, obj);
var so = new SerializedObject;
var typedef;
switch (typeof obj.TransactionType) { switch (typeof obj.TransactionType) {
case 'number': case 'number':
obj.TransactionType = SerializedObject.lookup_type_tx(obj.TransactionType); obj.TransactionType = SerializedObject.lookup_type_tx(obj.TransactionType);
if (!obj.TransactionType) { if (!obj.TransactionType) {
throw new Error("Transaction type ID is invalid."); throw new Error('Transaction type ID is invalid.');
} }
break; break;
case 'string': case 'string':
typedef = binformat.tx[obj.TransactionType].slice(); typedef = binformat.tx[obj.TransactionType];
if (!Array.isArray(typedef)) {
throw new Error('Transaction type is invalid');
}
typedef = typedef.slice();
obj.TransactionType = typedef.shift(); obj.TransactionType = typedef.shift();
break; break;
default: default:
if (typeof obj.LedgerEntryType !== 'undefined') { if (typeof obj.LedgerEntryType !== 'undefined') {
// XXX: TODO // XXX: TODO
throw new Error("Ledger entry binary format not yet implemented."); throw new Error('Ledger entry binary format not yet implemented.');
} else { } else {
throw new Error("Object to be serialized must contain either " + "TransactionType or LedgerEntryType."); throw new Error('Object to be serialized must contain either ' + 'TransactionType or LedgerEntryType.');
} }
} }
@@ -60,19 +66,22 @@ SerializedObject.prototype.resetPointer = function () {
}; };
function readOrPeek(advance) { function readOrPeek(advance) {
return function(numberOfBytes) { return function(bytes) {
var start = this.pointer; var start = this.pointer;
var end = start + numberOfBytes; var end = start + bytes;
if (end > this.buffer.length) { if (end > this.buffer.length) {
throw new Error("There aren't that many bytes left."); throw new Error('Buffer length exceeded');
} else { }
var result = this.buffer.slice(start, end); var result = this.buffer.slice(start, end);
if (advance) { if (advance) {
this.pointer = end; this.pointer = end;
} }
return result; return result;
} }
}
}; };
SerializedObject.prototype.read = readOrPeek(true); SerializedObject.prototype.read = readOrPeek(true);
@@ -87,51 +96,51 @@ SerializedObject.prototype.to_hex = function () {
}; };
var TRANSACTION_TYPES = { var TRANSACTION_TYPES = {
0: "Payment", 0: 'Payment',
3: "AccountSet", 3: 'AccountSet',
5: "SetRegularKey", 5: 'SetRegularKey',
7: "OfferCreate", 7: 'OfferCreate',
8: "OfferCancel", 8: 'OfferCancel',
9: "Contract", 9: 'Contract',
10: "RemoveContract", 10: 'RemoveContract',
20: "TrustSet", 20: 'TrustSet',
100: "EnableFeature", 100: 'EnableFeature',
101: "SetFee" 101: 'SetFee'
}; };
var LEDGER_ENTRY_TYPES = { var LEDGER_ENTRY_TYPES = {
97: "AccountRoot", 97: 'AccountRoot',
99: "Contract", 99: 'Contract',
100: "DirectoryNode", 100: 'DirectoryNode',
102: "Features", 102: 'Features',
103: "GeneratorMap", 103: 'GeneratorMap',
104: "LedgerHashes", 104: 'LedgerHashes',
110: "Nickname", 110: 'Nickname',
111: "Offer", 111: 'Offer',
114: "RippleState", 114: 'RippleState',
115: "FeeSettings" 115: 'FeeSettings'
}; };
var TRANSACTION_RESULTS = { var TRANSACTION_RESULTS = {
0 : "tesSUCCESS", 0 : 'tesSUCCESS',
100: "tecCLAIM", 100: 'tecCLAIM',
101: "tecPATH_PARTIAL", 101: 'tecPATH_PARTIAL',
102: "tecUNFUNDED_ADD", 102: 'tecUNFUNDED_ADD',
103: "tecUNFUNDED_OFFER", 103: 'tecUNFUNDED_OFFER',
104: "tecUNFUNDED_PAYMENT", 104: 'tecUNFUNDED_PAYMENT',
105: "tecFAILED_PROCESSING", 105: 'tecFAILED_PROCESSING',
121: "tecDIR_FULL", 121: 'tecDIR_FULL',
122: "tecINSUF_RESERVE_LINE", 122: 'tecINSUF_RESERVE_LINE',
123: "tecINSUF_RESERVE_OFFER", 123: 'tecINSUF_RESERVE_OFFER',
124: "tecNO_DST", 124: 'tecNO_DST',
125: "tecNO_DST_INSUF_XRP", 125: 'tecNO_DST_INSUF_XRP',
126: "tecNO_LINE_INSUF_RESERVE", 126: 'tecNO_LINE_INSUF_RESERVE',
127: "tecNO_LINE_REDUNDANT", 127: 'tecNO_LINE_REDUNDANT',
128: "tecPATH_DRY", 128: 'tecPATH_DRY',
129: "tecUNFUNDED", // Deprecated, old ambiguous unfunded. 129: 'tecUNFUNDED', // Deprecated, old ambiguous unfunded.
130: "tecMASTER_DISABLED", 130: 'tecMASTER_DISABLED',
131: "tecNO_REGULAR_KEY", 131: 'tecNO_REGULAR_KEY',
132: "tecOWNERS" 132: 'tecOWNERS'
}; };
SerializedObject.prototype.to_json = function() { SerializedObject.prototype.to_json = function() {
@@ -143,7 +152,7 @@ SerializedObject.prototype.to_json = function() {
var key_and_value = stypes.parse_whatever(this); var key_and_value = stypes.parse_whatever(this);
var key = key_and_value[0]; var key = key_and_value[0];
var value = key_and_value[1]; var value = key_and_value[1];
output[key] = jsonify_structure(value,key); output[key] = jsonify_structure(value, key);
} }
this.pointer = old_pointer; this.pointer = old_pointer;
@@ -151,41 +160,42 @@ SerializedObject.prototype.to_json = function() {
return output; return output;
} }
function jsonify_structure(thing, field_name) { function jsonify_structure(structure, field_name) {
var output; var output;
switch (typeof thing) {
switch (typeof structure) {
case 'number': case 'number':
switch (field_name) { switch (field_name) {
case 'LedgerEntryType': case 'LedgerEntryType':
output = LEDGER_ENTRY_TYPES[thing] || thing; output = LEDGER_ENTRY_TYPES[structure] || thing;
break; break;
case 'TransactionResult': case 'TransactionResult':
output = TRANSACTION_RESULTS[thing] || thing; output = TRANSACTION_RESULTS[structure] || thing;
break; break;
case 'TransactionType': case 'TransactionType':
output = TRANSACTION_TYPES[thing] || thing; output = TRANSACTION_TYPES[structure] || thing;
break; break;
default: default:
output = thing; output = structure;
} }
break; break;
case 'object': case 'object':
if (typeof thing.to_json === 'function') { if (!structure) break; //null
output = thing.to_json(); if (typeof structure.to_json === 'function') {
} else if (thing === null) { output = structure.to_json();
break;
} else { } else {
output = new thing.constructor; output = new structure.constructor; //new Array or Object
var keys = Object.keys(thing); var keys = Object.keys(structure);
for (var i=0; i<keys.length; i++) { for (var i=0, l=keys.length; i<l; i++) {
var key = keys[i]; var key = keys[i];
output[key] = jsonify_structure(thing[key], key); output[key] = jsonify_structure(structure[key], key);
} }
} }
break; break;
default: default:
output = thing; output = structure;
} }
return output; return output;
}; };
@@ -193,12 +203,11 @@ SerializedObject.jsonify_structure = jsonify_structure; //So that we can access
SerializedObject.prototype.serialize = function (typedef, obj) { SerializedObject.prototype.serialize = function (typedef, obj) {
// Ensure canonical order // Ensure canonical order
typedef = SerializedObject._sort_typedef(typedef.slice()); var typedef = SerializedObject._sort_typedef(typedef);
// Serialize fields // Serialize fields
for (var i=0, l=typedef.length; i<l; i++) { for (var i=0, l=typedef.length; i<l; i++) {
var spec = typedef[i]; this.serialize_field(typedef[i], obj);
this.serialize_field(spec, obj);
} }
}; };
@@ -210,27 +219,24 @@ SerializedObject.prototype.signing_hash = function (prefix) {
}; };
SerializedObject.prototype.hash_sha512_half = function () { SerializedObject.prototype.hash_sha512_half = function () {
var bits = sjcl.codec.bytes.toBits(this.buffer), var bits = sjcl.codec.bytes.toBits(this.buffer);
hash = sjcl.bitArray.bitSlice(sjcl.hash.sha512.hash(bits), 0, 256); var hash = sjcl.bitArray.bitSlice(sjcl.hash.sha512.hash(bits), 0, 256);
return UInt256.from_hex(sjcl.codec.hex.fromBits(hash)); return UInt256.from_hex(sjcl.codec.hex.fromBits(hash));
}; };
SerializedObject.prototype.serialize_field = function (spec, obj) { SerializedObject.prototype.serialize_field = function (spec, obj) {
var spec = spec.slice(); var name = spec[0];
var name = spec.shift(); var presence = spec[1];
var presence = spec.shift(); var field_id = spec[2];
var field_id = spec.shift(); var Type = spec[3];
var Type = spec.shift();
if (typeof obj[name] !== 'undefined') { if (typeof obj[name] !== 'undefined') {
//console.log(name, Type.id, field_id);
this.append(SerializedObject.get_field_header(Type.id, field_id)); this.append(SerializedObject.get_field_header(Type.id, field_id));
try { try {
Type.serialize(this, obj[name]); Type.serialize(this, obj[name]);
} catch (e) { } catch (e) {
// Add field name to message and rethrow // Add field name to message and rethrow
e.message = "Error serializing '" + name + "': " + e.message; e.message = 'Error serializing "' + name + '": ' + e.message;
throw e; throw e;
} }
} else if (presence === binformat.REQUIRED) { } else if (presence === binformat.REQUIRED) {
@@ -239,18 +245,18 @@ SerializedObject.prototype.serialize_field = function (spec, obj) {
}; };
SerializedObject.get_field_header = function (type_id, field_id) { SerializedObject.get_field_header = function (type_id, field_id) {
var buffer = [0]; var buffer = [ 0 ];
if (type_id > 0xf) { if (type_id > 0xF) {
buffer.push(type_id & 0xff); buffer.push(type_id & 0xFF);
} else { } else {
buffer[0] += (type_id & 0xf) << 4; buffer[0] += (type_id & 0xF) << 4;
} }
if (field_id > 0xf) { if (field_id > 0xF) {
buffer.push(field_id & 0xff); buffer.push(field_id & 0xFF);
} else { } else {
buffer[0] += field_id & 0xf; buffer[0] += field_id & 0xF;
} }
return buffer; return buffer;
@@ -269,7 +275,7 @@ SerializedObject.lookup_type_tx = function (id) {
var keys = Object.keys(binformat.tx); var keys = Object.keys(binformat.tx);
var result = null; var result = null;
for (var i=0; i<keys.length; i++) { for (var i=0, l=keys.length; i<l; i++) {
var key = keys[i]; var key = keys[i];
if (binformat.tx[key][0] === id) { if (binformat.tx[key][0] === id) {
result = key; result = key;