cryptocoin 0.0.1b

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.
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