Bitcoin Forum

Bitcoin => Development & Technical Discussion => Topic started by: Sanka555 on November 23, 2021, 02:16:04 PM



Title: How to get a masterKey faster. Need Java developer advice
Post by: Sanka555 on November 23, 2021, 02:16:04 PM
String seedCode="any-word"

Quote
         byte[] seed = PBKDF2SHA512.derive(seedCode, "mnemonic", 2048, 64);

         DeterministicKey deterministicKey = HDKeyDerivation.createMasterPrivateKey(seed);
      
         DeterministicKey common = deterministicKey;
         deterministicKey = HDKeyDerivation.deriveChildKey(deterministicKey, new ChildNumber(84, true));
         deterministicKey = HDKeyDerivation.deriveChildKey(deterministicKey, new ChildNumber(0, true));
         deterministicKey = HDKeyDerivation.deriveChildKey(deterministicKey, new ChildNumber(0, true));
         deterministicKey = HDKeyDerivation.deriveChildKey(deterministicKey, new ChildNumber(0, false));

         temp = (Address.fromKey(MainNetParams.get(),
               HDKeyDerivation.deriveChildKey(deterministicKey, new ChildNumber(0, false)),
               Script.ScriptType.P2WPKH)).toString();
         outputMap.put(temp, seedCode);

Quote
      <dependency>
         <groupId>org.bitcoinj</groupId>
         <artifactId>bitcoinj-core</artifactId>
         <version>0.15.10</version>
      </dependency>

making an address to Java out of seed.
But this is very slow. It takes a very long time. Is there some way to speed up the process? Maybe other libraries or my logic is wrong?

Thanks in advance for any help.


Title: Re: How to get a masterKey faster. Need Java developer advice
Post by: BlackHatCoiner on November 23, 2021, 02:26:41 PM
Look, I don't know what are you trying to accomplish, but my suggestion is that if this is going to be used with real money, I advice you not to! Judging by the code, you are far from familiar with programming/Java and there's a high chance you make a serious mistake during either derivation of children, generation of seed, private keys etc.

This says it all:
Code:
deterministicKey = HDKeyDerivation.deriveChildKey(deterministicKey, new ChildNumber(84, true));
deterministicKey = HDKeyDerivation.deriveChildKey(deterministicKey, new ChildNumber(0, true));
deterministicKey = HDKeyDerivation.deriveChildKey(deterministicKey, new ChildNumber(0, true));
deterministicKey = HDKeyDerivation.deriveChildKey(deterministicKey, new ChildNumber(0, false));

You're setting a different value each time for the variable deterministicKey which is meaningless and slows down the process. What do you want? A p2pwkh address, AKA Segwit Native? Also, what's the type of that variable? You're using it as a parameter inside the deriveChildKey function AND as its result.

It should look like this:
address = HDKeyDerivation.deriveChildKey(deterministicKey, new ChildNumber(84, true));

Didn't it return you an error once you ran your code? Just on the second line, it would try to derive a child key from an address which is syntactically incorrect.

Edit: Read the reply below.


Title: Re: How to get a masterKey faster. Need Java developer advice
Post by: Sanka555 on November 23, 2021, 02:58:04 PM
I don’t know how it works. It won't work with real money. It's just a hobby)
I understand that a new value is assigned each time.
And that this is idiocy from the point of view of JAVA. But this code actually works. And it gives the CORRECT value of the address. Moreover, if you remove at least one of these 4 idiotic repeating lines, the meaning will be different. WRONG.  ;D


Title: Re: How to get a masterKey faster. Need Java developer advice
Post by: ymgve2 on November 23, 2021, 03:14:48 PM
Look, I don't know what are you trying to accomplish, but my suggestion is that if this is going to be used with real money, I advice you not to! Judging by the code, you are far from familiar with programming/Java and there's a high chance you make a serious mistake during either derivation of children, generation of seed, private keys etc.

This says it all:
Code:
deterministicKey = HDKeyDerivation.deriveChildKey(deterministicKey, new ChildNumber(84, true));
deterministicKey = HDKeyDerivation.deriveChildKey(deterministicKey, new ChildNumber(0, true));
deterministicKey = HDKeyDerivation.deriveChildKey(deterministicKey, new ChildNumber(0, true));
deterministicKey = HDKeyDerivation.deriveChildKey(deterministicKey, new ChildNumber(0, false));

You're setting a different value each time for the variable deterministicKey which is meaningless and slows down the process. What do you want? A p2pwkh address, AKA Segwit Native? Also, what's the type of that variable? You're using it as a parameter inside the deriveChildKey function AND as its result.

It should look like this:
address = HDKeyDerivation.deriveChildKey(deterministicKey, new ChildNumber(84, true));

Didn't it return you an error once you ran your code? Just on the second line, it would try to derive a child key from an address which is syntactically incorrect.

That original code looks correct to me - note that deterministicKey is used as input to the function too, so it's updated every time. Each function call basically adds another part of the path to the key, so the final will be 84'/0'/0'/0


Title: Re: How to get a masterKey faster. Need Java developer advice
Post by: BlackHatCoiner on November 23, 2021, 03:22:59 PM
That original code looks correct to me

My bad then! I don't know the library and it seemed wrong.


Title: Re: How to get a masterKey faster. Need Java developer advice
Post by: PawGo on November 23, 2021, 03:24:51 PM
Sanka555 uses piece of code which I posted here long time ago. Obtaining the address is correct, four repeated lines are used to create address on the specific derivation path - of course it is not parametrized (coin, account, address number, hardened or not), but idea is correct. It corresponds to path 84'/0'/0'/0
There is nothing wrong with reusing variable deterministicKey. Of course if you would like to generate x addresses, you must keep "one to last" key and then generate child based on it.

Sanka555: what exactly is slow and what does it mean 'slow'? Which speed do you expect?
Now I am guessing, I have no time now to check source code:
If you launch it only once, it is possible that during first launch you must initiate Digests (functions for hash) etc. Some of them probably are reused later.
Try to launch the same code several times, just to see if next iterations have different execution time than the first one.
Other approach would be to see what you may externalize and initialize before you calculate address.


Update:
I was right, method HDKeyDerivation.createMasterPrivateKey(seed); creates HmacSha512 digest, which may take some time. You may take a look how I calculate address in my program (and what is externalized or calculated outside).
See method check() (line 126):
https://github.com/PawelGorny/lostword/blob/master/src/main/java/com/pawelgorny/lostword/Worker.java

I really have no idea how to help you, as you create many topics about similar issues and it seems you really do not know what you do.


Title: Re: How to get a masterKey faster. Need Java developer advice
Post by: Sanka555 on November 23, 2021, 03:41:25 PM
Sanka555 uses piece of code which I posted here long time ago. Obtaining the address is correct, four repeated lines are used to create address on the specific derivation path - of course it is not parametrized (coin, account, address number, hardened or not), but idea is correct. It corresponds to path 84'/0'/0'/0
There is nothing wrong with reusing variable deterministicKey. Of course if you would like to generate x addresses, you must keep "one to last" key and then generate child based on it.

Sanka555: what exactly is slow and what does it mean 'slow'? Which speed do you expect?
Now I am guessing, I have no time now to check source code:
If you launch it only once, it is possible that during first launch you must initiate Digests (functions for hash) etc. Some of them probably are reused later.
Try to launch the same code several times, just to see if next iterations have different execution time than the first one.
Other approach would be to see what you may externalize and initialize before you calculate address.


Thanks again for your code. He really helped me out a lot.
 I get 4 different addresses from it on 4 different derivation paths. I reuse the first deterministic key every time.
Intuitively, I understood how it works))
But the maximum speed of this code is 5 per processor core per second. I would like to speed up. Once every ten)))


Title: Re: How to get a masterKey faster. Need Java developer advice
Post by: PawGo on November 23, 2021, 05:17:46 PM
Thanks again for your code. He really helped me out a lot.
 I get 4 different addresses from it on 4 different derivation paths. I reuse the first deterministic key every time.
Intuitively, I understood how it works))
But the maximum speed of this code is 5 per processor core per second. I would like to speed up. Once every ten)))

Very slow, indeed. I have just checked (curiosity...) and my code generates 2048 addresses in about 12 second using one thread (it gives around 160 per sec), one address per seed.
It counts only addresses generated from proper seed, so there was additionally checksum verification, rejection wrong seeds etc. If it would be intended to generate addresses only (without checksum tests), it would be much faster. And if you generate multiple addresses from one seed, the result should be even better.


Title: Re: How to get a masterKey faster. Need Java developer advice
Post by: bitcoinbeto on November 24, 2021, 03:41:12 AM
I've been working on this bitcoin java library recently: https://github.com/bitcoin-education/bitcoin-java

Instructions to install it on README.

Generating a master key should be fast and easy. With bitcoin-java library:

Code:
String mnemonicSeedString = MnemonicSeedGenerator.generateRandom(256).getSentence(); // 24 words mnemonic seed as String
MnemonicSeed mnemonicSeed = new MnemonicSeed(mnemonicSeedString); // as an object
ExtendedPrivateKey masterKey = mnemonicSeed.toMasterKey(password, ExtendedKeyPrefixes.MAINNET_PREFIX.getPrivatePrefix()); // masterkey
masterPrivateKey.ckd("0'/1/2'/2/1000000000", true, ExtendedKeyPrefixes.MAINNET_PREFIX.getPrivatePrefix()) //first parameter is the derivation path, choose at will. second parameter is true to derive a private extended key, false for public