Skip to content

Instantly share code, notes, and snippets.

@thehenster
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thehenster/9368139 to your computer and use it in GitHub Desktop.
Save thehenster/9368139 to your computer and use it in GitHub Desktop.
An example of Bitcoin's proof of work concept in Ruby
# https://en.bitcoin.it/wiki/Proof_of_work
# usage: ProofOfWork.new("Hello World!", 3).nonce_and_hash
# In this example think of the "Hello World!" as a a collection of Bitcoin transactions waiting to be verified.
# 3 is the arbitary number that makes it harder to verify the transactions. Over time 3 goes up and up and the
# difficulty is exponential.
require 'digest'
class ProofOfWork
attr :input, :accuracy
def initialize(input, accuracy=1)
@input = input
@accuracy = accuracy
end
def nonce_and_hash
hash = ""
nonce = 0
until prefix_for(hash) == target_prefix
hash = Digest::SHA256.hexdigest("#{input}#{nonce}")
nonce += 1
end
[nonce, hash]
end
private
def prefix_for(hash)
hash[0..accuracy-1]
end
def target_prefix
@_target_prefix ||= Array.new(accuracy, "0").join("")
end
end
if __FILE__ == $0
require 'minitest/autorun'
require 'minitest/unit'
require 'minitest/benchmark'
class TestProofOfWork < MiniTest::Unit::TestCase
def test_hello_world
nonce, hash = ProofOfWork.new("Hello World!", 2).nonce_and_hash
assert_equal 30, nonce
assert_equal "0063c24653b3f0a21d126fc7bb754bb70b0b97782cf989191ebc420a4dc6208f", hash
end
# sensible accuracies to attempt benchmark...
def self.bench_range
[1, 2, 3, 4, 5]
end
def test_benchmark
assert_performance_exponential 0.7 do |n|
ProofOfWork.new("Hello World!", n).nonce_and_hash
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment