SerializedObject to_json method, and a simple test for that. Tests are still preliminary, and refactoring is still necessary.

This commit is contained in:
jatchili
2013-08-14 18:33:01 -07:00
parent 942bfe88c1
commit 0c18f6157d
5 changed files with 185 additions and 27 deletions

View File

@@ -97,6 +97,95 @@ SerializedObject.prototype.to_hex = function () {
return sjcl.codec.hex.fromBits(this.to_bits()).toUpperCase();
};
var TRANSACTION_TYPES = {
0:"Payment",
3:"AccountSet",
5:"SetRegularKey",
7:"OfferCreate",
8:"OfferCancel",
9:"Contract",
10:"RemoveContract",
20:"TrustSet",
100:"EnableFeature",
101:"SetFee"
};
SerializedObject.prototype.to_json = function() {
var old_pointer = this.pointer;
this.resetPointer();
var output = "{";
while (true) {
var key_and_value = stypes.parse_whatever(this);
var key = key_and_value[0];
var value = key_and_value[1];
output += ("\"" + key + "\":" + jsonify_structure(value,key));
output += ",";
if (this.pointer == this.buffer.length) {
break;
} else if (this.pointer > this.buffer.length) {
console.log("WARNING: Buffer length exceeded during SerializedObject.to_json");
break;
}
}
output = output.slice(0,-1);
output += "}";
this.pointer = old_pointer;
output = JSON.parse(output);
return output;
}
function jsonify_structure(thing,field_name) {
var output;
var typeof_thing = typeof thing;
if (typeof_thing === "number") { //Special codes
if (field_name) {
if (field_name === "LedgerEntryType") {
output = thing; //TODO: Do we have special codes for LedgerEntryType?
} else if (field_name === "TransactionType") {
output = "\""+TRANSACTION_TYPES[thing]+"\"" || thing;
} else {
output = thing;
}
} else {
output = thing;
}
} else if (typeof_thing === "boolean") {
output = thing;
} else if (typeof_thing === "string") {
output = "\"" + thing + "\"";
} else if ( "function" === typeof thing.to_json ) {
output = "\"" + thing.to_json() + "\"";
} else if (Array.isArray(thing)) {
//console.log("here2");
//iterate over array []
output = "[";
for (var i=0; i< thing.length; i++) {
output += jsonify_structure(thing[i]);
output += ",";
}
output = output.slice(0,-1);
output += "]";
} else {
//console.log("here1", thing);
//iterate over object {}
output = "{";
var keys = Object.keys(thing);
//console.log(keys);
for (var i=0; i<keys.length; i++) {
var key = keys[i];
var value = thing[key]
output += "\""+ key + "\":" + jsonify_structure(value);
output += ","
}
output = output.slice(0,-1);
output += "}";
}
return output;
}
SerializedObject.prototype.serialize = function (typedef, obj)
{
// Ensure canonical order
@@ -184,4 +273,5 @@ SerializedObject.lookup_type_tx = function (id) {
return null;
};
exports.SerializedObject = SerializedObject;

View File

@@ -43,7 +43,7 @@ function serialize_hex(so, hexData, noLength) {
* parses bytes as hex
*/
function convert_bytes_to_hex (byte_array) {
return sjcl.codec.hex.fromBits(sjcl.codec.bytes.toBits(byte_array));
return sjcl.codec.hex.fromBits(sjcl.codec.bytes.toBits(byte_array)).toUpperCase();
}
SerializedType.serialize_varint = function (so, val) {
@@ -83,6 +83,10 @@ SerializedType.prototype.parse_varint = function (so) {
}
};
// In the following, we assume that the inputs are in the proper range. Is this correct?
// Helper functions for 1-, 2-, and 4-byte integers.
@@ -374,7 +378,7 @@ var STAccount = exports.Account = new SerializedType({
},
parse: function (so) {
var len = this.parse_varint(so);
console.log("KKKKKKKKKKK",len);
//console.log("KKKKKKKKKKK",len);
if (len !== 20) {
throw new Error("Non-standard-length account ID");
}
@@ -529,25 +533,26 @@ function serialize_whatever(so, field_name, value) {
//What should this helper function be attached to?
//Take the serialized object, figure out what type/field it is, and return the parsing of that.
function parse_whatever(so) {
var parse_whatever = exports.parse_whatever = function(so) {
var tag_byte = so.read(1)[0];
var type_bits = tag_byte >> 4;
var field_bits = tag_byte & 0x0f;
var type;
var field_name;
if (type_bits === 0) {
type = TYPES_MAP[so.read(1)[0]];
} else {
type = TYPES_MAP[type_bits];
type_bits = so.read(1)[0];
}
type = TYPES_MAP[type_bits];
if ("undefined" === typeof type) {
throw Error("Unknown type");
} else {
if (field_bits === 0) {
field_name = FIELDS_MAP[type_bits][so.read(1)[0]];
} else {
//console.log("!!!!!!!!!!IJOIOJIOJO", type_bits, field_bits);
field_name = FIELDS_MAP[type_bits][field_bits];
}
//console.log("PARSING WHATEVER!!!!", type_bits, type, field_name);
if ("undefined" === typeof field_name) {
throw Error("Unknown field");
} else {
@@ -587,13 +592,16 @@ var STObject = exports.Object = new SerializedType({
STInt8.serialize(so, 0xe1); //Object ending marker
},
parse: function (so) {
//console.log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", so.buffer, so.pointer);
var output = {};
while (true) {
if (so.peek(1)[0] === 0xe1) { //ending marker
break;
} else {
//console.log("WTF M8");
var key_and_value = parse_whatever(so);
output[key_and_value[0]] = key_and_value[1];
//console.log("BBBBBBBBBBBBB", key_and_value, output);
}
}
return output;
@@ -722,4 +730,3 @@ for (var key1 in FIELDS_MAP) {
INVERSE_FIELDS_MAP[FIELDS_MAP[key1][key2]] = [key1, key2];
}
}

View File

@@ -217,7 +217,6 @@ UInt.prototype.to_hex = function () {
return null;
var bytes = this.to_bytes();
return sjcl.codec.hex.fromBits(sjcl.codec.bytes.toBits(bytes)).toUpperCase();
};

View File

@@ -0,0 +1,47 @@
var buster = require("buster");
var SerializedObject = require("../src/js/ripple/serializedobject").SerializedObject;
//var types = require("../src/js/ripple/serializedtypes");
var jsbn = require('../src/js/ripple/jsbn');
var BigInteger = jsbn.BigInteger;
try {
var conf = require('./config');
} catch(exception) {
var conf = require('./config-example');
}
var config = require('../src/js/ripple/config').load(conf);
buster.testCase("Serialized objects", {
"SerializedObject" : {
"From json and back" : function () {
var input_json = {
"Account":"r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS",
"Amount":"274579388",
"Destination":"r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS",
"Fee":"15",
"Flags":0,
"Paths":[[{"account":"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV","currency":"USD","issuer":"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV"},{"currency":"XRP"}]],
"SendMax":{"currency":"USD","issuer":"r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS","value":"2.74579388"},
"Sequence":351,
"SigningPubKey":"02854B06CE8F3E65323F89260E9E19B33DA3E01B30EA4CA172612DE77973FAC58A",
"TransactionType":"Payment",
"TxnSignature":"30450221009DA3A42DD25E3B22EC45AD8BA8FC7A954264264A816D300B2DF69F814D7D4DD2022072C9627F97EEC6DA13DE841E06E2CD985EF06A0FBB15DDBF0800D0730C8986BF"
}
so = SerializedObject.from_json(input_json);
var output_json = so.to_json();
//console.log(input_json);
assert.equals(input_json,output_json);
}
}
});
// vim:sw=2:sts=2:ts=8:et

View File

@@ -14,7 +14,7 @@ try {
var config = require('../src/js/ripple/config').load(conf);
buster.testCase("Serialized types", { /*
buster.testCase("Serialized types", {
"Int8" : {
"Serialize 0" : function () {
var so = new SerializedObject();
@@ -433,8 +433,8 @@ buster.testCase("Serialized types", { /*
var so = new SerializedObject("94838D7EA4C680000000000000000000000000005553440000000000B5F762798A53D543A014CAF8B297CFF8F2F937E8");
assert.equals(types.Amount.parse(so).to_text_full(), "-1/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh");
},
}
*/
},
"PathSet" : {
"Serialize single empty path [[]]" : function () {
@@ -445,7 +445,6 @@ buster.testCase("Serialized types", { /*
"Serialize [[e],[e,e]]" : function () {
var so = new SerializedObject();
//types.PathSet.serialize(so, [[{account:123, currency:"USD", issuer:789}],[{account:123, currency:"BTC", issuer:789},{account:987, currency:"EUR", issuer:321}]]);
types.PathSet.serialize(so, [[{account:123, currency:"USD", issuer:789}],[{account:123, currency:"BTC", issuer:789},{account:987, currency:"EUR", issuer:321}]]);
assert.equals(so.to_hex(), "31000000000000000000000000000000000000007B00000000000000000000000055534400000000000000000000000000000000000000000000000315FF31000000000000000000000000000000000000007B000000000000000000000000425443000000000000000000000000000000000000000000000003153100000000000000000000000000000000000003DB0000000000000000000000004555520000000000000000000000000000000000000000000000014100"); //TODO: Check this independently
},
@@ -458,9 +457,7 @@ buster.testCase("Serialized types", { /*
"Parse [[e],[e,e]]" : function () {
var so = new SerializedObject("31000000000000000000000000000000000000007B00000000000000000000000055534400000000000000000000000000000000000000000000000315FF31000000000000000000000000000000000000007B000000000000000000000000425443000000000000000000000000000000000000000000000003153100000000000000000000000000000000000003DB0000000000000000000000004555520000000000000000000000000000000000000000000000014100");
//console.log("AAAA!",types.PathSet);
parsed_path=types.PathSet.parse(so);
//console.log(parsed_path);
assert.equals(parsed_path,[[{account:{_value:123}, currency:{_value:"USD"}, issuer:{_value:789}}],[{account:{_value:123}, currency:{_value:"BTC"}, issuer:{_value:789}},{account:{_value:987}, currency:{_value:"EUR"}, issuer:{_value:321}}]]);
}
@@ -481,22 +478,41 @@ buster.testCase("Serialized types", { /*
var so = new SerializedObject();
types.Object.serialize(so, {"TakerPays":"87654321.12345678/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "TakerGets":"213", "Fee":789});
assert.equals(so.to_hex(), "64D65F241D335BF24E0000000000000000000000004555520000000000B5F762798A53D543A014CAF8B297CFF8F2F937E86540000000000000D5684000000000000315E1");
//console.log("!!!!!!!!!!!!!!!!!!",so.to_hex());
//TODO: Check independently.
},
"Parse same object" : function () {
var so = new SerializedObject("64D65F241D335BF24E0000000000000000000000004555520000000000B5F762798A53D543A014CAF8B297CFF8F2F937E86540000000000000D5684000000000000315E1");
var parsed_object=types.Object.parse(so);
refute.equals(parsed_object,{"TakerPays":{_value:123}, "TakerGets":{_value:456}, "Fee":{_value:789}});
assert.equals(parsed_object,
{ TakerPays:
{ _value: { '0': 56357454, '1': 32653779, t: 2, s: 0 },
_offset: -8,
_is_native: false,
_is_negative: false,
_currency: { _value: 'EUR' },
_issuer: { _value: -422657445385694440895149034202122766475892017176 } },
TakerGets:
{ _value: { '0': 213, '1': 0, '2': 0, t: 1, s: 0 },
_offset: 0,
_is_native: true,
_is_negative: false,
_currency: { _value: NaN },
_issuer: { _value: NaN } },
Fee:
{ _value: { '0': 789, '1': 0, '2': 0, t: 1, s: 0 },
_offset: 0,
_is_native: true,
_is_negative: false,
_currency: { _value: NaN },
_issuer: { _value: NaN } } }
);
//TODO: Check independently.
console.log("LEFT OFF HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!! MAKE THIS WORK!!!!!!!!!!");
console.log(parsed_object);
},
'Serialize simple object {"DestinationTag":123, "QualityIn":456, "QualityOut":789}' : function () {
var so = new SerializedObject();
types.Object.serialize(so, {"DestinationTag":123, "QualityIn":456, "QualityOut":789});
//console.log("what?", so.to_hex());
//console.log("DOES THE JSON METHOD WORK?", so.to_json());
assert.equals(so.to_hex(), "2E0000007B2014000001C8201500000315E1");
//TODO: Check independently.
},
@@ -505,11 +521,11 @@ buster.testCase("Serialized types", { /*
var parsed_object=types.Object.parse(so);
assert.equals(parsed_object,{"DestinationTag":123, "QualityIn":456, "QualityOut":789});
//TODO: Check independently.
},
}
},
"Array" : {/*
"Array" : {
"Serialize empty array []" : function () {
var so = new SerializedObject();
types.Array.serialize(so, []);
@@ -519,36 +535,35 @@ buster.testCase("Serialized types", { /*
var so = new SerializedObject("F1");
var parsed_object=types.Array.parse(so);
assert.equals(parsed_object,[]);
},*/
},
'Serialize 3-length array [{"TakerPays":123}, {"TakerGets":456}, {"Fee":789}]' : function () {
var so = new SerializedObject();
types.Array.serialize(so, [{"TakerPays":123}, {"TakerGets":456}, {"Fee":789}]);
//TODO: Check this manually
assert.equals(so.to_hex(), "64400000000000007B6540000000000001C8684000000000000315F1");
},
"Parse the same array" : function () {
var so = new SerializedObject("64400000000000007B6540000000000001C8684000000000000315F1");
var parsed_object=types.Array.parse(so);
//console.log("WE GOT:", parsed_object[0].TakerPays._value, parsed_object[1].TakerGets._value, parsed_object[2].Fee._value);
console.log("WE GOT BACK 1:", parsed_object);
assert.equals([123,456,789],[parsed_object[0].TakerPays._value, parsed_object[1].TakerGets._value, parsed_object[2].Fee._value]);
},
'Serialize 3-length array [{"DestinationTag":123}, {"QualityIn":456}, {"Fee":789}]' : function () {
var so = new SerializedObject();
types.Array.serialize(so, [{"DestinationTag":123}, {"QualityIn":456}, {"Fee":789}]);
//TODO: Check this manually
console.log("WE GOT!!:",so.to_hex());
//console.log("DOES THE JSON METHOD WORK2?", so.to_json());
assert.equals(so.to_hex(), "2E0000007B2014000001C8684000000000000315F1");
},
"Parse the same array 2" : function () {
var so = new SerializedObject("2E0000007B2014000001C8684000000000000315F1");
var parsed_object=types.Array.parse(so);
console.log("WE GOT BACK 2:", parsed_object);
//TODO: Is this correct? Return some things as integers, and others as objects?
assert.equals([123,456,789],[parsed_object[0].DestinationTag, parsed_object[1].QualityIn, parsed_object[2].Fee._value]);
},
}
}
});