Bitcoin Forum

Bitcoin => Development & Technical Discussion => Topic started by: shahzad73 on September 18, 2018, 06:17:51 PM



Title: Generating public compressed/uncompressed key from given private key in C#
Post by: shahzad73 on September 18, 2018, 06:17:51 PM
I am using C# core 2.2 for below code and i testing code on i5 7th Gen laptop

I was developing a sort of Vanity Generator that can target few characters in the begging and using C# to do so. Using nBticoin library to generate the addresses  but unfortunately it's very very slow.  Here is the code that was generating these addresses. I put comments at the beginning of code block please read those comments

I am using the nBitcoin C# library


//Declared once in global scope
byte[] tempBitcoinAddressArrayWithChecksum2 = new byte[37]


// Part 1.  This part in code converts currentAddress (which is byte array of bitcoin HEX characters) into Bitcoin WIF format       
tmpBitcoinHash256Output = sha256.ComputeHash(sha256.ComputeHash(currentAddress));
Array.Copy(currentAddress, tempBitcoinAddressArrayWithChecksum2, currentAddress.Length);
Array.Copy(tmpBitcoinHash256Output, 0, tempBitcoinAddressArrayWithChecksum2, currentAddress.Length, 4);    //add checksome at end of bitcoin

// Part 2. Create nBitcoin Bitcoin Secret object
BitcoinSecret secretKey = new BitcoinSecret(Base58.Encode(tempBitcoinAddressArrayWithChecksum2));


// Part 3. finally get the compressed and uncompressed public keys
string unCompressedBitcoinAddress = secretKey.PubKey.GetAddress(Network.Main).ToString()
string compressedBitcoinAddress = secretKey.PubKey.Compress().GetAddress(Network.Main).ToString()



I collected statistics for every 5000 random addresses and found following times

Average time took every 5000 addresses processed   =  6.3 seconds
Part 1 of above code took average 0.02 seconds for every 5000 addresses
Part 2 of above code took average 0.3 seconds for every 5000 addresses mainly because of base58 conversion
Part 3 of above code took average 5.5 - 6 seconds for every 5000 addresses

in average for every 5000 addresses processed this is taking 6 - 6.5 seconds   which is way way too slow for me to generate even 3 or 4 character vanity addresses


Now i am looking for following 2 solutions that may help me speed up the process

1. Fast C# Base58 conversion        at the moment this is taking 0.3 seconds       this is second priority i tried many solutions from web nothing works

2. Most important eliminate nBitcoin's BitcoinSecret  object creation from Part 2 and use that WIF string to produce compressed and uncompressed keys directly    any reduction from 5.5 down to around 1 second will be huge boost       looking for a direct C$ code for this

Can a C++ code in C# speed up the processes ?  if yes please suggest any code and how to put it in my .NET core C# code

Also can i use GPU to speed up the number of keys being processed ? 

In any case i need to speed up the 5.5 second 5000 address speed


Title: Re: Generating public compressed/uncompressed key from given private key in C#
Post by: Coding Enthusiast on September 19, 2018, 04:36:13 AM
If you want a vanity address then use the project here:
Source: https://github.com/samr7/vanitygen
ANN: https://bitcointalk.org/index.php?topic=25804.0
It is fast and tested.

If you want to create your own code then I'm afraid you have to write it from scratch if you want it to be fast. NBitcoin has a lot of bottlenecks that is slowing the process down. That library was not meant to be used for speed.

I can't understand parts of your code. For instance what is currentAddress in part 1, is it public key? And why perform double sha256 on it?
Also try Buffer.BlockCopy it is slightly faster.

In your part 2 the base58 encoding is entirely unnecessary since BitcoinSecret constructor will decode it again! https://github.com/MetacoSA/NBitcoin/blob/master/NBitcoin/Base58Data.cs#L63
Create a new instance of Key and pass that in the ctor instead:
https://github.com/MetacoSA/NBitcoin/blob/d21f31311180041a15524588b443767cf95951ec/NBitcoin/Key.cs#L48-L62

Your part 3 has multiple cases where it slows down. The ECC which is unavoidable to convert private to public key (although some methods of scalar multiplications are way faster than others, I believe NBitcoin uses bouncy castle for that which will most probably use a fixed time method. This can be improved if you care to rewrite ECC but I wouldn't recommend it), then another base58 decode and check (https://github.com/MetacoSA/NBitcoin/blob/d21f31311180041a15524588b443767cf95951ec/NBitcoin/BitcoinPubKeyAddress.cs#L28) of the input which can be avoided if you code it from scratch yourself and another base58 encode which may be avoided but I am not sure, have to really check how vanity address creation works under the hood.

P.S. All the Base58 encode/decode functions are slow because they are all using BigInteger which will slow things down drastically (specifically 6 times slower based on my tests)