vsv68, you're absolutely right...
In this way, we would need 11 steps for the key 10111 and a sequential search is indeed faster.
However, there's a small detail that needs to be reiterated, only keys with sufficient length will benefit from using this method. Hence, I suggest ignoring the small keys, as we are focused on the search for the #66 key, right?
For example, starting from #54, no key has less than 40% of bits set to 1 or more than 60% either.
In a sequential search, how many keys do we need to test to reach the minimum key of #65, for example?
bin = 10000000000000000000000000000000000001111111111111111111111111111 hex = 1000000000FFFFFFF
268,435,455 keys were skipped just by starting the search.
Now let's move on to the second key
bin = 10000000000000000000000000000000000010111111111111111111111111111 hex = 10000000017FFFFFF
We skipped another 134,217,728 keys with just one key.
In a sequential search, we would still be on the same key.
bin = 10000000000000000000000000000000000000000000000000000000000000010 hex = 10000000000000002
For small keys, we indeed don't benefit from this method, but do we really need to?
Obviously, we can make mistakes in determining the number of bits set to 1 and bits set to 0. This is why we need to traverse these intervals faster and/or utilize the power of a GPU for parallel calculations, such as scanning 2 or 4 intervals simultaneously or subdividing an interval into smaller chunks that can be checked in parallel.
I have many ideas for improvements that can be made, but I need to proceed cautiously since I'm quite new to parallel programming. However, I already have code that doesn't involve additional iterations over the keys or calculating the powers that will be added. With each step, I'm amazed by the pattern that the numbers follow when we talk about bits.
Please don't focus on the Python code as a ready-to-use tool for searching. It serves to illustrate the idea, even if it's functional up to a certain number of bits. Focus on the patterns, and if you notice anything else, let's examine and discuss it. import math
KEY_SIZE = 5
ONES = 2
n = KEY_SIZE - 1
r = ONES - 1
combinations = math.factorial(n) // (math.factorial(r) * math.factorial(n-r))
Wow, this was exactly the code I needed to calculate the combinations, thank you!!
Another thing we can consider is that no random key will start with 1000, 2000, 3000, 4000, 5000... among other patterns, agree?
Surely, we could start from the key:
bin = 10000000000000000100000000000000000000111111111111111111111111111 hex = 10000800007ffffff
Or better approaches, the sky's the limit.
This way, we eliminate a significant portion of the total keys and one of my next steps will be a way to skip these keys as well.
Just for the purpose of illustrating a code snippet that could be used to replace the iteration over the private key and power calculations, as we know that the points to be added are decreasing powers of 2 and the increment is increasing.
KEYSIZE = 30
ONES = 16
pows = []
increment = 1
position = 16
point = g
for j in range(position, -1, -1):
for i in range(position, -1, -1):
if i == j:
# 2^i + increment
pointToAdd = pows[i + 1]
point = point + pointToAdd + increment
for k in range(i - 1, -1, -1):
# 2^k
pointToAdd = pows[k + 1]
point = point + pointToAdd
if position == 0:
position = ONES
else:
position -= 1
if increment != 3:
increment = 3
else:
# 2^i + 1
pointToAdd = pows[i + 1]
point = point + pointToAdd + 1
for k in range(i - 1, -1, -1):
# 2^k
pointToAdd = pows[k + 1]
point = point + pointToAdd