spec/bitcoin/protocol/block_spec.rb in bitcoin-ruby-0.0.1 vs spec/bitcoin/protocol/block_spec.rb in bitcoin-ruby-0.0.2

- old
+ new

@@ -1,41 +1,45 @@ +# encoding: ascii-8bit + require_relative '../spec_helper.rb' +include Bitcoin::Protocol describe 'Bitcoin::Protocol::Block' do - @blocks = { - # block 0: 00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048 - '0' => fixtures_file('rawblock-0.bin'), - # block 1: 000000006a625f06636b8bb6ac7b960a8d03705d1ace08b1a19da3fdcc99ddbd - '1' => fixtures_file('rawblock-1.bin'), - # block 9: 000000008d9dc510f23c2657fc4f67bea30078cc05a90eb89e84cc475c080805 - '9' => fixtures_file('rawblock-9.bin'), - # block 170: 00000000d1145790a8694403d4063f323d499e655c83426834d4ce2f8dd4a2ee - '170' => fixtures_file('rawblock-170.bin'), - # block 131025: 00000000000007d938dbdd433c5ae12a782de74abf7f566518bc2b2d0a1df145 - '131025' => fixtures_file('rawblock-131025.bin'), - # block 26478: 000000000214a3f06ee99a033a7f2252762d6a18d27c3cd8c8fe2278190da9f3 - 'testnet-26478' => fixtures_file('rawblock-testnet-26478.bin'), - } + before do + @blocks = { + # block 0: 00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048 + '0' => fixtures_file('rawblock-0.bin'), + # block 1: 000000006a625f06636b8bb6ac7b960a8d03705d1ace08b1a19da3fdcc99ddbd + '1' => fixtures_file('rawblock-1.bin'), + # block 9: 000000008d9dc510f23c2657fc4f67bea30078cc05a90eb89e84cc475c080805 + '9' => fixtures_file('rawblock-9.bin'), + # block 170: 00000000d1145790a8694403d4063f323d499e655c83426834d4ce2f8dd4a2ee + '170' => fixtures_file('rawblock-170.bin'), + # block 131025: 00000000000007d938dbdd433c5ae12a782de74abf7f566518bc2b2d0a1df145 + '131025' => fixtures_file('rawblock-131025.bin'), + # block 26478: 000000000214a3f06ee99a033a7f2252762d6a18d27c3cd8c8fe2278190da9f3 + 'testnet-26478' => fixtures_file('rawblock-testnet-26478.bin'), + } + end - it '#new' do proc{ - Bitcoin::Protocol::Block.new( nil ) - @block = Bitcoin::Protocol::Block.new( @blocks['0'] ) + Block.new( nil ) + @block = Block.new( @blocks['0'] ) }.should.not.raise Exception proc{ - Bitcoin::Protocol::Block.new( @blocks['0'][0..20] ) + Block.new( @blocks['0'][0..20] ) }.should.raise Exception - block = Bitcoin::Protocol::Block.new(nil) + block = Block.new(nil) block.parse_data(@blocks['0']).should == true block.header_info[7].should == 215 block.to_payload.should == @blocks['0'] - block = Bitcoin::Protocol::Block.new(nil) + block = Block.new(nil) block.parse_data(@blocks['0'] + "AAAA").should == "AAAA" block.header_info[7].should == 215 block.to_payload.should == @blocks['0'] end @@ -43,45 +47,114 @@ @block.hash.should == "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048" end it '#tx' do @block.tx.size.should == 1 - @block.tx[0].is_a?(Bitcoin::Protocol::Tx).should == true + @block.tx[0].is_a?(Tx).should == true @block.tx[0].hash.should == "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098" end it '#to_hash' do @block.to_hash.keys.should == ["hash", "ver", "prev_block", "mrkl_root", "time", "bits", "nonce", "n_tx", "size", "tx", "mrkl_tree"] end it '#to_json' do @block.to_json.should == fixtures_file('rawblock-0.json') - Bitcoin::Protocol::Block.new( @blocks['1'] ).to_json.should == fixtures_file('rawblock-1.json') - Bitcoin::Protocol::Block.new( @blocks['131025'] ).to_json.should == fixtures_file('rawblock-131025.json') - Bitcoin::Protocol::Block.new( @blocks['testnet-26478'] ).to_json.should == fixtures_file('rawblock-testnet-26478.json') - Bitcoin::P::Block.from_json(@block.to_json).tx[0].in[0].sequence.should == "\xff\xff\xff\xff" + Block.new( @blocks['1'] ).to_json.should == fixtures_file('rawblock-1.json') + Block.new( @blocks['131025'] ).to_json.should == fixtures_file('rawblock-131025.json') + Block.new( @blocks['testnet-26478'] ).to_json.should == fixtures_file('rawblock-testnet-26478.json') + Block.from_json(@block.to_json).tx[0].in[0].sequence.should == "\xff\xff\xff\xff" end it '#to_payload' do @block.to_payload.should == @block.payload - Bitcoin::Protocol::Block.new( @block.to_payload ).to_payload.should == @block.payload - Bitcoin::Protocol::Block.new( @blocks['1'] ).to_payload.should == @blocks['1'] - Bitcoin::Protocol::Block.new( @blocks['131025'] ).to_payload.should == @blocks['131025'] - Bitcoin::Protocol::Block.new( @blocks['testnet-26478'] ).to_payload.should == @blocks['testnet-26478'] + Block.new( @block.to_payload ).to_payload.should == @block.payload + Block.new( @blocks['1'] ).to_payload.should == @blocks['1'] + Block.new( @blocks['131025'] ).to_payload.should == @blocks['131025'] + Block.new( @blocks['testnet-26478'] ).to_payload.should == @blocks['testnet-26478'] end - it '#from_json' do - block = Bitcoin::Protocol::Block.from_json(fixtures_file('rawblock-0.json')) - block.to_payload.should == @blocks['0'] - block.tx[0].in[0].sequence.should == "\xff\xff\xff\xff" - Bitcoin::Protocol::Block.from_json(fixtures_file('rawblock-1.json')).to_payload.should == @blocks['1'] + describe "Block.from_json" do - Bitcoin::Protocol::Block.from_json(fixtures_file('rawblock-131025.json')) - .to_payload.should == @blocks['131025'] + it 'should load blocks from json' do + block = Block.from_json(fixtures_file('rawblock-0.json')) + block.to_payload.should == @blocks['0'] + block.tx[0].in[0].sequence.should == "\xff\xff\xff\xff" + Block.from_json(fixtures_file('rawblock-1.json')).to_payload.should == @blocks['1'] + + Block.from_json(fixtures_file('rawblock-131025.json')) + .to_payload.should == @blocks['131025'] + + Block.from_json(fixtures_file('rawblock-testnet-26478.json')) + .to_payload.should == @blocks['testnet-26478'] - Bitcoin::Protocol::Block.from_json(fixtures_file('rawblock-testnet-26478.json')) - .to_payload.should == @blocks['testnet-26478'] + # testnet3 block 0000000000ac85bb2530a05a4214a387e6be02b22d3348abc5e7a5d9c4ce8dab + block_raw = fixtures_file('block-testnet-0000000000ac85bb2530a05a4214a387e6be02b22d3348abc5e7a5d9c4ce8dab.bin') + Block.new(block_raw).to_payload.should == block_raw + # Block.from_json(Block.new(block_raw).to_json).to_payload.should == block_raw # slow test + end + + it "should work with litecoin blocks" do + Bitcoin.network = :litecoin # change to litecoin + litecoin_block = "litecoin-genesis-block-12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2" + Block.from_json(fixtures_file(litecoin_block + '.json')) + .to_payload.should == fixtures_file(litecoin_block + '.bin') + + json = Block.new(fixtures_file(litecoin_block + '.bin')).to_json + Block.from_json(json) + .to_payload.should == fixtures_file(litecoin_block + '.bin') + Block.from_json(json).hash == litecoin_block.split("-").last + + litecoin_block = "litecoin-block-80ca095ed10b02e53d769eb6eaf92cd04e9e0759e5be4a8477b42911ba49c78f" + Block.from_json(fixtures_file(litecoin_block + '.json')) + .to_payload.should == fixtures_file(litecoin_block + '.bin') + + json = Block.new(fixtures_file(litecoin_block + '.bin')).to_json + Block.from_json(json) + .to_payload.should == fixtures_file(litecoin_block + '.bin') + Block.from_json(json).hash == litecoin_block.split("-").last + Bitcoin.network = :bitcoin + end + + it "should work with freicoin blocks" do + Bitcoin.network = :freicoin # change to freicoin + freicoin_block = "freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c" + Block.from_json(fixtures_file(freicoin_block + '.json')) + .to_payload.should == fixtures_file(freicoin_block + '.bin') + + json = Block.new(fixtures_file(freicoin_block + '.bin')).to_json + Block.from_json(json) + .to_payload.should == fixtures_file(freicoin_block + '.bin') + Block.from_json(json).hash == freicoin_block.split("-").last + + freicoin_block = "freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c" + Block.from_json(fixtures_file(freicoin_block + '.json')) + .to_payload.should == fixtures_file(freicoin_block + '.bin') + + json = Block.new(fixtures_file(freicoin_block + '.bin')).to_json + Block.from_json(json) + .to_payload.should == fixtures_file(freicoin_block + '.bin') + Block.from_json(json).hash == freicoin_block.split("-").last + Bitcoin.network = :bitcoin + end + + it 'should check block hash' do + block = Block.from_json(fixtures_file('rawblock-0.json')) + h = block.to_hash + h['hash'][0] = "1" + -> { Block.from_hash(h) }.should.raise(Exception) + .message.should == "Block hash mismatch! Claimed: 10000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048, Actual: 00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048" + end + + it "should check merkle tree" do + block = Block.from_json(fixtures_file('rawblock-0.json')) + h = block.to_hash + h['tx'][0]['ver'] = 2 + -> { Block.from_hash(h) }.should.raise(Exception) + .message.should.include?("Block merkle root mismatch!") + end + end it '#header_to_json' do @block.header_to_json.should == (<<-JSON).chomp { @@ -94,8 +167,30 @@ "nonce":2573394689, "n_tx":1, "size":215 } JSON + end + + it '#verify_mrkl_root' do + block0 = Block.from_json(fixtures_file('rawblock-0.json')) + block1 = Block.from_json(fixtures_file('rawblock-1.json')) + block0.tx.size.should == 1 + block0.verify_mrkl_root.should == true + block0.tx << block.tx.last # test against CVE-2012-2459 + block0.verify_mrkl_root.should == false + block0.tx = block1.tx + block0.verify_mrkl_root.should == false + end + + it '#bip34_block_height' do + # block version 1 + block = Block.from_json(fixtures_file('rawblock-131025.json')) + block.ver.should == 1 + block.bip34_block_height.should == nil + # block version 2 (introduced by BIP_0034) + block = Block.from_json(fixtures_file('000000000000056b1a3d84a1e2b33cde8915a4b61c0cae14fca6d3e1490b4f98.json')) + block.ver.should == 2 + block.bip34_block_height.should == 197657 end end