From 624abdbcd52461ff6375422cfd5f026e14ca2a2e Mon Sep 17 00:00:00 2001 From: comboy Date: Wed, 26 Mar 2014 19:29:34 +0100 Subject: [PATCH 1/9] fake blockchain generator + some simple performance test --- .gitignore | 1 + lib/bitcoin/builder.rb | 1 + spec/bitcoin/helpers/fake_blockchain.rb | 182 +++++++++++++++++++++++ spec/bitcoin/performance/storage_spec.rb | 41 +++++ spec/bitcoin/spec_helper.rb | 8 +- 5 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 spec/bitcoin/helpers/fake_blockchain.rb create mode 100644 spec/bitcoin/performance/storage_spec.rb diff --git a/.gitignore b/.gitignore index 4004bee9..6cd4effe 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ tmp/ log/ rdoc/ coverage/ +spec/bitcoin/fixtures/fake_chain *.conf *.db .rbx/ diff --git a/lib/bitcoin/builder.rb b/lib/bitcoin/builder.rb index 880b208e..099c4449 100644 --- a/lib/bitcoin/builder.rb +++ b/lib/bitcoin/builder.rb @@ -71,6 +71,7 @@ def time time def tx tx = nil tx ||= ( c = TxBuilder.new; yield c; c.tx ) @block.tx << tx + tx end # create the block according to values specified via DSL. diff --git a/spec/bitcoin/helpers/fake_blockchain.rb b/spec/bitcoin/helpers/fake_blockchain.rb new file mode 100644 index 00000000..82020a5f --- /dev/null +++ b/spec/bitcoin/helpers/fake_blockchain.rb @@ -0,0 +1,182 @@ +require_relative '../spec_helper' +require 'fileutils' + +Bitcoin::NETWORKS[:fake] = { + :project => :bitcoin, + :magic_head => "fake", + :address_version => "00", + :p2sh_version => "05", + :privkey_version => "80", + :default_port => 78333, + :coinbase_maturity => 0, + :protocol_version => 70001, + :max_money => 21_000_000 * 100_000_000, + :dns_seeds => [], + :genesis_hash => "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943", + :proof_of_work_limit => 553713663, + :alert_pubkeys => [], + :known_nodes => [], + :checkpoints => {}, + :min_tx_fee => 10_000, + :min_relay_tx_fee => 10_000, +} + +class Bitcoin::Validation::Block; def difficulty; true; end; end + + +# Small utility to generate fake blocks mostly to be able to test performance +# They are full from the start, so that we don't have to import 100K blocks to check +# how performance looks when storing or validating 1K transactions +class FakeBlockchain + + # Generate fake blockchain with +num+ number of blocks + # Blocks are provided as an argument to the block given to the method + # E.g. + # FakeBlockChain.generate(5) {|b| save_block(b) } + def self.generate(num = 50, opts = {}) + Bitcoin.network = :fake + srand 1337 + + default_opts = { + block_size: 950_000, # minimum block size + num_keys: 1000, # number of different keys being used + genesis_timestamp: Time.new(2009).to_i, + verbose: true, # print out debug information + } + + opts = default_opts.merge(opts) + + to_spend = [] # table of outputs that we can spend + lost_count = 0 # keeping track of lost coins + keys = Array.new(opts[:num_keys]) { Bitcoin::Key.generate } + timestamp = opts[:genesis_timestamp] + + genesis = Bitcoin::Builder.build_block do |blk| + blk.time timestamp + blk.prev_block "00"*32 + blk.tx do |t| + t.input {|i| i.coinbase } + t.output {|o| o.value 50*Bitcoin::COIN; o.script {|s| s.recipient keys[0].addr } } + end + end + Bitcoin.network[:genesis_hash] = genesis.hash + + to_spend << {tx: genesis.tx[0], tx_idx: 0, key: keys[0], value: 50e8} + + prev_block = genesis + + + num.times do |blk_i| + + timestamp += 600 + t0 = Time.now + + block = Bitcoin::Builder.build_block do |blk| + blk.time timestamp + blk.prev_block prev_block.hash + key0 = keys.sample + tx0 = blk.tx do |t| + t.input {|i| i.coinbase } + t.output {|o| o.value 50e8; o.script {|s| s.recipient key0.addr } } + end + + # We "lose" some coins, that is we decide never to spend some outputs + # It's to keep utxo growing without making block generation time growing + lost_count += to_spend.size + to_spend = to_spend.reject.with_index {|x,i| i==0 ? false : (((to_spend.size - i) / to_spend.size.to_f)**2 * rand > rand*0.2) } + lost_count -= to_spend.size + + # many txs vs many tx outputs in given block + many_outputs_prob = 0.5 * (rand ** 3) + + total_tx_size = 0 + + # generate tranasctions + loop do + # we want utxo to keep growing so we use many inputs only with some small probability + ins = to_spend[(rand(to_spend.size)).to_i..-1].sample(rand < 0.01 ? (rand(50) + 1) : 1) + total = ins.map{|i| i[:value]}.inject(:+) + next if total < 20_000 + + new_outs = [] + + tx = blk.tx do |t| + + # generate inputs + ins.map do |input| + t.input do |i| + i.prev_out input[:tx] + i.prev_out_index input[:tx_idx] + i.signature_key input[:key] + end + end + # remove outputs that we just used + ins.each {|i| to_spend.delete i} + + fee = 10_000 + # helper to split value randomly in a half + half_split = ->(v) { split = [rand, 0.1].max; [v*split, v*(1-split)] } + # helper to split value randomly to many pieces + value_split = ->(v, depth=0) {(depth < 10 && rand > 0.2) ? half_split[v].map{|x| value_split[x, depth+1]} : [v] } + + if rand < many_outputs_prob + # every now and then there are many outptus + out_values = value_split[total-fee].flatten.map {|x| x.round(8)} + out_values.each.with_index do |v,i| + key = keys.sample + t.output {|o| o.value v; o.script {|s| s.recipient key.addr }} + new_outs << {tx_idx: i, key: key, value: v} + end + else + # most txs seem to have 2 outputs + k1 = keys.sample + k2 = keys.sample + v1, v2 = half_split[total-fee] + t.output {|o| o.value v1; o.script {|s| s.recipient k1.addr }} + t.output {|o| o.value v2; o.script {|s| s.recipient k2.addr }} + new_outs << {tx_idx: 0, key: k1, value: v2} + new_outs << {tx_idx: 1, key: k2, value: v2} + end + end + + new_outs.each {|o| to_spend << {tx: tx}.merge(o) } # fun fact: the opposite merge is way slower + + total_tx_size += tx.to_payload.size + break if total_tx_size > opts[:block_size] + end + + # coinbase + to_spend << {tx: tx0, tx_idx: 0, key: key0, value: 50e8} + end + puts "depth #{blk_i}/#{num} \t txcount: #{block.tx.size} \t size: #{block.to_payload.size} \t utxo count: #{to_spend.size + lost_count} (#{to_spend.size}) \t ttg: #{'%.2f' % (Time.now - t0)}s" if opts[:verbose] + yield(block) + prev_block = block + end + true + end + + def self.prepare + Bitcoin.network = :fake + if File.exist? block_path(0) + genesis = Bitcoin::P::Block.new File.read block_path 0 + Bitcoin.network[:genesis_hash] = genesis.hash + else + STDERR.puts "\nFake blockchain not present, generating (go take a nap)..." + depth = 0 + FileUtils.mkdir_p fixtures_path "fake_chain" + generate(50) do |blk| + File.open(block_path(depth),'w') {|f| f.write blk.to_payload } + depth += 1 + end + end + end + + def self.block(depth) + Bitcoin::Protocol::Block.new File.read block_path depth + end + + def self.block_path(depth) + fixtures_path "fake_chain/#{depth}.blk" + end + +end diff --git a/spec/bitcoin/performance/storage_spec.rb b/spec/bitcoin/performance/storage_spec.rb new file mode 100644 index 00000000..31f523f2 --- /dev/null +++ b/spec/bitcoin/performance/storage_spec.rb @@ -0,0 +1,41 @@ +# encoding: ascii-8bit + +require_relative '../spec_helper' +require_relative '../helpers/fake_blockchain' +require 'benchmark' + +[ + [:sequel, :postgres] +].compact.each do |options| + + next unless storage = setup_db(*options) + + describe "#{storage.backend_name} block storage" do + + before do + @store = storage + @store.reset + @store.log.level = :error + class Bitcoin::Validation::Block; def difficulty; true; end; end + + FakeBlockchain.prepare + end + + it "block storage" do + + bm = Benchmark.measure do + bm = Benchmark.bm do |b| + 10.times do |i| + b.report("storing fake block ##{i}") { @store.new_block FakeBlockchain.block(i) } + end + end + end + puts '-'*80 + puts "TOTAL #{bm.format}" + + should.satisfy { "human" } + end + + + end +end diff --git a/spec/bitcoin/spec_helper.rb b/spec/bitcoin/spec_helper.rb index a80bace2..960e2182 100644 --- a/spec/bitcoin/spec_helper.rb +++ b/spec/bitcoin/spec_helper.rb @@ -20,11 +20,15 @@ require 'bitcoin' +def fixtures_path(relative_path) + File.join(File.dirname(__FILE__), 'fixtures', relative_path) +end + def fixtures_file(relative_path) - basedir = File.join(File.dirname(__FILE__), 'fixtures') - Bitcoin::Protocol.read_binary_file( File.join(basedir, relative_path) ) + Bitcoin::Protocol.read_binary_file( fixtures_path(relative_path) ) end + include Bitcoin::Builder # create block for given +prev+ block From 32314aa0a1cc3ecb7069a764e95d1b33f2de2e60 Mon Sep 17 00:00:00 2001 From: comboy Date: Wed, 26 Mar 2014 20:01:04 +0100 Subject: [PATCH 2/9] network :no_difficulty option to avoid monkey patching --- lib/bitcoin.rb | 1 + lib/bitcoin/validation.rb | 2 +- spec/bitcoin/helpers/fake_blockchain.rb | 2 +- spec/bitcoin/namecoin_spec.rb | 2 +- spec/bitcoin/performance/storage_spec.rb | 2 -- spec/bitcoin/storage/models_spec.rb | 9 ++------- spec/bitcoin/storage/reorg_spec.rb | 12 +++--------- spec/bitcoin/storage/storage_spec.rb | 9 ++------- 8 files changed, 11 insertions(+), 28 deletions(-) diff --git a/lib/bitcoin.rb b/lib/bitcoin.rb index a163f8d9..1d0ac04f 100644 --- a/lib/bitcoin.rb +++ b/lib/bitcoin.rb @@ -552,6 +552,7 @@ def self.network=(name) :target_spacing => 600, # block interval :max_money => 21_000_000 * COIN, :min_tx_fee => 10_000, + :no_difficulty => true, :min_relay_tx_fee => 10_000, :dns_seeds => [ "testnet-seed.bitcoin.petertodd.org", diff --git a/lib/bitcoin/validation.rb b/lib/bitcoin/validation.rb index 28df5c09..78a4fce3 100644 --- a/lib/bitcoin/validation.rb +++ b/lib/bitcoin/validation.rb @@ -109,7 +109,7 @@ def prev_hash # check that bits satisfy required difficulty def difficulty - return true if Bitcoin.network_name == :testnet3 + return true if Bitcoin.network[:no_difficulty] == true block.bits == next_bits_required || [block.bits, next_bits_required] end diff --git a/spec/bitcoin/helpers/fake_blockchain.rb b/spec/bitcoin/helpers/fake_blockchain.rb index 82020a5f..c93cf105 100644 --- a/spec/bitcoin/helpers/fake_blockchain.rb +++ b/spec/bitcoin/helpers/fake_blockchain.rb @@ -3,6 +3,7 @@ Bitcoin::NETWORKS[:fake] = { :project => :bitcoin, + :no_difficulty => true, :magic_head => "fake", :address_version => "00", :p2sh_version => "05", @@ -21,7 +22,6 @@ :min_relay_tx_fee => 10_000, } -class Bitcoin::Validation::Block; def difficulty; true; end; end # Small utility to generate fake blocks mostly to be able to test performance diff --git a/spec/bitcoin/namecoin_spec.rb b/spec/bitcoin/namecoin_spec.rb index d2f6a79a..516994ef 100644 --- a/spec/bitcoin/namecoin_spec.rb +++ b/spec/bitcoin/namecoin_spec.rb @@ -89,7 +89,7 @@ def set_rand rand; @rand = rand; end before do Bitcoin.network = :namecoin - class Bitcoin::Validation::Block; def difficulty; true; end; end + Bitcoin.network[:no_difficulty] = true class Bitcoin::Validation::Block; def min_timestamp; true; end; end Bitcoin.network[:proof_of_work_limit] = Bitcoin.encode_compact_bits("ff"*32) [:name_new, :name_firstupdate, :name_update].each {|type| diff --git a/spec/bitcoin/performance/storage_spec.rb b/spec/bitcoin/performance/storage_spec.rb index 31f523f2..35614681 100644 --- a/spec/bitcoin/performance/storage_spec.rb +++ b/spec/bitcoin/performance/storage_spec.rb @@ -16,8 +16,6 @@ @store = storage @store.reset @store.log.level = :error - class Bitcoin::Validation::Block; def difficulty; true; end; end - FakeBlockchain.prepare end diff --git a/spec/bitcoin/storage/models_spec.rb b/spec/bitcoin/storage/models_spec.rb index 830a2c5b..a71f5dcc 100644 --- a/spec/bitcoin/storage/models_spec.rb +++ b/spec/bitcoin/storage/models_spec.rb @@ -22,7 +22,7 @@ describe "Storage::Models (#{options[0].to_s.capitalize}Store, #{options[1]})" do before do - class Bitcoin::Validation::Block; def difficulty; true; end; end + Bitcoin.network[:no_difficulty] = true Bitcoin.network[:proof_of_work_limit] = Bitcoin.encode_compact_bits("ff"*32) @store = storage @@ -44,12 +44,7 @@ def @store.in_sync?; true; end end after do - class Bitcoin::Validation::Block - def difficulty - return true if Bitcoin.network_name == :testnet3 - block.bits == next_bits_required || [block.bits, next_bits_required] - end - end + Bitcoin.network.delete :no_difficulty end describe "Block" do diff --git a/spec/bitcoin/storage/reorg_spec.rb b/spec/bitcoin/storage/reorg_spec.rb index 018da0b1..55a75968 100644 --- a/spec/bitcoin/storage/reorg_spec.rb +++ b/spec/bitcoin/storage/reorg_spec.rb @@ -208,9 +208,9 @@ def @store.in_sync?; true; end # see https://bitcointalk.org/index.php?topic=46370.0 it "should pass reorg unit tests" do - # Disable difficulty checks. Hackish, should be replaced with some sane API.** - class Bitcoin::Validation::Block; def difficulty; true; end; end Bitcoin.network = :bitcoin + # Disable difficulty check + Bitcoin.network[:no_difficulty] = true @store.import "./spec/bitcoin/fixtures/reorg/blk_0_to_4.dat" @store.get_depth.should == 4 @store.get_head.hash.should =~ /000000002f264d65040/ @@ -228,14 +228,8 @@ class Bitcoin::Validation::Block; def difficulty; true; end; end balance("1NiEGXeURREqqMjCvjCeZn6SwEBZ9AdVet").should == 1000000000 balance("1KXFNhNtrRMfgbdiQeuJqnfD7dR4PhniyJ").should == 0 balance("1JyMKvPHkrCQd8jQrqTR1rBsAd1VpRhTiE").should == 14000000000 + Bitcoin.network.delete :no_difficulty Bitcoin.network = :testnet - # Re-enable difficulty checks. Hackish, should be replaced with some sane API. - class Bitcoin::Validation::Block - def difficulty - return true if Bitcoin.network_name == :testnet3 - block.bits == next_bits_required || [block.bits, next_bits_required] - end - end end end diff --git a/spec/bitcoin/storage/storage_spec.rb b/spec/bitcoin/storage/storage_spec.rb index 6103b8e9..6ef4799f 100644 --- a/spec/bitcoin/storage/storage_spec.rb +++ b/spec/bitcoin/storage/storage_spec.rb @@ -24,7 +24,7 @@ describe "Storage::Backends::#{options[0].to_s.capitalize}Store (#{options[1]})" do before do - class Bitcoin::Validation::Block; def difficulty; true; end; end + Bitcoin.network[:no_difficulty] = true Bitcoin.network[:proof_of_work_limit] = Bitcoin.encode_compact_bits("ff"*32) @store = storage @@ -46,12 +46,7 @@ def @store.in_sync?; true; end end after do - class Bitcoin::Validation::Block - def difficulty - return true if Bitcoin.network_name == :testnet3 - block.bits == next_bits_required || [block.bits, next_bits_required] - end - end + Bitcoin.network.delete :no_difficulty end it "should get backend name" do From 2ffaeb44da07152d5efc5a891b4e1d20b0bcc40a Mon Sep 17 00:00:00 2001 From: Marius Hanne Date: Fri, 28 Mar 2014 15:25:23 +0100 Subject: [PATCH 3/9] refactor FakeBlockchain to work around caching issue --- spec/bitcoin/helpers/fake_blockchain.rb | 45 +++++++++++++----------- spec/bitcoin/performance/storage_spec.rb | 4 +-- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/spec/bitcoin/helpers/fake_blockchain.rb b/spec/bitcoin/helpers/fake_blockchain.rb index c93cf105..d1a86f7b 100644 --- a/spec/bitcoin/helpers/fake_blockchain.rb +++ b/spec/bitcoin/helpers/fake_blockchain.rb @@ -29,11 +29,30 @@ # how performance looks when storing or validating 1K transactions class FakeBlockchain + # Initialize fake blockchain and generate +num_blocks+ starting blocks with given + # +opts+ (see #generate). + def initialize num = 50, opts = {} + Bitcoin.network = :fake + if File.exist? block_path(0) + genesis = Bitcoin::P::Block.new File.read block_path 0 + Bitcoin.network[:genesis_hash] = genesis.hash + else + STDERR.puts "\nFake blockchain not present, generating (go take a nap)..." + depth = 0 + FileUtils.mkdir_p fixtures_path "fake_chain" + generate(num, opts) do |blk| + File.open(block_path(depth),'w') {|f| f.write blk.to_payload } + depth += 1 + end + # return new instance because this one apparently has half the data cached now + self.class.new + end + end + # Generate fake blockchain with +num+ number of blocks # Blocks are provided as an argument to the block given to the method - # E.g. - # FakeBlockChain.generate(5) {|b| save_block(b) } - def self.generate(num = 50, opts = {}) + # fake_chain.generate(5) {|b| save_block(b) } + def generate(num = 50, opts = {}) Bitcoin.network = :fake srand 1337 @@ -155,27 +174,11 @@ def self.generate(num = 50, opts = {}) true end - def self.prepare - Bitcoin.network = :fake - if File.exist? block_path(0) - genesis = Bitcoin::P::Block.new File.read block_path 0 - Bitcoin.network[:genesis_hash] = genesis.hash - else - STDERR.puts "\nFake blockchain not present, generating (go take a nap)..." - depth = 0 - FileUtils.mkdir_p fixtures_path "fake_chain" - generate(50) do |blk| - File.open(block_path(depth),'w') {|f| f.write blk.to_payload } - depth += 1 - end - end - end - - def self.block(depth) + def block(depth) Bitcoin::Protocol::Block.new File.read block_path depth end - def self.block_path(depth) + def block_path(depth) fixtures_path "fake_chain/#{depth}.blk" end diff --git a/spec/bitcoin/performance/storage_spec.rb b/spec/bitcoin/performance/storage_spec.rb index 35614681..fcc233fd 100644 --- a/spec/bitcoin/performance/storage_spec.rb +++ b/spec/bitcoin/performance/storage_spec.rb @@ -16,7 +16,7 @@ @store = storage @store.reset @store.log.level = :error - FakeBlockchain.prepare + @fake_chain = FakeBlockchain.new 10 end it "block storage" do @@ -24,7 +24,7 @@ bm = Benchmark.measure do bm = Benchmark.bm do |b| 10.times do |i| - b.report("storing fake block ##{i}") { @store.new_block FakeBlockchain.block(i) } + b.report("storing fake block ##{i}") { @store.new_block @fake_chain.block(i) } end end end From 0a34508352196f47067fbb1bfb03fa9cc2b5ab69 Mon Sep 17 00:00:00 2001 From: comboy Date: Sat, 29 Mar 2014 21:37:36 +0100 Subject: [PATCH 4/9] fix fake chain generation genesis block was not being yield, so the blocki #1 was becoming genesis * moved parsing blocks from disk away from the benchmark * added check to make sure block was really stored in the main chain --- spec/bitcoin/helpers/fake_blockchain.rb | 12 +++++------- spec/bitcoin/performance/storage_spec.rb | 10 ++++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/spec/bitcoin/helpers/fake_blockchain.rb b/spec/bitcoin/helpers/fake_blockchain.rb index d1a86f7b..8b8151f4 100644 --- a/spec/bitcoin/helpers/fake_blockchain.rb +++ b/spec/bitcoin/helpers/fake_blockchain.rb @@ -31,7 +31,7 @@ class FakeBlockchain # Initialize fake blockchain and generate +num_blocks+ starting blocks with given # +opts+ (see #generate). - def initialize num = 50, opts = {} + def initialize(num = 50, opts = {}) Bitcoin.network = :fake if File.exist? block_path(0) genesis = Bitcoin::P::Block.new File.read block_path 0 @@ -44,8 +44,6 @@ def initialize num = 50, opts = {} File.open(block_path(depth),'w') {|f| f.write blk.to_payload } depth += 1 end - # return new instance because this one apparently has half the data cached now - self.class.new end end @@ -53,7 +51,6 @@ def initialize num = 50, opts = {} # Blocks are provided as an argument to the block given to the method # fake_chain.generate(5) {|b| save_block(b) } def generate(num = 50, opts = {}) - Bitcoin.network = :fake srand 1337 default_opts = { @@ -66,19 +63,20 @@ def generate(num = 50, opts = {}) opts = default_opts.merge(opts) to_spend = [] # table of outputs that we can spend - lost_count = 0 # keeping track of lost coins + lost_count = 0 # keeping track of lost coins keys = Array.new(opts[:num_keys]) { Bitcoin::Key.generate } timestamp = opts[:genesis_timestamp] genesis = Bitcoin::Builder.build_block do |blk| blk.time timestamp - blk.prev_block "00"*32 + blk.prev_block "00"*32 blk.tx do |t| t.input {|i| i.coinbase } t.output {|o| o.value 50*Bitcoin::COIN; o.script {|s| s.recipient keys[0].addr } } end end Bitcoin.network[:genesis_hash] = genesis.hash + yield(genesis) to_spend << {tx: genesis.tx[0], tx_idx: 0, key: keys[0], value: 50e8} @@ -167,7 +165,7 @@ def generate(num = 50, opts = {}) # coinbase to_spend << {tx: tx0, tx_idx: 0, key: key0, value: 50e8} end - puts "depth #{blk_i}/#{num} \t txcount: #{block.tx.size} \t size: #{block.to_payload.size} \t utxo count: #{to_spend.size + lost_count} (#{to_spend.size}) \t ttg: #{'%.2f' % (Time.now - t0)}s" if opts[:verbose] + puts "depth #{blk_i+1}/#{num} \t txcount: #{block.tx.size} \t size: #{block.to_payload.size} \t utxo count: #{to_spend.size + lost_count} (#{to_spend.size}) \t ttg: #{'%.2f' % (Time.now - t0)}s" if opts[:verbose] yield(block) prev_block = block end diff --git a/spec/bitcoin/performance/storage_spec.rb b/spec/bitcoin/performance/storage_spec.rb index fcc233fd..a48e8018 100644 --- a/spec/bitcoin/performance/storage_spec.rb +++ b/spec/bitcoin/performance/storage_spec.rb @@ -20,18 +20,20 @@ end it "block storage" do + blocks = (0..10).to_a.map{|i| @fake_chain.block(i) } bm = Benchmark.measure do bm = Benchmark.bm do |b| - 10.times do |i| - b.report("storing fake block ##{i}") { @store.new_block @fake_chain.block(i) } + blocks.each.with_index do |blk,i| + b.report("storing fake block ##{i}") do + depth, chain = @store.new_block blk + chain.should == 0 + end end end end puts '-'*80 puts "TOTAL #{bm.format}" - - should.satisfy { "human" } end From cc46b080ec62fea3a92cd820862bfc92d13d671f Mon Sep 17 00:00:00 2001 From: comboy Date: Mon, 17 Mar 2014 19:51:04 +0100 Subject: [PATCH 5/9] check for already spent outputs with a single query during block validation + add index on txin (prev_out, prev_out_index) --- .../007_add_prev_out_index_index.rb | 16 +++++++++++++ lib/bitcoin/validation.rb | 24 +++++++++++++++---- 2 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 lib/bitcoin/storage/sequel/migrations/007_add_prev_out_index_index.rb diff --git a/lib/bitcoin/storage/sequel/migrations/007_add_prev_out_index_index.rb b/lib/bitcoin/storage/sequel/migrations/007_add_prev_out_index_index.rb new file mode 100644 index 00000000..cdf6b49d --- /dev/null +++ b/lib/bitcoin/storage/sequel/migrations/007_add_prev_out_index_index.rb @@ -0,0 +1,16 @@ +Sequel.migration do + + up do + + @log.info { "Running migration #{__FILE__}" } + + # Naming seems to be different on different adapters and sequel's + # "drop_index(:txin, :prev_out)" doesn't seem to be handling it correctly + execute "DROP INDEX IF EXISTS txin_prev_out_idx;" + execute "DROP INDEX IF EXISTS txin_prev_out_index;" + + add_index :txin, [:prev_out, :prev_out_index] + + end + +end diff --git a/lib/bitcoin/validation.rb b/lib/bitcoin/validation.rb index 28df5c09..a50188a2 100644 --- a/lib/bitcoin/validation.rb +++ b/lib/bitcoin/validation.rb @@ -155,19 +155,28 @@ def transactions_context end def tx_validators - @tx_validators ||= block.tx[1..-1].map {|tx| tx.validator(store, block, tx_cache: prev_txs_hash)} + @tx_validators ||= block.tx[1..-1].map {|tx| tx.validator(store, block, tx_cache: prev_txs_hash, spent_outs_txins: spent_outs_txins)} end # Fetch all prev_txs that will be needed for validation # Used for optimization in tx validators def prev_txs_hash @prev_tx_hash ||= ( - inputs = block.tx.map {|tx| tx.in }.flatten + inputs = block.tx[1..-1].map {|tx| tx.in }.flatten txs = store.get_txs(inputs.map{|i| i.prev_out.reverse_hth }) Hash[*txs.map {|tx| [tx.hash, tx] }.flatten] ) end + def spent_outs_txins + @spent_outs_txins ||= ( + next_ins = store.get_txins_for_txouts(block.tx[1..-1].map(&:in).flatten.map.with_index {|txin, idx| [txin.prev_out.reverse_hth, txin.prev_out_index] }) + # OPTIMIZE normally next_ins is empty, but in case of some reorgs this could be pain, becouse get_tx is heavy + # and all we need is a few joins (but some general abstraction is needed for that in storage) + next_ins.select {|i| i.get_tx.blk_id } + ) + end + def next_bits_required retarget = (Bitcoin.network[:retarget_interval] || Bitcoin::RETARGET_INTERVAL) index = (prev_block.depth + 1) / retarget @@ -234,10 +243,13 @@ def validate(opts = {}) # setup new validator for given +tx+, validating context with +store+. # also needs the +block+ to find prev_outs for chains of tx inside one block. - # opts+ may include :tx_cache which should be hash with transactiotns including prev_txs + # opts+ may include: + # * :tx_cache which should be hash with transactiotns including prev_txs + # * :spent_outs_txins txins for txouts that were already spent def initialize(tx, store, block = nil, opts = {}) @tx, @store, @block, @errors = tx, store, block, [] @tx_cache = opts[:tx_cache] + @spent_outs_txins = opts[:spent_outs_txins] end # check that tx hash matches data @@ -308,9 +320,11 @@ def signatures # check that none of the prev_outs are already spent in the main chain or in the current block def not_spent + # if we received cached spents, use it + return @spent_outs_txins.empty? if @spent_outs_txins + # find all spent txouts - # OPTIMIZE: these could be fetched in one query for all transactions and cached - next_ins = store.get_txins_for_txouts(tx.in.map.with_index {|txin, idx| [prev_txs[idx].hash, txin.prev_out_index] }) + next_ins = store.get_txins_for_txouts(tx.in.map.with_index {|txin, idx| [txin.prev_out.reverse_hth, txin.prev_out_index] }) # no txouts found spending these txins, we can safely return true return true if next_ins.empty? From ca0c6c2491a80ed23a510066c9f6162abd5aa4de Mon Sep 17 00:00:00 2001 From: Marius Hanne Date: Sat, 29 Mar 2014 22:07:48 +0100 Subject: [PATCH 6/9] don't log "relaying block ..." before deciding if the block is relayed --- lib/bitcoin/network/node.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bitcoin/network/node.rb b/lib/bitcoin/network/node.rb index 7bbc304e..316dcdd3 100644 --- a/lib/bitcoin/network/node.rb +++ b/lib/bitcoin/network/node.rb @@ -254,8 +254,8 @@ def run end subscribe(:block) do |blk, depth| - @log.debug { "Relaying block #{blk.hash}" } 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) From f0b5bca7da0d388311df37ce9f81473a5c7beefa Mon Sep 17 00:00:00 2001 From: Marius Hanne Date: Thu, 27 Mar 2014 05:13:58 +0100 Subject: [PATCH 7/9] use storage config instead of asking to build tx.nhash index during migrations --- .../sequel/migrations/006_add_tx_nhash.rb | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/lib/bitcoin/storage/sequel/migrations/006_add_tx_nhash.rb b/lib/bitcoin/storage/sequel/migrations/006_add_tx_nhash.rb index fb390dfe..d3601119 100644 --- a/lib/bitcoin/storage/sequel/migrations/006_add_tx_nhash.rb +++ b/lib/bitcoin/storage/sequel/migrations/006_add_tx_nhash.rb @@ -11,23 +11,20 @@ def process_block blk end end - if $stdin.tty? - print "Do you want to build an index for normalized tx hashes? (~1GB) (y/N) " - if $0 =~ /spec/ || $stdin.gets.chomp == "y" - puts "Building normalized hash index..." + if @store.config[:index_nhash] + puts "Building normalized hash index..." - add_column :tx, :nhash, :bytea + add_column :tx, :nhash, :bytea - if blk = @store.get_block_by_depth(0) + if blk = @store.get_block_by_depth(0) + process_block(blk) + while blk = blk.get_next_block process_block(blk) - while blk = blk.get_next_block - process_block(blk) - end end + end - add_index :tx, :nhash + add_index :tx, :nhash - end end end From 3c9acebabe52d637f9917407210c78cc3594d4d5 Mon Sep 17 00:00:00 2001 From: Michael Witrant Date: Sun, 4 May 2014 09:10:02 +0200 Subject: [PATCH 8/9] Imported ppcoin support from Julian Langschaedel on commit cc107af98b302ae3110625b67f77c88feaeb05f8 --- lib/bitcoin.rb | 33 ++++++++++++++ lib/bitcoin/protocol/block.rb | 8 ++++ lib/bitcoin/protocol/tx.rb | 15 ++++++- ...515c7510767f42ec9e40c5fba56775ff296658.bin | Bin 0 -> 267 bytes ...15c7510767f42ec9e40c5fba56775ff296658.json | 41 ++++++++++++++++++ ...2a4677d8957e87c508eaa4fd7eb1c880cd27e3.bin | Bin 0 -> 230 bytes ...a4677d8957e87c508eaa4fd7eb1c880cd27e3.json | 41 ++++++++++++++++++ spec/bitcoin/protocol/block_spec.rb | 23 ++++++++++ 8 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 spec/bitcoin/fixtures/ppcoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658.bin create mode 100644 spec/bitcoin/fixtures/ppcoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658.json create mode 100644 spec/bitcoin/fixtures/ppcoin-genesis-block-0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3.bin create mode 100644 spec/bitcoin/fixtures/ppcoin-genesis-block-0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3.json diff --git a/lib/bitcoin.rb b/lib/bitcoin.rb index 1d0ac04f..b594284e 100644 --- a/lib/bitcoin.rb +++ b/lib/bitcoin.rb @@ -702,6 +702,39 @@ def self.network=(name) } }, + + :ppcoin => { + :project => :ppcoin, + :magic_head => "\xe6\xe8\xe9\xe5", + :address_version => "37", + :p2sh_version => "75", + :privkey_version => "b7", + :default_port => 9901, + :dns_seeds => [ "seed.ppcoin.net" ], + :genesis_hash => "0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3", + :proof_of_work_limit => 0, + :alert_pubkeys => [], + :known_nodes => [ "theseven.bounceme.net", "cryptocoinexplorer.com" ], + :checkpoints => [ + [19080, "000000000000bca54d9ac17881f94193fd6a270c1bb21c3bf0b37f588a40dbd7"], + [30583, "d39d1481a7eecba48932ea5913be58ad3894c7ee6d5a8ba8abeb772c66a6696e"], + ] + }, + + :ppcoin_testnet => { + :project => :ppcoin, + :magic_head => "\xcb\xf2\xc0\xef", + :address_version => "6f", + :p2sh_version => "c4", + :privkey_version => "ef", + :default_port => 9903, + :dns_seeds => [ "tnseed.ppcoin.net" ], + :genesis_hash => "00000001f757bb737f6596503e17cd17b0658ce630cc727c0cca81aec47c9f06", + :proof_of_work_limit => 0, + :alert_pubkeys => [], + :known_nodes => [], + :checkpoints => [] + }, } end diff --git a/lib/bitcoin/protocol/block.rb b/lib/bitcoin/protocol/block.rb index 119f8dfb..5f0c2ba5 100644 --- a/lib/bitcoin/protocol/block.rb +++ b/lib/bitcoin/protocol/block.rb @@ -90,6 +90,11 @@ def parse_data_from_io(buf, header_only=false) @tx << t } + if Bitcoin.network_project == :ppcoin + @block_signature = Protocol.unpack_var_string_from_io(buf) + @block_signature ||= "" + end + @payload = to_payload buf end @@ -121,6 +126,7 @@ def to_payload return head if @tx.size == 0 head << Protocol.pack_var_int(@tx.size) @tx.each{|tx| head << tx.to_payload } + head << Protocol.pack_var_string(@block_signature) if Bitcoin.network_project == :ppcoin head end @@ -135,6 +141,7 @@ def to_hash 'mrkl_tree' => Bitcoin.hash_mrkl_tree( @tx.map{|i| i.hash } ) } h['aux_pow'] = @aux_pow.to_hash if @aux_pow + h['signature'] = @block_signature.reverse_hth if Bitcoin.network_project == :ppcoin h end @@ -196,6 +203,7 @@ def self.from_hash(h, do_raise=true) if h['tx'].any? && !Bitcoin.freicoin? (raise "Block merkle root mismatch! Block: #{h['hash']}" unless verify_mrkl_root) if do_raise end + @block_signature = h['signature'].htb_reverse if Bitcoin.network_project == :ppcoin } blk end diff --git a/lib/bitcoin/protocol/tx.rb b/lib/bitcoin/protocol/tx.rb index 9361d4ab..57f68e1d 100644 --- a/lib/bitcoin/protocol/tx.rb +++ b/lib/bitcoin/protocol/tx.rb @@ -41,6 +41,7 @@ def binary_hash # create tx from raw binary +data+ def initialize(data=nil) @ver, @lock_time, @in, @out = 1, 0, [], [] + @time = Time.now.to_i if Bitcoin.network_project == :ppcoin parse_data_from_io(data) if data end @@ -63,6 +64,8 @@ def parse_data_from_io(data) @ver = buf.read(4).unpack("V")[0] + @time = buf.read(4).unpack("V")[0] if Bitcoin.network_project == :ppcoin + in_size = Protocol.unpack_var_int_from_io(buf) @in = [] in_size.times{ @in << TxIn.from_io(buf) } @@ -94,7 +97,9 @@ def to_payload pout = "" @out.each{|output| pout << output.to_payload } - [@ver].pack("V") << Protocol.pack_var_int(@in.size) << pin << Protocol.pack_var_int(@out.size) << pout << [@lock_time].pack("V") + result = [@ver].pack("V") + result << [@time].pack("V") if Bitcoin.network_project == :ppcoin + result << Protocol.pack_var_int(@in.size) << pin << Protocol.pack_var_int(@out.size) << pout << [@lock_time].pack("V") end @@ -150,7 +155,11 @@ def signature_hash_for_input(input_idx, subscript, hash_type=nil) in_size, pin = Protocol.pack_var_int(1), [ pin[input_idx] ] end - buf = [ [@ver].pack("V"), in_size, pin, out_size, pout, [@lock_time, hash_type].pack("VV") ].join + if Bitcoin.network_project == :ppcoin + buf = [ [@ver, @time].pack("VV"), in_size, pin, out_size, pout, [@lock_time, hash_type].pack("VV") ].join + else + buf = [ [@ver].pack("V"), in_size, pin, out_size, pout, [@lock_time, hash_type].pack("VV") ].join + end Digest::SHA256.digest( Digest::SHA256.digest( buf ) ) end @@ -185,6 +194,7 @@ def to_hash(options = {}) 'in' => @in.map{|i| i.to_hash(options) }, 'out' => @out.map{|o| o.to_hash(options) } } + h['time'] = @time if Bitcoin.network_project == :ppcoin h end @@ -205,6 +215,7 @@ def self.from_hash(h) tx.ver, tx.lock_time = *h.values_at('ver', 'lock_time') h['in'] .each{|input| tx.add_in TxIn.from_hash(input) } h['out'].each{|output| tx.add_out TxOut.from_hash(output) } + tx.instance_eval{ @time = h['time'] } if Bitcoin.network_project == :ppcoin tx.instance_eval{ @hash = hash_from_payload(@payload = to_payload) } tx end diff --git a/spec/bitcoin/fixtures/ppcoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658.bin b/spec/bitcoin/fixtures/ppcoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658.bin new file mode 100644 index 0000000000000000000000000000000000000000..9351d0b072f136d3372394977a3607d7bca5b577 GIT binary patch literal 267 zcmZQ%U|@KxezxJn#=5^tUU3|4ubXYkK&J zzBilKfYiAgxH2g+OgxeBBXjNJgTYx-j{kfr^;~O#bHlewiZhIOi>;zxWgTTwFnw}s j{nw51zI!Jx&^bO=p=O`4@Tr}K60y$|QRmM-)-))Ts>>f)APt^K+-_0c*3|Nk?{u5NnT z$jAsZZ&9R90Eos5{sTb>3rHUmzq+??Vo82pX0d{SxvpcVyRMOep^-vBVo_pFPHK*V zb7@ggYF=_?YO#W2UW!6UMyf(kequ^)Vu3 Date: Mon, 5 May 2014 07:39:49 +0200 Subject: [PATCH 9/9] Renamed ppcoin to peercoin --- lib/bitcoin.rb | 8 +++--- lib/bitcoin/protocol/block.rb | 8 +++--- lib/bitcoin/protocol/tx.rb | 12 ++++---- ...15c7510767f42ec9e40c5fba56775ff296658.bin} | Bin ...5c7510767f42ec9e40c5fba56775ff296658.json} | 0 ...a4677d8957e87c508eaa4fd7eb1c880cd27e3.bin} | Bin ...4677d8957e87c508eaa4fd7eb1c880cd27e3.json} | 0 spec/bitcoin/protocol/block_spec.rb | 26 +++++++++--------- 8 files changed, 27 insertions(+), 27 deletions(-) rename spec/bitcoin/fixtures/{ppcoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658.bin => peercoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658.bin} (100%) rename spec/bitcoin/fixtures/{ppcoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658.json => peercoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658.json} (100%) rename spec/bitcoin/fixtures/{ppcoin-genesis-block-0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3.bin => peercoin-genesis-block-0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3.bin} (100%) rename spec/bitcoin/fixtures/{ppcoin-genesis-block-0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3.json => peercoin-genesis-block-0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3.json} (100%) diff --git a/lib/bitcoin.rb b/lib/bitcoin.rb index b594284e..4f2e73e2 100644 --- a/lib/bitcoin.rb +++ b/lib/bitcoin.rb @@ -703,8 +703,8 @@ def self.network=(name) } }, - :ppcoin => { - :project => :ppcoin, + :peercoin => { + :project => :peercoin, :magic_head => "\xe6\xe8\xe9\xe5", :address_version => "37", :p2sh_version => "75", @@ -721,8 +721,8 @@ def self.network=(name) ] }, - :ppcoin_testnet => { - :project => :ppcoin, + :peercoin_testnet => { + :project => :peercoin, :magic_head => "\xcb\xf2\xc0\xef", :address_version => "6f", :p2sh_version => "c4", diff --git a/lib/bitcoin/protocol/block.rb b/lib/bitcoin/protocol/block.rb index 5f0c2ba5..68c66a13 100644 --- a/lib/bitcoin/protocol/block.rb +++ b/lib/bitcoin/protocol/block.rb @@ -90,7 +90,7 @@ def parse_data_from_io(buf, header_only=false) @tx << t } - if Bitcoin.network_project == :ppcoin + if Bitcoin.network_project == :peercoin @block_signature = Protocol.unpack_var_string_from_io(buf) @block_signature ||= "" end @@ -126,7 +126,7 @@ def to_payload return head if @tx.size == 0 head << Protocol.pack_var_int(@tx.size) @tx.each{|tx| head << tx.to_payload } - head << Protocol.pack_var_string(@block_signature) if Bitcoin.network_project == :ppcoin + head << Protocol.pack_var_string(@block_signature) if Bitcoin.network_project == :peercoin head end @@ -141,7 +141,7 @@ def to_hash 'mrkl_tree' => Bitcoin.hash_mrkl_tree( @tx.map{|i| i.hash } ) } h['aux_pow'] = @aux_pow.to_hash if @aux_pow - h['signature'] = @block_signature.reverse_hth if Bitcoin.network_project == :ppcoin + h['signature'] = @block_signature.reverse_hth if Bitcoin.network_project == :peercoin h end @@ -203,7 +203,7 @@ def self.from_hash(h, do_raise=true) if h['tx'].any? && !Bitcoin.freicoin? (raise "Block merkle root mismatch! Block: #{h['hash']}" unless verify_mrkl_root) if do_raise end - @block_signature = h['signature'].htb_reverse if Bitcoin.network_project == :ppcoin + @block_signature = h['signature'].htb_reverse if Bitcoin.network_project == :peercoin } blk end diff --git a/lib/bitcoin/protocol/tx.rb b/lib/bitcoin/protocol/tx.rb index 57f68e1d..0f8376ce 100644 --- a/lib/bitcoin/protocol/tx.rb +++ b/lib/bitcoin/protocol/tx.rb @@ -41,7 +41,7 @@ def binary_hash # create tx from raw binary +data+ def initialize(data=nil) @ver, @lock_time, @in, @out = 1, 0, [], [] - @time = Time.now.to_i if Bitcoin.network_project == :ppcoin + @time = Time.now.to_i if Bitcoin.network_project == :peercoin parse_data_from_io(data) if data end @@ -64,7 +64,7 @@ def parse_data_from_io(data) @ver = buf.read(4).unpack("V")[0] - @time = buf.read(4).unpack("V")[0] if Bitcoin.network_project == :ppcoin + @time = buf.read(4).unpack("V")[0] if Bitcoin.network_project == :peercoin in_size = Protocol.unpack_var_int_from_io(buf) @in = [] @@ -98,7 +98,7 @@ def to_payload @out.each{|output| pout << output.to_payload } result = [@ver].pack("V") - result << [@time].pack("V") if Bitcoin.network_project == :ppcoin + result << [@time].pack("V") if Bitcoin.network_project == :peercoin result << Protocol.pack_var_int(@in.size) << pin << Protocol.pack_var_int(@out.size) << pout << [@lock_time].pack("V") end @@ -155,7 +155,7 @@ def signature_hash_for_input(input_idx, subscript, hash_type=nil) in_size, pin = Protocol.pack_var_int(1), [ pin[input_idx] ] end - if Bitcoin.network_project == :ppcoin + if Bitcoin.network_project == :peercoin buf = [ [@ver, @time].pack("VV"), in_size, pin, out_size, pout, [@lock_time, hash_type].pack("VV") ].join else buf = [ [@ver].pack("V"), in_size, pin, out_size, pout, [@lock_time, hash_type].pack("VV") ].join @@ -194,7 +194,7 @@ def to_hash(options = {}) 'in' => @in.map{|i| i.to_hash(options) }, 'out' => @out.map{|o| o.to_hash(options) } } - h['time'] = @time if Bitcoin.network_project == :ppcoin + h['time'] = @time if Bitcoin.network_project == :peercoin h end @@ -215,7 +215,7 @@ def self.from_hash(h) tx.ver, tx.lock_time = *h.values_at('ver', 'lock_time') h['in'] .each{|input| tx.add_in TxIn.from_hash(input) } h['out'].each{|output| tx.add_out TxOut.from_hash(output) } - tx.instance_eval{ @time = h['time'] } if Bitcoin.network_project == :ppcoin + tx.instance_eval{ @time = h['time'] } if Bitcoin.network_project == :peercoin tx.instance_eval{ @hash = hash_from_payload(@payload = to_payload) } tx end diff --git a/spec/bitcoin/fixtures/ppcoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658.bin b/spec/bitcoin/fixtures/peercoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658.bin similarity index 100% rename from spec/bitcoin/fixtures/ppcoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658.bin rename to spec/bitcoin/fixtures/peercoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658.bin diff --git a/spec/bitcoin/fixtures/ppcoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658.json b/spec/bitcoin/fixtures/peercoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658.json similarity index 100% rename from spec/bitcoin/fixtures/ppcoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658.json rename to spec/bitcoin/fixtures/peercoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658.json diff --git a/spec/bitcoin/fixtures/ppcoin-genesis-block-0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3.bin b/spec/bitcoin/fixtures/peercoin-genesis-block-0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3.bin similarity index 100% rename from spec/bitcoin/fixtures/ppcoin-genesis-block-0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3.bin rename to spec/bitcoin/fixtures/peercoin-genesis-block-0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3.bin diff --git a/spec/bitcoin/fixtures/ppcoin-genesis-block-0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3.json b/spec/bitcoin/fixtures/peercoin-genesis-block-0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3.json similarity index 100% rename from spec/bitcoin/fixtures/ppcoin-genesis-block-0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3.json rename to spec/bitcoin/fixtures/peercoin-genesis-block-0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3.json diff --git a/spec/bitcoin/protocol/block_spec.rb b/spec/bitcoin/protocol/block_spec.rb index 0cff0482..fe51ffe4 100644 --- a/spec/bitcoin/protocol/block_spec.rb +++ b/spec/bitcoin/protocol/block_spec.rb @@ -154,24 +154,24 @@ end it "should work on peercoin" do - Bitcoin.network = :ppcoin # change to ppcoin - ppcoin_block = "ppcoin-genesis-block-0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3" - Bitcoin::Protocol::Block.from_json(fixtures_file(ppcoin_block + '.json')) - .to_payload.should == fixtures_file(ppcoin_block + '.bin') + Bitcoin.network = :peercoin # change to peercoin + peercoin_block = "peercoin-genesis-block-0000000032fe677166d54963b62a4677d8957e87c508eaa4fd7eb1c880cd27e3" + Bitcoin::Protocol::Block.from_json(fixtures_file(peercoin_block + '.json')) + .to_payload.should == fixtures_file(peercoin_block + '.bin') - json = Bitcoin::Protocol::Block.new(fixtures_file(ppcoin_block + '.bin')).to_json + json = Bitcoin::Protocol::Block.new(fixtures_file(peercoin_block + '.bin')).to_json Bitcoin::Protocol::Block.from_json(json) - .to_payload.should == fixtures_file(ppcoin_block + '.bin') - Bitcoin::Protocol::Block.from_json(json).hash == ppcoin_block.split("-").last + .to_payload.should == fixtures_file(peercoin_block + '.bin') + Bitcoin::Protocol::Block.from_json(json).hash == peercoin_block.split("-").last - ppcoin_block = "ppcoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658" - Bitcoin::Protocol::Block.from_json(fixtures_file(ppcoin_block + '.json')) - .to_payload.should == fixtures_file(ppcoin_block + '.bin') + peercoin_block = "peercoin-block-00000000000be4e024af5071ba515c7510767f42ec9e40c5fba56775ff296658" + Bitcoin::Protocol::Block.from_json(fixtures_file(peercoin_block + '.json')) + .to_payload.should == fixtures_file(peercoin_block + '.bin') - json = Bitcoin::Protocol::Block.new(fixtures_file(ppcoin_block + '.bin')).to_json + json = Bitcoin::Protocol::Block.new(fixtures_file(peercoin_block + '.bin')).to_json Bitcoin::Protocol::Block.from_json(json) - .to_payload.should == fixtures_file(ppcoin_block + '.bin') - Bitcoin::Protocol::Block.from_json(json).hash == ppcoin_block.split("-").last + .to_payload.should == fixtures_file(peercoin_block + '.bin') + Bitcoin::Protocol::Block.from_json(json).hash == peercoin_block.split("-").last Bitcoin.network = :bitcoin # change back to bitcoin