Module: BTC::ProofOfWork
Overview
Proof of work is specified using several terms.
targetis big unsigned integer derived from 256-bit hash (interpreted as little-endian integer). Hash of a valid block should be below target.bitsis a 'satoshi compact' representation of a target as uint32.difficultyis a floating point multiple of the minimum difficulty. Difficulty = 2 means the block is 2x more difficult than the minimal difficulty.
Constant Summary collapse
- MAX_TARGET_MAINNET =
0x00000000ffff0000000000000000000000000000000000000000000000000000- MAX_TARGET_TESTNET =
0x00000007fff80000000000000000000000000000000000000000000000000000
Instance Method Summary collapse
-
#bits_from_difficulty(difficulty, max_target: MAX_TARGET_MAINNET) ⇒ Object
Computes bits from difficulty.
-
#bits_from_target(target) ⇒ Object
Converts 256-bit integer to 32-bit compact representation.
-
#difficulty_from_bits(bits, max_target: MAX_TARGET_MAINNET) ⇒ Object
Computes difficulty from bits.
-
#difficulty_from_target(target, max_target: MAX_TARGET_MAINNET) ⇒ Object
Compute relative difficulty from a given target.
-
#hash_from_target(target) ⇒ Object
Converts target integer to a binary 32-byte hash.
-
#target_from_bits(bits) ⇒ Object
Converts 32-bit compact representation to a 256-bit integer.
-
#target_from_difficulty(difficulty, max_target: MAX_TARGET_MAINNET) ⇒ Object
Computes target from difficulty.
-
#target_from_hash(hash) ⇒ Object
Converts 32-byte hash to target big integer (hash is treated as little-endian integer) hash256 -> bigint.
-
#work_from_hash(hash) ⇒ Object
hash256 -> bigint.
-
#work_from_target(target) ⇒ Object
Compute amount of work expressed as a target Based on
arith_uint256 GetBlockProof(const CBlockIndex& block)from Bitcoin Core bigint -> bigint.
Instance Method Details
#bits_from_difficulty(difficulty, max_target: MAX_TARGET_MAINNET) ⇒ Object
Computes bits from difficulty. Could be inaccurate since difficulty is a limited-precision floating-point number. Default max_target is for Bitcoin mainnet. float -> int32
64 65 66 |
# File 'lib/btcruby/proof_of_work.rb', line 64 def bits_from_difficulty(difficulty, max_target: MAX_TARGET_MAINNET) bits_from_target(target_from_difficulty(difficulty, max_target: max_target)) end |
#bits_from_target(target) ⇒ Object
Converts 256-bit integer to 32-bit compact representation.
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/btcruby/proof_of_work.rb', line 32 def bits_from_target(target) exponent = 3 signed = (target < 0) target = -target if signed while target > 0x7fffff target >>= 8 exponent += 1 end # The 0x00800000 bit denotes the sign. # Thus, if it is already set, divide the mantissa by 256 and increase the exponent. if (target & 0x00800000) > 0 target >>= 8 exponent += 1 end result = (exponent << 24) + target result = result | 0x00800000 if signed result end |
#difficulty_from_bits(bits, max_target: MAX_TARGET_MAINNET) ⇒ Object
Computes difficulty from bits. Default max_target is for Bitcoin mainnet. int32 -> float
71 72 73 |
# File 'lib/btcruby/proof_of_work.rb', line 71 def difficulty_from_bits(bits, max_target: MAX_TARGET_MAINNET) difficulty_from_target(target_from_bits(bits), max_target: max_target) end |
#difficulty_from_target(target, max_target: MAX_TARGET_MAINNET) ⇒ Object
Compute relative difficulty from a given target. E.g. returns 2.5 if target is 2.5 times harder to reach than the max_target. Default max_target is for Bitcoin mainnet. bigint -> float
87 88 89 |
# File 'lib/btcruby/proof_of_work.rb', line 87 def difficulty_from_target(target, max_target: MAX_TARGET_MAINNET) (max_target / target.to_f) end |
#hash_from_target(target) ⇒ Object
Converts target integer to a binary 32-byte hash. bigint -> hash256
93 94 95 96 97 98 99 100 |
# File 'lib/btcruby/proof_of_work.rb', line 93 def hash_from_target(target) bytes = [] while target > 0 bytes << (target % 256) target /= 256 end BTC::Data.data_from_bytes(bytes).ljust(32, "\x00".b) end |
#target_from_bits(bits) ⇒ Object
Converts 32-bit compact representation to a 256-bit integer. int32 -> bigint
53 54 55 56 57 58 |
# File 'lib/btcruby/proof_of_work.rb', line 53 def target_from_bits(bits) exponent = ((bits >> 24) & 0xff) mantissa = bits & 0x7fffff mantissa *= -1 if (bits & 0x800000) > 0 (mantissa * (256**(exponent-3))).to_i end |
#target_from_difficulty(difficulty, max_target: MAX_TARGET_MAINNET) ⇒ Object
Computes target from difficulty. Could be inaccurate since difficulty is a limited-precision floating-point number. Default max_target is for Bitcoin mainnet. float -> bigint
79 80 81 |
# File 'lib/btcruby/proof_of_work.rb', line 79 def target_from_difficulty(difficulty, max_target: MAX_TARGET_MAINNET) (max_target / difficulty).round.to_i end |
#target_from_hash(hash) ⇒ Object
Converts 32-byte hash to target big integer (hash is treated as little-endian integer) hash256 -> bigint
104 105 106 107 108 109 110 111 112 |
# File 'lib/btcruby/proof_of_work.rb', line 104 def target_from_hash(hash) target = 0 i = 0 hash.each_byte do |byte| target += byte * (256**i) i += 1 end target end |
#work_from_hash(hash) ⇒ Object
hash256 -> bigint
129 130 131 |
# File 'lib/btcruby/proof_of_work.rb', line 129 def work_from_hash(hash) work_from_target(target_from_hash(hash)) end |
#work_from_target(target) ⇒ Object
Compute amount of work expressed as a target
Based on arith_uint256 GetBlockProof(const CBlockIndex& block) from Bitcoin Core
bigint -> bigint
119 120 121 122 123 124 125 126 |
# File 'lib/btcruby/proof_of_work.rb', line 119 def work_from_target(target) # We need to compute 2**256 / (target+1), but we can't represent 2**256 # as it's too large for a arith_uint256. However, as 2**256 is at least as large # as target+1, it is equal to ((2**256 - target - 1) / (target+1)) + 1, # or ~target / (target+1) + 1. # In Ruby bigint is signed, so we can't use '~', but we can use 2**256 return ((2**256 - target - 1) / (target + 1)) + 1 end |