Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

react-native bitcoinjs install issues #976

Closed
wmpedersen opened this issue Jan 2, 2018 · 56 comments
Closed

react-native bitcoinjs install issues #976

wmpedersen opened this issue Jan 2, 2018 · 56 comments

Comments

@wmpedersen
Copy link
Contributor

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?

@dcousens
Copy link
Contributor

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

@dcousens dcousens self-assigned this Jan 17, 2018
@dcousens dcousens changed the title react-native bitcoinjs install react-native bitcoinjs install issues Jan 17, 2018
@wmpedersen
Copy link
Contributor Author

wmpedersen commented Jan 17, 2018

@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
Copy link
Contributor Author

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

@dcousens
Copy link
Contributor

dcousens commented Jan 18, 2018

@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 👍

@wmpedersen
Copy link
Contributor Author

wmpedersen commented Jan 18, 2018

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
Copy link
Contributor Author

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.

@coreyphillips
Copy link

coreyphillips commented Feb 24, 2018

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);

@dcousens
Copy link
Contributor

dcousens commented Feb 25, 2018

@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.

@coreyphillips
Copy link

coreyphillips commented Feb 25, 2018

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.

@dcousens
Copy link
Contributor

dcousens commented Feb 25, 2018

    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
Copy link
Contributor

dcousens commented Feb 25, 2018

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

@dcousens
Copy link
Contributor

dcousens commented Feb 25, 2018

@coreyphillips was the issue #559 (comment) not helpful to you?

@coreyphillips
Copy link

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

@coreyphillips
Copy link

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.

@dabura667
Copy link
Contributor

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.

@coreyphillips
Copy link

coreyphillips commented Feb 25, 2018

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.

@dcousens
Copy link
Contributor

dcousens commented Mar 21, 2018

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()?

@coreyphillips
Copy link

@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.

@dcousens
Copy link
Contributor

@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?

@dabura667
Copy link
Contributor

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

Facebook.

@coreyphillips
Copy link

@dcousens Basically what dabura667 said.

@liangfenxiaodao
Copy link

@corey-phillips the solution mentioned here works fine on simulator or debugging on device: #976 (comment), 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)')

@dcousens
Copy link
Contributor

@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.

@liangfenxiaodao
Copy link

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
Copy link

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

facebook/react-native#9711 (comment)

@zhaozhiming
Copy link

The error as follow:

The package at "node_modules/sjcl/sjcl.js" attempted to import the Node standard library module "crypto". It failed because React Native does not include the Node standard library.

I think it's the sjcl useing the node library crypto, and the sjcl was depended by react-native-randombytes

➜  react-native-bitcoinjs git:(master) ✗ yarn why sjcl
yarn why v1.5.1
[1/4] 🤔  Why do we have the module "sjcl"...?
[2/4] 🚚  Initialising dependency graph...
[3/4] 🔍  Finding dependency...
[4/4] 🚡  Calculating file sizes...
=> Found "sjcl@1.0.7"
info Reasons this module exists
   - "react-native-randombytes" depends on it
   - Hoisted from "react-native-randombytes#sjcl"
info Disk size without dependencies: "540MB"
info Disk size with unique dependencies: "540MB"
info Disk size with transitive dependencies: "540MB"
info Number of shared dependencies: 0
✨  Done in 1.87s.

My Env:

  Node: 6.9.2
  Yarn: 1.5.1
  npm: 3.10.9
  Watchman: 4.9.0
  Xcode: Xcode 9.2 Build version 9C40b
  Android Studio: 2.3 AI-162.4069837

Packages: (wanted => installed)
  expo: ^27.0.1 => 27.1.0
  react: 16.3.1 => 16.3.1
  react-native: ~0.55.2 => 0.55.4

This is the issue: mvayngrib/react-native-randombytes#10

@dcousens
Copy link
Contributor

dcousens commented Jun 15, 2018

@zhaozhiming maybe you should bump mvayngrib/react-native-randombytes#10 for answers?

As for how we could resolve this... we could optionally remove the default random-bytes RNG from our dependency tree, meaning users would always have to specify the rng in ECPair.makeRandom.

But that seems a bit overkill.
It may be a solution for react-native users though...

@zhaozhiming
Copy link

OK, Thank you.
BTW a question, the best practices of bitcoinjs-lib is to run in Node.js environment but not Browser like environment, right?

@zhaozhiming
Copy link

Could bitcoinjs-lib implement the ramdomBytes like this?

That library can use different randomBytes according with the environment, whether it’s Node.js or Browser.

@junderw
Copy link
Member

junderw commented Jun 18, 2018

Could bitcoinjs-lib implement the ramdomBytes like this?

That is reeeeally insecure.................. console.log with a warning is not sufficient. The randomness of those values should not be anywhere near an app that generates private keys.

@junderw
Copy link
Member

junderw commented Jun 18, 2018

looping 20 rounds shows that the person who made this has no understanding of how Math.random works.

@ShayanJa
Copy link

ShayanJa commented Aug 5, 2018

Do you have react-native-crypto & react-native-randombytes installed and linked?
You will need to change all import occurences of randombytes, and crypto, with their react-native equivalent.

I Followed what coreyphillips wrote above then added a few steps.
run

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

react-native link react-native-randombytes

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'))

Resolve Item In sjcl
npm install --save react-native-crypto

change in sjcl/sjcl.js where it says:

H=require("cryto") to

H=require("react-native-crypto")

Then there might be an error for asn1.js will be produced: vm cannot be found

npm install --save vm

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);

@rikardwissing
Copy link

I solved the missing buffer.reverse() simply by adding the following code to my shim.js.

if (typeof Buffer.prototype.reverse === 'undefined') {
  var bufferReverse = require('buffer-reverse');

  Buffer.prototype.reverse = function () {
    return bufferReverse(this);
  };
}

@coreyphillips
Copy link

@ShayanJa, to prevent updating or changing the sjcl/sjcl.js file, you can instead:

  1. Add "crypto" to your postinstall.
  2. Uncomment require('crypto') at the bottom of shim.js. Or add require('crypto') to the bottom of shim.js if it doesn't exist.

@coreyphillips
Copy link

Using the feedback from this thread I've created a gist that documents the setup process for getting version 4.0.1 of bitcoinjs-lib up and running in RN. Hopefully it will help to close this issue. Please let me know if there are any glaring issues or if you have any feedback in general.

@cbrwizard
Copy link

cbrwizard commented Sep 28, 2018

@coreyphillips followed the gist, receiving this error on start:

error: bundling failed: Error: While trying to resolve module `./payments` from file `/Users/cbrwizard/apps/mothership/exchange/MothershipCompanion/node_modules/bitcoinjs-lib/src/index.js`, the package `/Users/cbrwizard/apps/mothership/exchange/MothershipCompanion/node_modules/bitcoinjs-lib/src/payments/package.json` was successfully found. However, this package itself specifies a `main` module field that could not be resolved (`/Users/cbrwizard/apps/mothership/exchange/MothershipCompanion/node_modules/bitcoinjs-lib/src/payments/_testnet.js`. Indeed, none of these files exist:

Followed your suggestion in Resolve Item In bitcoinjs-lib/src/payments/package.json, got Buffer is not defined. Followed your suggestion in NOTE: (If you receive an error about "shim.js" not existing just run yarn install again):, still getting it :[

Update: looks like this happened because I used yarn. I added --yarn to postinstall and worked with https://github.com/novalabio/react-native-bitcoinjs-lib and it seems to be working now

Update 2: nope. Having issues with Error: Unable to resolve module 'vm' error now.

Update 3: running yarn add vm helped xD

@coreyphillips
Copy link

coreyphillips commented Sep 28, 2018

@cbrwizard Regarding your initial error, you'll want to make sure to apply the following step:

Resolve Item In bitcoinjs-lib/src/payments/package.json
Open package.json in .../bitcoinjs-lib/src/payments/package.json and replace "main": "_testnet.js", with the following: "main": "index.js",

For "shim.js" not existing, I would attempt to create the file manually and then re-run yarn install.

Regarding update 2 & 3, you should only need to add vm to your postinstall, but, hey, if it works... 😄

@junderw
Copy link
Member

junderw commented Oct 1, 2018

4.0.2 gets rid of the package.json btw

@cbrwizard
Copy link

cbrwizard commented Oct 1, 2018

Is there a way to automate these changes inside the node_modules btw? Because hard-coding them looks wrong and the changes get reverted back on packages installation. Or do I have to create a fork or something

@dcousens
Copy link
Contributor

dcousens commented Oct 1, 2018

@cbrwizard what changes are you referring to specifically?

@cbrwizard
Copy link

Had to switch to bitcoinjs-lib because the react native one is very outdated. Luckily, it worked after I followed https://gist.github.com/coreyphillips/f33d86f3d2307e58f0a5686e6cfc8a7e, so thanks @coreyphillips !

@dcousens I had to manually apply this change in my project's node module:

Open package.json in .../bitcoinjs-lib/src/payments/package.json and replace "main": "_testnet.js", with the following: "main": "index.js",

@junderw
Copy link
Member

junderw commented Oct 1, 2018

@cbrwizard package.json does not exist in 4.0.2

@junderw
Copy link
Member

junderw commented Oct 1, 2018

Check the folder @ 4.0.2
https://github.com/bitcoinjs/bitcoinjs-lib/tree/v4.0.2/src/payments

No package.json there at all. The error you experience should not occur.

@cbrwizard
Copy link

@junderw yup 4.0.2 works now without any manual changes in node_modules, so all good! Thank you!

@coreyphillips you might want to update the gist to reduce the number of steps with 4.0.2

@coreyphillips
Copy link

Thanks @cbrwizard. I've updated the 4.0.2 gist: https://gist.github.com/coreyphillips/928ae27ccea69cd0b494d13ad2b3f27d

I'm going to do my best to update and maintain a RN compatible repo here (https://github.com/coreyphillips/rn-bitcoinjs-lib) with setup instructions if you ever need it for reference.

@harunsmrkovic
Copy link

If you are experiencing issues with this library working fine in Simulator/Debug mode, but not working when preparing for release, you need to disable mangle from uglify.

No need to patch anything though, just add the following to your metro.config.js file:

module.exports = {
  transformer: {
    minifierConfig: {
      mangle: {
        keep_fnames: true
      }
    }
  }
}

🎉

@junderw
Copy link
Member

junderw commented Jul 25, 2019

Can anyone here check if the most recent version still has any of these issues.

We have switched to TypeScript, so some issues might just be solvable by messing with tsconfig.json???

@coreyphillips
Copy link

Versions tested:

"bitcoinjs-lib": "5.1.1",
"react-native": "0.60.4"

@junderw, the more recent versions definitely seem to have smoothed out a few of the previous issues. Using the versions listed above the minimum amount of work required to get it running in RN (as far as I can tell) is as follows: https://gist.github.com/coreyphillips/4d45160fed016417a5f583f179c2cbdb

@junderw
Copy link
Member

junderw commented Jul 25, 2019

@coreyphillips hmmm... I thought I removed all Buffer.prototype.reverse() instances...

Is that really needed?

@coreyphillips
Copy link

@junderw Awesome, you're correct, it isn't needed. I just forgot to remove the condition in shim.js that was causing a buffer-reverse error to throw. The Gist has been updated accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests