bitcoinjs-lib
bitcoinjs-lib copied to clipboard
React Native address derivation is slow
Hello. I'm trying to generate addresses by derivation path using the code below in my React Native app, it works fine on the IOS simulator, but when I want to run the app on my device it works very slow comparing with the simulator, like 10x faster than a physical device. Anyone knows why performance so different between them and maybe it can be fixed somehow? I'm using the 5.2.0 version of the library and the react-native version is 0.63.3. Thank you in advance!
const seed = bip39.mnemonicToSeedSync("kangaroo foam chapter physical swim scheme exercise put just faint venue impulse");
const root = bitcoin.bip32.fromSeed(seed);
const branch = root.deriveHardened(0).derive(0).derive(0);
let arr = [];
for (let i = 0; i < 20; ++i) {
arr.push(getAddress(branch.derive(i)));
}
#1057
This sounds like an issue better brought up with react-native devs... "Why is it slow (in general)" might be our problem... but "Why is it 10x slower on real iOS vs. iOS emulator?" is almost definitely a react-native issue.
Just FYI, we use C++ bindings for the nodeJS environment and native JS (much slower) when bundling for browser, so maybe that has something to do with it. (I don't know how RN or the emulator works) OR it could just be you have an slow iPhone and a fast MacBook?
This sounds like an issue better brought up with react-native devs... "Why is it slow (in general)" might be our problem... but "Why is it 10x slower on real iOS vs. iOS emulator?" is almost definitely a react-native issue.
Just FYI, we use C++ bindings for the nodeJS environment and native JS (much slower) when bundling for browser, so maybe that has something to do with it. (I don't know how RN or the emulator works) OR it could just be you have an slow iPhone and a fast MacBook?
Thank you for your reply. You are right about react native, I just wanted to make sure about that, I thought it could be fixed on javascript side. I should try moving bip32 and bip39 processes to native code for each platform, seems like it will work much better.
I had the same issue in the past, but I was able to fix it by adding a sleep between each iteration.
function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function getGeneratedAddressesAsync(
pubKey: string,
path: string,
segwit: boolean,
iteration: number,
network: bitcoin.Network = bitcoin.networks.bitcoin
): Promise<string[]> {
let node: bip32.BIP32Interface;
try {
node = bip32.fromBase58(pubKey, network);
} catch (err) {
console.log(err);
}
let derivedNode = node.derivePath(path.substring(0, path.length - 1));
let addr: string[] = [];
return new Promise(async (resolve) => {
for (let i = 0; i < iteration; i++) {
let gen: string = "";
let btcNodeDerivation = derivedNode.derive(i);
if (segwit) {
let p2wpkh = bitcoin.payments.p2wpkh({
pubkey: btcNodeDerivation.publicKey,
network
});
gen = bitcoin.payments.p2sh({
redeem: p2wpkh,
network
}).address;
} else {
gen = bitcoin.payments.p2pkh({
pubkey: btcNodeDerivation.publicKey,
network
}).address;
}
addr.push(gen);
await sleep(1); // delaying is mandatory, otherwise it's blocking other processes...
}
for (let b of addr) {
console.log(`addr : ${b}`);
}
resolve(addr);
});
}
basically, adding the sleep(1)
solve the issue on my side
@olexh, I know this thread is a few months old at this point, but switching to react-native-v8
yielded a significant boost in performance for my RN projects on Android. Have you managed to find any other solution?
Try the solution with the promise timeout. It works well
I stumbled upon the same issue a while ago, and the way I solved it:
- cache and reuse
derive()
calls whenever possible - don't generate too many addresses upfront. you probably need only
gap_limit
addresses for external path and only one for internal - generate and cache addresses when user is not expected to interact with the app - for example, when user is supposed to stare at mnemonic seed and write it down on paper