Bitcoinjs-lib: Error: RangeError: value out of range when decoding raw tx

Created on 26 Feb 2018  路  13Comments  路  Source: bitcoinjs/bitcoinjs-lib

Hi, I ran into issues when decoding some raw transactions, some will decode, some will not.

const bitcoinjs = require('bitcoinjs-lib')

const network = {
  messagePrefix: '\x18Monaize Signed Message:\n',
  bip32: {
    public: 0x0488B21E,
    private: 0x0488ADE4
  },
  pubKeyHash: 0x3c,
  scriptHash: 0x55,
  wif: 0xbc
}

let txValid = 
"0100000001605050d7b78352da4332f5f2798e33b3997a7ae296ff8369edcf1eb52c9ad4d6010000006b483045022100e950b4720dd6d4be823a02a70564a80b0174385e9c5242cb57f9ec1d6ac65ee002205b56ef3323d538b2aaa6579b8a17f3d1f5e6164e6b03873d03e608b2bdf848ba012103668e3368c9fb67d8fc808a5fe74d5a8d21b6eed726838122d5f7716fb3328998ffffffff0200e1f505000000001976a91486c7b9ada0107304932a603f19a57a4478d1a7e988ac00382e1b1f0000001976a91473122bcec852f394e51496e39fca5111c3d7ae5688ac00000000"

let txNonValid = 
"0100000001d6987930e07b72810a4be2b92f057b242e9d503452bee254e39c87e57fc3b4b6000000006b483045022100ce1ca28aa02102fce86c712a4dda983b3285cd78ece7108d4a4865cfaa4199ba022035996623faafef94da3ba4de1def041ac21950e82c9fa8d4ab32bc8f70502046012102300d29dc3ffc0e0b28abc64c04458bb57180a7c280fc65108460e16878d86c19feffffff021ab4ec6cc6b858001976a91438cbde195a5f6f6d3863e9dd33643fbf8d2d315f88acc054d228950000001976a91473122bcec852f394e51496e39fca5111c3d7ae5688acd2e8935a"

let decodedTx = bitcoinjs.Transaction.fromHex(txValid, network)
console.log(decodedTx)

let decodedTxNonValid = bitcoinjs.Transaction.fromHex(txNonValid, network)
console.log(decodedTxNonValid);

On the second tx I get this :

/home/xx/src/testbjs/node_modules/bitcoinjs-lib/src/bufferutils.js:8
  if (value > max) throw new Error('RangeError: value out of range')
                   ^

Error: RangeError: value out of range
    at verifuint (/home/xx/src/testbjs/node_modules/bitcoinjs-lib/src/bufferutils.js:8:26)
    at Object.readUInt64LE (/home/xx/src/testbjs/node_modules/bitcoinjs-lib/src/bufferutils.js:17:3)
    at readUInt64 (/home/xx/src/testbjs/node_modules/bitcoinjs-lib/src/transaction.js:69:25)
    at Function.Transaction.fromBuffer (/home/xx/src/testbjs/node_modules/bitcoinjs-lib/src/transaction.js:118:14)
    at Function.Transaction.fromHex (/home/xx/src/testbjs/node_modules/bitcoinjs-lib/src/transaction.js:141:22)
    at Object.<anonymous> (/home/xxx/src/testbjs/index.js:23:47)
    at Module._compile (module.js:643:30)
    at Object.Module._extensions..js (module.js:654:10)
    at Module.load (module.js:556:32)
    at tryModuleLoad (module.js:499:12)
how to / question / docs

Most helpful comment

You can split change if you want.

if (change > 90 * 1e6 * 1e8) {
  change1 = Math.ceil(change/2)
  change2 = change - change1
  txb.addOutput(address, change1)
  txb.addOutput(address, change2)
}

hehe

All 13 comments

@askz does Monaize match Bitcoin exactly for transaction serialization? This library isn't designed to catch-all bitcoin-derivatives.

@askz your first output has a satoshis value of over 0x001fffffffffffff which is why the check in bufferutils is mad at you.

Your output amount is within 8 bytes but it is over the check value.

@dcousens why check for that value specifically? because its the next bit mask higher than 21 million BTC?

@junderw

> (Math.pow(2, 53) - 1).toString(16)
'1fffffffffffff'

(64-bit floats lose precision after 53-bits, yay Javascript)

oh yeah! I forgot, javascript is special! :-D

Monaize is Komodo fork, that is Zcash fork, that is Bitcoin fork.. (phew)
It does handle tx serialization the same way for transparent to transparent address, which is the case here.
And I can confirm this issue happens on freshly mined block.. maybe it is the problem?

@askz I recommend you investigate why the value amount is encoded incorrectly, or, why is it higher than expected.

@askz if you resolved your issue, please post the solution here for others. If not, and you are certain the issue is the fault of bitcoinjs-lib, and not a monero related issue, then I'd be happy to re-open :+1:

Hi, Sorry for the late feedback.
It is a real issue, but with v8 engine, since we have high initial supply with our coin(s) the maximum integer isn't enough.
We fixed the issue by dividing supply in many accounts....
But the real solution would be to use something like https://github.com/peterolson/BigInteger.js I guess

Yes... unfortunately, bitcoinjs-lib has a lot of places where amount is used, you would need to modify all those areas to use Bigint style.

But I guess just keeping the rule: "Do not send more than 90 million coins to one output" is not a hard rule to follow........ lol

Yes I know @dabura667...
And yes it shouldn't be so hard ahahaah
But the fact is, when you send even 1 satoshi from an address that has >90M you still have the change at >90M :) it took me some minutes to remember it ahah.
I guess for now its not a big deal but later we'll come back

You can split change if you want.

if (change > 90 * 1e6 * 1e8) {
  change1 = Math.ceil(change/2)
  change2 = change - change1
  txb.addOutput(address, change1)
  txb.addOutput(address, change2)
}

hehe

ahahaha not that bad! thanks : )

Was this page helpful?
0 / 5 - 0 ratings

Related issues

coingeek picture coingeek  路  4Comments

prahaladbelavadi picture prahaladbelavadi  路  3Comments

thrastarson picture thrastarson  路  3Comments

yakitorifoodie picture yakitorifoodie  路  3Comments

hoshsadiq picture hoshsadiq  路  3Comments