Bitcoin Forum
September 13, 2025, 11:20:48 AM *
News: Latest Bitcoin Core release: 29.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: « 1 ... 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 [521] 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 ... 585 »
  Print  
Author Topic: Bitcoin puzzle transaction ~32 BTC prize to who solves it  (Read 337323 times)
kTimesG
Full Member
***
Offline Offline

Activity: 588
Merit: 199


View Profile
June 02, 2025, 08:38:58 AM
 #10401

I have tested it in  a step by step manner. On my machine everything works fine with point_search.
And moreover it is just a concept code. As almost everything that can be found in the open-source domain.
What is the purpose of your presence here?

That's pretty much how MT bugs present themselves: Heisenbugs that eventually manifest sooner or later. So your code is conceptually broken, even if it passes your tests. Also, are you aware that debugging a MT program is pretty much useless when running concurrent threads, especially if you have breakpoints that are reached one at a time? So of course everything works fine in that scenario, since debugging a concurrent function is basically identical as if running it single-threaded. Tests are not even needed to spot it as a bug. This is simple CS 101. At some point, at some time, you'll have two threads accessing the same bloom filter RAM, and the CPU cache lines will screw up the bloom filter because of R/W lack of sync.

Well, my presence here is definitely not to show off broken code to n00bz that think it actually works correctly, while calling other people that know their thing as main-branch BS-ers. See it as you wish, and take from it what you want.

Off the grid, training pigeons to broadcast signed messages.
nomachine
Full Member
***
Offline Offline

Activity: 742
Merit: 114


View Profile
June 02, 2025, 11:14:18 AM
 #10402

Guys, have you ever thought that maybe it’s not a piece-by-piece puzzle at all, but simply a quiz?
I mean, maybe the creator hid a pattern that could lead us straight to the solution. Has this idea been discussed already?
Could you give us some hints, please @saatoshi_rising?
We would really appreciate it!

Whoever came up with this Puzzle knows exactly what he's doing.

I use a trial-and-error method a problem-solving approach where you systematically try different options or solutions until you find one that works or achieves the desired result.

This is like the movie Groundhog Day, about a man reliving the same day over and over again.

All puzzles are created with one or similar random, seed - known to the creator.  The puzzle creator tattooed it on their upper arm.
And there is no pattern. It’s not a timestamp. It can’t be reproduced by going back in time.

I think it's obvious that he has his own custom deterministic wallet with errors = ZERO

There is no limit and way someone can search for a puzzle. It's like art. Mostly worthless art collection.

BTC: bc1qdwnxr7s08xwelpjy3cc52rrxg63xsmagv50fa8
Akito S. M. Hosana
Jr. Member
*
Offline Offline

Activity: 392
Merit: 8


View Profile
June 02, 2025, 11:32:22 AM
 #10403

This is like the movie Groundhog Day, about a man reliving the same day over and over again.

This is absolutely true. It's just that I'm not getting smarter and smarter like the character from the movie. Here  is always a groundhog behind the wheel driving down the cliff. Especially with AI experiments. A lost cause.  Undecided
zion3301
Newbie
*
Offline Offline

Activity: 8
Merit: 0


View Profile
June 02, 2025, 11:46:22 AM
 #10404

Guys, have you ever thought that maybe it’s not a piece-by-piece puzzle at all, but simply a quiz?
I mean, maybe the creator hid a pattern that could lead us straight to the solution. Has this idea been discussed already?
Could you give us some hints, please @saatoshi_rising?
We would really appreciate it!

Whoever came up with this Puzzle knows exactly what he's doing.

I use a trial-and-error method a problem-solving approach where you systematically try different options or solutions until you find one that works or achieves the desired result.

This is like the movie Groundhog Day, about a man reliving the same day over and over again.

All puzzles are created with one or similar random, seed - known to the creator.  The puzzle creator tattooed it on their upper arm.
And there is no pattern. It’s not a timestamp. It can’t be reproduced by going back in time.

I think it's obvious that he has his own custom deterministic wallet with errors = ZERO

There is no limit and way someone can search for a puzzle. It's like art. Mostly worthless art collection.


Thats true. The creator know 100% what he was doing. He constructed the a perfectly ordered transaction after he created consecutive keys and masked them. He also remembered the private keys after two years. He almost forgot about the puzzle and then moved funds from 162-255 to the lower ones.
if he used a seed-approach which contains methods like sha2, then there is truely no pattern, as the creator stated.
But in my opinion, if he used a seed approach then the seed is anywhere public or accessable.
I dont think its truely random, because of the fact, that the creator remembered the private keys after 2 years
nomachine
Full Member
***
Offline Offline

Activity: 742
Merit: 114


View Profile
June 02, 2025, 12:06:08 PM
 #10405

if he used a seed-approach which contains methods like sha2, then there is truely no pattern, as the creator stated.
But in my opinion, if he used a seed approach then the seed is anywhere public or accessable.
I dont think its truely random, because of the fact, that the creator remembered the private keys after 2 years


Here is example:

Code:
import random
import hashlib
import base58

for puzzle in range(1, 160):
      lower = 2 ** (puzzle - 1)
      upper = (2 ** puzzle) - 1
      seed = "SatoshiNakamotoPuzzle" + str(puzzle)
      random.seed(seed)
      dec = random.randint(lower, upper)
      private_key_hex = "%064x" %  dec
      private_key_bytes = bytes.fromhex(private_key_hex)
      extended_key = b'\x80' + private_key_bytes
      extended_key += b'\x01'
      checksum = hashlib.sha256(hashlib.sha256(extended_key).digest()).digest()[:4]
      wif_bytes = extended_key + checksum
      wif_compressed = base58.b58encode(wif_bytes).decode()
      print(f"Puzzle = {puzzle} seed = {seed} wif = {wif_compressed}")


Quote
Puzzle = 60 seed = SatoshiNakamotoPuzzle60 wif = KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYkwi7gQXBe3k1QZLZ3Z
Puzzle = 61 seed = SatoshiNakamotoPuzzle61 wif = KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYn9rYCpH1xFmXKYze83
Puzzle = 62 seed = SatoshiNakamotoPuzzle62 wif = KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYnqQxQ9uyUTp8A7vUwi
Puzzle = 63 seed = SatoshiNakamotoPuzzle63 wif = KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYstQ4L2v4VZxu6s83mL
Puzzle = 64 seed = SatoshiNakamotoPuzzle64 wif = KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qZ6CF5Nc1QqBfAA1Ynme
Puzzle = 65 seed = SatoshiNakamotoPuzzle65 wif = KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qZCe9JmRWhdKweDYrcZo
Puzzle = 66 seed = SatoshiNakamotoPuzzle66 wif = KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qZWCKpZnZsCqVzc1f9vt
Puzzle = 67 seed = SatoshiNakamotoPuzzle67 wif = KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qbeiYkkDLY2iKmA6JS3q
Puzzle = 68 seed = SatoshiNakamotoPuzzle68 wif = KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qcopt3giY39KjX9pfekV
Puzzle = 69 seed = SatoshiNakamotoPuzzle69 wif = KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qkTtFZibZ9tNE96yFsjS
Puzzle = 70 seed = SatoshiNakamotoPuzzle70 wif = KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qqDJuNu7s3FZKtsk9Pn7
Puzzle = 71 seed = SatoshiNakamotoPuzzle71 wif = KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3rBGXpLd8yP9kGu7rqRvw


You don’t need anything else, not even a deterministic wallet.
Just a Google Doc to save the code, and you’ll have all the WIFs.

BTC: bc1qdwnxr7s08xwelpjy3cc52rrxg63xsmagv50fa8
zion3301
Newbie
*
Offline Offline

Activity: 8
Merit: 0


View Profile
June 02, 2025, 12:14:50 PM
 #10406

if he used a seed-approach which contains methods like sha2, then there is truely no pattern, as the creator stated.
But in my opinion, if he used a seed approach then the seed is anywhere public or accessable.
I dont think its truely random, because of the fact, that the creator remembered the private keys after 2 years


Here is example:

Code:
import random
import hashlib
import base58

for puzzle in range(1, 160):
      lower = 2 ** (puzzle - 1)
      upper = (2 ** puzzle) - 1
      seed = "SatoshiNakamotoPuzzle" + str(puzzle)
      random.seed(seed)
      dec = random.randint(lower, upper)
      private_key_hex = "%064x" %  dec
      private_key_bytes = bytes.fromhex(private_key_hex)
      extended_key = b'\x80' + private_key_bytes
      extended_key += b'\x01'
      checksum = hashlib.sha256(hashlib.sha256(extended_key).digest()).digest()[:4]
      wif_bytes = extended_key + checksum
      wif_compressed = base58.b58encode(wif_bytes).decode()
      print(f"Puzzle = {puzzle} seed = {seed} wif = {wif_compressed}")

You don’t need anything else, not even a deterministic wallet.
Just a Google Doc to save the code, and you’ll have all the WIFs.

yes thats a kind of determinsitic wallet. you dont even need that line: dec = random.randint(lower, upper)
you can also take the sha256 output of the seed.
so there are many types of custom deterministic wallets and maaaany possible seed.
also the seed itsself dont have to be ascii compatible (human readable). we can input any kind of data om the sha256 methods in hex format
Akito S. M. Hosana
Jr. Member
*
Offline Offline

Activity: 392
Merit: 8


View Profile
June 02, 2025, 12:49:26 PM
 #10407

Just a Google Doc to save the code, and you’ll have all the WIFs.

Do you think the code is this simple? With a random seed in a document on Google Drive or ?  Tongue
AlexanderCurl
Jr. Member
*
Offline Offline

Activity: 43
Merit: 193


View Profile WWW
June 02, 2025, 12:50:26 PM
Last edit: June 03, 2025, 08:37:29 PM by AlexanderCurl
 #10408

I have tested it in  a step by step manner. On my machine everything works fine with point_search.
And moreover it is just a concept code. As almost everything that can be found in the open-source domain.
What is the purpose of your presence here?

That's pretty much how MT bugs present themselves: Heisenbugs that eventually manifest sooner or later. So your code is conceptually broken, even if it passes your tests. Also, are you aware that debugging a MT program is pretty much useless when running concurrent threads, especially if you have breakpoints that are reached one at a time? So of course everything works fine in that scenario, since debugging a concurrent function is basically identical as if running it single-threaded. Tests are not even needed to spot it as a bug. This is simple CS 101. At some point, at some time, you'll have two threads accessing the same bloom filter RAM, and the CPU cache lines will screw up the bloom filter because of R/W lack of sync.

Well, my presence here is definitely not to show off broken code to n00bz that think it actually works correctly, while calling other people that know their thing as main-branch BS-ers. See it as you wish, and take from it what you want.

Okay. Will break it down to you.
Tests for bloomfilter creation were made in terms of final binary image being equal for one thread and multiple threads creation.
In both cases the resulting binary image was equal.

Of course thanks a lot for spending some amount of your precious time to take a peek at my code.
Probably that break_down_to_pow10 function somehow omitted your peek.
It namely breaks the number to power of ten decomposition. That way I count the index of a bloomfilter hit.
It is a lot of consecutive bloomfilter hits. If any bit was damaged due to not using mutex lock Private key recovering could not be possible.
No matter what random scalar i chose, no matter what range, works like a charm on my side.
According to you I should smash my PC to pieces for showing right result when it should not.

The whole thing is just idea sharing that came from testing even/odd concept. This is not puzzle-solver or some BSGS improved version.
If you see ways to improve that concept well be my guest.

Every coder should somehow know that checks are nessary where they are really needed.
I do not put checks where not necessary.

Even JLP did not put (scalar % N) in his ComputePublicKey class method.
And lately one starter guy have found out and now thinks he can use that to break secp256k1 curve.
Well I tried to explain. But he keeps thinking that way anyway. Grin

.
nomachine
Full Member
***
Offline Offline

Activity: 742
Merit: 114


View Profile
June 02, 2025, 12:55:14 PM
 #10409

Just a Google Doc to save the code, and you’ll have all the WIFs.

Do you think the code is this simple? With a random seed in a document on Google Drive or ?  Tongue

Why would it be more complicated? Everything can die. A USB stick, an SSD, a hard drive, even a hardware wallet. You don’t have to publish the seed publicly, but you can publicly share the code on Git, Pastebin, your email, or Google Drive. Who cares? It’ll still be there 50 years from now. You could even tattoo the seed on your lower leg so you don’t forget.  Grin

BTC: bc1qdwnxr7s08xwelpjy3cc52rrxg63xsmagv50fa8
kTimesG
Full Member
***
Offline Offline

Activity: 588
Merit: 199


View Profile
June 02, 2025, 03:49:55 PM
 #10410

Okay. Will break it down to you.
Tests for bloomfilter creation were made in terms of final binary image being equal for one thread and multiple threads creation.
In both cases the resulting binary image was equal.
.

Not sure what you're trying to explain, I didn't see a mention that the insert method is thread-safe (that would have been sufficient, but also required). It's your code after all, so I guess when you get burned, you're doing it in a very assumed way. Bugs of these type can show up after executing many trillions of cycles, or instantly, depending on the input. Having identical outputs after thousands of runs means nothing, since the core issue is unaddressed. Smiley

Off the grid, training pigeons to broadcast signed messages.
AlexanderCurl
Jr. Member
*
Offline Offline

Activity: 43
Merit: 193


View Profile WWW
June 02, 2025, 04:56:02 PM
Last edit: June 02, 2025, 06:22:30 PM by AlexanderCurl
 #10411

Okay. Will break it down to you.
Tests for bloomfilter creation were made in terms of final binary image being equal for one thread and multiple threads creation.
In both cases the resulting binary image was equal.
.

Not sure what you're trying to explain, I didn't see a mention that the insert method is thread-safe (that would have been sufficient, but also required). It's your code after all, so I guess when you get burned, you're doing it in a very assumed way. Bugs of these type can show up after executing many trillions of cycles, or instantly, depending on the input. Having identical outputs after thousands of runs means nothing, since the core issue is unaddressed. Smiley

The bloomfilter binary images are identical for one thread approach and for multiple threads.
So what is hard for you to grasp. The two have identical bits in every byte.
Mutex locks are necessary when multiple threads read, write and modify the same value. And order of their actions matters.

At the beginning all bits of a bloomfilter are off (set to 0).
The insert function sets some bit to 1 according to hash_value modulo bloomfilter size.
The race condition may happen very often. But which one thread will set the bit to 1 first does not matter.
The bit will be set to one as a result. If you are so worried about that feel free to use mutex lock on bloomfilter insert action.
It is easy to test when collision situation will happen. But I do not feel it necessary.

The whole principle of open-source code is that anyone can download and modify to the extent he desires.
Be my guest to present the improved version in your github. But I do not know what for.
It is not a puzzle-solver. RetiredC has already shown what is needed for that.
Array of GPUS and a SOTA method. Grin

Since I have doubts that someone will ever find what is needed for inverse function to SCALAR_MULTIPLICATION.


kTimesG
Full Member
***
Offline Offline

Activity: 588
Merit: 199


View Profile
June 03, 2025, 06:07:05 AM
Last edit: June 03, 2025, 06:43:08 AM by kTimesG
 #10412

Mutex locks are necessary when multiple threads read, write and modify the same value. And order of their actions matters.

At the beginning all bits of a bloomfilter are off (set to 0).
The insert function sets some bit to 1 according to hash_value modulo bloomfilter size.
The race condition may happen very often. But which one thread will set the bit to 1 first does not matter.
The bit will be set to one as a result.


Writing a value involves reading the value. You're just ignoring this, and describing a perfect fallacy. When the different bits that need to be written end up on the same cache lines (let's say, in the same 64 bytes region, and a lot of cache lines can fit in L1) of different cores, you have two different results, both wrong, and one of those will end up in your filter.

You're not seeing the issue because the allocated area is very large, so the probability of updating nearby bits is low, but a low probability just means it will eventually happen, not that it is impossible to happen.

Off the grid, training pigeons to broadcast signed messages.
AlexanderCurl
Jr. Member
*
Offline Offline

Activity: 43
Merit: 193


View Profile WWW
June 03, 2025, 07:55:11 AM
Last edit: June 03, 2025, 08:08:45 AM by AlexanderCurl
 #10413

Mutex locks are necessary when multiple threads read, write and modify the same value. And order of their actions matters.

At the beginning all bits of a bloomfilter are off (set to 0).
The insert function sets some bit to 1 according to hash_value modulo bloomfilter size.
The race condition may happen very often. But which one thread will set the bit to 1 first does not matter.
The bit will be set to one as a result.


I have tested it up to 67 bits. Not all possibilities but many for each range from 40 bits up to 67 bits. Max 2^32 bloomfilter size.
Writing a value involves reading the value. You're just ignoring this, and describing a perfect fallacy. When the different bits that need to be written end up on the same cache lines (let's say, in the same 64 bytes region, and a lot of cache lines can fit in L1) of different cores, you have two different results, both wrong, and one of those will end up in your filter.

You're not seeing the issue because the allocated area is very large, so the probability of updating nearby bits is low, but a low probability just means it will eventually happen, not that it is impossible to happen.

It is easy to check when two or more threads try to access the same byte/bit to set it to 1 concurrently.
The first one I already did. Comparing the resulting binary images to be equal.

Since each thread is just a sequence of instructions. We can log each step of its insertion way and compare the results afterwards.
To be near or exact, at which step, in what quantity.
No need for debugger.

For classic BSGS it is much easier since the babyTable is just a sequence from 1 to some power of two value.
And I guess for home PC 2^40 or lower is the limit and that is with 256G RAM.

What I see good in this is that at least now kTimesG started to write answers as the sane man and not some perverse nutcase.
kTimesG
Full Member
***
Offline Offline

Activity: 588
Merit: 199


View Profile
June 03, 2025, 09:19:06 AM
 #10414

Writing a value involves reading the value.
Since each thread is just a sequence of instructions. We can log each step of its insertion way and compare the results afterwards.

Yeah, but those instructions run in parallel, hence it's guaranteed that, without an access sync, at some point, a r/w race condition will occur. You should know best what'ya doin', so I won't insist.
Or are you saying this can never happen:

Code:
X = 0

Cycle T0       T1
0     read X   read X      // T0: is X 0 or 32? T1: is X 0 or 8?
1     set x[3] set X[5]    // T0: is X 8 or 40? T1: is X 32 or 40?
2     write X  write X     // what X is final? what about cache lines refresh?
3     X = ????????         // one of 8, 32, or 40

Off the grid, training pigeons to broadcast signed messages.
AlexanderCurl
Jr. Member
*
Offline Offline

Activity: 43
Merit: 193


View Profile WWW
June 03, 2025, 12:24:23 PM
Last edit: June 03, 2025, 08:40:04 PM by AlexanderCurl
 #10415

Writing a value involves reading the value.
Since each thread is just a sequence of instructions. We can log each step of its insertion way and compare the results afterwards.

Yeah, but those instructions run in parallel, hence it's guaranteed that, without an access sync, at some point, a r/w race condition will occur. You should know best what'ya doin', so I won't insist.
Or are you saying this can never happen:

Code:
X = 0

Cycle T0       T1
0     read X   read X      // T0: is X 0 or 32? T1: is X 0 or 8?
1     set x[3] set X[5]    // T0: is X 8 or 40? T1: is X 32 or 40?
2     write X  write X     // what X is final? what about cache lines refresh?
3     X = ????????         // one of 8, 32, or 40


It can happen. But in practice I have everything working fine.
Bloomfilters due to their multiple use of hash functions to insert one element are sure to hit the same bit in the same byte or different bits in the same byte in multi-threaded context.
But no matter how many times I tested this never caused any broken state to the resulting binary image of the bloomfilter file.
And concerning my code concept bloomfilter is used excessively to count the decimal places in order to get the index of the bloomfilter hit .
That is used later to calculate the private key.
If bloomfilter integrity was broken this would never happen.

All in all thanks for explanation. Added mutex locks to make sure everything is fine.
Nuclearkeys
Newbie
*
Offline Offline

Activity: 4
Merit: 0


View Profile
June 03, 2025, 09:55:06 PM
 #10416

3 seconds on PYTHON! PK found.

Code:
import math, time, sys, os
from gmpy2 import mpz, powmod, invert, jacobi
import xxhash  
from sortedcontainers import SortedDict

# Clear screen and initialize
os.system("cls||clear")
t = time.ctime()
sys.stdout.write(f"\033[?25l\033[01;33m[+] BSGS: {t}\n")
sys.stdout.flush()

# Elliptic Curve Parameters (secp256k1)
modulo = mpz(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F)
order = mpz(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141)
Gx = mpz(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798)
Gy = mpz(0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8)
PG = (Gx, Gy)

# Point Addition on Elliptic Curve
def add(P, Q):
    if P == (0, 0):
        return Q
    if Q == (0, 0):
        return P
    Px, Py = P
    Qx, Qy = Q
    if Px == Qx:
        if Py == Qy:
            inv_2Py = invert((Py << 1) % modulo, modulo)
            m = (3 * Px * Px * inv_2Py) % modulo
        else:
            return (0, 0)
    else:
        inv_diff_x = invert(Qx - Px, modulo)
        m = ((Qy - Py) * inv_diff_x) % modulo
    x = (m * m - Px - Qx) % modulo
    y = (m * (Px - x) - Py) % modulo
    return (x, y)

# Scalar Multiplication on Elliptic Curve
def mul(k, P=PG):
    R0, R1 = (0, 0), P
    for i in reversed(range(k.bit_length())):
        if (k >> i) & 1:
            R0, R1 = add(R0, R1), add(R1, R1)
        else:
            R1, R0 = add(R0, R1), add(R0, R0)
    return R0

# Point Subtraction
def point_subtraction(P, Q):
    Q_neg = (Q[0], (-Q[1]) % modulo)
    return add(P, Q_neg)

# Compute Y from X using curve equation
def X2Y(X, y_parity, p=modulo):
    X3_7 = (pow(X, 3, p) + 7) % p
    if jacobi(X3_7, p) != 1:
        return None
    Y = powmod(X3_7, (p + 1) >> 2, p)
    return Y if (Y & 1) == y_parity else (p - Y)

# Convert point to compressed public key
def point_to_cpub(point):
    x, y = point
    y_parity = y & 1
    prefix = '02' if y_parity == 0 else '03'
    compressed_pubkey = prefix + format(x, '064x')
    return compressed_pubkey

# Hash a compressed public key using xxhash and store only the first 8 characters
def hash_cpub(cpub):
    return xxhash.xxh64(cpub.encode()).hexdigest()[:8]

# Main Script
if __name__ == "__main__":
    # Puzzle Parameters
    puzzle = 40
    start_range, end_range = 2**(puzzle-1), (2**puzzle) - 1
    puzzle_pubkey = '03a2efa402fd5268400c77c20e574ba86409ededee7c4020e4b9f0edbee53de0d4'

    # Parse Public Key
    if len(puzzle_pubkey) != 66:
        print("[error] Public key length invalid!")
        sys.exit(1)
    prefix = puzzle_pubkey[:2]
    X = mpz(int(puzzle_pubkey[2:], 16))
    y_parity = int(prefix) - 2
    Y = X2Y(X, y_parity)
    if Y is None:
        print("[error] Invalid compressed public key!")
        sys.exit(1)
    P = (X, Y)  # Uncompressed public key

    # Precompute m and mP for BSGS
    m = int(math.floor(math.sqrt(end_range - start_range)))
    m_P = mul(m)

    # Create Baby Table with SortedDict
    print('[+] Creating babyTable...')
    baby_table = SortedDict()  
    Ps = (0, 0)  # Start with the point at infinity
    for i in range(m + 1):
        cpub = point_to_cpub(Ps)
        cpub_hash = hash_cpub(cpub)  # Use xxhash and store only 8 characters
        baby_table[cpub_hash] = i  # Store the hash as the key and index as the value
        Ps = add(Ps, PG)  # Incrementally add PG

    # BSGS Search
    print('[+] BSGS Search in progress')
    S = point_subtraction(P, mul(start_range))
    step = 0
    st = time.time()
    while step < (end_range - start_range):
        cpub = point_to_cpub(S)
        cpub_hash = hash_cpub(cpub)  # Hash the current compressed public key
        # Check if the hash exists in the baby_table
        if cpub_hash in baby_table:
            b = baby_table[cpub_hash]
            k = start_range + step + b
            if point_to_cpub(mul(k)) == puzzle_pubkey:
                print(f'[+] m={m} step={step} b={b}')
                print(f'[+] Key found: {k}')
                print("[+] Time Spent : {0:.2f} seconds".format(time.time() - st))
                sys.exit()
        S = point_subtraction(S, m_P)
        step += m

    print('[+] Key not found')
    print("[+] Time Spent : {0:.2f} seconds".format(time.time() - st))


puzzle 40
  • BSGS: Thu Feb 20 21:49:30 2025
  • Creating babyTable...
  • BSGS Search in progress
  • m=741455 step=453895024440 b=574622
  • Key found: 1003651412950
  • Time Spent : 2.90 seconds


puzzle 50
  • BSGS: Thu Feb 20 22:13:12 2025
  • Creating babyTable...
  • BSGS Search in progress
  • m=23726566 step=48190529944714 b=12801738
  • Key found: 611140496167764
  • Time Spent : 12.71 seconds

This is the result... on a single core Grin

P.S. For puzzles above 50, you'll need a Bloom Filter



Who wrote this code?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Share your donation address I can see light at the end of a tunnel.
cctv5go
Newbie
*
Offline Offline

Activity: 48
Merit: 0


View Profile
June 04, 2025, 12:05:25 AM
 #10417

Does anyone know who the author of the puzzle is?JPL?…
Frequence
Jr. Member
*
Offline Offline

Activity: 35
Merit: 2


View Profile
June 04, 2025, 12:35:12 AM
 #10418

Does anyone know who the author of the puzzle is?JPL?…

Here is the creator :
https://bitcointalk.org/index.php?action=profile;u=991321
Frequence
Jr. Member
*
Offline Offline

Activity: 35
Merit: 2


View Profile
June 04, 2025, 12:49:30 AM
Merited by bitstonps (1)
 #10419

3 seconds on PYTHON! PK found.

Code:
import math, time, sys, os
from gmpy2 import mpz, powmod, invert, jacobi
import xxhash  
from sortedcontainers import SortedDict

# Clear screen and initialize
os.system("cls||clear")
t = time.ctime()
sys.stdout.write(f"\033[?25l\033[01;33m[+] BSGS: {t}\n")
sys.stdout.flush()

# Elliptic Curve Parameters (secp256k1)
modulo = mpz(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F)
order = mpz(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141)
Gx = mpz(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798)
Gy = mpz(0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8)
PG = (Gx, Gy)

# Point Addition on Elliptic Curve
def add(P, Q):
    if P == (0, 0):
        return Q
    if Q == (0, 0):
        return P
    Px, Py = P
    Qx, Qy = Q
    if Px == Qx:
        if Py == Qy:
            inv_2Py = invert((Py << 1) % modulo, modulo)
            m = (3 * Px * Px * inv_2Py) % modulo
        else:
            return (0, 0)
    else:
        inv_diff_x = invert(Qx - Px, modulo)
        m = ((Qy - Py) * inv_diff_x) % modulo
    x = (m * m - Px - Qx) % modulo
    y = (m * (Px - x) - Py) % modulo
    return (x, y)

# Scalar Multiplication on Elliptic Curve
def mul(k, P=PG):
    R0, R1 = (0, 0), P
    for i in reversed(range(k.bit_length())):
        if (k >> i) & 1:
            R0, R1 = add(R0, R1), add(R1, R1)
        else:
            R1, R0 = add(R0, R1), add(R0, R0)
    return R0

# Point Subtraction
def point_subtraction(P, Q):
    Q_neg = (Q[0], (-Q[1]) % modulo)
    return add(P, Q_neg)

# Compute Y from X using curve equation
def X2Y(X, y_parity, p=modulo):
    X3_7 = (pow(X, 3, p) + 7) % p
    if jacobi(X3_7, p) != 1:
        return None
    Y = powmod(X3_7, (p + 1) >> 2, p)
    return Y if (Y & 1) == y_parity else (p - Y)

# Convert point to compressed public key
def point_to_cpub(point):
    x, y = point
    y_parity = y & 1
    prefix = '02' if y_parity == 0 else '03'
    compressed_pubkey = prefix + format(x, '064x')
    return compressed_pubkey

# Hash a compressed public key using xxhash and store only the first 8 characters
def hash_cpub(cpub):
    return xxhash.xxh64(cpub.encode()).hexdigest()[:8]

# Main Script
if __name__ == "__main__":
    # Puzzle Parameters
    puzzle = 40
    start_range, end_range = 2**(puzzle-1), (2**puzzle) - 1
    puzzle_pubkey = '03a2efa402fd5268400c77c20e574ba86409ededee7c4020e4b9f0edbee53de0d4'

    # Parse Public Key
    if len(puzzle_pubkey) != 66:
        print("[error] Public key length invalid!")
        sys.exit(1)
    prefix = puzzle_pubkey[:2]
    X = mpz(int(puzzle_pubkey[2:], 16))
    y_parity = int(prefix) - 2
    Y = X2Y(X, y_parity)
    if Y is None:
        print("[error] Invalid compressed public key!")
        sys.exit(1)
    P = (X, Y)  # Uncompressed public key

    # Precompute m and mP for BSGS
    m = int(math.floor(math.sqrt(end_range - start_range)))
    m_P = mul(m)

    # Create Baby Table with SortedDict
    print('[+] Creating babyTable...')
    baby_table = SortedDict()  
    Ps = (0, 0)  # Start with the point at infinity
    for i in range(m + 1):
        cpub = point_to_cpub(Ps)
        cpub_hash = hash_cpub(cpub)  # Use xxhash and store only 8 characters
        baby_table[cpub_hash] = i  # Store the hash as the key and index as the value
        Ps = add(Ps, PG)  # Incrementally add PG

    # BSGS Search
    print('[+] BSGS Search in progress')
    S = point_subtraction(P, mul(start_range))
    step = 0
    st = time.time()
    while step < (end_range - start_range):
        cpub = point_to_cpub(S)
        cpub_hash = hash_cpub(cpub)  # Hash the current compressed public key
        # Check if the hash exists in the baby_table
        if cpub_hash in baby_table:
            b = baby_table[cpub_hash]
            k = start_range + step + b
            if point_to_cpub(mul(k)) == puzzle_pubkey:
                print(f'[+] m={m} step={step} b={b}')
                print(f'[+] Key found: {k}')
                print("[+] Time Spent : {0:.2f} seconds".format(time.time() - st))
                sys.exit()
        S = point_subtraction(S, m_P)
        step += m

    print('[+] Key not found')
    print("[+] Time Spent : {0:.2f} seconds".format(time.time() - st))


puzzle 40
  • BSGS: Thu Feb 20 21:49:30 2025
  • Creating babyTable...
  • BSGS Search in progress
  • m=741455 step=453895024440 b=574622
  • Key found: 1003651412950
  • Time Spent : 2.90 seconds


puzzle 50
  • BSGS: Thu Feb 20 22:13:12 2025
  • Creating babyTable...
  • BSGS Search in progress
  • m=23726566 step=48190529944714 b=12801738
  • Key found: 611140496167764
  • Time Spent : 12.71 seconds

This is the result... on a single core Grin

P.S. For puzzles above 50, you'll need a Bloom Filter



Who wrote this code?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Share your donation address I can see light at the end of a tunnel.

Yes, I agree that NoMachine is great for coding, but did you know it only works if you have a public key!!? That’s clearly tied to the current puzzles.

Also, there's a better option from RC that uses GPU.

Regards.
Vilandro
Newbie
*
Offline Offline

Activity: 3
Merit: 0


View Profile
June 04, 2025, 05:03:52 AM
 #10420

Does anyone know who the author of the puzzle is?JPL?…

Adam Back
Pages: « 1 ... 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 [521] 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 ... 585 »
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!