bitcoinjs-lib icon indicating copy to clipboard operation
bitcoinjs-lib copied to clipboard

react-native bitcoinjs install issues

Open wmpedersen opened this issue 7 years ago • 56 comments
trafficstars

I'm trying to implement bitcoinjs-lib in react-native, but I get errors when it looks for Buffer and other crypto libraries. I have used rn-nodeify as referenced in #582 and #797 and imported the shim but it's still complaining. My install process to include bitcoinjs-lib/bip39 is as follows:

npm install --save bitcoinjs-lib bip39 react-native-crypto npm install (at this point the post-install does rn-nodeify --install fs,dgram,process,path,console --hack) react-native start and react-native run-android for my emulator

react-native is still complaining about stream, and once I include stream it complains about buffer/safe-buffer/cipher-base and once I include any of those and rebuild it gives the infamous "Can't find variable Buffer"

I've read around that others have got it to work but have yet to be able to build it myself. Any pointers in the install process?

wmpedersen avatar Jan 02 '18 19:01 wmpedersen

@wmpedersen could you please post your log dump from npm install?

dcousens avatar Jan 17 '18 01:01 dcousens

@dcousens it doesn't seem like an issue with my app including bitcoinjs - there's no problem with npm install (other than the dependencies), more of how I include it in a react-native app. I've got the dependencies listed below in my app's node_modules folder, so I don't know why it's not finding them...

EDIT: I did seem to figure it out - looks like I had most of the setup correct and followed #559's

npm i
npm i -S bitcoinjs-lib asyncstorage-down assert
npm i -D rn-nodeify

//Add the following to the scripts tag in your package.json file
"postinstall": "./node_modules/.bin/rn-nodeify --install buffer,events,process,stream,util,inherits,fs,path --hack"

And can properly generate a mnemonic with bip39. More testing needs to be done to confirm other crypto libraries, but if my helper library has made it this far, it's looking good.

wmpedersen avatar Jan 17 '18 04:01 wmpedersen

weird, now it's giving me secure RNG issues...

wmpedersen avatar Jan 18 '18 02:01 wmpedersen

@wmpedersen it may seem like no one is listening, but I guarantee any information you post about the problems you're having will help someone in the future, so please post the details :+1:

dcousens avatar Jan 18 '18 03:01 dcousens

seems like it's doing the same thing but I have react-native-randombytes^3.0.0

I don't know what changed. I might just try from my test repo from the beginning again and add my code. I was messing about with things - I seem to remember import com.bitgo.randombytes.RandomBytesPackage in my android app - but for some reason it's gone now. It's good to know it was working at one point and I should be able to replicate it. I'll have to write down the steps as I go along.

wmpedersen avatar Jan 18 '18 03:01 wmpedersen

So no matter what I've done I can't seem to put it back in my working state. My project uses react-native-randombytes properly in terms of importing it into the project again, but it seems bip39 is still complaining about my RNG because it's still trying to use non-react randombytes.

wmpedersen avatar Jan 18 '18 05:01 wmpedersen

edit by @dcousens: Warning, this comment contains unsafe code, do not use for generating private keys

@wmpedersen If you're still having this issue hopefully the following will help you out. I created a repo here (https://github.com/coreyphillips/react-native-bitcoinjs-lib/blob/master/src/ecpair.js) if you would like to use it as an aid for the ecpair section below:

  • npm i -S bitcoinjs-lib react-native-randombytes buffer-reverse buffer@5
  • npm i -D rn-nodeify
  • Add the following postinstall to your script in package.json: "postinstall": "./node_modules/.bin/rn-nodeify --install buffer,stream,assert,events --hack && npm i -S buffer@5"

Resolve Item In Ecpair.js

  • Open ecpair.js in .../bitcoinjs-lib/src/ecpair.js and replace var randomBytes = require('randombytes') with the following: var randomBytes = require('react-native-randombytes')

Resolve Item in Transaction Builder

  • Open transaction_builder.js in .../bitcoinjs-lib/src/transaction_builder.js and require the following: var bufferReverse = require('buffer-reverse')

  • Locate the TransactionBuilder.prototype.addInput function in transaction_builder.js and replace txHash = Buffer.from(txHash, 'hex').reverse() with the following: txHash = bufferReverse(new Buffer(txHash, 'hex'))

  • To test if everything is working as expected place the following in render:

import "./shim";
const bitcoin = require("bitcoinjs-lib");
const keyPair = bitcoin.ECPair.makeRandom();
const address = keyPair.getAddress();
console.log(address);

coreyphillips avatar Feb 24 '18 21:02 coreyphillips

@coreyphillips phillips you understand you could pass in myRng as the options argument, { rng: myRng } instead of modifying the library?

Additionally, your RNG is initializing the mt19937 every time... what does autoSeed do? I wouldn't use the above code as it IT IS NOT CRYPTOGRAPHICALLY SAFE.

edit: mt19937 is defaulting to https://github.com/ckknight/random-js/blob/8a51f321c1fb1725a593fec59299af6ad7118631/lib/random.js#L49-L51.

That is terrible.

@coreyphillips if you have generated private keys with that code, I'd recommend sweeping them as fast as possible.

dcousens avatar Feb 25 '18 00:02 dcousens

Thanks @dcousens. I've updated the makeRandom function to reflect your input.

Regarding the myRng function, is there anything that you would suggest implementing there that would be both cryptographically secure and compatible for a React Native implementation?

Edit: I haven't generated any private keys using this method. This is just my best effort in getting a working build going for React Native.

coreyphillips avatar Feb 25 '18 00:02 coreyphillips

    var num = random.int32();
    buf.fill(num)
    return buf

int32 is not 32-bytes, its 32-bits. That is a Buffer with 32 copies of the same number...

dcousens avatar Feb 25 '18 00:02 dcousens

@coreyphillips I'd recommend you open an issue at random-bytes

dcousens avatar Feb 25 '18 00:02 dcousens

@coreyphillips was the issue https://github.com/bitcoinjs/bitcoinjs-lib/issues/559#issuecomment-205040571 not helpful to you?

dcousens avatar Feb 25 '18 00:02 dcousens

@dcousens I did see that. Unfortunately, react-native-randombytes continues to throw an error. Still more troubleshooting ahead. Almost there though :-)

coreyphillips avatar Feb 25 '18 00:02 coreyphillips

Huzzah, looks like it may have been a linking issue with react-native-randombytes. It appears to be working now.

I've updated the ecpair.js file here. The only change made to the file is the require for react-native-randombytes instead of randombytes.

coreyphillips avatar Feb 25 '18 01:02 coreyphillips

The only change made to the file is the require for react-native-randombytes instead of randombytes.

Again, you don't need to modify bitcoinjs for this. You can pass react-native-randombytes as an argument to ECPair.

dabura667 avatar Feb 25 '18 01:02 dabura667

Thanks @dabura667. Understood.

Edit: Just to clarify, while ecpair.js no longer requires any modification when using the library in RN. txHash = Buffer.from(txHash, 'hex').reverse() still fails in transaction_builder.js. To work around this I had to add and require buffer-reverse and replace txHash = Buffer.from(txHash, 'hex').reverse() with txHash = bufferReverse(new Buffer(txHash, 'hex')) Example here

This appears to be the only remaining issue encountered when using this library in RN.

coreyphillips avatar Feb 25 '18 02:02 coreyphillips

This appears to be the only remaining issue encountered when using this library in RN.

@corey-phillips what about the other reverse() calls?

tx.getId()?

dcousens avatar Mar 21 '18 04:03 dcousens

@dcousens, you are correct. The remaining .reverse() calls fail as well and would require a similar update as the example above in order to get it working in a RN project.

coreyphillips avatar Mar 23 '18 02:03 coreyphillips

@corey-phillips OK... I'm not against re-introducing buffer-reverse for the sake of RN... but, it is a bit frustrating. Why isn't RN addressing this with an up-to-date Buffer?

dcousens avatar Mar 23 '18 05:03 dcousens

Why isn't RN addressing this with an up-to-date Buffer?

Facebook.

dabura667 avatar Mar 23 '18 15:03 dabura667

@dcousens Basically what dabura667 said.

coreyphillips avatar Mar 24 '18 01:03 coreyphillips

@corey-phillips the solution mentioned here works fine on simulator or debugging on device: https://github.com/bitcoinjs/bitcoinjs-lib/issues/976#issuecomment-368261162, however, when I package an release APK file and install it on device, then I get error:

ReactNativeJS: TypeError: undefined is not a function (evaluating 'Error.captureStackTrace(this,y)')

liangfenxiaodao avatar Apr 30 '18 06:04 liangfenxiaodao

@jackylimel great to know! I wasn't aware that Error.captureStackTrace wasn't standard to JS, but V8-specific. It is used by https://github.com/dcousens/typeforce ... that will need to be fixed.

dcousens avatar Apr 30 '18 06:04 dcousens

The weird thing is. If I just call bjs.ECPair.makeRandom(), then it works fine on both debug and release mode, but if I call bjs.HDNode.fromBase58('example_xpub_key'), then it would succeed on debug mode but fails on release mode ( running as a signed apk file, even on simulator).

Could someone please help?

liangfenxiaodao avatar May 01 '18 00:05 liangfenxiaodao

I've found the problem is caused by uglifijs and will use the solution here:

https://github.com/facebook/react-native/issues/9711#issuecomment-327552716

liangfenxiaodao avatar May 01 '18 01:05 liangfenxiaodao

@jackylimel so, Error.captureStackTrace is no longer undefined?

dcousens avatar May 01 '18 01:05 dcousens

Once I apply the patches for uglifyjs, then I no longer get typeforce error...

liangfenxiaodao avatar May 01 '18 01:05 liangfenxiaodao

@jackylimel maybe it does exist in RN (via polyfill?), but was mangled. In any case, I'll leave https://github.com/dcousens/typeforce/issues/49 open

dcousens avatar May 01 '18 03:05 dcousens

hello :) what is the status of this? is this documented somewhere?

DaniGuardiola avatar May 24 '18 12:05 DaniGuardiola

Same problem here. The solution mentioned here not work for me. It make the project can't start.
Any other solution or document of this problem?

zhaozhiming avatar Jun 15 '18 06:06 zhaozhiming