bitcoin-ruby 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +7 -7
- data/README.rdoc +1 -1
- data/examples/simple_network_monitor_and_util.rb +8 -0
- data/lib/bitcoin.rb +57 -17
- data/lib/bitcoin/builder.rb +15 -10
- data/lib/bitcoin/ffi/bitcoinconsensus.rb +3 -2
- data/lib/bitcoin/ffi/secp256k1.rb +143 -81
- data/lib/bitcoin/key.rb +4 -6
- data/lib/bitcoin/logger.rb +11 -0
- data/lib/bitcoin/protocol.rb +19 -6
- data/lib/bitcoin/protocol/aux_pow.rb +62 -62
- data/lib/bitcoin/protocol/block.rb +20 -15
- data/lib/bitcoin/protocol/handler.rb +4 -0
- data/lib/bitcoin/protocol/parser.rb +30 -29
- data/lib/bitcoin/protocol/reject.rb +38 -0
- data/lib/bitcoin/protocol/tx.rb +19 -3
- data/lib/bitcoin/protocol/txin.rb +14 -8
- data/lib/bitcoin/script.rb +6 -1
- data/lib/bitcoin/version.rb +1 -1
- data/spec/bitcoin/bitcoin_spec.rb +4 -0
- data/spec/bitcoin/builder_spec.rb +11 -0
- data/spec/bitcoin/dogecoin_spec.rb +6 -6
- data/spec/bitcoin/protocol/addr_spec.rb +11 -1
- data/spec/bitcoin/protocol/aux_pow_spec.rb +9 -9
- data/spec/bitcoin/protocol/block_spec.rb +1 -0
- data/spec/bitcoin/protocol/inv_spec.rb +10 -2
- data/spec/bitcoin/protocol/parser_spec.rb +50 -0
- data/spec/bitcoin/protocol/reject.rb +17 -0
- data/spec/bitcoin/protocol/tx_spec.rb +5 -1
- data/spec/bitcoin/script/script_spec.rb +1 -1
- data/spec/bitcoin/secp256k1_spec.rb +8 -0
- data/spec/bitcoin/spec_helper.rb +6 -0
- metadata +8 -3
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
module Bitcoin
|
4
|
+
module Protocol
|
5
|
+
|
6
|
+
class Reject < Struct.new(:message, :ccode, :reason, :data)
|
7
|
+
CCODE_TABLE = {
|
8
|
+
0x01 => :malformed,
|
9
|
+
0x10 => :invalid,
|
10
|
+
0x11 => :obsolete,
|
11
|
+
0x12 => :duplicate,
|
12
|
+
0x40 => :nonstandard,
|
13
|
+
0x41 => :dust,
|
14
|
+
0x42 => :insufficientfee,
|
15
|
+
0x43 => :checkpoint,
|
16
|
+
}
|
17
|
+
|
18
|
+
def self.parse(payload)
|
19
|
+
message, payload = Bitcoin::Protocol.unpack_var_string(payload)
|
20
|
+
ccode, payload = payload.unpack("Ca*")
|
21
|
+
reason, payload = Bitcoin::Protocol.unpack_var_string(payload)
|
22
|
+
data = payload
|
23
|
+
|
24
|
+
code = CCODE_TABLE[ccode] || ccode
|
25
|
+
new(message, code, reason, data)
|
26
|
+
end
|
27
|
+
|
28
|
+
def tx_hash
|
29
|
+
message == "tx" && self[:data].reverse.bth
|
30
|
+
end
|
31
|
+
|
32
|
+
def block_hash
|
33
|
+
message == "block" && self[:data].reverse.bth
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
data/lib/bitcoin/protocol/tx.rb
CHANGED
@@ -67,13 +67,25 @@ module Bitcoin
|
|
67
67
|
|
68
68
|
@ver = buf.read(4).unpack("V")[0]
|
69
69
|
|
70
|
+
return false if buf.eof?
|
71
|
+
|
70
72
|
in_size = Protocol.unpack_var_int_from_io(buf)
|
71
73
|
@in = []
|
72
|
-
in_size.times{
|
74
|
+
in_size.times{
|
75
|
+
break if buf.eof?
|
76
|
+
@in << TxIn.from_io(buf)
|
77
|
+
}
|
78
|
+
|
79
|
+
return false if buf.eof?
|
73
80
|
|
74
81
|
out_size = Protocol.unpack_var_int_from_io(buf)
|
75
82
|
@out = []
|
76
|
-
out_size.times{
|
83
|
+
out_size.times{
|
84
|
+
break if buf.eof?
|
85
|
+
@out << TxOut.from_io(buf)
|
86
|
+
}
|
87
|
+
|
88
|
+
return false if buf.eof?
|
77
89
|
|
78
90
|
@lock_time = buf.read(4).unpack("V")[0]
|
79
91
|
|
@@ -225,6 +237,7 @@ module Bitcoin
|
|
225
237
|
'in' => @in.map{|i| i.to_hash(options) },
|
226
238
|
'out' => @out.map{|o| o.to_hash(options) }
|
227
239
|
}
|
240
|
+
h['nid'] = normalized_hash if options[:with_nid]
|
228
241
|
h
|
229
242
|
end
|
230
243
|
|
@@ -240,7 +253,7 @@ module Bitcoin
|
|
240
253
|
end
|
241
254
|
|
242
255
|
# parse ruby hash (see also #to_hash)
|
243
|
-
def self.from_hash(h)
|
256
|
+
def self.from_hash(h, do_raise=true)
|
244
257
|
tx = new(nil)
|
245
258
|
tx.ver, tx.lock_time = (h['ver'] || h['version']), h['lock_time']
|
246
259
|
ins = h['in'] || h['inputs']
|
@@ -248,6 +261,9 @@ module Bitcoin
|
|
248
261
|
ins .each{|input| tx.add_in TxIn.from_hash(input) }
|
249
262
|
outs.each{|output| tx.add_out TxOut.from_hash(output) }
|
250
263
|
tx.instance_eval{ @hash = hash_from_payload(@payload = to_payload) }
|
264
|
+
unless h['hash'] == tx.hash
|
265
|
+
raise "Tx hash mismatch! Claimed: #{h['hash']}, Actual: #{tx.hash}" if do_raise
|
266
|
+
end
|
251
267
|
tx
|
252
268
|
end
|
253
269
|
|
@@ -6,7 +6,9 @@ module Bitcoin
|
|
6
6
|
class TxIn
|
7
7
|
|
8
8
|
# previous output hash
|
9
|
-
attr_accessor :
|
9
|
+
attr_accessor :prev_out_hash
|
10
|
+
alias :prev_out :prev_out_hash
|
11
|
+
def prev_out=(hash); @prev_out_hash = hash; end
|
10
12
|
|
11
13
|
# previous output index
|
12
14
|
attr_accessor :prev_out_index
|
@@ -29,7 +31,7 @@ module Bitcoin
|
|
29
31
|
COINBASE_INDEX = 0xffffffff
|
30
32
|
|
31
33
|
def initialize *args
|
32
|
-
@
|
34
|
+
@prev_out_hash, @prev_out_index, @script_sig_length,
|
33
35
|
@script_sig, @sequence = *args
|
34
36
|
@script_sig_length ||= 0
|
35
37
|
@script_sig ||= ''
|
@@ -38,7 +40,7 @@ module Bitcoin
|
|
38
40
|
|
39
41
|
# compare to another txout
|
40
42
|
def ==(other)
|
41
|
-
@
|
43
|
+
@prev_out_hash == other.prev_out_hash &&
|
42
44
|
@prev_out_index == other.prev_out_index &&
|
43
45
|
@script_sig == other.script_sig &&
|
44
46
|
@sequence == other.sequence
|
@@ -63,18 +65,22 @@ module Bitcoin
|
|
63
65
|
end
|
64
66
|
|
65
67
|
def parse_data_from_io(buf)
|
66
|
-
@
|
68
|
+
@prev_out_hash, @prev_out_index = buf.read(36).unpack("a32V")
|
67
69
|
@script_sig_length = Protocol.unpack_var_int_from_io(buf)
|
68
70
|
@script_sig = buf.read(@script_sig_length)
|
69
71
|
@sequence = buf.read(4)
|
70
72
|
end
|
71
73
|
|
74
|
+
def parsed_script
|
75
|
+
@parsed_script ||= Bitcoin::Script.new(script_sig)
|
76
|
+
end
|
77
|
+
|
72
78
|
def to_payload(script=@script_sig, sequence=@sequence)
|
73
|
-
[@
|
79
|
+
[@prev_out_hash, @prev_out_index].pack("a32V") << Protocol.pack_var_int(script.bytesize) << script << (sequence || DEFAULT_SEQUENCE)
|
74
80
|
end
|
75
81
|
|
76
82
|
def to_hash(options = {})
|
77
|
-
t = { 'prev_out' => { 'hash' => @
|
83
|
+
t = { 'prev_out' => { 'hash' => @prev_out_hash.reverse_hth, 'n' => @prev_out_index } }
|
78
84
|
if coinbase?
|
79
85
|
t['coinbase'] = @script_sig.unpack("H*")[0]
|
80
86
|
else # coinbase tx
|
@@ -103,12 +109,12 @@ module Bitcoin
|
|
103
109
|
|
104
110
|
# previous output in hex
|
105
111
|
def previous_output
|
106
|
-
@
|
112
|
+
@prev_out_hash.reverse_hth
|
107
113
|
end
|
108
114
|
|
109
115
|
# check if input is coinbase
|
110
116
|
def coinbase?
|
111
|
-
(@prev_out_index == COINBASE_INDEX) && (@
|
117
|
+
(@prev_out_index == COINBASE_INDEX) && (@prev_out_hash == NULL_HASH)
|
112
118
|
end
|
113
119
|
|
114
120
|
# set script_sig and script_sig_length
|
data/lib/bitcoin/script.rb
CHANGED
@@ -663,7 +663,7 @@ class Bitcoin::Script
|
|
663
663
|
Bitcoin::Key.new(nil, pub.unpack("H*")[0]).addr
|
664
664
|
rescue OpenSSL::PKey::ECError, OpenSSL::PKey::EC::Point::Error
|
665
665
|
end
|
666
|
-
}
|
666
|
+
}
|
667
667
|
end
|
668
668
|
|
669
669
|
def get_p2sh_address
|
@@ -827,6 +827,11 @@ class Bitcoin::Script
|
|
827
827
|
@chunks[0] - 80
|
828
828
|
end
|
829
829
|
|
830
|
+
def get_keys_provided
|
831
|
+
return false unless is_multisig?
|
832
|
+
@chunks[-2] - 80
|
833
|
+
end
|
834
|
+
|
830
835
|
# This matches CScript::GetSigOpCount(bool fAccurate)
|
831
836
|
# Note: this does not cover P2SH script which is to be unserialized
|
832
837
|
# and checked explicitly when validating blocks.
|
data/lib/bitcoin/version.rb
CHANGED
@@ -447,6 +447,10 @@ describe 'Bitcoin Address/Hash160/PubKey' do
|
|
447
447
|
Bitcoin.verify_message(s['address'], s['signature'], s['message']).should == true
|
448
448
|
}
|
449
449
|
}
|
450
|
+
|
451
|
+
Bitcoin.network = :testnet3
|
452
|
+
Bitcoin.verify_message("mwPVMbZQgkpwJJt2YP3sLSgbEBQw3FWZSc", "H5GER0Nz+L7TPZMQzXtv0hnLSsyfPok9lkdHIv01vksREpEpOhTPTonU1xvyPAOIIKhU3++Ol+LaWKWmsfyxDXk=", "A"*500).should == true
|
453
|
+
Bitcoin.network = :bitcoin
|
450
454
|
end
|
451
455
|
rescue LoadError
|
452
456
|
end
|
@@ -103,6 +103,17 @@ describe "Bitcoin::Builder" do
|
|
103
103
|
tx1.in[0].should == tx2.in[0]
|
104
104
|
end
|
105
105
|
|
106
|
+
it "should provide tx#output shortcut" do
|
107
|
+
tx1 = build_tx {|t| t.output(123, @keys[1].addr) }
|
108
|
+
tx1.should == build_tx do |t|
|
109
|
+
t.output {|o| o.value 123; o.to @keys[1].addr }
|
110
|
+
end
|
111
|
+
|
112
|
+
tx2 = build_tx {|t| t.output(123, @keys[1].pub, :pubkey) }
|
113
|
+
tx2.should == build_tx do |t|
|
114
|
+
t.output {|o| o.value 123; o.to @keys[1].pub, :pubkey }
|
115
|
+
end
|
116
|
+
end
|
106
117
|
|
107
118
|
it "should provide txout#to shortcut" do
|
108
119
|
tx1 = build_tx do |t|
|
@@ -139,19 +139,19 @@ describe 'Bitcoin::Dogecoin' do
|
|
139
139
|
block = P::Block.new(data)
|
140
140
|
aux_pow = block.aux_pow
|
141
141
|
aux_pow.nil?.should == false
|
142
|
-
aux_pow.
|
142
|
+
aux_pow.coinbase_index.should == 0
|
143
143
|
|
144
|
-
parent_block_merkle_root = Bitcoin.mrkl_branch_root(aux_pow.
|
144
|
+
parent_block_merkle_root = Bitcoin.mrkl_branch_root(aux_pow.coinbase_branch, aux_pow.coinbase_tx.hash, aux_pow.coinbase_index)
|
145
145
|
parent_block_merkle_root.should == aux_pow.parent_block.mrkl_root.reverse.unpack("H*")[0]
|
146
146
|
|
147
147
|
# Find the merged mining header in the coinbase input script
|
148
148
|
merged_mining_header = "\xfa\xbemm"
|
149
|
-
script = aux_pow.
|
149
|
+
script = aux_pow.coinbase_tx.in[0].script
|
150
150
|
header_idx = script.index(merged_mining_header)
|
151
151
|
|
152
152
|
header_idx.should == 4
|
153
153
|
|
154
|
-
chain_merkle_root = Bitcoin.mrkl_branch_root(aux_pow.
|
154
|
+
chain_merkle_root = Bitcoin.mrkl_branch_root(aux_pow.chain_branch, block_hash, aux_pow.chain_index)
|
155
155
|
|
156
156
|
# Drop everything up to the merged mining data
|
157
157
|
script = script.slice(header_idx + merged_mining_header.length, chain_merkle_root.length / 2 + 8)
|
@@ -160,7 +160,7 @@ describe 'Bitcoin::Dogecoin' do
|
|
160
160
|
chain_merkle_root.should == tx_root_hash
|
161
161
|
|
162
162
|
merkle_branch_size = script.slice(chain_merkle_root.length / 2, 4).unpack("V")[0]
|
163
|
-
merkle_branch_size.should == (1 << aux_pow.
|
163
|
+
merkle_branch_size.should == (1 << aux_pow.chain_branch.length)
|
164
164
|
|
165
165
|
# Choose a pseudo-random slot in the chain merkle tree
|
166
166
|
# but have it be fixed for a size/nonce/chain combination.
|
@@ -170,7 +170,7 @@ describe 'Bitcoin::Dogecoin' do
|
|
170
170
|
rand += Bitcoin.network[:auxpow_chain_id]
|
171
171
|
rand = rand * 1103515245 + 12345
|
172
172
|
|
173
|
-
aux_pow.
|
173
|
+
aux_pow.chain_index.should == (rand % merkle_branch_size)
|
174
174
|
end
|
175
175
|
|
176
176
|
end
|
@@ -10,8 +10,9 @@ describe 'Bitcoin::Protocol::Parser (addr)' do
|
|
10
10
|
.split(" ").join].pack("H*")
|
11
11
|
|
12
12
|
class Addr_Handler < Bitcoin::Protocol::Handler
|
13
|
-
attr_reader :addr
|
13
|
+
attr_reader :addr, :err
|
14
14
|
def on_addr(addr); (@addr ||= []) << addr; end
|
15
|
+
def on_error(*err); (@err ||= []) << err; end
|
15
16
|
end
|
16
17
|
|
17
18
|
parser = Bitcoin::Protocol::Parser.new( handler = Addr_Handler.new )
|
@@ -24,6 +25,14 @@ describe 'Bitcoin::Protocol::Parser (addr)' do
|
|
24
25
|
]
|
25
26
|
end
|
26
27
|
|
28
|
+
it "parses broken address packet" do
|
29
|
+
pkt = ["01 00 00 00 00".split(" ").join].pack("H*")
|
30
|
+
parser = Bitcoin::Protocol::Parser.new( handler = Addr_Handler.new )
|
31
|
+
parser.parse_addr(pkt).should == nil
|
32
|
+
handler.addr.should == nil
|
33
|
+
handler.err.should == [[:addr, pkt[1..-1]]]
|
34
|
+
end
|
35
|
+
|
27
36
|
end
|
28
37
|
|
29
38
|
describe 'Bitcoin::Protocol::Addr' do
|
@@ -69,4 +78,5 @@ describe 'Bitcoin::Protocol::Addr' do
|
|
69
78
|
Bitcoin::Protocol::Addr.pkt(addr).should ==
|
70
79
|
Bitcoin::Protocol.pkt("addr", "\x01" + addr.to_payload)
|
71
80
|
end
|
81
|
+
|
72
82
|
end
|
@@ -17,14 +17,14 @@ describe Bitcoin::Protocol::AuxPow do
|
|
17
17
|
@aux_pow.should != nil
|
18
18
|
@aux_pow.block_hash.hth.should ==
|
19
19
|
"b42124fd99e67ddabe52ebbfcb30a82b8c74268a320b3c5e2311000000000000"
|
20
|
-
@aux_pow.
|
21
|
-
"
|
22
|
-
"
|
23
|
-
"
|
24
|
-
"
|
25
|
-
@aux_pow.
|
26
|
-
@aux_pow.
|
27
|
-
@aux_pow.
|
20
|
+
@aux_pow.coinbase_branch.should == [
|
21
|
+
"c22f79ba86968a5285225008b2740f074f44f44ef27b8efb61ecff09e9eb4f6d",
|
22
|
+
"99696473beb0caa79d4209dbaa6e18fdc23ebdc67210f86fec0c4559847252d0",
|
23
|
+
"20cbcff309ec8c267892a476c1b22d23d9e5d7a6fdfd025658de6c2ae4e7c564",
|
24
|
+
"e4317593d6ad8d735ded56c336376b7409207c3ea6b92b2451f79eced606944e" ]
|
25
|
+
@aux_pow.coinbase_index.should == 0
|
26
|
+
@aux_pow.chain_branch.should == []
|
27
|
+
@aux_pow.chain_index.should == 0
|
28
28
|
@aux_pow.parent_block.hash.should ==
|
29
29
|
"00000000000011235e3c0b328a26748c2ba830cbbfeb52beda7de699fd2421b4"
|
30
30
|
end
|
@@ -42,4 +42,4 @@ describe Bitcoin::Protocol::AuxPow do
|
|
42
42
|
P::Block.from_json(@blk.to_json).to_payload.should == @data
|
43
43
|
end
|
44
44
|
|
45
|
-
|
45
|
+
end
|
@@ -128,6 +128,7 @@ describe 'Bitcoin::Protocol::Block' do
|
|
128
128
|
block = Block.from_json(fixtures_file('rawblock-0.json'))
|
129
129
|
h = block.to_hash
|
130
130
|
h['tx'][0]['ver'] = 2
|
131
|
+
h['tx'][0]['hash'] = "5ea04451af738d113f0ae8559225b7f893f186f099d88c72230a5e19c0bb830d"
|
131
132
|
-> { Block.from_hash(h) }.should.raise(Exception)
|
132
133
|
.message.should.include?("Block merkle root mismatch!")
|
133
134
|
end
|
@@ -5,12 +5,12 @@ require_relative '../spec_helper.rb'
|
|
5
5
|
describe 'Bitcoin::Protocol::Parser - Inventory Vectors' do
|
6
6
|
|
7
7
|
class Test_Handler < Bitcoin::Protocol::Handler
|
8
|
-
attr_reader :tx_inv
|
9
|
-
attr_reader :block_inv
|
8
|
+
attr_reader :tx_inv, :block_inv, :err
|
10
9
|
def on_inv_transaction(hash); (@tx_inv ||= []) << hash.hth; end
|
11
10
|
def on_get_transaction(hash); (@tx_inv ||= []) << hash.hth; end
|
12
11
|
def on_inv_block(hash); (@block_inv ||= []) << hash.hth; end
|
13
12
|
def on_get_block(hash); (@block_inv ||= []) << hash.hth; end
|
13
|
+
def on_error(*err); (@err ||= []) << err; end
|
14
14
|
end
|
15
15
|
|
16
16
|
|
@@ -123,4 +123,12 @@ describe 'Bitcoin::Protocol::Parser - Inventory Vectors' do
|
|
123
123
|
}
|
124
124
|
end
|
125
125
|
|
126
|
+
it 'parses broken inv packet' do
|
127
|
+
pkt = [("01 00 00 00 00" + " 00"*32).split(" ").join].pack("H*")
|
128
|
+
parser = Bitcoin::Protocol::Parser.new( handler = Test_Handler.new )
|
129
|
+
parser.parse_inv(pkt).should == nil
|
130
|
+
handler.tx_inv.should == nil
|
131
|
+
handler.err.should == [[:parse_inv, pkt[1..-1]]]
|
132
|
+
end
|
133
|
+
|
126
134
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
require_relative '../spec_helper.rb'
|
4
|
+
require 'minitest/mock'
|
5
|
+
|
6
|
+
include Bitcoin::Protocol
|
7
|
+
|
8
|
+
describe 'Bitcoin::Protocol::Parser' do
|
9
|
+
|
10
|
+
|
11
|
+
before {
|
12
|
+
@pkt= [
|
13
|
+
"f9 be b4 d9", # magic head
|
14
|
+
"69 6e 76 00 00 00 00 00 00 00 00 00", # command ("inv")
|
15
|
+
"49 00 00 00", # message length
|
16
|
+
"11 ea 1c 91", # checksum
|
17
|
+
|
18
|
+
"02", # n hashes
|
19
|
+
"01 00 00 00", # type (1=tx)
|
20
|
+
"e0 41 c2 38 f7 32 1a 68 0a 34 06 bf fd 72 12 e3 d1 2c b5 12 2a 8c 0b 52 76 de 82 30 b1 00 7a 42",
|
21
|
+
"01 00 00 00", # type (1=tx)
|
22
|
+
"33 00 09 71 a9 70 7b 6c 6d 6e 77 aa 2e ac 43 f3 e5 67 84 cb 61 b2 35 fb 8d fe e0 86 8b 40 7c f3"
|
23
|
+
].map{|s| s.split(" ")}.flatten.join.htb
|
24
|
+
@handler = MiniTest::Mock.new }
|
25
|
+
after { @handler.verify }
|
26
|
+
|
27
|
+
it 'should call appropriate handler' do
|
28
|
+
@handler.expect(:on_inv_transaction, nil, [@pkt[29..60].reverse])
|
29
|
+
@handler.expect(:on_inv_transaction, nil, [@pkt[-32..-1].reverse])
|
30
|
+
Parser.new( @handler ).parse( @pkt ).should == ""
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should count total packets and bytes' do
|
34
|
+
parser = Parser.new
|
35
|
+
parser.parse @pkt
|
36
|
+
parser.stats.should == {"total_packets"=>1, "total_bytes"=>73, "total_errors" => 0, "inv"=>1}
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should call error handler for unknown command' do
|
40
|
+
@handler.expect(:on_error, nil, [:unknown_packet, ["foo", "626172"]])
|
41
|
+
Parser.new( @handler ).process_pkt('foo', "bar").should == nil
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should count total errors' do
|
45
|
+
parser = Parser.new
|
46
|
+
parser.process_pkt('foo', 'bar')
|
47
|
+
parser.stats['total_errors'].should == 1
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
require_relative '../spec_helper.rb'
|
4
|
+
|
5
|
+
describe 'Bitcoin::Protocol::Parser (reject)' do
|
6
|
+
|
7
|
+
it 'parses alert' do
|
8
|
+
payload = "\x02tx\x10\bcoinbase\xB5\x93\x84\x8D\x99\xF4\x1AE\xE9\xD2\x90T\x9919\xF0X %\xBBE\x19\x19\x86\xBC\r\x812\x7F\xC4\xEDN"
|
9
|
+
|
10
|
+
alert = Bitcoin::Protocol::Reject.parse(payload)
|
11
|
+
alert.message.should == "tx"
|
12
|
+
alert.ccode.should == :invalid
|
13
|
+
alert.reason.should == "coinbase"
|
14
|
+
alert.tx_hash.should == "4eedc47f32810dbc86191945bb252058f03931995490d2e9451af4998d8493b5"
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -59,7 +59,7 @@ describe 'Tx' do
|
|
59
59
|
script.chunks[0].bitcoin_pushdata = Bitcoin::Script::OP_PUSHDATA2
|
60
60
|
script.chunks[0].bitcoin_pushdata_length = script.chunks[0].bytesize
|
61
61
|
new_tx['in'][0]['scriptSig'] = script.to_string
|
62
|
-
new_tx = Bitcoin::P::Tx.from_hash(new_tx)
|
62
|
+
new_tx = Bitcoin::P::Tx.from_hash(new_tx, false)
|
63
63
|
|
64
64
|
new_tx.hash.should != tx.hash
|
65
65
|
new_tx.normalized_hash.size.should == 64
|
@@ -84,6 +84,10 @@ describe 'Tx' do
|
|
84
84
|
tx.to_payload.should == @payload[0]
|
85
85
|
tx.to_hash.should == orig_tx.to_hash
|
86
86
|
Tx.binary_from_hash( orig_tx.to_hash ).should == @payload[0]
|
87
|
+
|
88
|
+
h = orig_tx.to_hash.merge("ver" => 123)
|
89
|
+
-> { tx = Tx.from_hash(h) }.should.raise(Exception)
|
90
|
+
.message.should == "Tx hash mismatch! Claimed: 6e9dd16625b62cfcd4bf02edb89ca1f5a8c30c4b1601507090fb28e59f2d02b4, Actual: 395cd28c334ac84ed125ec5ccd5bc29eadcc96b79c337d0a87a19df64ea3b548"
|
87
91
|
end
|
88
92
|
|
89
93
|
it 'Tx.binary_from_hash' do
|