lib/bitcoin.rb in bitcoin-ruby-0.0.6 vs lib/bitcoin.rb in bitcoin-ruby-0.0.7
- old
+ new
@@ -11,56 +11,24 @@
autoload :Connection, 'bitcoin/connection'
autoload :Protocol, 'bitcoin/protocol'
autoload :P, 'bitcoin/protocol'
autoload :Script, 'bitcoin/script'
autoload :VERSION, 'bitcoin/version'
- autoload :Storage, 'bitcoin/storage/storage'
autoload :Logger, 'bitcoin/logger'
autoload :Key, 'bitcoin/key'
- autoload :Config, 'bitcoin/config'
autoload :Builder, 'bitcoin/builder'
- autoload :Validation, 'bitcoin/validation'
- autoload :Namecoin, 'bitcoin/namecoin'
+ autoload :Dogecoin, 'bitcoin/dogecoin'
autoload :Litecoin, 'bitcoin/litecoin'
- module Network
- autoload :ConnectionHandler, 'bitcoin/network/connection_handler'
- autoload :CommandHandler, 'bitcoin/network/command_handler'
- autoload :CommandClient, 'bitcoin/network/command_client'
- autoload :Node, 'bitcoin/network/node'
- end
+ autoload :ContractHash, 'bitcoin/contracthash'
- module Wallet
- autoload :KeyGenerator, 'bitcoin/wallet/keygenerator'
- autoload :SimpleKeyStore, 'bitcoin/wallet/keystore'
- autoload :DeterministicKeyStore, 'bitcoin/wallet/keystore'
- autoload :SimpleCoinSelector, 'bitcoin/wallet/coinselector'
- autoload :Wallet, 'bitcoin/wallet/wallet'
- autoload :TxDP, 'bitcoin/wallet/txdp'
+ module Trezor
+ autoload :Mnemonic, 'bitcoin/trezor/mnemonic'
end
- module Gui
- autoload :Gui, 'bitcoin/gui/gui'
- autoload :Connection, 'bitcoin/gui/connection'
- end
- def self.require_dependency name, opts = {}
- begin
- require name.to_s
- rescue LoadError
- return false if name.to_s == "log4r"
- print "Cannot load #{opts[:exit] == false ? 'optional' : 'required'} dependency '#{name}'"
- (opts[:gem] == false) ? puts("") :
- puts(" - install with `gem install #{opts[:gem] || name}`")
- puts opts[:message] if opts[:message]
- exit 1 unless opts[:exit] == false
- return false
- end
- true
- end
-
module Util
def address_version; Bitcoin.network[:address_version]; end
def p2sh_version; Bitcoin.network[:p2sh_version]; end
@@ -78,11 +46,11 @@
# verify base58 checksum for given +base58+ data.
def base58_checksum?(base58)
hex = decode_base58(base58) rescue nil
return false unless hex
- Bitcoin.checksum( hex[0...42] ) == hex[-8..-1]
+ checksum( hex[0...42] ) == hex[-8..-1]
end
alias :address_checksum? :base58_checksum?
# check if given +address+ is valid.
# this means having a correct version byte, length and checksum.
@@ -91,10 +59,18 @@
return false unless hex && hex.bytesize == 50
return false unless [address_version, p2sh_version].include?(hex[0...2])
address_checksum?(address)
end
+ # check if given +pubkey+ is valid.
+ def valid_pubkey?(pubkey)
+ ::OpenSSL::PKey::EC::Point.from_hex(bitcoin_elliptic_curve.group, pubkey)
+ true
+ rescue OpenSSL::PKey::EC::Point::Error
+ false
+ end
+
# get hash160 for given +address+. returns nil if address is invalid.
def hash160_from_address(address)
return nil unless valid_address?(address)
decode_base58(address)[2...42]
end
@@ -157,11 +133,10 @@
def encode_base58(hex)
leading_zero_bytes = (hex.match(/^([0]+)/) ? $1 : '').size / 2
("1"*leading_zero_bytes) + int_to_base58( hex.to_i(16) )
end
-
def decode_base58(base58_val)
s = base58_to_int(base58_val).to_s(16); s = (s.bytesize.odd? ? '0'+s : s)
s = '' if s == '00'
leading_zero_bytes = (base58_val.match(/^([1]+)/) ? $1 : '').size
s = ("00"*leading_zero_bytes) + s if leading_zero_bytes > 0
@@ -169,15 +144,29 @@
end
alias_method :base58_to_hex, :decode_base58
# target compact bits (int) to bignum hex
def decode_compact_bits(bits)
- bytes = Array.new(size=((bits >> 24) & 255), 0)
- bytes[0] = (bits >> 16) & 255 if size >= 1
- bytes[1] = (bits >> 8) & 255 if size >= 2
- bytes[2] = (bits ) & 255 if size >= 3
- bytes.pack("C*").unpack("H*")[0].rjust(64, '0')
+ if Bitcoin.network_project == :dogecoin
+ bytes = Array.new(size=((bits >> 24) & 255), 0)
+ bytes[0] = (bits >> 16) & 0x7f if size >= 1
+ bytes[1] = (bits >> 8) & 255 if size >= 2
+ bytes[2] = (bits ) & 255 if size >= 3
+ target = bytes.pack("C*").unpack("H*")[0].rjust(64, '0')
+ # Bit number 24 represents the sign
+ if (bits & 0x00800000) != 0
+ "-" + target
+ else
+ target
+ end
+ else
+ bytes = Array.new(size=((bits >> 24) & 255), 0)
+ bytes[0] = (bits >> 16) & 255 if size >= 1
+ bytes[1] = (bits >> 8) & 255 if size >= 2
+ bytes[2] = (bits ) & 255 if size >= 3
+ bytes.pack("C*").unpack("H*")[0].rjust(64, '0')
+ end
end
# target bignum hex to compact bits (int)
def encode_compact_bits(target)
bytes = OpenSSL::BN.new(target, 16).to_mpi
@@ -217,11 +206,11 @@
end
def bitcoin_hash(hex)
Digest::SHA256.digest(
Digest::SHA256.digest( [hex].pack("H*").reverse )
- ).reverse.unpack("H*")[0]
+ ).reverse.bth
end
def bitcoin_byte_hash(bytes)
Digest::SHA256.digest(Digest::SHA256.digest(bytes))
end
@@ -254,48 +243,59 @@
# get merkle tree for given +tx+ list.
def hash_mrkl_tree(tx)
return [nil] if tx != tx.uniq
chunks = [ tx.dup ]
while chunks.last.size >= 2
- chunks << chunks.last.each_slice(2).map {|a, b|
- Bitcoin.bitcoin_mrkl( a, b || a ) }
+ chunks << chunks.last.each_slice(2).map {|a, b| bitcoin_mrkl( a, b || a ) }
end
chunks.flatten
end
# get merkle branch connecting given +target+ to the merkle root of +tx+ list
def hash_mrkl_branch(tx, target)
return [ nil ] if tx != tx.uniq
branch, chunks = [], [ tx.dup ]
while chunks.last.size >= 2
chunks << chunks.last.each_slice(2).map {|a, b|
- hash = Bitcoin.bitcoin_mrkl( a, b || a )
+ hash = bitcoin_mrkl( a, b || a )
next hash unless [a, b].include?(target)
branch << (a == target ? (b || a) : a)
target = hash
}
end
branch
end
# get merkle root from +branch+ and +target+.
def mrkl_branch_root(branch, target, idx)
- branch.map do |hash|
+ branch.each do |hash|
a, b = *( idx & 1 == 0 ? [target, hash] : [hash, target] )
- idx >>= 1; target = Bitcoin.bitcoin_mrkl( a, b )
- end.last
+ idx >>= 1;
+ target = bitcoin_mrkl( a, b )
+ end
+ target
end
def sign_data(key, data)
- key.dsa_sign_asn1(data)
+ sig = key.dsa_sign_asn1(data)
+ if Script.is_low_der_signature?(sig)
+ sig
+ else
+ Bitcoin::OpenSSL_EC.signature_to_low_s(sig)
+ end
end
def verify_signature(hash, signature, public_key)
key = bitcoin_elliptic_curve
key.public_key = ::OpenSSL::PKey::EC::Point.from_hex(key.group, public_key)
- key.dsa_verify_asn1(hash, signature)
- rescue OpenSSL::PKey::ECError, OpenSSL::PKey::EC::Point::Error
+ signature = Bitcoin::OpenSSL_EC.repack_der_signature(signature)
+ if signature
+ key.dsa_verify_asn1(hash, signature)
+ else
+ false
+ end
+ rescue OpenSSL::PKey::ECError, OpenSSL::PKey::EC::Point::Error, OpenSSL::BNError
false
end
def open_key(private_key, public_key=nil)
key = bitcoin_elliptic_curve
@@ -304,38 +304,35 @@
key.public_key = ::OpenSSL::PKey::EC::Point.from_hex(key.group, public_key)
key
end
def regenerate_public_key(private_key)
- Bitcoin::OpenSSL_EC.regenerate_key(private_key)[1]
+ OpenSSL_EC.regenerate_key(private_key)[1]
end
def bitcoin_signed_message_hash(message)
# TODO: this will fail horribly on messages with len > 255. It's a cheap implementation of Bitcoin's CDataStream.
data = "\x18Bitcoin Signed Message:\n" + [message.bytesize].pack("C") + message
Digest::SHA256.digest(Digest::SHA256.digest(data))
end
def sign_message(private_key_hex, public_key_hex, message)
hash = bitcoin_signed_message_hash(message)
- signature = Bitcoin::OpenSSL_EC.sign_compact(hash, private_key_hex, public_key_hex)
+ signature = OpenSSL_EC.sign_compact(hash, private_key_hex, public_key_hex)
{ 'address' => pubkey_to_address(public_key_hex), 'message' => message, 'signature' => [ signature ].pack("m0") }
end
def verify_message(address, signature, message)
- hash = bitcoin_signed_message_hash(message)
signature = signature.unpack("m0")[0] rescue nil # decode base64
- raise "invalid address" unless valid_address?(address)
- raise "malformed base64 encoding" unless signature
- raise "malformed signature" unless signature.bytesize == 65
- pubkey = Bitcoin::OpenSSL_EC.recover_compact(hash, signature)
+ return false unless valid_address?(address)
+ return false unless signature
+ return false unless signature.bytesize == 65
+ hash = bitcoin_signed_message_hash(message)
+ pubkey = OpenSSL_EC.recover_compact(hash, signature)
pubkey_to_address(pubkey) == address if pubkey
- rescue => ex
- p [ex.message, ex.backtrace]; false
end
-
# block count when the next retarget will take place.
def block_next_retarget(block_height)
(block_height + (RETARGET_INTERVAL-block_height.divmod(RETARGET_INTERVAL).last)) - 1
end
@@ -346,19 +343,51 @@
# "%.7f" % (max_target / current_target.to_f)
bits, max_body, scaland = target_nbits, Math.log(0x00ffff), Math.log(256)
"%.7f" % Math.exp(max_body - Math.log(bits&0x00ffffff) + scaland * (0x1d - ((bits&0xff000000)>>24)))
end
+ # Calculate new difficulty target. Note this takes in details of the preceeding
+ # block, not the current one.
+ #
+ # prev_height is the height of the block before the retarget occurs
+ # prev_block_time "time" field from the block before the retarget occurs
+ # prev_block_bits "bits" field from the block before the retarget occurs (target as a compact value)
+ # last_retarget_time is the "time" field from the block when a retarget last occurred
+ def block_new_target(prev_height, prev_block_time, prev_block_bits, last_retarget_time)
+ # target interval - what is the ideal interval between the blocks
+ retarget_time = Bitcoin.network[:retarget_time]
+
+ actual_time = prev_block_time - last_retarget_time
+
+ min = retarget_time / 4
+ max = retarget_time * 4
+
+ actual_time = min if actual_time < min
+ actual_time = max if actual_time > max
+
+ # It could be a bit confusing: we are adjusting difficulty of the previous block, while logically
+ # we should use difficulty of the previous retarget block
+
+ prev_target = decode_compact_bits(prev_block_bits).to_i(16)
+
+ new_target = prev_target * actual_time / retarget_time
+ if new_target < Bitcoin.decode_compact_bits(Bitcoin.network[:proof_of_work_limit]).to_i(16)
+ encode_compact_bits(new_target.to_s(16))
+ else
+ Bitcoin.network[:proof_of_work_limit]
+ end
+ end
+
# average number of hashes required to win a block with the current target. (nbits)
def block_hashes_to_win(target_nbits)
- current_target = Bitcoin.decode_compact_bits(target_nbits).to_i(16)
+ current_target = decode_compact_bits(target_nbits).to_i(16)
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff / current_target
end
# probability of a single hash solving a block with the current difficulty.
def block_probability(target_nbits)
- current_target = Bitcoin.decode_compact_bits(target_nbits).to_i(16)
+ current_target = decode_compact_bits(target_nbits).to_i(16)
"%.55f" % (current_target.to_f / 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
end
# average time to find a block in seconds with the current target. (nbits)
def block_average_hashing_time(target_nbits, hashes_per_second)
@@ -366,17 +395,17 @@
end
# average mining time (in days) using Mh/s to get btc
def block_average_mining_time(block_nbits, block_height, mega_hashes_per_second, target_btc=1.0)
seconds = block_average_hashing_time(block_nbits, mega_hashes_per_second * 1_000_000)
- reward = block_creation_reward(block_height) / Bitcoin::COIN # satoshis to btc
+ reward = block_creation_reward(block_height) / COIN # satoshis to btc
(days = seconds / 60 / 60 / 24) * (target_btc / reward)
end
# shows the total number of Bitcoins in circulation, reward era and reward in that era.
def blockchain_total_btc(height)
- reward, interval = 5000000000, 210000
+ reward, interval = Bitcoin.network[:reward_base], Bitcoin.network[:reward_halving]
total_btc = reward
reward_era, remainder = (height).divmod(interval)
reward_era.times{
total_btc += interval * reward
reward = reward / 2
@@ -384,22 +413,26 @@
total_btc += remainder * reward
[total_btc, reward_era+1, reward, height]
end
def block_creation_reward(block_height)
- 5000000000 / (2 ** (block_height / 210000.0).floor)
+ Bitcoin.network[:reward_base] / (2 ** (block_height / Bitcoin.network[:reward_halving].to_f).floor)
end
end
extend Util
module BinaryExtensions
- def hth; unpack("H*")[0]; end
- def reverse_hth; reverse.hth; end
+ # bin-to-hex
+ def bth; unpack("H*")[0]; end
+ # hex-to-bin
def htb; [self].pack("H*"); end
+
def htb_reverse; htb.reverse; end
+ def hth; unpack("H*")[0]; end
+ def reverse_hth; reverse.hth; end
end
class ::String
include Bitcoin::BinaryExtensions
end
@@ -420,15 +453,19 @@
def self.from_hex(group, hex)
new(group, BN.from_hex(hex))
end
def to_hex; to_bn.to_hex; end
def self.bn2mpi(hex) BN.from_hex(hex).to_mpi; end
+ def ec_add(point); self.class.new(group, OpenSSL::BN.from_hex(OpenSSL_EC.ec_add(self, point))); end
end
end
autoload :OpenSSL_EC, "bitcoin/ffi/openssl"
+ autoload :Secp256k1, "bitcoin/ffi/secp256k1"
+ autoload :BitcoinConsensus, "bitcoin/ffi/bitcoinconsensus"
+
@network = :bitcoin
def self.network
# Store the copy of network options so we can modify them in tests without breaking the defaults
@network_options ||= NETWORKS[@network].dup
@@ -445,15 +482,16 @@
def self.network=(name)
raise "Network descriptor '#{name}' not found." unless NETWORKS[name.to_sym]
@network_options = nil # clear cached parameters
@network = name.to_sym
@network_project = network[:project] rescue nil
- Bitcoin::Namecoin.load if namecoin?
+ Dogecoin.load if dogecoin? || dogecoin_testnet?
+ Namecoin.load if namecoin? && defined?(Namecoin)
@network
end
- [:bitcoin, :namecoin, :litecoin, :freicoin].each do |n|
+ [:bitcoin, :namecoin, :litecoin, :dogecoin, :dogecoin_testnet].each do |n|
instance_eval "def #{n}?; network_project == :#{n}; end"
end
# maximum size of a block (in bytes)
@@ -490,45 +528,48 @@
COIN = 100_000_000
MIN_FEE_MODE = [ :block, :relay, :send ]
NETWORKS = {
-
- :bitcoin => {
- :project => :bitcoin,
- :magic_head => "\xF9\xBE\xB4\xD9",
- :address_version => "00",
- :p2sh_version => "05",
- :privkey_version => "80",
- :default_port => 8333,
- :protocol_version => 70001,
- :coinbase_maturity => 100,
- :retarget_interval => 2016,
- :retarget_time => 1209600, # 2 weeks
- :target_spacing => 600, # block interval
- :max_money => 21_000_000 * COIN,
- :min_tx_fee => 10_000,
- :min_relay_tx_fee => 10_000,
- :free_tx_bytes => 1_000,
- :dust => CENT,
- :per_dust_fee => false,
- :dns_seeds => [
+ bitcoin: {
+ project: :bitcoin,
+ magic_head: "\xF9\xBE\xB4\xD9",
+ address_version: "00",
+ p2sh_version: "05",
+ privkey_version: "80",
+ extended_privkey_version: "0488ade4",
+ extended_pubkey_version: "0488b21e",
+ default_port: 8333,
+ protocol_version: 70001,
+ coinbase_maturity: 100,
+ reward_base: 50 * COIN,
+ reward_halving: 210_000,
+ retarget_interval: 2016,
+ retarget_time: 1209600, # 2 weeks
+ target_spacing: 600, # block interval
+ max_money: 21_000_000 * COIN,
+ min_tx_fee: 10_000,
+ min_relay_tx_fee: 10_000,
+ free_tx_bytes: 1_000,
+ dust: CENT,
+ per_dust_fee: false,
+ dns_seeds: [
"seed.bitcoin.sipa.be",
"dnsseed.bluematt.me",
"dnsseed.bitcoin.dashjr.org",
"bitseed.xf2.org",
],
- :genesis_hash => "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
- :proof_of_work_limit => 0x1d00ffff,
- :alert_pubkeys => ["04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284"],
- :known_nodes => [
+ genesis_hash: "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
+ proof_of_work_limit: 0x1d00ffff,
+ alert_pubkeys: ["04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284"],
+ known_nodes: [
'relay.eligius.st',
'mining.bitcoin.cz',
'blockchain.info',
'blockexplorer.com',
],
- :checkpoints => {
+ checkpoints: {
11111 => "0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d",
33333 => "000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6",
74000 => "0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20",
105000 => "00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97",
134444 => "00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe",
@@ -539,129 +580,85 @@
225430 => "00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932",
290000 => "0000000000000000fa0b2badd05db0178623ebf8dd081fe7eb874c26e27d0b3b",
300000 => "000000000000000082ccf8f1557c5d40b21edabb18d2d691cfbf87118bac7254",
305000 => "0000000000000000142bb90561e1a907d500bf534a6727a63a92af5b6abc6160",
}
- },
+ }
+ }
- :regtest => {
- :project => :bitcoin,
- :magic_head => "\xFA\xBF\xB5\xDA",
- :address_version => "6f",
- :p2sh_version => "c4",
- :privkey_version => "ef",
- :default_port => 18444,
- :max_money => 21_000_000 * COIN,
- :dns_seeds => [ ],
- :genesis_hash => "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206",
- :proof_of_work_limit => (1<<255) - 1,
- :alert_pubkeys => ["04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a"],
- :known_nodes => [],
- :checkpoints => {},
- :coinbase_maturity => 100,
- :retarget_interval => 2016,
- :retarget_time => 1209600, # 2 weeks
- :target_spacing => 600, # block interval
- :max_money => 21_000_000 * COIN,
- :min_tx_fee => 10_000,
- :min_relay_tx_fee => 10_000,
- :free_tx_bytes => 1_000,
- :dust => CENT,
- :per_dust_fee => false,
- },
+ NETWORKS[:testnet] = NETWORKS[:bitcoin].merge({
+ magic_head: "\xFA\xBF\xB5\xDA",
+ address_version: "6f",
+ p2sh_version: "c4",
+ privkey_version: "ef",
+ extended_privkey_version: "04358394",
+ extended_pubkey_version: "043587cf",
+ default_port: 18333,
+ dns_seeds: [ ],
+ genesis_hash: "00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008",
+ proof_of_work_limit: 0x1d07fff8,
+ alert_pubkeys: ["04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a"],
+ known_nodes: [],
+ checkpoints: {},
+ })
- :testnet => {
- :project => :bitcoin,
- :magic_head => "\xFA\xBF\xB5\xDA",
- :address_version => "6f",
- :p2sh_version => "c4",
- :privkey_version => "ef",
- :default_port => 18333,
- :max_money => 21_000_000 * COIN,
- :dns_seeds => [ ],
- :genesis_hash => "00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008",
- :proof_of_work_limit => 0x1d07fff8,
- :alert_pubkeys => ["04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a"],
- :known_nodes => [],
- :checkpoints => {},
- :coinbase_maturity => 100,
- :retarget_interval => 2016,
- :retarget_time => 1209600, # 2 weeks
- :target_spacing => 600, # block interval
- :max_money => 21_000_000 * COIN,
- :min_tx_fee => 10_000,
- :min_relay_tx_fee => 10_000,
- :free_tx_bytes => 1_000,
- :dust => CENT,
- :per_dust_fee => false,
- },
+ NETWORKS[:regtest] = NETWORKS[:testnet].merge({
+ default_port: 18444,
+ genesis_hash: "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206",
+ proof_of_work_limit: (1 << 255) - 1,
+ })
- :testnet3 => {
- :project => :bitcoin,
- :magic_head => "\x0b\x11\x09\x07",
- :address_version => "6f",
- :p2sh_version => "c4",
- :privkey_version => "ef",
- :default_port => 18333,
- :protocol_version => 70001,
- :coinbase_maturity => 100,
- :retarget_interval => 2016,
- :retarget_time => 1209600, # 2 weeks
- :target_spacing => 600, # block interval
- :max_money => 21_000_000 * COIN,
- :min_tx_fee => 10_000,
- :no_difficulty => true, # no good. add right testnet3 difficulty calculation instead
- :min_relay_tx_fee => 10_000,
- :free_tx_bytes => 1_000,
- :dust => CENT,
- :per_dust_fee => false,
- :dns_seeds => [
+ NETWORKS[:testnet3] = NETWORKS[:testnet].merge({
+ magic_head: "\x0B\x11\x09\x07",
+ no_difficulty: true, # no good. add right testnet3 difficulty calculation instead
+ genesis_hash: "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943",
+ proof_of_work_limit: 0x1d00ffff,
+ dns_seeds: [
+ "testnet-seed.alexykot.me",
+ "testnet-seed.bitcoin.schildbach.de",
"testnet-seed.bitcoin.petertodd.org",
"testnet-seed.bluematt.me",
],
- :genesis_hash => "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943",
- :proof_of_work_limit => 0x1d00ffff,
- :alert_pubkeys => ["04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a"],
- :known_nodes => [],
- :checkpoints => {
+ checkpoints: {
# 542 contains invalid transaction
542 => "0000000083c1f82cf72c6724f7a317325806384b06408bce7a4327f418dfd5ad",
71018 => "000000000010dd93dc55541116b2744eb8f4c3b706df6e8512d231a03fb9e435",
200000 => "0000000000287bffd321963ef05feab753ebe274e1d78b2fd4e2bfe9ad3aa6f2",
250000 => "0000000005910c146e4e8d71e8aa6617393738a9794b43cf113076dbaf08460b",
}
- },
+ })
- :litecoin => {
- :project => :litecoin,
- :magic_head => "\xfb\xc0\xb6\xdb",
- :address_version => "30",
- :p2sh_version => "05",
- :privkey_version => "b0",
- :default_port => 9333,
- :protocol_version => 70002,
- :max_money => 84_000_000 * COIN,
- :min_tx_fee => 100_000, # 0.001 LTC
- :min_relay_tx_fee => 100_000, # 0.001 LTC
- :free_tx_bytes => 5_000,
- :dust => CENT / 10,
- :per_dust_fee => true,
- :coinbase_maturity => 100,
- :retarget_interval => 2016,
- :retarget_time => 302400, # 3.5 days
- :dns_seeds => [
+ NETWORKS[:litecoin] = NETWORKS[:bitcoin].merge({
+ project: :litecoin,
+ magic_head: "\xfb\xc0\xb6\xdb",
+ address_version: "30",
+ p2sh_version: "05",
+ privkey_version: "b0",
+ extended_privkey_version: "019d9cfe",
+ extended_pubkey_version: "019da462",
+ default_port: 9333,
+ protocol_version: 70002,
+ max_money: 84_000_000 * COIN,
+ min_tx_fee: 100_000, # 0.001 LTC
+ min_relay_tx_fee: 100_000, # 0.001 LTC
+ free_tx_bytes: 5_000,
+ dust: CENT / 10,
+ per_dust_fee: true,
+ reward_halving: 840_000,
+ retarget_time: 302400, # 3.5 days
+ dns_seeds: [
"dnsseed.litecointools.com",
"dnsseed.litecoinpool.org",
"dnsseed.ltc.xurious.com",
"dnsseed.koin-project.com",
"dnsseed.weminemnc.com",
],
- :genesis_hash => "12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2",
- :proof_of_work_limit => 0,
- :alert_pubkeys => ["040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9"],
- :known_nodes => [],
- :checkpoints => {
+ genesis_hash: "12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2",
+ proof_of_work_limit: 0x1e0fffff,
+ alert_pubkeys: ["040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9"],
+ known_nodes: [],
+ checkpoints: {
1 => "80ca095ed10b02e53d769eb6eaf92cd04e9e0759e5be4a8477b42911ba49c78f",
2 => "13957807cdd1d02f993909fa59510e318763f99a506c4c426e3b254af09f40d7",
1500 => "841a2965955dd288cfa707a755d05a54e45f8bd476835ec9af4402a2b59a2967",
4032 => "9ce90e427198fc0ef05e5905ce3503725b80e26afd35a987965fd7e3d9cf0846",
8064 => "eb984353fc5190f210651f150c40b8a4bab9eeeff0b729fcb3987da694430d70",
@@ -675,115 +672,172 @@
240000 => "7140d1c4b4c2157ca217ee7636f24c9c73db39c4590c4e6eab2e3ea1555088aa",
383640 => "2b6809f094a9215bafc65eb3f110a35127a34be94b7d0590a096c3f126c6f364",
409004 => "487518d663d9f1fa08611d9395ad74d982b667fbdc0e77e9cf39b4f1355908a3",
456000 => "bf34f71cc6366cd487930d06be22f897e34ca6a40501ac7d401be32456372004",
541794 => "1cbccbe6920e7c258bbce1f26211084efb19764aa3224bec3f4320d77d6a2fd2",
- }
- },
+ },
+ auxpow_chain_id: 1,
+ })
- :litecoin_testnet => {
- :project => :litecoin,
- :magic_head => "\xfc\xc1\xb7\xdc",
- :address_version => "6f",
- :p2sh_version => "c4",
- :privkey_version => "ef",
- :default_port => 19333,
- :protocol_version => 70002,
- :min_tx_fee => 100_000, # 0.001 LTC
- :min_relay_tx_fee => 100_000, # 0.001 LTC
- :dust => CENT / 10,
- :per_dust_fee => true,
- :free_tx_bytes => 5_000,
- :coinbase_maturity => 100,
- :retarget_interval => 2016,
- :retarget_time => 302400, # 3.5 days
- :max_money => 84_000_000 * COIN,
- :dns_seeds => [
+ NETWORKS[:litecoin_testnet] = NETWORKS[:litecoin].merge({
+ magic_head: "\xfc\xc1\xb7\xdc",
+ address_version: "6f",
+ p2sh_version: "c4",
+ privkey_version: "ef",
+ extended_privkey_version: "0436ef7d",
+ extended_pubkey_version: "0436f6e1",
+ default_port: 19333,
+ dns_seeds: [
"testnet-seed.litecointools.com",
"testnet-seed.ltc.xurious.com",
"testnet-seed.weminemnc.com",
],
- :genesis_hash => "f5ae71e26c74beacc88382716aced69cddf3dffff24f384e1808905e0188f68f",
- :proof_of_work_limit => 0,
- :alert_pubkeys => ["04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a"],
- :known_nodes => [],
- :checkpoints => {
+ genesis_hash: "f5ae71e26c74beacc88382716aced69cddf3dffff24f384e1808905e0188f68f",
+ alert_pubkeys: ["04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a"],
+ known_nodes: [],
+ checkpoints: {
546 => "a0fea99a6897f531600c8ae53367b126824fd6a847b2b2b73817a95b8e27e602",
}
- },
+ })
+ NETWORKS[:dogecoin] = NETWORKS[:litecoin].merge({
+ project: :dogecoin,
+ magic_head: "\xc0\xc0\xc0\xc0",
+ address_version: "1e",
+ p2sh_version: "16",
+ privkey_version: "9e",
+ extended_privkey_version: "02fac398",
+ extended_pubkey_version: "02facafd",
+ default_port: 22556,
+ protocol_version: 70003,
+ max_money: 100_000_000_000 * COIN,
+ min_tx_fee: COIN,
+ min_relay_tx_fee: COIN,
+ free_tx_bytes: 26_000,
+ dust: COIN,
+ per_dust_fee: true,
+ coinbase_maturity: 30,
+ coinbase_maturity_new: 240,
+ reward_base: 500_000 * COIN,
+ reward_halving: 100_000,
+ retarget_interval: 240,
+ retarget_time: 14400, # 4 hours
+ retarget_time_new: 60, # 1 minute
+ target_spacing: 60, # block interval
+ dns_seeds: [
+ "seed.dogechain.info",
+ "seed.dogecoin.com",
+ ],
+ genesis_hash: "1a91e3dace36e2be3bf030a65679fe821aa1d6ef92e7c9902eb318182c355691",
+ proof_of_work_limit: 0x1e0fffff,
+ alert_pubkeys: [],
+ known_nodes: [
+ "daemons.chain.so",
+ "bootstrap.chain.so",
+ ],
+ checkpoints: {
+ 0 => "1a91e3dace36e2be3bf030a65679fe821aa1d6ef92e7c9902eb318182c355691",
+ 42279 => "8444c3ef39a46222e87584ef956ad2c9ef401578bd8b51e8e4b9a86ec3134d3a",
+ 42400 => "557bb7c17ed9e6d4a6f9361cfddf7c1fc0bdc394af7019167442b41f507252b4",
+ 104679 => "35eb87ae90d44b98898fec8c39577b76cb1eb08e1261cfc10706c8ce9a1d01cf",
+ 128370 => "3f9265c94cab7dc3bd6a2ad2fb26c8845cb41cff437e0a75ae006997b4974be6",
+ 145000 => "cc47cae70d7c5c92828d3214a266331dde59087d4a39071fa76ddfff9b7bde72",
+ 165393 => "7154efb4009e18c1c6a6a79fc6015f48502bcd0a1edd9c20e44cd7cbbe2eeef1",
+ 186774 => "3c712c49b34a5f34d4b963750d6ba02b73e8a938d2ee415dcda141d89f5cb23a",
+ 199992 => "3408ff829b7104eebaf61fd2ba2203ef2a43af38b95b353e992ef48f00ebb190",
+ 225000 => "be148d9c5eab4a33392a6367198796784479720d06bfdd07bd547fe934eea15a",
+ 250000 => "0e4bcfe8d970979f7e30e2809ab51908d435677998cf759169407824d4f36460",
+ 270639 => "c587a36dd4f60725b9dd01d99694799bef111fc584d659f6756ab06d2a90d911",
+ 299742 => "1cc89c0c8a58046bf0222fe131c099852bd9af25a80e07922918ef5fb39d6742",
+ 323141 => "60c9f919f9b271add6ef5671e9538bad296d79f7fdc6487ba702bf2ba131d31d",
+ 339202 => "8c29048df5ae9df38a67ea9470fdd404d281a3a5c6f33080cd5bf14aa496ab03"
+ },
+ auxpow_chain_id: 0x0062,
+ # Doge-specific hard-fork cutoffs
+ difficulty_change_block: 145000,
+ maturity_change_block: 145000,
+ auxpow_start_block: 371337
+ })
- :freicoin => {
- :project => :freicoin,
- :magic_head => "\x2c\xfe\x7e\x6d",
- :address_version => "00",
- :p2sh_version => "05",
- :privkey_version => "80",
- :default_port => 8639,
- :protocol_version => 60002,
- :max_money => 21_000_000 * COIN,
- :min_tx_fee => 50_000,
- :min_relay_tx_fee => 10_000,
- :free_tx_bytes => 1_000,
- :dust => CENT,
- :per_dust_fee => false,
- :dns_seeds => [ "seed.freico.in", "fledge.freico.in" ],
- :genesis_hash => "000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c",
- :proof_of_work_limit => 0,
- :alert_pubkeys => [],
- :known_nodes => [],
- :checkpoints => {
- 10080 => "00000000003ff9c4b806639ec4376cc9acafcdded0e18e9dbcc2fc42e8e72331",
- 15779 => "000000000003eb31742b35f5efd8ffb5cdd19dcd8e82cdaad90e592c450363b6",
- }
- },
+ NETWORKS[:dogecoin_testnet] = NETWORKS[:dogecoin].merge({
+ project: :dogecoin,
+ magic_head: "\xfc\xc1\xb7\xdc",
+ address_version: "71",
+ p2sh_version: "c4",
+ privkey_version: "f1",
+ extended_privkey_version: "0432a243",
+ extended_pubkey_version: "0432a9a8",
+ default_port: 44556,
+ protocol_version: 70003,
+ min_tx_fee: COIN,
+ min_relay_tx_fee: COIN,
+ dust: COIN,
+ per_dust_fee: true,
+ free_tx_bytes: 26_000,
+ coinbase_maturity: 30,
+ coinbase_maturity_new: 240,
+ reward_base: 500_000 * COIN,
+ reward_halving: 100_000,
+ retarget_interval: 240,
+ retarget_time: 14400, # 4 hours
+ retarget_time_new: 60, # 1 minute
+ target_spacing: 60, # block interval
+ max_money: 100_000_000_000 * COIN,
+ dns_seeds: [
+ "testdoge-seed.lionservers.de",
+ ],
+ genesis_hash: "bb0a78264637406b6360aad926284d544d7049f45189db5664f3c4d07350559e",
+ proof_of_work_limit: 0x1e0fffff,
+ alert_pubkeys: [],
+ known_nodes: [
+ "localhost",
+ "testnets.chain.so",
+ ],
+ checkpoints: {
+ 546 => "ac537cfeda975e45040e9938d08e40a16e0fbd6388d02d9b4928b8ae0108c626",
+ },
+ auxpow_chain_id: 0x0062,
+ # Doge-specific hard-fork cutoffs
+ difficulty_change_block: 145000,
+ maturity_change_block: 145000,
+ reset_target_block: 157500,
+ auxpow_start_block: 158100
+ })
- :namecoin => {
- :project => :namecoin,
- :magic_head => "\xF9\xBE\xB4\xFE",
- :address_version => "34",
- :default_port => 8334,
- :protocol_version => 35000,
- :max_money => 21_000_000 * COIN,
- :min_tx_fee => 50_000,
- :min_relay_tx_fee => 10_000,
- :free_tx_bytes => 1_000,
- :dust => CENT,
- :per_dust_fee => true,
- :dns_seeds => [],
- :genesis_hash => "000000000062b72c5e2ceb45fbc8587e807c155b0da735e6483dfba2f0a9c770",
- :proof_of_work_limit => 0x1d00ffff,
- :known_nodes => ["bitcoin.tunl.in", "webbtc.com", "178.32.31.41",
- "78.47.86.43", "69.164.206.88", ""],
- :checkpoints => {
+ NETWORKS[:namecoin] = NETWORKS[:bitcoin].merge({
+ project: :namecoin,
+ magic_head: "\xF9\xBE\xB4\xFE",
+ address_version: "34",
+ default_port: 8334,
+ protocol_version: 35000,
+ min_tx_fee: 50_000,
+ per_dust_fee: true,
+ dns_seeds: [],
+ genesis_hash: "000000000062b72c5e2ceb45fbc8587e807c155b0da735e6483dfba2f0a9c770",
+ known_nodes: [
+ "bitcoin.tunl.in",
+ "webbtc.com",
+ "178.32.31.41",
+ "78.47.86.43",
+ "69.164.206.88",
+ ],
+ checkpoints: {
0 => "000000000062b72c5e2ceb45fbc8587e807c155b0da735e6483dfba2f0a9c770",
19200 => "d8a7c3e01e1e95bcee015e6fcc7583a2ca60b79e5a3aa0a171eddd344ada903d",
24000 => "425ab0983cf04f43f346a4ca53049d0dc2db952c0a68eb0b55c3bb64108d5371",
97778 => "7553b1e43da01cfcda4335de1caf623e941d43894bd81c2af27b6582f9d83c6f",
165000 => "823d7a54ebab04d14c4ba3508f6b5f25977406f4d389539eac0174d52c6b4b62",
- }
- },
+ },
+ auxpow_chain_id: 1
+ })
- :namecoin_testnet => {
- :project => :namecoin,
- :magic_head => "\xFA\xBF\xB5\xFE",
- :address_version => "34",
- :default_port => 18334,
- :protocol_version => 35000,
- :min_tx_fee => 50_000,
- :min_relay_tx_fee => 10_000,
- :free_tx_bytes => 1_000,
- :dust => CENT,
- :per_dust_fee => true,
- :max_money => 21_000_000 * COIN,
- :dns_seeds => [],
- :genesis_hash => "00000001f8ab0d14bceaeb50d163b0bef15aecf62b87bd5f5c864d37f201db97",
- :proof_of_work_limit => 0x1d00ffff,
- :known_nodes => ["178.32.31.41"],
- :checkpoints => {
+ NETWORKS[:namecoin_testnet] = NETWORKS[:namecoin].merge({
+ magic_head: "\xFA\xBF\xB5\xFE",
+ default_port: 18334,
+ genesis_hash: "00000001f8ab0d14bceaeb50d163b0bef15aecf62b87bd5f5c864d37f201db97",
+ known_nodes: ["178.32.31.41"],
+ checkpoints: {
0 => "000000000062b72c5e2ceb45fbc8587e807c155b0da735e6483dfba2f0a9c770",
-
}
- },
- }
+ })
end