cryptocoin 0.0.1b

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +85 -0
  7. data/Rakefile +2 -0
  8. data/cryptocoin.gemspec +24 -0
  9. data/lib/cryptocoin/core_ext/integer.rb +24 -0
  10. data/lib/cryptocoin/core_ext/string.rb +30 -0
  11. data/lib/cryptocoin/digest.rb +36 -0
  12. data/lib/cryptocoin/merkle_tree.rb +78 -0
  13. data/lib/cryptocoin/network/bitcoin.rb +9 -0
  14. data/lib/cryptocoin/network/dogecoin.rb +9 -0
  15. data/lib/cryptocoin/network/litecoin.rb +9 -0
  16. data/lib/cryptocoin/network.rb +53 -0
  17. data/lib/cryptocoin/protocol/block_header.rb +58 -0
  18. data/lib/cryptocoin/protocol/inventory_vector.rb +28 -0
  19. data/lib/cryptocoin/protocol/message/addr.rb +29 -0
  20. data/lib/cryptocoin/protocol/message/alert.rb +0 -0
  21. data/lib/cryptocoin/protocol/message/block.rb +13 -0
  22. data/lib/cryptocoin/protocol/message/getaddr.rb +17 -0
  23. data/lib/cryptocoin/protocol/message/getblocks.rb +44 -0
  24. data/lib/cryptocoin/protocol/message/getdata.rb +31 -0
  25. data/lib/cryptocoin/protocol/message/getheaders.rb +44 -0
  26. data/lib/cryptocoin/protocol/message/headers.rb +30 -0
  27. data/lib/cryptocoin/protocol/message/inv.rb +31 -0
  28. data/lib/cryptocoin/protocol/message/mempool.rb +16 -0
  29. data/lib/cryptocoin/protocol/message/notfound.rb +31 -0
  30. data/lib/cryptocoin/protocol/message/ping.rb +24 -0
  31. data/lib/cryptocoin/protocol/message/pong.rb +24 -0
  32. data/lib/cryptocoin/protocol/message/reject.rb +54 -0
  33. data/lib/cryptocoin/protocol/message/tx.rb +11 -0
  34. data/lib/cryptocoin/protocol/message/verack.rb +16 -0
  35. data/lib/cryptocoin/protocol/message/version.rb +59 -0
  36. data/lib/cryptocoin/protocol/message.rb +27 -0
  37. data/lib/cryptocoin/protocol/net_addr.rb +55 -0
  38. data/lib/cryptocoin/protocol/packet.rb +74 -0
  39. data/lib/cryptocoin/protocol/var_len_int.rb +85 -0
  40. data/lib/cryptocoin/protocol/var_len_str.rb +18 -0
  41. data/lib/cryptocoin/protocol.rb +8 -0
  42. data/lib/cryptocoin/script/op_code/constants.rb +157 -0
  43. data/lib/cryptocoin/script/op_code/functions.rb +515 -0
  44. data/lib/cryptocoin/script/op_code.rb +59 -0
  45. data/lib/cryptocoin/script.rb +234 -0
  46. data/lib/cryptocoin/structure/address.rb +64 -0
  47. data/lib/cryptocoin/structure/block.rb +109 -0
  48. data/lib/cryptocoin/structure/key_pair.rb +57 -0
  49. data/lib/cryptocoin/structure/merkle_branch.rb +37 -0
  50. data/lib/cryptocoin/structure/transaction/input.rb +80 -0
  51. data/lib/cryptocoin/structure/transaction/output.rb +49 -0
  52. data/lib/cryptocoin/structure/transaction.rb +94 -0
  53. data/lib/cryptocoin/version.rb +3 -0
  54. data/lib/cryptocoin.rb +29 -0
  55. data/spec/script_spec.rb +42 -0
  56. data/spec/spec_helper.rb +20 -0
  57. metadata +145 -0
@@ -0,0 +1,157 @@
1
+ module Cryptocoin
2
+ class Script
3
+ # Taken from the Bitcoin official client
4
+ class OpCode
5
+ module Constants
6
+ # push value onto stack
7
+ OP_0 = 0x00
8
+ OP_FALSE = OP_0
9
+ OP_PUSHDATA0 = 0x01
10
+ OP_PUSHDATA1 = 0x4c
11
+ OP_PUSHDATA2 = 0x4d
12
+ OP_PUSHDATA4 = 0x4e
13
+ OP_1NEGATE = 0x4f
14
+ OP_RESERVED = 0x50
15
+ OP_1 = 0x51
16
+ OP_TRUE = OP_1
17
+ OP_2 = 0x52
18
+ OP_3 = 0x53
19
+ OP_4 = 0x54
20
+ OP_5 = 0x55
21
+ OP_6 = 0x56
22
+ OP_7 = 0x57
23
+ OP_8 = 0x58
24
+ OP_9 = 0x59
25
+ OP_10 = 0x5a
26
+ OP_11 = 0x5b
27
+ OP_12 = 0x5c
28
+ OP_13 = 0x5d
29
+ OP_14 = 0x5e
30
+ OP_15 = 0x5f
31
+ OP_16 = 0x60
32
+
33
+ # control
34
+ OP_NOP = 0x61
35
+ OP_VER = 0x62
36
+ OP_IF = 0x63
37
+ OP_NOTIF = 0x64
38
+ OP_VERIF = 0x65
39
+ OP_VERNOTIF = 0x66
40
+ OP_ELSE = 0x67
41
+ OP_ENDIF = 0x68
42
+ OP_VERIFY = 0x69
43
+ OP_RETURN = 0x6a
44
+
45
+ # stack ops
46
+ OP_TOALTSTACK = 0x6b
47
+ OP_FROMALTSTACK = 0x6c
48
+ OP_2DROP = 0x6d
49
+ OP_2DUP = 0x6e
50
+ OP_3DUP = 0x6f
51
+ OP_2OVER = 0x70
52
+ OP_2ROT = 0x71
53
+ OP_2SWAP = 0x72
54
+ OP_IFDUP = 0x73
55
+ OP_DEPTH = 0x74
56
+ OP_DROP = 0x75
57
+ OP_DUP = 0x76
58
+ OP_NIP = 0x77
59
+ OP_OVER = 0x78
60
+ OP_PICK = 0x79
61
+ OP_ROLL = 0x7a
62
+ OP_ROT = 0x7b
63
+ OP_SWAP = 0x7c
64
+ OP_TUCK = 0x7d
65
+
66
+ # splice ops
67
+ OP_CAT = 0x7e
68
+ OP_SUBSTR = 0x7f
69
+ OP_LEFT = 0x80
70
+ OP_RIGHT = 0x81
71
+ OP_SIZE = 0x82
72
+
73
+ # bit logic
74
+ OP_INVERT = 0x83
75
+ OP_AND = 0x84
76
+ OP_OR = 0x85
77
+ OP_XOR = 0x86
78
+ OP_EQUAL = 0x87
79
+ OP_EQUALVERIFY = 0x88
80
+ OP_RESERVED1 = 0x89
81
+ OP_RESERVED2 = 0x8a
82
+
83
+ # numeric
84
+ OP_1ADD = 0x8b
85
+ OP_1SUB = 0x8c
86
+ OP_2MUL = 0x8d
87
+ OP_2DIV = 0x8e
88
+ OP_NEGATE = 0x8f
89
+ OP_ABS = 0x90
90
+ OP_NOT = 0x91
91
+ OP_0NOTEQUAL = 0x92
92
+
93
+ OP_ADD = 0x93
94
+ OP_SUB = 0x94
95
+ OP_MUL = 0x95
96
+ OP_DIV = 0x96
97
+ OP_MOD = 0x97
98
+ OP_LSHIFT = 0x98
99
+ OP_RSHIFT = 0x99
100
+
101
+ OP_BOOLAND = 0x9a
102
+ OP_BOOLOR = 0x9b
103
+ OP_NUMEQUAL = 0x9c
104
+ OP_NUMEQUALVERIFY = 0x9d
105
+ OP_NUMNOTEQUAL = 0x9e
106
+ OP_LESSTHAN = 0x9f
107
+ OP_GREATERTHAN = 0xa0
108
+ OP_LESSTHANOREQUAL = 0xa1
109
+ OP_GREATERTHANOREQUAL = 0xa2
110
+ OP_MIN = 0xa3
111
+ OP_MAX = 0xa4
112
+
113
+ OP_WITHIN = 0xa5
114
+
115
+ # crypto
116
+ OP_RIPEMD160 = 0xa6
117
+ OP_SHA1 = 0xa7
118
+ OP_SHA256 = 0xa8
119
+ OP_HASH160 = 0xa9
120
+ OP_HASH256 = 0xaa
121
+ OP_CODESEPARATOR = 0xab
122
+ OP_CHECKSIG = 0xac
123
+ OP_CHECKSIGVERIFY = 0xad
124
+ OP_CHECKMULTISIG = 0xae
125
+ OP_CHECKMULTISIGVERIFY = 0xaf
126
+
127
+ # expansion
128
+ OP_NOP1 = 0xb0
129
+ OP_NOP2 = 0xb1
130
+ OP_NOP3 = 0xb2
131
+ OP_NOP4 = 0xb3
132
+ OP_NOP5 = 0xb4
133
+ OP_NOP6 = 0xb5
134
+ OP_NOP7 = 0xb6
135
+ OP_NOP8 = 0xb7
136
+ OP_NOP9 = 0xb8
137
+ OP_NOP10 = 0xb9
138
+
139
+ # template matching params
140
+ OP_SMALLDATA = 0xf9
141
+ OP_SMALLINTEGER = 0xfa
142
+ OP_PUBKEYS = 0xfb
143
+ OP_PUBKEYHASH = 0xfd
144
+ OP_PUBKEY = 0xfe
145
+
146
+ OP_INVALIDOPCODE = 0xff
147
+
148
+ def self.const_get(*args)
149
+ super(*args)
150
+ rescue NameError => msg
151
+ return OP_PUSHDATA0 if args[0] == "OP_PUSHDATA0"
152
+ raise NameError, msg
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,515 @@
1
+ require 'cryptocoin/core_ext/integer'
2
+ require 'cryptocoin/core_ext/string'
3
+ require 'cryptocoin/script/op_code/constants'
4
+ require 'digest/sha2'
5
+ require 'digest/rmd160'
6
+
7
+ module Cryptocoin
8
+ class Script
9
+ class OpCode
10
+ module Functions
11
+ include Cryptocoin::Script::OpCode::Constants
12
+
13
+ # One of a kind function
14
+ # Sends back the stack, modified string, raw, seek
15
+ def op_pushdata(stack, opcode, script, script_string, raw, seek)
16
+ bytes = case opcode.hex
17
+ when OP_PUSHDATA0..OP_PUSHDATA1
18
+ opcode.raw
19
+ when OP_PUSHDATA1
20
+ seek+=1
21
+ script[seek-1]
22
+ when OP_PUSHDATA2
23
+ seek+=2
24
+ script[seek-2..seek]
25
+ when OP_PUSHDATA4
26
+ seek+=4
27
+ script[seek-4..seek]
28
+ end
29
+
30
+ bytes = bytes.unpack('H*')[0].to_i(16)
31
+
32
+ unless OP_PUSHDATA0..OP_PUSHDATA1 === opcode.hex
33
+ raw += [bytes].pack('H*')
34
+ script_string.push(bytes)
35
+ end
36
+
37
+ # Read the value from the bytes and see how much to read
38
+ # return nil if invalid according to spec
39
+ return false if bytes > 520
40
+ j = script[seek..seek+bytes-1]
41
+ script_string.push(j.unpack('H*')[0])
42
+ raw += j
43
+ stack.push(j)
44
+ seek+=bytes
45
+ [stack, script_string, raw, seek]
46
+ end
47
+
48
+ def op_numeric(stack, opcode)
49
+ stack.push((opcode.hex - (OP_1 - 1)).to_openssl_bn)
50
+ end
51
+
52
+ def op_if(stack, exec_stack, opcode)
53
+ require_stack stack do
54
+ val = false
55
+ i = stack.pop
56
+ if !!i.to_openssl_bn_int
57
+ val = true if opcode.hex == OP_IF
58
+ else
59
+ val = true if opcode.hex == OP_NOTIF
60
+ end
61
+ exec_stack.push(val)
62
+ [stack, exec_stack]
63
+ end
64
+ end
65
+
66
+ def op_else(exec_stack)
67
+ require_stack exec_stack do
68
+ exec_stack[-1] = !exec_stack[-1]
69
+ exec_stack
70
+ end
71
+ end
72
+
73
+ def op_endif(exec_stack)
74
+ require_stack exec_stack do
75
+ exec_stack.pop
76
+ exec_stack
77
+ end
78
+ end
79
+
80
+ def op_verify(stack, transaction_valid)
81
+ require_stack stack do
82
+ i = stack.pop
83
+ if i.to_openssl_bn_int == 0
84
+ stack.push(i)
85
+ transaction_valid = false
86
+ end
87
+ [stack, transaction_valid]
88
+ end
89
+ end
90
+
91
+ def op_toaltstack(stack, alt_stack)
92
+ require_stack stack do
93
+ alt_stack.push(stack.pop)
94
+ end
95
+ [stack, alt_stack]
96
+ end
97
+
98
+ def op_fromaltstack(stack, alt_stack)
99
+ require_stack alt_stack do
100
+ stack.push(alt_stack.pop)
101
+ end
102
+ [stack, alt_stack]
103
+ end
104
+
105
+ def op_2drop(stack)
106
+ require_stack stack, 2 do
107
+ 2.times do
108
+ stack.pop
109
+ end
110
+ stack
111
+ end
112
+ end
113
+
114
+ def op_2dup(stack)
115
+ require_stack stack, 2 do
116
+ i = stack[-1]
117
+ j = stack[-2]
118
+ stack.push(i, j)
119
+ stack
120
+ end
121
+ end
122
+
123
+ def op_3dup(stack)
124
+ require_stack stack, 3 do
125
+ i = stack[-1]
126
+ j = stack[-2]
127
+ k = stack[-3]
128
+ stack.push(i, j, k)
129
+ stack
130
+ end
131
+ end
132
+
133
+ def op_2over(stack)
134
+ require_stack stack, 4 do
135
+ i = stack[-3]
136
+ j = stack[-4]
137
+ stack.push(i, j)
138
+ stack
139
+ end
140
+ end
141
+
142
+ def op_2rot(stack)
143
+ require_stack stack, 6 do
144
+ i = stack.slize!(-6,2)
145
+ stack.push(i).flatten!
146
+ stack
147
+ end
148
+ end
149
+
150
+ def op_2swap(stack)
151
+ require_stack stack, 4 do
152
+ i = stack.pop(2)
153
+ j = stack.pop(2)
154
+ stack.push(i, j)
155
+ stack
156
+ end
157
+ end
158
+
159
+ def op_ifdup(stack)
160
+ require_stack stack do
161
+ stack.push(stack.last) if stack.last != 0.to_openssl_bn_int
162
+ end
163
+ end
164
+
165
+ def op_depth(stack)
166
+ stack.push(stack.size.to_openssl_bn)
167
+ stack
168
+ end
169
+
170
+ def op_nop
171
+ # Doesn't do anything
172
+ true
173
+ end
174
+
175
+ def op_drop(stack)
176
+ require_stack stack do
177
+ stack.pop
178
+ stack
179
+ end
180
+ end
181
+
182
+ def op_dup(stack)
183
+ require_stack stack do
184
+ stack.push(stack.last)
185
+ stack
186
+ end
187
+ end
188
+
189
+ def op_nip(stack)
190
+ require_stack stack, 2 do
191
+ stack.slice!(-2)
192
+ stack
193
+ end
194
+ end
195
+
196
+ def op_over(stack)
197
+ require_stack stack, 2 do
198
+ stack.push(stack.slice(-2))
199
+ stack
200
+ end
201
+ end
202
+
203
+ def op_pick_or_roll(stack, opcode)
204
+ require_stack stack, 2 do
205
+ p = stack.pop
206
+ i = stack.slice(p, 1) if opcode.hex == OP_PICK
207
+ i = stack.slice!(p, 1) if opcode.hex == OP_ROLL
208
+ stack.push(i)
209
+ stack
210
+ end
211
+ end
212
+
213
+ def op_rot(stack)
214
+ require_stack stack, 3 do
215
+ i = stack.slice!(-3,1)
216
+ stack.push(i)
217
+ stack
218
+ end
219
+ end
220
+
221
+ def op_swap(stack)
222
+ require_stack stack, 2 do
223
+ i = stack.slice!(-2,1)
224
+ stack.push(i)
225
+ stack
226
+ end
227
+ end
228
+
229
+ def op_tuck(stack)
230
+ require_stack stack, 2 do
231
+ stack.insert(-3, stack.last)
232
+ end
233
+ end
234
+
235
+ # Pushes the size of the item at the top of the stack
236
+ # Note: the stack processing is done in binary, and Ruby treats
237
+ # binary as strings
238
+ def op_size(stack)
239
+ stack.push([stack.last.bytesize].pack('C*'))
240
+ stack
241
+ end
242
+
243
+ # Reference client treats OP_RETURN as fail condition
244
+ # for script. OP_RETURN sets the transaction as invalid
245
+ # but otherwise the script can be valid
246
+ def op_return
247
+ false
248
+ end
249
+
250
+ def op_verify(stack, transaction_valid)
251
+ require_stack stack do
252
+ i = stack.pop
253
+ if i.to_bn.to_i == 0
254
+ stack.push(i)
255
+ transaction_valid = false
256
+ end
257
+ [stack, transaction_valid]
258
+ end
259
+ end
260
+
261
+ def op_equal(stack)
262
+ require_stack stack, 2 do
263
+ i, j = stack.pop(2)
264
+ stack.push(i == j ? 1 : 0)
265
+ stack
266
+ end
267
+ end
268
+
269
+ def single_stack_arithmetic(stack, opcode)
270
+ require_stack stack do
271
+ i = stack.pop.to_openssl_bn_int
272
+ case opcode.hex
273
+ when OP_1ADD
274
+ i += 1
275
+ when OP_1SUB
276
+ i -= 1
277
+ when OP_NEGATE
278
+ i = -i
279
+ when OP_ABS
280
+ i = i.abs
281
+ when OP_NOT
282
+ i = (i == 0)
283
+ when OP_0NOTEQUAL
284
+ i = (i != 0)
285
+ end
286
+ stack.push(i.to_openssl_bn)
287
+ stack
288
+ end
289
+ end
290
+
291
+ def double_stack_arithmetic(stack)
292
+ require_stack stack, 2 do
293
+ i, j = stack.pop.map { |e| e.to_openssl_bn_int }
294
+ case opcode.hex
295
+ when OP_ADD
296
+ k = i + j
297
+ when OP_SUB
298
+ k = i - j
299
+ when OP_BOOLAND
300
+ k = (i != 0 and j != 0)
301
+ when OP_BOOLOR
302
+ k = (i != 0 or j != 0)
303
+ when OP_NUMEQUAL, OP_NUMEQUALVERIFY
304
+ k = (i == j)
305
+ op_verify if @opcode == OP_NUMEQUALVERIFY
306
+ when OP_NUMNOTEQUAL
307
+ k = (i != j)
308
+ when OP_LESSTHAN
309
+ k = (i < j)
310
+ when OP_GREATERTHAN
311
+ k = (i > j)
312
+ when OP_LESSTHANOREQUAL
313
+ k = (i <= j)
314
+ when OP_GREATERTHANOREQUAL
315
+ k = (i >= j)
316
+ when OP_MIN
317
+ k = (i < j ? i : j)
318
+ when OP_MAX
319
+ k = (i < j ? j : i)
320
+ end
321
+ stack.push(k.to_openssl_bn)
322
+ stack
323
+ end
324
+ end
325
+
326
+ def op_within(stack)
327
+ require_stack stack do
328
+ i, j, k = stack.pop(3).map{|e| e.to_openssl_bn_int}
329
+ l = (j <= i and i < k)
330
+ stack.push(l.to_openssl_bn)
331
+ stack
332
+ end
333
+ end
334
+
335
+ def digest(stack, opcode)
336
+ require_stack stack do
337
+ i = stack.pop
338
+ case opcode.hex
339
+ when OP_RIPEMD160
340
+ j = Digest::RMD160.digest(i)
341
+ when OP_SHA256
342
+ j = Digest::SHA256.digest(i)
343
+ when OP_SHA1
344
+ j = Digest::SHA1.digest(i)
345
+ when OP_HASH160
346
+ j = Digest::RMD160.digest(Digest::SHA256.digest(i))
347
+ when OP_HASH256
348
+ j = Digest::SHA256.digest(Digest::SHA256.digest(i))
349
+ end
350
+ stack.push(j)
351
+ stack
352
+ end
353
+ end
354
+
355
+ def op_codeseparator(seek)
356
+ seek # Allow for future changes to this opcode
357
+ end
358
+
359
+ # One of the two opcodes that requires outside knowledge from
360
+ # the stack itself, since the transaction information isn't
361
+ # directly part of the script
362
+ def op_checksig(stack, script, code_separator, transaction)
363
+ pubkey = stack.pop
364
+ sig = stack.pop
365
+
366
+ hash_type = sig[-1].unpack('C')[0]
367
+ signature = sig[0..-2]
368
+
369
+ if is_canonical_pubkey?(pubkey) and is_canonical_signature?(signature)
370
+ stack = check_sig(signature, hash_type, pubkey, script, code_separator, transaction)
371
+ return stack.push(0.to_openssl_bn) if !stack
372
+ stack.push(1.to_openssl_bn)
373
+ else
374
+ stack.push(0.to_openssl_bn)
375
+ end
376
+ stack
377
+ end
378
+
379
+ def op_multisig(stack, script, code_separator, transaction, opcode_count)
380
+ require_stack do
381
+ i = stack.pop.to_openssl_bn_int
382
+ return false if !i.between?(1,19) #inclusive
383
+ opcode_count += i
384
+ return false if opcode_count > 201
385
+ return false if stack.size < i+1
386
+ j = stack.size
387
+ while stack.size > j-i
388
+ stack = op_checksig(stack, script, code_separator, transaction)
389
+ return stack.push(0.to_openssl_bn) if !stack
390
+ end
391
+ stack.push(1.to_openssl_bn)
392
+ end
393
+ end
394
+
395
+ private
396
+
397
+ def check_sig(signature, hash_type, pubkey, script, code_separator, transaction)
398
+ # get the script from codeseparator to end as subscript
399
+ # remove codeseparator from resulting script
400
+ # remove signature from script
401
+ subscript = Cryptocoin::Script.new(script[code_separator..-1])
402
+ subscript.is_subscript! # calls for removal of op_separate and signature
403
+
404
+ tx_copy = transaction.copy # in case we need to reset tx_copy
405
+ tx_copy.inputs.each do |i|
406
+ if i.index == @input_index
407
+ i.script_sig_length = Cryptocoin::Protocol::VarLenInt.from_int(subscript.raw.bytesize)
408
+ i.script_sig = subscript.raw
409
+ else
410
+ i.script_sig_length = 0.to_openssl_bn
411
+ i.script_sig = 0.to_openssl_bn
412
+ end
413
+ end
414
+ case hash_type
415
+ when 2
416
+ # SIGHASH_NONE
417
+ tx_copy.out_length = Cryptocoin::Protocol::VarLenInt.from_int(0)
418
+ tx_copy.outputs = ''
419
+ tx_copy.inputs.each do |i|
420
+ i.sequence = [0].pack('V') unless i == @input_index
421
+ end
422
+ when 3
423
+ # SIGHASH_SINGLE
424
+ if input_index >= tx_copy.outputs.length
425
+ # Special case, see https://github.com/bitcoinj/bitcoinj/blob/4df728a7d9210dc9ac5a5ae5188c89f5e9d41852/core/src/main/java/com/google/bitcoin/core/Transaction.java#L1018
426
+ # We're essentially resetting the transaction due to a bug
427
+ tx_copy = transaction
428
+ hash = Digest::SHA256([0100000000000000000000000000000000000000000000000000000000000000].pack('C*'))
429
+ bug = true
430
+ else
431
+ n_o = []
432
+ tx_copy.outputs.each do |o|
433
+ if o.index == @input_index
434
+ n_o.push(i)
435
+ elsif o.index < @input_index
436
+ # TODO: Implement this in a transaction builder
437
+ n_o.push(Cryptocoin::Structure::Transaction::Output.new(0, [-1].pack('q') + Cryptocoin::Protocol::VarLenInt.from_int(0)))
438
+ end
439
+ end
440
+ tx_copy.outputs = n_o
441
+ tx_copy.inputs.each do |i|
442
+ i.sequence = 0.to_openssl_bn_int
443
+ end
444
+ end
445
+ when 80
446
+ # SIGHASH_ANYONECANPAY
447
+ n_i = []
448
+ tx_copy.inputs.each do |i|
449
+ n_i.push(i) if i.index == @input.index
450
+ end
451
+ end
452
+ if !bug
453
+ # Do this if there's a bug in the reference client *SIGHASH_SINGLE*
454
+ i = tx_copy.raw + [hash_type].pack('V')
455
+ hash = Digest::SHA256.digest(Digest::SHA256.digest(i))
456
+ end
457
+ begin
458
+ k = OpenSSL::PKey::EC.new("secp256k1")
459
+ k.public_key = OpenSSL::PKey::EC::Point.new(k.group, OpenSSL::BN.new(pubkey.unpack('H*')[0], 16))
460
+ if k.dsa_verify_asn1(hash, signature)
461
+ stack.push(1.to_openssl_bn)
462
+ else
463
+ stack.push(0.to_openssl_bn)
464
+ end
465
+ rescue OpenSSL::PKey::ECError, OpenSSL::PKey::EC::Point::Error
466
+ stack.push(0.to_openssl_bn)
467
+ end
468
+ stack
469
+ end
470
+
471
+ def is_canonical_signature?(sig)
472
+ return false if sig.bytesize < 9
473
+ return false if sig.bytesize > 73
474
+ return false if !["\x01", "\x02", "\x03", "\x80"].include?(sig[-1])
475
+ return false if sig[0] != "\x30"
476
+ return false if sig[1].to_bn_to_i != sig.bytesize-3
477
+ r_length = sig[3].to_bn.to_i
478
+ return false if 5 + r_length >= sig.bytesize
479
+ s_length = sig[5+r_length]
480
+ return false if r_length + s_length + 7 != sig.bytesize
481
+ r = sig[4, r_length]
482
+ return false if r[-2] != "\x02"
483
+ return false if r.bytesize == 0
484
+ return false if r.bytes.inject{|x,y| (x<<8) | y} & 0x80
485
+ return false if r.bytesize > 1 and (r[0] == "\x00" and !(r[1].getbyte(0) & 0x80))
486
+ true
487
+ end
488
+
489
+ def is_canonical_pubkey?(pubkey)
490
+ return false if pubkey.bytesize < 33
491
+ case pubkey[0]
492
+ when "\x04"
493
+ # uncompressed pubkey
494
+ return false if pubkey.bytesize != 65
495
+ when "\x02", "\x03"
496
+ # compressed pubkey
497
+ return false if pubkey.bytesize != 33
498
+ else
499
+ # invalid first byte
500
+ return false
501
+ end
502
+ true
503
+ end
504
+
505
+ def require_stack(stack, size=1, &block)
506
+ if stack.size >= size
507
+ yield
508
+ else
509
+ nil
510
+ end
511
+ end
512
+ end
513
+ end
514
+ end
515
+ end