Skip to content

Instantly share code, notes, and snippets.

@qbig
Created September 18, 2020 12:29
Show Gist options
  • Save qbig/4659cbde4447ab9b85e66a98274024b8 to your computer and use it in GitHub Desktop.
Save qbig/4659cbde4447ab9b85e66a98274024b8 to your computer and use it in GitHub Desktop.
Bitcoin Mining Ruby
require 'digest/sha2'
# -----------------
# Utility Functions
# -----------------
# The hash function used in mining (convert hexadecimal to binary first, then SHA256 twice)
def hash256(data)
binary = [data].pack("H*")
hash1 = Digest::SHA256.digest(binary)
hash2 = Digest::SHA256.hexdigest(hash1)
end
# Convert a number to fit inside a field that is a specific number of bytes e.g. field(1, 4) = 00000001
def field(data, size)
hex = data.to_i.to_s(16).rjust(size * 2, '0')
end
# Reverse the order of bytes (happens often when working with raw bitcoin data)
def reversebytes(data)
data.scan(/../).reverse.join
end
# ------------
# Block Header
# ------------
# Target (optional)
target = '000000000004864c000000000000000000000000000000000000000000000000'
# Block Header (Fields)
version = '1'
prevblock = '000000000002d01c1fccc21636b607dfd930d31d01c3a62104612a1719011250'
merkleroot = 'f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766'
time = '1293623863' # Unixtime (29 Dec 2010, 11:57:43)
bits = '1b04864c'
nonce = 0 # 274148111
# Block Header (Serialized)
header = reversebytes(field(version, 4)) + reversebytes(prevblock) + reversebytes(merkleroot) + reversebytes(field(time, 4)) + reversebytes(bits)
# -----
# Mine!
# -----
loop do
# hash the block header
attempt = header + reversebytes(field(nonce, 4))
result = reversebytes(hash256(attempt))
# show result
puts "#{nonce}: #{result}"
# end if we get a block hash below the target
if result.to_i(16) < target.to_i(16)
break
end
# increment the nonce and try again...
nonce += 1
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment