#!/usr/bin/env ruby $:.unshift( File.expand_path("../../lib", __FILE__) ) require 'bitcoin' require 'optparse' require 'fileutils' Bitcoin.require_dependency :eventmachine Bitcoin.require_dependency :json defaults = Bitcoin::Network::Node::DEFAULT_CONFIG options = Bitcoin::Config.load(defaults, :blockchain) optparse = OptionParser.new do |opts| opts.banner = "Usage: bitcoin_node [options]" opts.separator("\nAvailable options:\n") opts.on("-c", "--config FILE", "Config file (default: #{Bitcoin::Config::CONFIG_PATHS})") do |file| options = Bitcoin::Config.load_file(options, file, :blockchain) end opts.on("-n", "--network [NETWORK]", "User Network (default: #{options[:network]})") do |network| options[:network] = network end opts.on("--command [HOST:PORT]", "Command socket (default: #{options[:command].join(':')})") do |command| options[:command] = command.split(":") end opts.on("-l", "--listen [HOST:PORT]", "Listen address/port (default: #{options[:listen].join(':')})") do |listen| options[:listen] = listen.split(":") end opts.on("--connect [HOST:PORT]", "Hosts to connect to (default: #{options[:connect].map{|c|c.join(':')}.join(',')})") do |connect| connect.split(",").each do |host| options[:connect] << host.split(":") end end opts.on("-s", "--storage [BACKEND::CONFIG]", "Use storage backend (default: #{options[:storage]})") do |storage| options[:storage] = storage end opts.on("--skip-validation", "Skip validation of blocks and transactions") do options[:skip_validation] = true end opts.on("--check-blocks COUNT", "Check consistency of COUNT latest blocks; -1 for all (default: 1000)") do |check| options[:check_blocks] = check.to_i end opts.on("--ho", "--headers-only", "Download only block headers") do options[:headers_only] = true end opts.on("-d", "--dns", "Use DNS seeds (default)") do options[:dns] = true end opts.on("--nd", "--no-dns", "Don't use DNS seeds") do options[:dns] = false end opts.on("--epoll", "Enable epoll support") do options[:epoll] = true end opts.on("--epoll-limit [NUM]", "Increase socket descriptor limit to NUM") do |num| options[:epoll_limit] = num.to_i end opts.on("--epoll-user [NAME]", "Set effective user after increasing socket descriptor limit") do |user| options[:epoll_user] = user end opts.on("--mco", "--max-connections-out COUNT", "Maximum number of outgoing connections (default: #{options[:max][:connections_out]})") do |count| options[:max][:connections_out] = count.to_i end opts.on("--mci", "--max-connections-in COUNT", "Maximum number of incoming connections (default: #{options[:max][:connections_in]})") do |count| options[:max][:connections_in] = count.to_i end [:addr, :queue, :inv, :unconfirmed].each do |name| opts.on("--m#{name.to_s[0]}", "--max-#{name} [COUNT]", "Max #{name} (default: #{options[:max][name]})") do |count| options[:max][name] = count.to_i end end [:queue, :inv_queue, :blocks, :addrs, :connect].each do |name| opts.on("--i#{name.to_s[0]}", "--interval-#{name} [SECONDS]", "Interval for #{name} worker (default: #{options[:intervals][name]})") do |sec| options[:intervals][name] = sec.to_i end end [:network, :storage].each do |name| opts.on("--l#{name.to_s[0]}", "--log-#{name} [LEVEL]", "Log level for #{name} (default: #{options[:log][name]})") do |level| options[:log][name] = level.to_sym end end opts.on("--import DIR", "Import blk*.dat files from DIR") do |dir| options[:import] = dir end opts.on("-v", "--verbose", "Set all loggers to debug") do options[:log].each_key {|k| options[:log][k] = :debug } end opts.on("-q", "--quiet", "Set all loggers to warn") do options[:log].each_key {|k| options[:log][k] = :warn } end opts.on( '-h', '--help', 'Display this screen' ) do puts opts; exit end end optparse.parse! Bitcoin.network = options[:network] FileUtils.mkdir_p File.join(ENV['HOME'], ".bitcoin-ruby/#{Bitcoin.network_name}") if ARGV.any? EM.run do Bitcoin::Network::CommandClient.connect(*options[:command]) do on_response do |cmd, data| unless cmd == "monitor" puts JSON.pretty_generate data EM.stop end end on_block do |block, depth| puts "block: #{block['hash']} (#{depth})" end on_tx do |tx, confirmations| puts "tx(#{confirmations}): #{tx['hash']}" end on_output do |tx_hash, address, value, confirmations| puts "output(#{confirmations}): tx #{tx_hash[0..8]}: #{address} received #{value.to_f / 1e8} BTC" end on_connection do |type, host| if type == "connected" puts "Connected: #{host['host']}:#{host['port']}" else puts "Disconnected: #{host.inspect}" end end on_connected do request(ARGV[0], *(ARGV[1] || "").split(" ")) end end end else node = Bitcoin::Network::Node.new(options) node.run end