From f9bd8c3a04d098f37c07a99229e5cf965298733c Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 6 Aug 2014 13:07:16 -0700 Subject: [PATCH] paypro: try to keep everything big endian to avoid bignum bug in node. --- js/models/core/Wallet.js | 25 +++++--- test/test.PayPro.js | 123 ++++++++++++++++++++++++++++++--------- 2 files changed, 115 insertions(+), 33 deletions(-) diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index e89dc437e..15e39040a 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -979,10 +979,21 @@ Wallet.prototype.sendPaymentTx = function(ntxid, options, cb) { if (options.refund_to) { var total = txp.merchant.pr.pd.outputs.reduce(function(total, _, i) { - return total.add(bignum.fromBuffer(tx.outs[i].v, { - endian: 'little', + // XXX reverse endianness to work around bignum bug: + var txv = tx.outs[i].v; + var v = new Buffer(8); + for (var j = 0; j < 8; j++) v[j] = txv[7 - j]; + return total.add(bignum.fromBuffer(v, { + endian: 'big', size: 1 })); + + // XXX potential problem: bignum seems bugged in node - tx outputs use + // little endian, but fromBuffer(endian=little) ends up being big endian + // return total.add(bignum.fromBuffer(tx.outs[i].v, { + // endian: 'little', + // size: 1 + // })); }, bignum('0', 10)); var rpo = new PayPro(); @@ -1145,13 +1156,13 @@ Wallet.prototype.createPaymentTxSync = function(options, merchantData, unspent) outs.push({ address: addr[0].toString(), amountSatStr: bignum.fromBuffer(v, { - endian: 'little', + endian: 'big', size: 1 }).toString(10) }); merchantData.total = merchantData.total.add(bignum.fromBuffer(v, { - endian: 'little', + endian: 'big', size: 1 })); }); @@ -1280,7 +1291,7 @@ Wallet.prototype.verifyPaymentRequest = function(ntxid) { v[6] = (amount.low >> 8) & 0xff; v[7] = (amount.low >> 0) & 0xff; total = total.add(bignum.fromBuffer(v, { - endian: 'little', + endian: 'big', size: 1 })); } @@ -1299,7 +1310,7 @@ Wallet.prototype.verifyPaymentRequest = function(ntxid) { }; // Expected value - // little endian + // little endian (keep this LE to compare with tx output value) var ev = new Buffer(8); ev[0] = (amount.low >> 0) & 0xff; ev[1] = (amount.low >> 8) & 0xff; @@ -1345,7 +1356,7 @@ Wallet.prototype.verifyPaymentRequest = function(ntxid) { var ro = txp.merchant.pr.pd.outputs[i]; // Actual value - // little endian + // little endian (keep this LE to compare with the ev above) var av = new Buffer(8); av[0] = (ro.amount.low >> 0) & 0xff; av[1] = (ro.amount.low >> 8) & 0xff; diff --git a/test/test.PayPro.js b/test/test.PayPro.js index 309107a4b..e276eb079 100644 --- a/test/test.PayPro.js +++ b/test/test.PayPro.js @@ -21,6 +21,7 @@ var TransactionBuilder = bitcore.TransactionBuilder; var Transaction = bitcore.Transaction; var Address = bitcore.Address; var PayPro = bitcore.PayPro; +var bignum = bitcore.Bignum; var startServer = require('./mocks/FakePayProServer'); var server; @@ -246,15 +247,26 @@ describe('PayPro (in Wallet) model', function() { }; // little endian + // var v = new Buffer(8); + // v[0] = (amount.low >> 0) & 0xff; + // v[1] = (amount.low >> 8) & 0xff; + // v[2] = (amount.low >> 16) & 0xff; + // v[3] = (amount.low >> 24) & 0xff; + // v[4] = (amount.high >> 0) & 0xff; + // v[5] = (amount.high >> 8) & 0xff; + // v[6] = (amount.high >> 16) & 0xff; + // v[7] = (amount.high >> 24) & 0xff; + + // big endian var v = new Buffer(8); - v[0] = (amount.low >> 0) & 0xff; - v[1] = (amount.low >> 8) & 0xff; - v[2] = (amount.low >> 16) & 0xff; - v[3] = (amount.low >> 24) & 0xff; - v[4] = (amount.high >> 0) & 0xff; - v[5] = (amount.high >> 8) & 0xff; - v[6] = (amount.high >> 16) & 0xff; - v[7] = (amount.high >> 24) & 0xff; + v[0] = (amount.high >> 24) & 0xff; + v[1] = (amount.high >> 16) & 0xff; + v[2] = (amount.high >> 8) & 0xff; + v[3] = (amount.high >> 0) & 0xff; + v[4] = (amount.low >> 24) & 0xff; + v[5] = (amount.low >> 16) & 0xff; + v[6] = (amount.low >> 8) & 0xff; + v[7] = (amount.low >> 0) & 0xff; var s = script.buffer.slice(script.offset, script.limit); var net = network === 'main' ? 'livenet' : 'testnet'; @@ -265,7 +277,8 @@ describe('PayPro (in Wallet) model', function() { amountSatStr: bitcore.Bignum.fromBuffer(v, { // XXX for some reason, endian is ALWAYS 'big' // in node (in the browser it behaves correctly) - endian: 'little', + // endian: 'little', + endian: 'big', size: 1 }).toString(10) }); @@ -309,10 +322,21 @@ describe('PayPro (in Wallet) model', function() { var refund_to = w.publicKeyRing.getPubKeys(0, false, w.getMyCopayerId())[0]; var total = outputs.reduce(function(total, _, i) { - return total.add(bitcore.Bignum.fromBuffer(tx.outs[i].v, { - endian: 'little', + // XXX reverse endianness to work around bignum bug: + var txv = tx.outs[i].v; + var v = new Buffer(8); + for (var j = 0; j < 8; j++) v[j] = txv[7 - j]; + return total.add(bignum.fromBuffer(v, { + endian: 'big', size: 1 })); + + // XXX potential problem: bignum seems bugged in node - tx outputs use + // little endian, but fromBuffer(endian=little) ends up being big endian + // return total.add(bitcore.Bignum.fromBuffer(tx.outs[i].v, { + // endian: 'little', + // size: 1 + // })); }, bitcore.Bignum('0', 10)); var rpo = new PayPro(); @@ -397,10 +421,21 @@ describe('PayPro (in Wallet) model', function() { } var ackTotal = outputs.reduce(function(total, _, i) { - return total.add(bitcore.Bignum.fromBuffer(tx.outs[i].v, { - endian: 'little', + // XXX reverse endianness to work around bignum bug: + var txv = tx.outs[i].v; + var v = new Buffer(8); + for (var j = 0; j < 8; j++) v[j] = txv[7 - j]; + return total.add(bignum.fromBuffer(v, { + endian: 'big', size: 1 })); + + // XXX potential problem: bignum seems bugged in node - tx outputs use + // little endian, but fromBuffer(endian=little) ends up being big endian + // return total.add(bitcore.Bignum.fromBuffer(tx.outs[i].v, { + // endian: 'little', + // size: 1 + // })); }, bitcore.Bignum('0', 10)); ackTotal.toString(10).should.equal(total.toString(10)); @@ -491,15 +526,26 @@ describe('PayPro (in Wallet) model', function() { }; // little endian + // var v = new Buffer(8); + // v[0] = (amount.low >> 0) & 0xff; + // v[1] = (amount.low >> 8) & 0xff; + // v[2] = (amount.low >> 16) & 0xff; + // v[3] = (amount.low >> 24) & 0xff; + // v[4] = (amount.high >> 0) & 0xff; + // v[5] = (amount.high >> 8) & 0xff; + // v[6] = (amount.high >> 16) & 0xff; + // v[7] = (amount.high >> 24) & 0xff; + + // big endian var v = new Buffer(8); - v[0] = (amount.low >> 0) & 0xff; - v[1] = (amount.low >> 8) & 0xff; - v[2] = (amount.low >> 16) & 0xff; - v[3] = (amount.low >> 24) & 0xff; - v[4] = (amount.high >> 0) & 0xff; - v[5] = (amount.high >> 8) & 0xff; - v[6] = (amount.high >> 16) & 0xff; - v[7] = (amount.high >> 24) & 0xff; + v[0] = (amount.high >> 24) & 0xff; + v[1] = (amount.high >> 16) & 0xff; + v[2] = (amount.high >> 8) & 0xff; + v[3] = (amount.high >> 0) & 0xff; + v[4] = (amount.low >> 24) & 0xff; + v[5] = (amount.low >> 16) & 0xff; + v[6] = (amount.low >> 8) & 0xff; + v[7] = (amount.low >> 0) & 0xff; var s = script.buffer.slice(script.offset, script.limit); var net = network === 'main' ? 'livenet' : 'testnet'; @@ -508,7 +554,10 @@ describe('PayPro (in Wallet) model', function() { outs.push({ address: addr[0].toString(), amountSatStr: bitcore.Bignum.fromBuffer(v, { - endian: 'little', + // XXX for some reason, endian is ALWAYS 'big' + // in node (in the browser it behaves correctly) + // endian: 'little', + endian: 'big', size: 1 }).toString(10) }); @@ -552,10 +601,21 @@ describe('PayPro (in Wallet) model', function() { var refund_to = w.publicKeyRing.getPubKeys(0, false, w.getMyCopayerId())[0]; var total = outputs.reduce(function(total, _, i) { - return total.add(bitcore.Bignum.fromBuffer(tx.outs[i].v, { - endian: 'little', + // XXX reverse endianness to work around bignum bug: + var txv = tx.outs[i].v; + var v = new Buffer(8); + for (var j = 0; j < 8; j++) v[j] = txv[7 - j]; + return total.add(bignum.fromBuffer(v, { + endian: 'big', size: 1 })); + + // XXX potential problem: bignum seems bugged in node - tx outputs use + // little endian, but fromBuffer(endian=little) ends up being big endian + // return total.add(bitcore.Bignum.fromBuffer(tx.outs[i].v, { + // endian: 'little', + // size: 1 + // })); }, bitcore.Bignum('0', 10)); var rpo = new PayPro(); @@ -640,10 +700,21 @@ describe('PayPro (in Wallet) model', function() { } var ackTotal = outputs.reduce(function(total, _, i) { - return total.add(bitcore.Bignum.fromBuffer(tx.outs[i].v, { - endian: 'little', + // XXX reverse endianness to work around bignum bug: + var txv = tx.outs[i].v; + var v = new Buffer(8); + for (var j = 0; j < 8; j++) v[j] = txv[7 - j]; + return total.add(bignum.fromBuffer(v, { + endian: 'big', size: 1 })); + + // XXX potential problem: bignum seems bugged in node - tx outputs use + // little endian, but fromBuffer(endian=little) ends up being big endian + // return total.add(bitcore.Bignum.fromBuffer(tx.outs[i].v, { + // endian: 'little', + // size: 1 + // })); }, bitcore.Bignum('0', 10)); ackTotal.toString(10).should.equal(total.toString(10));