Pymmdrza / SoloMiner

SoloMiner Bitcoin Mining With Python

Home Page:https://mmdrza.com/bitcoin-mining-with-python-solo-miner/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Confirmed working?

invpe opened this issue · comments

By any chance, has this been confirmed working ?
Since this is rather impossible to succeed in mining, i wonder if the logic really works when nonce matches.

Have you been able to test drive this against a known block?

By any chance, has this been confirmed working ? Since this is rather impossible to succeed in mining, i wonder if the logic really works when nonce matches.

Have you been able to test drive this against a known block?

More Detail's

That's not what i asked about,

you see what i asked was; whether the way you're building up a block before hashing for example is correct?
There are endianess nuances to consider, i haven't seen any of these in your code.

For example : https://en.bitcoin.it/wiki/Block_hashing_algorithm

$version = littleEndian(1);
  $prevBlockHash = SwapOrder('00000000000008a3a41b85b8b29ad444def299fee21793cd8b9e567eab02cd81');
  $rootHash = SwapOrder('2b12fcf1b09288fcaff797d71e950e71ae42b91e8bdb2304758dfcffc2b620e3');
  $time = littleEndian(1305998791);
  $bits = littleEndian(440711666); 
  $nonce = littleEndian(2504433986); 

Where in your code you just concatenate things as they come

 nonce = hex(random.randint(0, 2 ** 32 - 1))[2:].zfill(8)  # nnonve   #hex(int(nonce,16)+1)[2:]
        blockheader = version + prevhash + merkle_root + nbits + ntime + nonce + \
                      '000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000'
        hash = hashlib.sha256(hashlib.sha256(binascii.unhexlify(blockheader)).digest()).digest()
        hash = binascii.hexlify(hash).decode()

Have you tested this ?

@invpe Yes, I've tested the block creation process in my code and made sure the logic I'm using works. However, it is important to pay attention to issues such as the extent and type of data that may affect the process of hashing blocks.
This detail is not explicitly considered in the code you provided. For example, in the Bitcoin block hash algorithm, data order (Endianess) must also be taken care of. You need to make sure that all the data is concatenated correctly and that there are no errors that might lead to improper hashing.
I suggest that you use a valid Bitcoin block as input and test the hashing process for your block to make sure your logic and code are correct. Also, it is better to use data type related functions like littleEndian and SwapOrder to avoid problems like sorting bytes and their order in the hashing process.

This code is a simple example of a process that creates an encrypted block for mining in Bitcoin. This code example uses two functions:

import hashlib, binascii, random


# // Function to convert an integer to little-endian hexadecimal string
def littleEndian(value):
    return value.to_bytes(4, byteorder='little').hex()


# // Function to swap byte order in a hexadecimal string
def SwapOrder(hex_string):
    bytes_swapped = bytearray.fromhex(hex_string)
    bytes_swapped.reverse()
    return bytes_swapped.hex()


# // Example usage
version = littleEndian(1)
prevBlockHash = SwapOrder('00000000000008a3a41b85b8b29ad444def299fee21793cd8b9e567eab02cd81')
rootHash = SwapOrder('2b12fcf1b09288fcaff797d71e950e71ae42b91e8bdb2304758dfcffc2b620e3')
time = littleEndian(1305998791)
bits = littleEndian(440711666)
nonce = littleEndian(2504433986)
# // Generating a random nonce as in your original code
nonce = hex(random.randint(0, 2 ** 32 - 1))[2:].zfill(8)
# // Constructing the block header
blockheader = version + prevBlockHash + rootHash + bits + time + nonce + '0000008........80020000'
# // Hashing the block header
hash = hashlib.sha256(hashlib.sha256(binascii.unhexlify(blockheader)).digest()).digest()
hash = binascii.hexlify(hash).decode()
print("Block Hash:", hash)

littleEndian: This function converts an integer to a hexadecimal string in little-endian mode. In Bitcoin, numbers must be represented in this way for various purposes such as time and nonce.
SwapOrder: This function swaps an input hexadecimal string so that the bytes are in reverse order. This work is necessary to convert the data into a suitable format for use in mining algorithms.

Then, an example of using these functions to build a sample header block is provided. This process involves creating a header block using information about Bitcoin and then encrypting it using common hash functions.

Thanks @Pymmdrza , there is a reason i am asking here - as for example the code provided from bitcoin wiki does things on big endian values, since your miner works with the solo.ckpool.org, they for example send out (as part of notify message) previous hash which is already reversed from what i understand:

7e11f0eeecfb2c4e3675001b04cfe538a17be9810002aaf30000000000000000

  1. That basically means Previous Hash obtained within the pool notify message is ready to use with your code for block header, and that's why you're not reversing any data correct?

  2. Merkle root is reversed in your code:

merkle_root = ''.join([merkle_root[i] + merkle_root[i + 1] for i in range(0, len(merkle_root), 2)][::-1])

This i guess follows the https://en.bitcoin.it/wiki/Block_hashing_algorithm wiki.

  1. Block header and the zero'es you're adding - what's the need for the ....080020000 being added to the block before hashing?

blockheader = version + prevhash + merkle_root + nbits + ntime + nonce + '000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000'

  1. Finally, the block after being hashed, according to the above wiki, it should be reversed:
  //fix the order
  $FinalHash = SwapOrder($pass2);

I don't see you reversing the final block hash, is there a reason for it?

@invpe Yes, you're correct. Since the script operates with solo.ckpool.org, where the previous hash is sent pre-reversed, there's no need for data reversal in the code.

Merkle Root: Indeed, the code reverses the Merkle root as outlined in the Bitcoin wiki.
Appending Zeroes: The addition of this string to the block before hashing is essential for creating a valid block header according to the standard. These data, including this string, are crucial for validating the block hash.
Reversing Final Hash: In the provided code, the final hash isn't reversed. While some standards or implementations might require this, it seems unnecessary here as the hash appears valid without reversal.
Regarding your request for the code snippet, here's how your code should accommodate the concerns raised: Solominer_v2.py

I got to think about it more.. so will keep this updated frequently ;-)

If the ckpool is sending prevhash ready to use, then we can agree that no more work is required on this part of header.
But let's be carefull here because bitcoin wiki provides prevhash in it's example in other format, and thats why they reverse it:

$prevBlockHash = SwapOrder('00000000000008a3a41b85b8b29ad444def299fee21793cd8b9e567eab02cd81');

Let's take this example from ckpool:

{"params":["64851638000e9d09","3bb97923247963f8d85949f611fe8070f04d709a00029b100000000000000000","01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff35037fd20c000484282666041edb85090c","0a636b706f6f6c112f736f6c6f2e636b706f6f6c2e6f72672fffffffff03e2b1f718000000001976a914c987a18977a2139835193b3df2eea097f834966888ac587182000000000016001451ed61d2f6aa260cc72cdf743e4e436a82c010270000000000000000266a24aa21a9ed08ad4fd2c3396f1f11b1c4a89636a21af80423876207a7a9556c7007a312ee9600000000",["7e729c8458ec0bb3f76a6b8ea373a96f65ddf24cb3ec8f2b0a16f951cea01897","543869510855aa6ba445eaeb542e61aacd29bae7e34b6c13db680e26a31c742d","bbe48e97aeaf3467121549408aa90c6616111df39f1d583f37188eda0014d98a","9baa7fc52f0b34690bfd2412314ab7ec54e19bf8e3558cd1acbd890d5dceeaea","31580f698953af4b047966fbd16859b25312131ad612b99de01ec8fcc9563de3","206b299871eaa89dc6126f30ac2b9ea83028f4177c286da87dc828bfad5ed9fa","4a7b0f383b32c4f5348f683f76f29256858174007e5eb31c8dfdbdd8991bb5e6","5afca7a80d165bf4eaeddf3c378904445f26c530f8e9fb75a3d6410478222a9e","4a0806f2844242c4c1f3c0e6fcf303fe3a6efb64701a69747b1a1e3109d54b86","849f661716ffaa285aacd653694d1b0443765f7dbd0f4a10e56f9da0250c0e67","ccebb0dd504da0243278f942b70b80dfe8e3fe068ed69ef2a1711c2f0b10ebdd","35c5b60e93890b11dfa48d60d3afdab679ffcc407812fab29a29c3252b3449b3"],"20000000","17034219","66262884",true],"id":null,"method":"mining.notify"}

ckpool_prevhash: 3bb97923247963f8d85949f611fe8070f04d709a00029b100000000000000000

So it looks like the prevhash from ckpool are ready to use indeed. as BITcoin wiki is Swapping them from:

00000000000008a3a41b85b8b29ad444def299fee21793cd8b9e567eab02cd81
to
81cd02ab7e569e8bcd9317e2fe99f2de44d49ab2b8851ba4a308000000000000

which looks like the the format from ckpool. 👍

Merkle root - the Bitcoin wiki reverses it - makes sense, because this is an out of SHA256. So - reverse

Appending zeroes - i don't think necessary, the padding is done by the SHA256 lib used - but this is a pure guess based on references i've seen.

Then the final hash, if all header values are in correct order at this time, we hash it and reverse as by definition:

"The output of the SHA-256 hash function itself is a sequence of bytes in big endian format as standard for hash functions (the first byte of the output is the most significant)." then if we have target in the same format, we have to reverse hash to compare properly."

So based on that, for the given two jsons from ckpool (subscribe,notify)

{"result":[[["mining.notify","718a771d"]],"dd24df6e",8],"id":1,"error":null}


{"params":["64851638000e7f59","7e11f0eeecfb2c4e3675001b04cfe538a17be9810002aaf30000000000000000","01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff350326d10c0004ced5226604e4fbc6270c","0a636b706f6f6c112f736f6c6f2e636b706f6f6c2e6f72672fffffffff038a42bf2a000000001976a914c987a18977a2139835193b3df2eea097f834966888acf354df000000000016001451ed61d2f6aa260cc72cdf743e4e436a82c010270000000000000000266a24aa21a9ed17210933e34ecc57ec05f3e19a9cf15e7ebae2907c2b2f527e9ec28e70f2048f00000000",["347d2dcc80a31e45cc4e11d4a80d06c79c70e5b76c4723ac97c655b16a915ec0","e80f454439ed8b2adb6f1b2b83b71ae202aa1a1de41f70722c4a2b3a1ad95be0","a5190b11c8ca1cb37fce03e8bf2eb0e36397cc7ee86da8808ac38088a6cd77f8","19035259d114135f4c798293f20bd58728beaa615d652b38715b563526e95bb1","e6cd833a8a89f446f1b036ae2641fadf60d13b36f5cb93edc33d3e92cb785313","3c422b7bf302d65b232a1f444782fcdebb5c81dcecc59ecd5f79e06126fffe5c","04a39a1e145bf8ae7a33fa8dddc5914d1099d28cc2929fb291d1724044dbc527","4c4ced96bbee9eaed655e9f2fd1c70b9889c88c9c0d2c13615e22c1088e0d74b","c1e0ed8b0e90a88a92aff0d99de6240b0ab687cb3dfb3885282a9742c9294f33","cbb4c04632c16e12beaef67b87858f0eae9d569266add284b728b8306e9873ff","6053a6b64785d7c7a67b535f73b6a7ed67914d9408f3dc4eeed92c241b00ab4f","037f4f4bc258ee4bb84b33d92bb33cb2ef9d56721ac508e3d75d12659f5b83d6"],"20000000","17034219","6622d5ce",false],"id":null,"method":"mining.notify"}

The output i am getting:

Coinbase1           : 01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff350326d10c0004ced5226604e4fbc6270c
Coinbase2           : 0a636b706f6f6c112f736f6c6f2e636b706f6f6c2e6f72672fffffffff038a42bf2a000000001976a914c987a18977a2139835193b3df2eea097f834966888acf354df000000000016001451ed61d2f6aa260cc72cdf743e4e436a82c010270000000000000000266a24aa21a9ed17210933e34ecc57ec05f3e19a9cf15e7ebae2907c2b2f527e9ec28e70f2048f00000000
Extranonce1         : dd24df6e
Extranonce2         : 000000004f55231b
Extranonce2 size    : 8
Merkle 0            :347d2dcc80a31e45cc4e11d4a80d06c79c70e5b76c4723ac97c655b16a915ec0
Merkle 1            :e80f454439ed8b2adb6f1b2b83b71ae202aa1a1de41f70722c4a2b3a1ad95be0
Merkle 2            :a5190b11c8ca1cb37fce03e8bf2eb0e36397cc7ee86da8808ac38088a6cd77f8
Merkle 3            :19035259d114135f4c798293f20bd58728beaa615d652b38715b563526e95bb1
Merkle 4            :e6cd833a8a89f446f1b036ae2641fadf60d13b36f5cb93edc33d3e92cb785313
Merkle 5            :3c422b7bf302d65b232a1f444782fcdebb5c81dcecc59ecd5f79e06126fffe5c
Merkle 6            :04a39a1e145bf8ae7a33fa8dddc5914d1099d28cc2929fb291d1724044dbc527
Merkle 7            :4c4ced96bbee9eaed655e9f2fd1c70b9889c88c9c0d2c13615e22c1088e0d74b
Merkle 8            :c1e0ed8b0e90a88a92aff0d99de6240b0ab687cb3dfb3885282a9742c9294f33
Merkle 9            :cbb4c04632c16e12beaef67b87858f0eae9d569266add284b728b8306e9873ff
Merkle 10            :6053a6b64785d7c7a67b535f73b6a7ed67914d9408f3dc4eeed92c241b00ab4f
Merkle 11            :037f4f4bc258ee4bb84b33d92bb33cb2ef9d56721ac508e3d75d12659f5b83d6
Version             : 536870912
Merklehash          : 6108dd0aa5203f21c0d1cbadbc84b57789fa27388ebdca1b3fdd1e5aca784fd8
ntime               : 1713558990
nbits               : 386089497
Nonce               : 0
Block prevhash      : 7e11f0eeecfb2c4e3675001b04cfe538a17be9810002aaf30000000000000000
Block Header        : 000000207e11f0eeecfb2c4e3675001b04cfe538a17be9810002aaf30000000000000000d84f78ca5a1edd3f1bcabd8e3827fa8977b584bcadcbd1c0213f20a50add0861ced522661942031700000000
Block hash(reversed): f7fcfb39428bb6f42dd1002aa6f6a4770960efa169d1d5248951780b24f9c7c4
Target(reversed)    : 0000000000000000000000000000000000000000194203000000000000000000

We also assume that these parts of block header: version nbits ntime nonce are kept in the same order.
So version,nbits,ntime come from the pool - assume just leave as is.

What do you think?

Ps. i made so many edits as i went through this, i hit a record for sure 😄