bitcoin-ruby 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|