Skip to content

Commit

Permalink
BREAKING CHANGE: Use ripple-binary-codec
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Clark committed Oct 8, 2015
1 parent 57ecbc5 commit 91a6413
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 64 deletions.
36 changes: 36 additions & 0 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -27,6 +27,7 @@
"lodash": "^3.1.0",
"lru-cache": "~2.5.0",
"ripple-address-codec": "^2.0.1",
"ripple-binary-codec": "^0.0.5",
"ripple-keypairs": "^0.9.0",
"ripple-lib-transactionparser": "^0.5.1",
"ripple-lib-value": "0.1.0",
Expand Down
25 changes: 14 additions & 11 deletions src/api/transaction/sign.js
Expand Up @@ -2,7 +2,8 @@
'use strict';
const utils = require('./utils');
const keypairs = require('ripple-keypairs');
const core = utils.common.core;
const binary = require('ripple-binary-codec');
const sha512 = require('hash.js').sha512;
const validate = utils.common.validate;

/**
Expand All @@ -17,20 +18,22 @@ const validate = utils.common.validate;
*/
const HASH_TX_ID = 0x54584E00; // 'TXN'

function serialize(txJSON) {
return core.SerializedObject.from_json(txJSON);
// For a hash function, rippled uses SHA-512 and then truncates the result
// to the first 256 bytes. This algorithm, informally called SHA-512Half,
// provides an output that has comparable security to SHA-256, but runs
// faster on 64-bit processors.
function sha512half(buffer) {
return sha512().update(buffer).digest('hex').toUpperCase().slice(0, 64);
}

function hashSerialization(serialized, prefix) {
return serialized.hash(prefix || HASH_TX_ID).to_hex();
}

function signingData(txJSON) {
return core.Transaction.from_json(txJSON).signingData().buffer;
const hexPrefix = prefix.toString(16).toUpperCase();
return sha512half(new Buffer(hexPrefix + serialized, 'hex'));
}

function computeSignature(txJSON, privateKey) {
return keypairs.sign(signingData(txJSON), privateKey);
const signingData = binary.encodeForSigning(txJSON);
return keypairs.sign(new Buffer(signingData, 'hex'), privateKey);
}

function sign(txJSON: string, secret: string
Expand All @@ -44,9 +47,9 @@ function sign(txJSON: string, secret: string
tx.SigningPubKey = keypair.publicKey;
}
tx.TxnSignature = computeSignature(tx, keypair.privateKey);
const serialized = serialize(tx);
const serialized = binary.encode(tx);
return {
signedTransaction: serialized.to_hex(),
signedTransaction: serialized,
id: hashSerialization(serialized, HASH_TX_ID)
};
}
Expand Down
1 change: 1 addition & 0 deletions src/core/index.js
Expand Up @@ -25,6 +25,7 @@ exports._test = {
UInt128: require('./uint128').UInt128,
UInt160: require('./uint160').UInt160,
UInt256: require('./uint256').UInt256,
OrderbookUtils: require('./orderbookutils'),
constants: require('./constants')
};

Expand Down
2 changes: 1 addition & 1 deletion src/core/ledger.js
Expand Up @@ -109,7 +109,7 @@ Ledger.prototype.calc_tx_hash = function() {
const meta = SerializedObject.from_json(tx_json.metaData);

const data = new SerializedObject();
stypes.VariableLength.serialize(data, tx.serialize().to_hex());
stypes.VariableLength.serialize(data, tx.serialize());
stypes.VariableLength.serialize(data, meta.to_hex());
tx_map.add_item(tx.hash(), data, SHAMapTreeNode.TYPE_TRANSACTION_MD);
});
Expand Down
16 changes: 3 additions & 13 deletions src/core/orderbookutils.js
Expand Up @@ -3,11 +3,10 @@
const _ = require('lodash');
const assert = require('assert');
const constants = require('./constants');
const SerializedObject = require('./serializedobject').SerializedObject;
const Types = require('./serializedtypes');
const Amount = require('./amount').Amount;
const Currency = require('./currency').Currency;
const {IOUValue} = require('ripple-lib-value');
const binary = require('ripple-binary-codec');
const OrderBookUtils = {};

function assertValidNumber(number, message) {
Expand Down Expand Up @@ -143,11 +142,7 @@ OrderBookUtils.getOfferQuality = function(offer, currencyGets, currency_,

OrderBookUtils.convertOfferQualityToHex = function(quality) {
assert(quality instanceof Amount, 'Quality is not an amount');

const so = new SerializedObject();
Types.Quality.serialize(so, quality.to_text());

return so.to_hex();
return OrderBookUtils.convertOfferQualityToHex(quality.to_text());
};

/**
Expand All @@ -160,14 +155,9 @@ OrderBookUtils.convertOfferQualityToHex = function(quality) {
*/

OrderBookUtils.convertOfferQualityToHexFromText = function(quality) {

const so = new SerializedObject();
Types.Quality.serialize(so, quality);

return so.to_hex();
return binary.encodeQuality(quality);
};


OrderBookUtils.CURRENCY_ONE = Currency.from_json(1);

OrderBookUtils.ISSUER_ONE = constants.ACCOUNT_ONE;
Expand Down
28 changes: 11 additions & 17 deletions src/core/transaction.js
Expand Up @@ -9,11 +9,11 @@ const utils = require('./utils');
const sjclcodec = require('sjcl-codec');
const Amount = require('./amount').Amount;
const Currency = require('./currency').Currency;
const SerializedObject = require('./serializedobject').SerializedObject;
const RippleError = require('./rippleerror').RippleError;
const hashprefixes = require('./hashprefixes');
const log = require('./log').internal.sub('transaction');
const {isValidAddress, decodeAddress} = require('ripple-address-codec');
const binary = require('ripple-binary-codec');

/**
* @constructor Transaction
Expand Down Expand Up @@ -451,30 +451,24 @@ Transaction.prototype.setCanonicalFlag = function() {
};

Transaction.prototype.serialize = function() {
return SerializedObject.from_json(this.tx_json);
return binary.encode(this.tx_json);
};

Transaction.prototype.signingHash = function(testnet) {
return this.hash(testnet ? 'HASH_TX_SIGN_TESTNET' : 'HASH_TX_SIGN');
};

Transaction.prototype.signingData = function() {
const so = new SerializedObject();
so.append(hashprefixes.HASH_TX_SIGN_BYTES);
so.parse_json(this.tx_json);
return so;
return binary.encodeForSigning(this.tx_json);
};

Transaction.prototype.multiSigningData = function(account) {
const so = new SerializedObject();
so.append(hashprefixes.HASH_TX_MULTISIGN_BYTES);
so.parse_json(this.tx_json);
so.append(decodeAddress(account));
return so;
return binary.encodeForMultisigning(this.tx_json, account);
};

Transaction.prototype.hash = function(prefix_, asUINT256, serialized) {
Transaction.prototype.hash = function(prefix_, serialized_) {
let prefix;
assert(serialized_ === undefined || _.isString(serialized_));

if (typeof prefix_ !== 'string') {
prefix = hashprefixes.HASH_TX_ID;
Expand All @@ -484,9 +478,9 @@ Transaction.prototype.hash = function(prefix_, asUINT256, serialized) {
prefix = hashprefixes[prefix_];
}

const hash = (serialized || this.serialize()).hash(prefix);

return asUINT256 ? hash : hash.to_hex();
const hexPrefix = prefix.toString(16).toUpperCase();
const serialized = serialized_ || this.serialize();
return utils.sha512half(new Buffer(hexPrefix + serialized, 'hex'));
};

Transaction.prototype.sign = function(secret) {
Expand All @@ -505,7 +499,7 @@ Transaction.prototype.sign = function(secret) {
}

const keypair = deriveKeypair(secret || this._secret);
this.tx_json.TxnSignature = sign(this.signingData().buffer,
this.tx_json.TxnSignature = sign(new Buffer(this.signingData(), 'hex'),
keypair.privateKey);
this.previousSigningHash = hash;

Expand Down Expand Up @@ -1654,7 +1648,7 @@ Transaction.prototype.multiSign = function(account, secret) {

const signer = {
Account: account,
TxnSignature: sign(signingData.buffer, keypair.privateKey),
TxnSignature: sign(new Buffer(signingData, 'hex'), keypair.privateKey),
SigningPubKey: keypair.publicKey
};

Expand Down
4 changes: 2 additions & 2 deletions src/core/transactionmanager.js
Expand Up @@ -524,9 +524,9 @@ TransactionManager.prototype._prepareRequest = function(tx) {
tx.sign();

const serialized = tx.serialize();
submitRequest.txBlob(serialized.to_hex());
submitRequest.txBlob(serialized);

const hash = tx.hash(null, null, serialized);
const hash = tx.hash(null, serialized);
tx.addId(hash);
} else {
if (tx.hasMultiSigners()) {
Expand Down
15 changes: 13 additions & 2 deletions src/core/utils.js
@@ -1,4 +1,13 @@
'use strict';
const sha512 = require('hash.js').sha512;

// For a hash function, rippled uses SHA-512 and then truncates the result
// to the first 256 bytes. This algorithm, informally called SHA-512Half,
// provides an output that has comparable security to SHA-256, but runs
// faster on 64-bit processors.
function sha512half(buffer) {
return sha512().update(buffer).digest('hex').toUpperCase().slice(0, 64);
}

// returns the mantissa from the passed in string,
// adding zeros until it has 16 sd
Expand All @@ -21,7 +30,7 @@ function getMantissaDecimalString(bignum) {

function trace(comment, func) {
return function() {
console.log('%s: %s', trace, arguments.toString);
console.log('%s: %s', comment, arguments.toString);
func(arguments);
};
}
Expand Down Expand Up @@ -112,7 +121,8 @@ function assert(assertion, msg) {
* @return {Array} unique values (for string representation of value) in `arr`
*/
function arrayUnique(arr) {
const u = {}, a = [];
const u = {};
const a = [];

for (let i = 0, l = arr.length; i < l; i++) {
const k = arr[i];
Expand Down Expand Up @@ -151,6 +161,7 @@ exports.time = {
toRipple: fromTimestamp
};

exports.sha512half = sha512half;
exports.trace = trace;
exports.arraySet = arraySet;
exports.hexToString = hexToString;
Expand Down
14 changes: 7 additions & 7 deletions test/fixtures/api/requests/compute-ledger-hash-transactions.json
@@ -1,6 +1,6 @@
[
{
"hash": "f8f337dee5d5b238a10af4a4d56926ba26c83ee7af5a5a6474340c56f9252df3",
"hash": "F8F337DEE5D5B238A10AF4A4D56926BA26C83EE7AF5A5A6474340C56F9252DF3",
"date": "2015-08-12T01:01:10+00:00",
"ledger_index": 15202439,
"tx": {
Expand Down Expand Up @@ -60,7 +60,7 @@
}
},
{
"hash": "f8d5de632b1d8b64e577c46912cce483d6df4fd4e2cf4a3d586a099de3b27021",
"hash": "F8D5DE632B1D8B64E577C46912CCE483D6DF4FD4E2CF4A3D586A099DE3B27021",
"date": "2015-08-12T01:01:10+00:00",
"ledger_index": 15202439,
"tx": {
Expand Down Expand Up @@ -120,7 +120,7 @@
}
},
{
"hash": "e9004490a92413e92dacd621ac73fd434a8950c350f7572ffeaf4d6aaf8fc288",
"hash": "E9004490A92413E92DACD621AC73FD434A8950C350F7572FFEAF4D6AAF8FC288",
"date": "2015-08-12T01:01:10+00:00",
"ledger_index": 15202439,
"tx": {
Expand Down Expand Up @@ -180,7 +180,7 @@
}
},
{
"hash": "d44bff924d23211b82b8f604af6d92f260f8dd13103a96f03e48825c4a978fd6",
"hash": "D44BFF924D23211B82B8F604AF6D92F260F8DD13103A96F03E48825C4A978FD6",
"date": "2015-08-12T01:01:10+00:00",
"ledger_index": 15202439,
"tx": {
Expand Down Expand Up @@ -240,7 +240,7 @@
}
},
{
"hash": "c978d915bfb17687335cbfc4b207d9e7213bcee35b468c2eee016cdce4edb6e4",
"hash": "C978D915BFB17687335CBFC4B207D9E7213BCEE35B468C2EEE016CDCE4EDB6E4",
"date": "2015-08-12T01:01:10+00:00",
"ledger_index": 15202439,
"tx": {
Expand Down Expand Up @@ -372,7 +372,7 @@
}
},
{
"hash": "31b34fd7c90cdc6cf680a814debc6f616c69275c0e99711f904de088a8ed4b28",
"hash": "31B34FD7C90CDC6CF680A814DEBC6F616C69275C0E99711F904DE088A8ED4B28",
"date": "2015-08-12T01:01:10+00:00",
"ledger_index": 15202439,
"tx": {
Expand Down Expand Up @@ -412,7 +412,7 @@
}
},
{
"hash": "260bc2964ffe6d81cb25c152f8054ffb2ce6ed04ff89d8d0d0559bc14bef0e46",
"hash": "260BC2964FFE6D81CB25C152F8054FFB2CE6ED04FF89D8D0D0559BC14BEF0E46",
"date": "2015-08-12T01:01:10+00:00",
"ledger_index": 15202439,
"tx": {
Expand Down
11 changes: 11 additions & 0 deletions test/orderbook-autobridge-test.js
Expand Up @@ -6,6 +6,7 @@ const _ = require('lodash');
const assert = require('assert-diff');
const Remote = require('ripple-lib').Remote;
const Currency = require('ripple-lib').Currency;
const OrderbookUtils = require('ripple-lib')._test.OrderbookUtils;
const addresses = require('./fixtures/addresses');
const fixtures = require('./fixtures/orderbook');
const IOUValue = require('ripple-lib-value').IOUValue;
Expand Down Expand Up @@ -843,4 +844,14 @@ describe('OrderBook Autobridging', function() {
});

});

it('convertOfferQualityToHexFromText', function() {
const bookDirectory =
'4627DFFCFF8B5A265EDBD8AE8C14A52325DBFEDAF4F5C32E5D06F4C3362FE1D0';
const quality = '195796912.5171664';
assert.strictEqual(
OrderbookUtils.convertOfferQualityToHexFromText(quality),
bookDirectory.slice(-16)
);
});
});

0 comments on commit 91a6413

Please sign in to comment.