bitcoin-ruby 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -1
- data/Gemfile +21 -0
- data/README.rdoc +85 -25
- data/Rakefile +7 -3
- data/bin/bitcoin_node +39 -42
- data/bin/bitcoin_shell +1 -0
- data/bin/bitcoin_wallet +129 -53
- data/bitcoin-ruby.gemspec +4 -7
- data/concept-examples/blockchain-pow.rb +1 -1
- data/doc/CONFIG.rdoc +5 -5
- data/doc/EXAMPLES.rdoc +9 -5
- data/doc/NAMECOIN.rdoc +34 -0
- data/doc/NODE.rdoc +147 -10
- data/examples/balance.rb +10 -4
- data/examples/bbe_verify_tx.rb +7 -2
- data/examples/forwarder.rb +73 -0
- data/examples/generate_tx.rb +34 -0
- data/examples/simple_network_monitor_and_util.rb +187 -0
- data/examples/verify_tx.rb +1 -1
- data/lib/bitcoin.rb +308 -18
- data/lib/bitcoin/builder.rb +62 -36
- data/lib/bitcoin/config.rb +2 -0
- data/lib/bitcoin/connection.rb +11 -8
- data/lib/bitcoin/electrum/mnemonic.rb +162 -0
- data/lib/bitcoin/ffi/openssl.rb +187 -21
- data/lib/bitcoin/gui/addr_view.rb +2 -0
- data/lib/bitcoin/gui/conn_view.rb +2 -0
- data/lib/bitcoin/gui/connection.rb +2 -0
- data/lib/bitcoin/gui/em_gtk.rb +2 -0
- data/lib/bitcoin/gui/gui.rb +2 -0
- data/lib/bitcoin/gui/helpers.rb +2 -0
- data/lib/bitcoin/gui/tree_view.rb +2 -0
- data/lib/bitcoin/gui/tx_view.rb +2 -0
- data/lib/bitcoin/key.rb +77 -11
- data/lib/bitcoin/litecoin.rb +81 -0
- data/lib/bitcoin/logger.rb +20 -1
- data/lib/bitcoin/namecoin.rb +279 -0
- data/lib/bitcoin/network/command_client.rb +7 -6
- data/lib/bitcoin/network/command_handler.rb +229 -43
- data/lib/bitcoin/network/connection_handler.rb +182 -70
- data/lib/bitcoin/network/node.rb +231 -106
- data/lib/bitcoin/protocol.rb +44 -23
- data/lib/bitcoin/protocol/address.rb +5 -3
- data/lib/bitcoin/protocol/alert.rb +3 -4
- data/lib/bitcoin/protocol/aux_pow.rb +123 -0
- data/lib/bitcoin/protocol/block.rb +98 -18
- data/lib/bitcoin/protocol/handler.rb +6 -5
- data/lib/bitcoin/protocol/parser.rb +44 -19
- data/lib/bitcoin/protocol/tx.rb +105 -52
- data/lib/bitcoin/protocol/txin.rb +39 -19
- data/lib/bitcoin/protocol/txout.rb +28 -13
- data/lib/bitcoin/protocol/version.rb +16 -7
- data/lib/bitcoin/script.rb +579 -122
- data/lib/bitcoin/storage/{dummy.rb → dummy/dummy_store.rb} +8 -14
- data/lib/bitcoin/storage/models.rb +20 -7
- data/lib/bitcoin/storage/{sequel_store/sequel_migrations.rb → sequel/migrations.rb} +22 -7
- data/lib/bitcoin/storage/sequel/migrations/001_base_schema.rb +52 -0
- data/lib/bitcoin/storage/sequel/migrations/002_tx.rb +50 -0
- data/lib/bitcoin/storage/sequel/migrations/003_change_txin_script_sig_to_blob.rb +18 -0
- data/lib/bitcoin/storage/sequel/sequel_store.rb +436 -0
- data/lib/bitcoin/storage/storage.rb +233 -28
- data/lib/bitcoin/storage/utxo/migrations/001_base_schema.rb +52 -0
- data/lib/bitcoin/storage/utxo/migrations/002_utxo.rb +18 -0
- data/lib/bitcoin/storage/utxo/utxo_store.rb +361 -0
- data/lib/bitcoin/validation.rb +369 -0
- data/lib/bitcoin/version.rb +1 -1
- data/lib/bitcoin/wallet/coinselector.rb +3 -0
- data/lib/bitcoin/wallet/keygenerator.rb +3 -1
- data/lib/bitcoin/wallet/keystore.rb +6 -2
- data/lib/bitcoin/wallet/txdp.rb +6 -4
- data/lib/bitcoin/wallet/wallet.rb +54 -16
- data/spec/bitcoin/bitcoin_spec.rb +48 -3
- data/spec/bitcoin/builder_spec.rb +40 -17
- data/spec/bitcoin/fixtures/000000000000056b1a3d84a1e2b33cde8915a4b61c0cae14fca6d3e1490b4f98.json +3697 -0
- data/spec/bitcoin/fixtures/03d7e1fa4d5fefa169431f24f7798552861b255cd55d377066fedcd088fb0e99.json +23 -0
- data/spec/bitcoin/fixtures/0961c660358478829505e16a1f028757e54b5bbf9758341a7546573738f31429.json +24 -0
- data/spec/bitcoin/fixtures/0f24294a1d23efbb49c1765cf443fba7930702752aba6d765870082fe4f13cae.json +37 -0
- data/spec/bitcoin/fixtures/315ac7d4c26d69668129cc352851d9389b4a6868f1509c6c8b66bead11e2619f.json +31 -0
- data/spec/bitcoin/fixtures/35e2001b428891fefa0bfb73167c7360669d3cbd7b3aa78e7cad125ddfc51131.json +27 -0
- data/spec/bitcoin/fixtures/3a17dace09ffb919ed627a93f1873220f4c975c1248558b18d16bce25d38c4b7.json +72 -0
- data/spec/bitcoin/fixtures/3e58b7eed0fdb599019af08578effea25c8666bbe8e200845453cacce6314477.json +27 -0
- data/spec/bitcoin/fixtures/514c46f0b61714092f15c8dfcb576c9f79b3f959989b98de3944b19d98832b58.json +24 -0
- data/spec/bitcoin/fixtures/51bf528ecf3c161e7c021224197dbe84f9a8564212f6207baa014c01a1668e1e.json +30 -0
- data/spec/bitcoin/fixtures/69216b8aaa35b76d6613e5f527f4858640d986e1046238583bdad79b35e938dc.json +28 -0
- data/spec/bitcoin/fixtures/7208e5edf525f04e705fb3390194e316205b8f995c8c9fcd8c6093abe04fa27d.json +27 -0
- data/spec/bitcoin/fixtures/761d8c5210fdfd505f6dff38f740ae3728eb93d7d0971fb433f685d40a4c04f6.json +27 -0
- data/spec/bitcoin/fixtures/aea682d68a3ea5e3583e088dcbd699a5d44d4b083f02ad0aaf2598fe1fa4dfd4.json +27 -0
- data/spec/bitcoin/fixtures/bd1715f1abfdc62bea3f605bdb461b3ba1f2cca6ec0d73a18a548b7717ca8531.json +34 -0
- data/spec/bitcoin/fixtures/block-testnet-0000000000ac85bb2530a05a4214a387e6be02b22d3348abc5e7a5d9c4ce8dab.bin +0 -0
- data/spec/bitcoin/fixtures/cd874fa8cb0e2ec2d385735d5e1fd482c4fe648533efb4c50ee53bda58e15ae2.json +24 -0
- data/spec/bitcoin/fixtures/ce5fad9b4ef094d8f4937b0707edaf0a6e6ceeaf67d5edbfd51f660eac8f398b.json +41 -0
- data/spec/bitcoin/fixtures/f003f0c1193019db2497a675fd05d9f2edddf9b67c59e677c48d3dbd4ed5f00b.json +23 -0
- data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.bin +0 -0
- data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.json +43 -0
- data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.bin +0 -0
- data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.json +67 -0
- data/spec/bitcoin/fixtures/litecoin-block-80ca095ed10b02e53d769eb6eaf92cd04e9e0759e5be4a8477b42911ba49c78f.bin +0 -0
- data/spec/bitcoin/fixtures/litecoin-block-80ca095ed10b02e53d769eb6eaf92cd04e9e0759e5be4a8477b42911ba49c78f.json +39 -0
- data/spec/bitcoin/fixtures/litecoin-genesis-block-12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2.bin +0 -0
- data/spec/bitcoin/fixtures/litecoin-genesis-block-12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2.json +39 -0
- data/spec/bitcoin/fixtures/rawblock-auxpow.bin +0 -0
- data/spec/bitcoin/fixtures/tx-313897799b1e37e9ecae15010e56156dddde4e683c96b0e713af95272c38aee0.json +30 -0
- data/spec/bitcoin/fixtures/tx-3da75972766f0ad13319b0b461fd16823a731e44f6e9de4eb3c52d6a6fb6c8ae.json +23 -0
- data/spec/bitcoin/fixtures/tx-44b833074e671120ba33106877b49e86ece510824b9af477a3853972bcd8d06a.json +30 -0
- data/spec/bitcoin/fixtures/tx-d3d77d63709e47d9ef58f0b557800115a6b676c6a423012fbb96f45d8fcef830.json +28 -0
- data/spec/bitcoin/key_spec.rb +128 -3
- data/spec/bitcoin/namecoin_spec.rb +182 -0
- data/spec/bitcoin/network_spec.rb +5 -3
- data/spec/bitcoin/node/command_api_spec.rb +376 -0
- data/spec/bitcoin/protocol/addr_spec.rb +2 -0
- data/spec/bitcoin/protocol/alert_spec.rb +2 -0
- data/spec/bitcoin/protocol/aux_pow_spec.rb +44 -0
- data/spec/bitcoin/protocol/block_spec.rb +134 -39
- data/spec/bitcoin/protocol/getblocks_spec.rb +32 -0
- data/spec/bitcoin/protocol/inv_spec.rb +10 -8
- data/spec/bitcoin/protocol/notfound_spec.rb +31 -0
- data/spec/bitcoin/protocol/ping_spec.rb +2 -0
- data/spec/bitcoin/protocol/tx_spec.rb +83 -17
- data/spec/bitcoin/protocol/version_spec.rb +7 -5
- data/spec/bitcoin/script/opcodes_spec.rb +412 -133
- data/spec/bitcoin/script/script_spec.rb +112 -13
- data/spec/bitcoin/spec_helper.rb +68 -0
- data/spec/bitcoin/storage/reorg_spec.rb +199 -0
- data/spec/bitcoin/storage/storage_spec.rb +337 -0
- data/spec/bitcoin/storage/validation_spec.rb +261 -0
- data/spec/bitcoin/wallet/coinselector_spec.rb +10 -7
- data/spec/bitcoin/wallet/keygenerator_spec.rb +2 -0
- data/spec/bitcoin/wallet/keystore_spec.rb +2 -0
- data/spec/bitcoin/wallet/txdp_spec.rb +2 -0
- data/spec/bitcoin/wallet/wallet_spec.rb +91 -58
- metadata +105 -51
- data/lib/bitcoin/storage/sequel.rb +0 -335
- data/spec/bitcoin/fixtures/0d0affb5964abe804ffe85e53f1dbb9f29e406aa3046e2db04fba240e63c7fdd.json +0 -27
- data/spec/bitcoin/fixtures/477fff140b363ec2cc51f3a65c0c58eda38f4d41f04a295bbd62babf25e4c590.json +0 -27
- data/spec/bitcoin/reorg_spec.rb +0 -129
- data/spec/bitcoin/storage_spec.rb +0 -229
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
$:.unshift( File.expand_path("../../lib", __FILE__) )
|
|
2
|
+
require 'eventmachine'
|
|
3
|
+
require 'bitcoin'
|
|
4
|
+
require 'socket'
|
|
5
|
+
|
|
6
|
+
class Bitcoin::Protocol::Parser; def log; stub=Object.new; def stub.method_missing(*a); end; stub; end; end
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
module SimpleNode
|
|
10
|
+
class Connection < EM::Connection
|
|
11
|
+
|
|
12
|
+
def on_tx(tx)
|
|
13
|
+
log.info { "received transaction: #{tx.hash}" }
|
|
14
|
+
|
|
15
|
+
puts tx.to_json
|
|
16
|
+
|
|
17
|
+
if tx.hash == @ask_tx
|
|
18
|
+
@args[:result] = tx
|
|
19
|
+
@args[:callback] ? (close_connection; @args[:callback].call(tx)) : EM.stop
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def on_block(block)
|
|
24
|
+
log.info { "received block: #{block.hash}" }
|
|
25
|
+
|
|
26
|
+
puts block.to_json
|
|
27
|
+
|
|
28
|
+
if block.hash == @ask_block
|
|
29
|
+
if @ask_tx
|
|
30
|
+
if tx = block.tx.find{|tx| tx.hash == @ask_tx }
|
|
31
|
+
on_tx(tx)
|
|
32
|
+
else
|
|
33
|
+
log.info { "@ask_tx #{@ask_tx} not in @ask_block #{@ask_block}" }
|
|
34
|
+
@args[:result] = nil
|
|
35
|
+
@args[:callback] ? (close_connection; @args[:callback].call(nil)) : EM.stop
|
|
36
|
+
end
|
|
37
|
+
else
|
|
38
|
+
@args[:result] = block
|
|
39
|
+
@args[:callback] ? (close_connection; @args[:callback].call(block)) : EM.stop
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def on_handshake_complete
|
|
45
|
+
return if @connected
|
|
46
|
+
@connected = true
|
|
47
|
+
log.info { "handshake complete" }
|
|
48
|
+
|
|
49
|
+
EM.add_timer(0.5){
|
|
50
|
+
if @ask_block
|
|
51
|
+
log.info { "ask for @ask_block: #{@ask_block}" }
|
|
52
|
+
send_data Bitcoin::Protocol.getdata_pkt(:block, [htb(@ask_block)])
|
|
53
|
+
else
|
|
54
|
+
if @ask_tx
|
|
55
|
+
log.info { "ask for @ask_tx: #{@ask_tx}" }
|
|
56
|
+
send_data Bitcoin::Protocol.getdata_pkt(:tx, [htb(@ask_tx)])
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
if @send_tx
|
|
60
|
+
tx = Bitcoin::P::Tx.from_json(File.read(@send_tx))
|
|
61
|
+
send_data(Bitcoin::Protocol.pkt('tx', tx.to_payload))
|
|
62
|
+
p [:sent, tx.hash]
|
|
63
|
+
end
|
|
64
|
+
}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def on_get_transaction(hash); end
|
|
68
|
+
def on_get_block(hash); end
|
|
69
|
+
def on_addr(addr); end
|
|
70
|
+
def on_inv_transaction(hash)
|
|
71
|
+
log.info { "peer told us about transaction: #{hth(hash)}" }
|
|
72
|
+
log.info { "asking peer for transaction: #{hth(hash)}" }
|
|
73
|
+
send_data Bitcoin::Protocol.getdata_pkt(:tx, [hash])
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def on_inv_block(hash)
|
|
77
|
+
log.info { "peer told us about block: #{hth(hash)}" }
|
|
78
|
+
log.info { "asking peer for block: #{hth(hash)}" }
|
|
79
|
+
send_data Bitcoin::Protocol.getdata_pkt(:block, [hash])
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def on_handshake_begin
|
|
83
|
+
log.info { "handshake started" }
|
|
84
|
+
|
|
85
|
+
version = Bitcoin::Protocol::Version.new({
|
|
86
|
+
:user_agent => "/Satoshi:0.8.1/",
|
|
87
|
+
:last_block => 0,
|
|
88
|
+
:from => "127.0.0.1:#{Bitcoin.network[:default_port]}",
|
|
89
|
+
:to => "#{@host}:#{@port}",
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
log.info { "sending version: Version:%d (%s) Block:%d" % version.fields.values_at(:version, :user_agent, :last_block) }
|
|
93
|
+
send_data(version.to_pkt)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def on_version(version)
|
|
97
|
+
@version ||= version
|
|
98
|
+
log.info { "received version: Version:%d (%s) Block:%d" % version.fields.values_at(:version, :user_agent, :last_block) }
|
|
99
|
+
send_data( Bitcoin::Protocol.verack_pkt )
|
|
100
|
+
on_handshake_complete
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def initialize(host, port, node=nil, opts={})
|
|
104
|
+
set_host(host, port)
|
|
105
|
+
@node = node
|
|
106
|
+
@parser = Bitcoin::Protocol::Parser.new( self )
|
|
107
|
+
|
|
108
|
+
@args = opts
|
|
109
|
+
@ask_tx, @ask_block, @send_tx = opts.values_at(:ask_tx, :ask_block, :send_tx)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def receive_data(data); @parser.parse(data); end
|
|
113
|
+
def post_init; log.info { "peer connected" }; on_handshake_begin; end
|
|
114
|
+
def unbind; log.info { "peer disconnected" }; end
|
|
115
|
+
def set_host(host, port=8333); @host, @port = host, port; end
|
|
116
|
+
|
|
117
|
+
def log
|
|
118
|
+
return @log if @log
|
|
119
|
+
return (@log = (stub=Object.new; def stub.method_missing(*a); end; stub)) if @args[:nolog]
|
|
120
|
+
@logger ||= Bitcoin::Logger.create(:network, :info) unless @node.respond_to?(:log)
|
|
121
|
+
@log = Bitcoin::Logger::LogWrapper.new("#@host:#@port", @logger || @node.log)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def hth(h); h.unpack("H*")[0]; end
|
|
125
|
+
def htb(h); [h].pack("H*"); end
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def self.connect(host, port, *args)
|
|
129
|
+
EM.connect(host, port, self, host, port, *args)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def self.connect_random_from_dns(seeds=[], count=1, *args)
|
|
133
|
+
seeds = Bitcoin.network[:dns_seeds] unless seeds.any?
|
|
134
|
+
if seeds.any?
|
|
135
|
+
seeds.sample(count).map{|dns|
|
|
136
|
+
host = IPSocket.getaddress(dns)
|
|
137
|
+
connect(host, Bitcoin.network[:default_port], *args)
|
|
138
|
+
}
|
|
139
|
+
else
|
|
140
|
+
raise "No DNS seeds available. Provide IP, configure seeds, or use different network."
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def self.connect_known_nodes(count=1)
|
|
145
|
+
connect_random_from_dns(Bitcoin.network[:known_nodes], count)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
if $0 == __FILE__
|
|
152
|
+
|
|
153
|
+
args = {
|
|
154
|
+
ask_tx: ARGV.find{|a| a[/tx=(.+)/, 1] } && $1,
|
|
155
|
+
ask_block: ARGV.find{|a| a[/block=(.+)/, 1] } && $1,
|
|
156
|
+
use_node: ARGV.find{|a| a[/node=(.+)/, 1] } && $1,
|
|
157
|
+
send_tx: ARGV.find{|a| a[/send_tx=(.+)/, 1] } && $1,
|
|
158
|
+
set_project: ARGV.find{|a| a[/project=(.+)/, 1] } && $1,
|
|
159
|
+
callback: proc{|i|
|
|
160
|
+
case i
|
|
161
|
+
when Bitcoin::Protocol::Block
|
|
162
|
+
puts "INFO network: SAVING @ask_block: #{i.hash}"
|
|
163
|
+
File.open("block-#{i.hash}.bin", 'wb'){|f| f.print i.payload }
|
|
164
|
+
File.open("block-#{i.hash}.json", 'wb'){|f| f.print i.to_json }
|
|
165
|
+
when Bitcoin::Protocol::Tx
|
|
166
|
+
puts "INFO network: SAVING @ask_tx: #{i.hash}"
|
|
167
|
+
File.open("tx-#{i.hash}.bin", 'wb'){|f| f.print i.payload }
|
|
168
|
+
File.open("tx-#{i.hash}.json", 'wb'){|f| f.print i.to_json }
|
|
169
|
+
end
|
|
170
|
+
EM.stop
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
EM.run do
|
|
176
|
+
if args[:set_project]
|
|
177
|
+
Bitcoin.network = args[:set_project].to_sym
|
|
178
|
+
p Bitcoin.network_project
|
|
179
|
+
end
|
|
180
|
+
if args[:use_node]
|
|
181
|
+
SimpleNode::Connection.connect_random_from_dns([args[:use_node]], 1, nil, args)
|
|
182
|
+
else
|
|
183
|
+
SimpleNode::Connection.connect_random_from_dns([], 1, nil, args)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
end
|
data/examples/verify_tx.rb
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
#
|
|
8
8
|
# see Bitcoin::Protocol::Tx and Bitcoin::Script.
|
|
9
9
|
# Note: For this to work, you need to have the transactions in your storage. see NODE.
|
|
10
|
-
|
|
10
|
+
# Note: There is also Bitcoin::Validation::Tx which validates a lot more than signatures.
|
|
11
11
|
|
|
12
12
|
$:.unshift( File.expand_path("../../lib", __FILE__) )
|
|
13
13
|
require 'bitcoin'
|
data/lib/bitcoin.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# encoding: ascii-8bit
|
|
1
2
|
# Bitcoin Utils and Network Protocol in Ruby.
|
|
2
3
|
|
|
3
4
|
require 'digest/sha2'
|
|
@@ -17,6 +18,9 @@ module Bitcoin
|
|
|
17
18
|
autoload :Key, 'bitcoin/key'
|
|
18
19
|
autoload :Config, 'bitcoin/config'
|
|
19
20
|
autoload :Builder, 'bitcoin/builder'
|
|
21
|
+
autoload :Validation, 'bitcoin/validation'
|
|
22
|
+
|
|
23
|
+
autoload :Namecoin, 'bitcoin/namecoin'
|
|
20
24
|
|
|
21
25
|
module Network
|
|
22
26
|
autoload :ConnectionHandler, 'bitcoin/network/connection_handler'
|
|
@@ -43,6 +47,7 @@ module Bitcoin
|
|
|
43
47
|
begin
|
|
44
48
|
require name.to_s
|
|
45
49
|
rescue LoadError
|
|
50
|
+
return false if name.to_s == "log4r"
|
|
46
51
|
print "Cannot load #{opts[:exit] == false ? 'optional' : 'required'} dependency '#{name}'"
|
|
47
52
|
(opts[:gem] == false) ? puts("") :
|
|
48
53
|
puts(" - install with `gem install #{opts[:gem] || name}`")
|
|
@@ -55,9 +60,6 @@ module Bitcoin
|
|
|
55
60
|
|
|
56
61
|
module Util
|
|
57
62
|
|
|
58
|
-
def hth(h); h.unpack("H*")[0]; end
|
|
59
|
-
def htb(h); [h].pack("H*"); end
|
|
60
|
-
|
|
61
63
|
def address_version; Bitcoin.network[:address_version]; end
|
|
62
64
|
def p2sh_version; Bitcoin.network[:p2sh_version]; end
|
|
63
65
|
|
|
@@ -206,6 +208,10 @@ module Bitcoin
|
|
|
206
208
|
).reverse.unpack("H*")[0]
|
|
207
209
|
end
|
|
208
210
|
|
|
211
|
+
def bitcoin_byte_hash(bytes)
|
|
212
|
+
Digest::SHA256.digest(Digest::SHA256.digest(bytes))
|
|
213
|
+
end
|
|
214
|
+
|
|
209
215
|
def bitcoin_mrkl(a, b); bitcoin_hash(b + a); end
|
|
210
216
|
|
|
211
217
|
def block_hash(prev_block, mrkl_root, time, bits, nonce, ver)
|
|
@@ -214,16 +220,39 @@ module Bitcoin
|
|
|
214
220
|
bitcoin_hash(h)
|
|
215
221
|
end
|
|
216
222
|
|
|
223
|
+
# get merkle tree for given +tx+ list.
|
|
217
224
|
def hash_mrkl_tree(tx)
|
|
225
|
+
return [nil] if tx != tx.uniq
|
|
218
226
|
chunks = [ tx.dup ]
|
|
219
227
|
while chunks.last.size >= 2
|
|
220
|
-
chunks << chunks.last.each_slice(2).map{|
|
|
221
|
-
Bitcoin.bitcoin_mrkl(
|
|
222
|
-
}
|
|
228
|
+
chunks << chunks.last.each_slice(2).map {|a, b|
|
|
229
|
+
Bitcoin.bitcoin_mrkl( a, b || a ) }
|
|
223
230
|
end
|
|
224
231
|
chunks.flatten
|
|
225
232
|
end
|
|
226
233
|
|
|
234
|
+
# get merkle branch connecting given +target+ to the merkle root of +tx+ list
|
|
235
|
+
def hash_mrkl_branch(tx, target)
|
|
236
|
+
return [ nil ] if tx != tx.uniq
|
|
237
|
+
branch, chunks = [], [ tx.dup ]
|
|
238
|
+
while chunks.last.size >= 2
|
|
239
|
+
chunks << chunks.last.each_slice(2).map {|a, b|
|
|
240
|
+
hash = Bitcoin.bitcoin_mrkl( a, b || a )
|
|
241
|
+
next hash unless [a, b].include?(target)
|
|
242
|
+
branch << (a == target ? (b || a) : a)
|
|
243
|
+
target = hash
|
|
244
|
+
}
|
|
245
|
+
end
|
|
246
|
+
branch
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# get merkle root from +branch+ and +target+.
|
|
250
|
+
def mrkl_branch_root(branch, target, idx)
|
|
251
|
+
branch.map do |hash|
|
|
252
|
+
a, b = *( idx & 1 == 0 ? [target, hash] : [hash, target] )
|
|
253
|
+
idx >>= 1; target = Bitcoin.bitcoin_mrkl( a, b )
|
|
254
|
+
end.last
|
|
255
|
+
end
|
|
227
256
|
|
|
228
257
|
def sign_data(key, data)
|
|
229
258
|
key.dsa_sign_asn1(data)
|
|
@@ -235,7 +264,7 @@ module Bitcoin
|
|
|
235
264
|
key.dsa_verify_asn1(hash, signature)
|
|
236
265
|
rescue OpenSSL::PKey::ECError, OpenSSL::PKey::EC::Point::Error
|
|
237
266
|
false
|
|
238
|
-
end
|
|
267
|
+
end
|
|
239
268
|
|
|
240
269
|
def open_key(private_key, public_key=nil)
|
|
241
270
|
key = bitcoin_elliptic_curve
|
|
@@ -249,6 +278,30 @@ module Bitcoin
|
|
|
249
278
|
Bitcoin::OpenSSL_EC.regenerate_key(private_key)[1]
|
|
250
279
|
end
|
|
251
280
|
|
|
281
|
+
def bitcoin_signed_message_hash(message)
|
|
282
|
+
# TODO: this will fail horribly on messages with len > 255. It's a cheap implementation of Bitcoin's CDataStream.
|
|
283
|
+
data = "\x18Bitcoin Signed Message:\n" + [message.bytesize].pack("C") + message
|
|
284
|
+
Digest::SHA256.digest(Digest::SHA256.digest(data))
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def sign_message(private_key_hex, public_key_hex, message)
|
|
288
|
+
hash = bitcoin_signed_message_hash(message)
|
|
289
|
+
signature = Bitcoin::OpenSSL_EC.sign_compact(hash, private_key_hex, public_key_hex)
|
|
290
|
+
{ 'address' => pubkey_to_address(public_key_hex), 'message' => message, 'signature' => [ signature ].pack("m0") }
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def verify_message(address, signature, message)
|
|
294
|
+
hash = bitcoin_signed_message_hash(message)
|
|
295
|
+
signature = signature.unpack("m0")[0] rescue nil # decode base64
|
|
296
|
+
raise "invalid address" unless valid_address?(address)
|
|
297
|
+
raise "malformed base64 encoding" unless signature
|
|
298
|
+
raise "malformed signature" unless signature.bytesize == 65
|
|
299
|
+
pubkey = Bitcoin::OpenSSL_EC.recover_compact(hash, signature)
|
|
300
|
+
pubkey_to_address(pubkey) == address if pubkey
|
|
301
|
+
rescue Exception => ex
|
|
302
|
+
p [ex.message, ex.backtrace]; false
|
|
303
|
+
end
|
|
304
|
+
|
|
252
305
|
|
|
253
306
|
RETARGET_INTERVAL = 2016
|
|
254
307
|
|
|
@@ -283,6 +336,13 @@ module Bitcoin
|
|
|
283
336
|
block_hashes_to_win(target_nbits) / hashes_per_second
|
|
284
337
|
end
|
|
285
338
|
|
|
339
|
+
# average mining time (in days) using Mh/s to get btc
|
|
340
|
+
def block_average_mining_time(block_nbits, block_height, mega_hashes_per_second, target_btc=1.0)
|
|
341
|
+
seconds = block_average_hashing_time(block_nbits, mega_hashes_per_second * 1_000_000)
|
|
342
|
+
reward = block_creation_reward(block_height) / Bitcoin::COIN # satoshis to btc
|
|
343
|
+
(days = seconds / 60 / 60 / 24) * (target_btc / reward)
|
|
344
|
+
end
|
|
345
|
+
|
|
286
346
|
# shows the total number of Bitcoins in circulation, reward era and reward in that era.
|
|
287
347
|
def blockchain_total_btc(height)
|
|
288
348
|
reward, interval = 5000000000, 210000
|
|
@@ -301,6 +361,21 @@ module Bitcoin
|
|
|
301
361
|
end
|
|
302
362
|
end
|
|
303
363
|
|
|
364
|
+
extend Util
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
module BinaryExtensions
|
|
368
|
+
def hth; unpack("H*")[0]; end
|
|
369
|
+
def reverse_hth; reverse.hth; end
|
|
370
|
+
def htb; [self].pack("H*"); end
|
|
371
|
+
def htb_reverse; htb.reverse; end
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
class ::String
|
|
375
|
+
include Bitcoin::BinaryExtensions
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
|
|
304
379
|
module ::OpenSSL
|
|
305
380
|
class BN
|
|
306
381
|
def self.from_hex(hex); new(hex, 16); end
|
|
@@ -310,6 +385,7 @@ module Bitcoin
|
|
|
310
385
|
class PKey::EC
|
|
311
386
|
def private_key_hex; private_key.to_hex.rjust(64, '0'); end
|
|
312
387
|
def public_key_hex; public_key.to_hex.rjust(130, '0'); end
|
|
388
|
+
def pubkey_compressed?; public_key.group.point_conversion_form == :compressed; end
|
|
313
389
|
end
|
|
314
390
|
class PKey::EC::Point
|
|
315
391
|
def self.from_hex(group, hex)
|
|
@@ -322,49 +398,263 @@ module Bitcoin
|
|
|
322
398
|
|
|
323
399
|
autoload :OpenSSL_EC, "bitcoin/ffi/openssl"
|
|
324
400
|
|
|
325
|
-
|
|
326
|
-
extend Util
|
|
327
|
-
|
|
328
401
|
@network = :bitcoin
|
|
329
402
|
|
|
330
403
|
def self.network
|
|
331
404
|
NETWORKS[@network]
|
|
332
405
|
end
|
|
333
406
|
|
|
407
|
+
def self.network_name
|
|
408
|
+
@network
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
def self.network_project
|
|
412
|
+
@network_project
|
|
413
|
+
end
|
|
414
|
+
|
|
334
415
|
def self.network= name
|
|
416
|
+
raise "Network descriptor '#{name}' not found." unless NETWORKS[name.to_sym]
|
|
335
417
|
@network = name.to_sym
|
|
418
|
+
@network_project = network[:project] rescue nil
|
|
419
|
+
Bitcoin::Namecoin.load if namecoin?
|
|
420
|
+
@network
|
|
336
421
|
end
|
|
337
422
|
|
|
423
|
+
[:bitcoin, :namecoin, :litecoin, :freicoin].each do |n|
|
|
424
|
+
instance_eval "def #{n}?; network_project == :#{n}; end"
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
CENT = 1_000_000
|
|
429
|
+
COIN = 100_000_000
|
|
430
|
+
MAX_BLOCK_SIZE = 1_000_000
|
|
431
|
+
MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2
|
|
432
|
+
MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50
|
|
433
|
+
MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100
|
|
434
|
+
|
|
435
|
+
MIN_FEE_MODE = [ :block, :relay, :send ]
|
|
436
|
+
|
|
338
437
|
NETWORKS = {
|
|
438
|
+
|
|
339
439
|
:bitcoin => {
|
|
440
|
+
:project => :bitcoin,
|
|
340
441
|
:magic_head => "\xF9\xBE\xB4\xD9",
|
|
341
442
|
:address_version => "00",
|
|
342
443
|
:p2sh_version => "05",
|
|
343
444
|
:privkey_version => "80",
|
|
344
445
|
:default_port => 8333,
|
|
345
|
-
:
|
|
346
|
-
|
|
446
|
+
:protocol_version => 70001,
|
|
447
|
+
:coinbase_maturity => 100,
|
|
448
|
+
:retarget_interval => 2016,
|
|
449
|
+
:retarget_time => 1209600, # 2 weeks
|
|
450
|
+
:max_money => 21_000_000 * COIN,
|
|
451
|
+
:min_tx_fee => 50_000,
|
|
452
|
+
:min_relay_tx_fee => 10_000,
|
|
453
|
+
:dns_seeds => [
|
|
454
|
+
"seed.bitcoin.sipa.be",
|
|
455
|
+
"dnsseed.bluematt.me",
|
|
456
|
+
"dnsseed.bitcoin.dashjr.org",
|
|
457
|
+
"bitseed.xf2.org",
|
|
458
|
+
],
|
|
347
459
|
:genesis_hash => "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
|
|
348
460
|
:proof_of_work_limit => 0x1d00ffff,
|
|
461
|
+
:alert_pubkeys => ["04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284"],
|
|
349
462
|
:known_nodes => [
|
|
350
463
|
'relay.eligius.st',
|
|
351
464
|
'mining.bitcoin.cz',
|
|
352
|
-
'bitcoins.lc',
|
|
353
465
|
'blockchain.info',
|
|
354
466
|
'blockexplorer.com',
|
|
355
|
-
]
|
|
467
|
+
],
|
|
468
|
+
:checkpoints => {
|
|
469
|
+
11111 => "0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d",
|
|
470
|
+
33333 => "000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6",
|
|
471
|
+
74000 => "0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20",
|
|
472
|
+
105000 => "00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97",
|
|
473
|
+
134444 => "00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe",
|
|
474
|
+
168000 => "000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763",
|
|
475
|
+
193000 => "000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317",
|
|
476
|
+
210000 => "000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e",
|
|
477
|
+
216116 => "00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e",
|
|
478
|
+
225430 => "00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932",
|
|
479
|
+
}
|
|
356
480
|
},
|
|
481
|
+
|
|
357
482
|
:testnet => {
|
|
483
|
+
:project => :bitcoin,
|
|
358
484
|
:magic_head => "\xFA\xBF\xB5\xDA",
|
|
359
485
|
:address_version => "6f",
|
|
360
486
|
:p2sh_version => "c4",
|
|
361
487
|
:privkey_version => "ef",
|
|
362
488
|
:default_port => 18333,
|
|
363
|
-
:
|
|
489
|
+
:max_money => 21_000_000 * COIN,
|
|
490
|
+
:dns_seeds => [ "testseed.bitcoin.interesthings.de" ],
|
|
364
491
|
:genesis_hash => "00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008",
|
|
365
492
|
:proof_of_work_limit => 0x1d07fff8,
|
|
366
|
-
:
|
|
367
|
-
|
|
493
|
+
:alert_pubkeys => ["04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a"],
|
|
494
|
+
:known_nodes => [],
|
|
495
|
+
:checkpoints => {}
|
|
496
|
+
},
|
|
497
|
+
|
|
498
|
+
:testnet3 => {
|
|
499
|
+
:project => :bitcoin,
|
|
500
|
+
:magic_head => "\x0b\x11\x09\x07",
|
|
501
|
+
:address_version => "6f",
|
|
502
|
+
:p2sh_version => "c4",
|
|
503
|
+
:privkey_version => "ef",
|
|
504
|
+
:default_port => 18333,
|
|
505
|
+
:protocol_version => 70001,
|
|
506
|
+
:coinbase_maturity => 100,
|
|
507
|
+
:retarget_interval => 2016,
|
|
508
|
+
:retarget_time => 1209600, # 2 weeks
|
|
509
|
+
:max_money => 21_000_000 * COIN,
|
|
510
|
+
:min_tx_fee => 50_000,
|
|
511
|
+
:min_relay_tx_fee => 10_000,
|
|
512
|
+
:dns_seeds => [
|
|
513
|
+
"testnet-seed.bitcoin.petertodd.org",
|
|
514
|
+
"testnet-seed.bluematt.me",
|
|
515
|
+
],
|
|
516
|
+
:genesis_hash => "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943",
|
|
517
|
+
:proof_of_work_limit => 0x1d07fff8,
|
|
518
|
+
:alert_pubkeys => ["04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a"],
|
|
519
|
+
:known_nodes => [],
|
|
520
|
+
:checkpoints => {
|
|
521
|
+
# 542 contains invalid transaction
|
|
522
|
+
542 => "0000000083c1f82cf72c6724f7a317325806384b06408bce7a4327f418dfd5ad",
|
|
523
|
+
71018 => "000000000010dd93dc55541116b2744eb8f4c3b706df6e8512d231a03fb9e435",
|
|
524
|
+
}
|
|
525
|
+
},
|
|
526
|
+
|
|
527
|
+
:litecoin => {
|
|
528
|
+
:project => :litecoin,
|
|
529
|
+
:magic_head => "\xfb\xc0\xb6\xdb",
|
|
530
|
+
:address_version => "30",
|
|
531
|
+
:p2sh_version => "05",
|
|
532
|
+
:privkey_version => "ef",
|
|
533
|
+
:default_port => 9333,
|
|
534
|
+
:protocol_version => 60002,
|
|
535
|
+
:max_money => 84_000_000 * COIN,
|
|
536
|
+
:min_tx_fee => 2_000_000,
|
|
537
|
+
:coinbase_maturity => 100,
|
|
538
|
+
:retarget_interval => 2016,
|
|
539
|
+
:retarget_time => 302400, # 3.5 days
|
|
540
|
+
:min_relay_tx_fee => 1_000_000,
|
|
541
|
+
:dns_seeds => [
|
|
542
|
+
"dnsseed.litecointools.com",
|
|
543
|
+
"dnsseed.litecoinpool.org",
|
|
544
|
+
"dnsseed.ltc.xurious.com",
|
|
545
|
+
"dnsseed.koin-project.com",
|
|
546
|
+
"dnsseed.weminemnc.com",
|
|
547
|
+
],
|
|
548
|
+
:genesis_hash => "12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2",
|
|
549
|
+
:proof_of_work_limit => 0,
|
|
550
|
+
:alert_pubkeys => [],
|
|
551
|
+
:known_nodes => [],
|
|
552
|
+
:checkpoints => {
|
|
553
|
+
1 => "80ca095ed10b02e53d769eb6eaf92cd04e9e0759e5be4a8477b42911ba49c78f",
|
|
554
|
+
2 => "13957807cdd1d02f993909fa59510e318763f99a506c4c426e3b254af09f40d7",
|
|
555
|
+
1500 => "841a2965955dd288cfa707a755d05a54e45f8bd476835ec9af4402a2b59a2967",
|
|
556
|
+
4032 => "9ce90e427198fc0ef05e5905ce3503725b80e26afd35a987965fd7e3d9cf0846",
|
|
557
|
+
8064 => "eb984353fc5190f210651f150c40b8a4bab9eeeff0b729fcb3987da694430d70",
|
|
558
|
+
16128 => "602edf1859b7f9a6af809f1d9b0e6cb66fdc1d4d9dcd7a4bec03e12a1ccd153d",
|
|
559
|
+
23420 => "d80fdf9ca81afd0bd2b2a90ac3a9fe547da58f2530ec874e978fce0b5101b507",
|
|
560
|
+
50000 => "69dc37eb029b68f075a5012dcc0419c127672adb4f3a32882b2b3e71d07a20a6",
|
|
561
|
+
80000 => "4fcb7c02f676a300503f49c764a89955a8f920b46a8cbecb4867182ecdb2e90a",
|
|
562
|
+
120000 => "bd9d26924f05f6daa7f0155f32828ec89e8e29cee9e7121b026a7a3552ac6131",
|
|
563
|
+
161500 => "dbe89880474f4bb4f75c227c77ba1cdc024991123b28b8418dbbf7798471ff43",
|
|
564
|
+
179620 => "2ad9c65c990ac00426d18e446e0fd7be2ffa69e9a7dcb28358a50b2b78b9f709",
|
|
565
|
+
240000 => "7140d1c4b4c2157ca217ee7636f24c9c73db39c4590c4e6eab2e3ea1555088aa",
|
|
566
|
+
383640 => "2b6809f094a9215bafc65eb3f110a35127a34be94b7d0590a096c3f126c6f364",
|
|
567
|
+
}
|
|
568
|
+
},
|
|
569
|
+
|
|
570
|
+
:litecoin_testnet => {
|
|
571
|
+
:project => :litecoin,
|
|
572
|
+
:magic_head => "\xfc\xc1\xb7\xdc",
|
|
573
|
+
:address_version => "6f",
|
|
574
|
+
:p2sh_version => "c4",
|
|
575
|
+
:privkey_version => "ef",
|
|
576
|
+
:default_port => 19333,
|
|
577
|
+
:protocol_version => 60002,
|
|
578
|
+
:min_tx_fee => 2_000_000,
|
|
579
|
+
:min_relay_tx_fee => 1_000_000,
|
|
580
|
+
:coinbase_maturity => 100,
|
|
581
|
+
:retarget_interval => 2016,
|
|
582
|
+
:retarget_time => 302400, # 3.5 days
|
|
583
|
+
:max_money => 84_000_000 * COIN,
|
|
584
|
+
:dns_seeds => [
|
|
585
|
+
"testnet-seed.litecointools.com",
|
|
586
|
+
"testnet-seed.weminemnc.com",
|
|
587
|
+
],
|
|
588
|
+
:genesis_hash => "f5ae71e26c74beacc88382716aced69cddf3dffff24f384e1808905e0188f68f",
|
|
589
|
+
:proof_of_work_limit => 0,
|
|
590
|
+
:alert_pubkeys => [],
|
|
591
|
+
:known_nodes => [],
|
|
592
|
+
:checkpoints => {}
|
|
593
|
+
},
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
:freicoin => {
|
|
597
|
+
:project => :freicoin,
|
|
598
|
+
:magic_head => "\x2c\xfe\x7e\x6d",
|
|
599
|
+
:address_version => "00",
|
|
600
|
+
:p2sh_version => "05",
|
|
601
|
+
:privkey_version => "80",
|
|
602
|
+
:default_port => 8639,
|
|
603
|
+
:protocol_version => 60002,
|
|
604
|
+
:max_money => 21_000_000 * COIN,
|
|
605
|
+
:min_tx_fee => 50_000,
|
|
606
|
+
:min_relay_tx_fee => 10_000,
|
|
607
|
+
:dns_seeds => [ "seed.freico.in", "fledge.freico.in" ],
|
|
608
|
+
:genesis_hash => "000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c",
|
|
609
|
+
:proof_of_work_limit => 0,
|
|
610
|
+
:alert_pubkeys => [],
|
|
611
|
+
:known_nodes => [],
|
|
612
|
+
:checkpoints => {
|
|
613
|
+
10080 => "00000000003ff9c4b806639ec4376cc9acafcdded0e18e9dbcc2fc42e8e72331",
|
|
614
|
+
15779 => "000000000003eb31742b35f5efd8ffb5cdd19dcd8e82cdaad90e592c450363b6",
|
|
615
|
+
}
|
|
616
|
+
},
|
|
617
|
+
|
|
618
|
+
:namecoin => {
|
|
619
|
+
:project => :namecoin,
|
|
620
|
+
:magic_head => "\xF9\xBE\xB4\xFE",
|
|
621
|
+
:address_version => "34",
|
|
622
|
+
:default_port => 8334,
|
|
623
|
+
:protocol_version => 35000,
|
|
624
|
+
:max_money => 21_000_000 * COIN,
|
|
625
|
+
:min_tx_fee => 50_000,
|
|
626
|
+
:min_relay_tx_fee => 10_000,
|
|
627
|
+
:dns_seeds => [],
|
|
628
|
+
:genesis_hash => "000000000062b72c5e2ceb45fbc8587e807c155b0da735e6483dfba2f0a9c770",
|
|
629
|
+
:proof_of_work_limit => 0x1d00ffff,
|
|
630
|
+
:known_nodes => ["bitcoin.tunl.in", "webbtc.com", "178.32.31.41",
|
|
631
|
+
"78.47.86.43", "69.164.206.88", ""],
|
|
632
|
+
:checkpoints => {
|
|
633
|
+
0 => "000000000062b72c5e2ceb45fbc8587e807c155b0da735e6483dfba2f0a9c770",
|
|
634
|
+
19200 => "d8a7c3e01e1e95bcee015e6fcc7583a2ca60b79e5a3aa0a171eddd344ada903d",
|
|
635
|
+
24000 => "425ab0983cf04f43f346a4ca53049d0dc2db952c0a68eb0b55c3bb64108d5371",
|
|
636
|
+
97778 => "7553b1e43da01cfcda4335de1caf623e941d43894bd81c2af27b6582f9d83c6f",
|
|
637
|
+
}
|
|
638
|
+
},
|
|
639
|
+
|
|
640
|
+
:namecoin_testnet => {
|
|
641
|
+
:project => :namecoin,
|
|
642
|
+
:magic_head => "\xFA\xBF\xB5\xFE",
|
|
643
|
+
:address_version => "34",
|
|
644
|
+
:default_port => 18334,
|
|
645
|
+
:protocol_version => 35000,
|
|
646
|
+
:min_tx_fee => 50_000,
|
|
647
|
+
:min_relay_tx_fee => 10_000,
|
|
648
|
+
:max_money => 21_000_000 * COIN,
|
|
649
|
+
:dns_seeds => [],
|
|
650
|
+
:genesis_hash => "00000001f8ab0d14bceaeb50d163b0bef15aecf62b87bd5f5c864d37f201db97",
|
|
651
|
+
:proof_of_work_limit => 0x1d00ffff,
|
|
652
|
+
:known_nodes => ["178.32.31.41"],
|
|
653
|
+
:checkpoints => {
|
|
654
|
+
0 => "000000000062b72c5e2ceb45fbc8587e807c155b0da735e6483dfba2f0a9c770",
|
|
655
|
+
|
|
656
|
+
}
|
|
657
|
+
},
|
|
368
658
|
}
|
|
369
|
-
|
|
659
|
+
|
|
370
660
|
end
|