lib/bitcoin/network/node.rb in bitcoin-ruby-0.0.5 vs lib/bitcoin/network/node.rb in bitcoin-ruby-0.0.6
- old
+ new
@@ -48,15 +48,20 @@
attr_accessor :relay_propagation
DEFAULT_CONFIG = {
:network => :bitcoin,
- :listen => ["0.0.0.0", Bitcoin.network[:default_port]],
+ :listen => ["0.0.0.0", nil],
:connect => [],
:command => ["127.0.0.1", 9999],
:storage => "utxo::sqlite://~/.bitcoin-ruby/<network>/blocks.db",
+ :announce => false,
+ :external_port => nil,
:mode => :full,
+ :cache_head => true,
+ :index_nhash => false,
+ :index_p2sh_type => false,
:dns => true,
:epoll_limit => 10000,
:epoll_user => nil,
:addr_file => "~/.bitcoin-ruby/<network>/peers.json",
:log => {
@@ -100,12 +105,13 @@
end
def set_store
backend, config = @config[:storage].split('::')
@store = Bitcoin::Storage.send(backend, {
- db: config, mode: @config[:mode], cache_head: true,
- skip_validation: @config[:skip_validation],
+ db: config, mode: @config[:mode], cache_head: @config[:cache_head],
+ skip_validation: @config[:skip_validation], index_nhash: @config[:index_nhash],
+ index_p2sh_type: @config[:index_p2sh_type],
log_level: @config[:log][:storage]}, ->(locator) {
peer = @connections.select(&:connected?).sample
peer.send_getblocks(locator)
})
@store.log.level = @config[:log][:storage]
@@ -249,10 +255,35 @@
exit 1
end
self.stop
end
+ subscribe(:block) do |blk, depth|
+ next unless @store.in_sync?
+ @log.debug { "Relaying block #{blk.hash}" }
+ @connections.each do |conn|
+ next unless conn.connected?
+ conn.send_inv(:block, blk.hash)
+ end
+ end
+
+ @store.subscribe(:block) do |blk, depth, chain|
+ if chain == 0 && blk.hash == @store.get_head.hash
+ @last_block_time = Time.now
+ push_notification(:block, [blk, depth])
+ blk.tx.each {|tx| @unconfirmed.delete(tx.hash) }
+ end
+ getblocks if chain == 2 && @store.in_sync?
+ end
+
+ @store.subscribe(:reorg) do |new_main, new_side|
+ @log.warn { "Reorg of #{new_side.size} blocks." }
+ new_main.each {|b| @log.debug { "new main: #{b}" } }
+ new_side.each {|b| @log.debug { "new side: #{b}" } }
+ push_notification(:reorg, [new_main, new_side])
+ end
+
end
end
# connect to peer at given +host+ / +port+
def connect_peer host, port
@@ -376,31 +407,17 @@
end
while obj = @queue.shift
begin
if obj[0].to_sym == :block
- if res = @store.send("new_#{obj[0]}", obj[1])
- if res[1] == 0 && obj[1].hash == @store.get_head.hash
- @last_block_time = Time.now
- push_notification(:block, [obj[1], res[0]])
- obj[1].tx.each {|tx| @unconfirmed.delete(tx.hash) }
- end
- getblocks if res[1] == 2 && @store.in_sync?
- end
+ @store.new_block(obj[1])
else
drop = @unconfirmed.size - @config[:max][:unconfirmed] + 1
drop.times { @unconfirmed.shift } if drop > 0
unless @unconfirmed[obj[1].hash]
@unconfirmed[obj[1].hash] = obj[1]
push_notification(:tx, [obj[1], 0])
-
- if @notifiers[:output]
- obj[1].out.each do |out|
- address = Bitcoin::Script.new(out.pk_script).get_address
- push_notification(:output, [obj[1].hash, address, out.value, 0])
- end
- end
end
end
rescue Bitcoin::Validation::ValidationError
@log.warn { "ValidationError storing #{obj[0]} #{obj[1].hash}: #{$!.message}" }
# File.open("./validation_error_#{obj[0]}_#{obj[1].hash}.bin", "w") {|f|
@@ -454,25 +471,49 @@
@external_ips.group_by(&:dup).values.max_by(&:size).first
rescue
@config[:listen][0]
end
+ # get the external port
+ # assume the same as local port if config option :external_port isn't given explicitly
+ def external_port
+ @config[:external_port] || @config[:listen][1] || Bitcoin.network[:default_port]
+ end
+
# push notification +message+ to +channel+
def push_notification channel, message
@notifiers[channel.to_sym].push(message) if @notifiers[channel.to_sym]
end
# subscribe to notification +channel+.
# available channels are: block, tx, output, connection.
# see CommandHandler for details.
def subscribe channel
@notifiers[channel.to_sym] ||= EM::Channel.new
- @notifiers[channel.to_sym].subscribe {|*data| yield(*data) }
+ @notifiers[channel.to_sym].subscribe do |*data|
+ begin
+ yield(*data)
+ rescue
+ p $!; puts *$@
+ end
+ end
end
+ def unsubscribe channel, id
+ @notifiers[channel.to_sym].unsubscribe(id)
+ end
+
# should the node accept new incoming connections?
def accept_connections?
- connections.select(&:incoming?).size >= config[:max][:connections_in]
+ connections.select(&:incoming?).size < config[:max][:connections_in]
+ end
+
+ # get Addr object for our own server
+ def addr
+ @addr = Bitcoin::P::Addr.new
+ @addr.time, @addr.service, @addr.ip, @addr.port =
+ Time.now.tv_sec, (1 << 0), external_ip, external_port
+ @addr
end
end
end