btcruby 1.1.6 → 1.2
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/lib/btcruby/script/{cltv_plugin.rb → cltv_extension.rb} +2 -2
- data/lib/btcruby/script/{p2sh_plugin.rb → p2sh_extension.rb} +4 -4
- data/lib/btcruby/script/script_interpreter.rb +34 -34
- data/lib/btcruby/script/{script_interpreter_plugin.rb → script_interpreter_extension.rb} +10 -10
- data/lib/btcruby/version.rb +1 -1
- data/lib/btcruby.rb +3 -3
- data/spec/script_interpreter_spec.rb +4 -4
- data/spec/transaction_spec.rb +8 -8
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69203af0ce59eee2b3131a2df44cae9a7ca517be
|
4
|
+
data.tar.gz: f5fc80c6a9fed850298d7eb9b5812af45474e0d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 82f4dcc9b9114d38049baddc9675bbbde98ced25699cf4c03f9ff01c83217e265c06d096b6d945e967424ddad6b2975b755d821d5bfaecb1e9553b97c52d9bb3
|
7
|
+
data.tar.gz: 4818136ee80be83560ed4432889eb80de6b14973f1f8448cadebfc35cd47103f6ede63753656fc3b9ffcb32bdf814381abce98fd8dcd4d240f182182075bd497
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module BTC
|
2
2
|
# Performs CHECKLOCKTIMEVERIFY (BIP65) evaluation
|
3
|
-
class
|
4
|
-
include
|
3
|
+
class CLTVExtension
|
4
|
+
include ScriptInterpreterExtension
|
5
5
|
|
6
6
|
# Default `locktime_max_size` is 5.
|
7
7
|
# Default `lock_time_checker` equals current interpreter's signature checker.
|
@@ -1,15 +1,15 @@
|
|
1
1
|
module BTC
|
2
2
|
# Performs Pay-to-Script-Hash (BIP16) evaluation
|
3
|
-
class
|
4
|
-
include
|
3
|
+
class P2SHExtension
|
4
|
+
include ScriptInterpreterExtension
|
5
5
|
|
6
6
|
# Returns additional flags to be available to #flag? checks during script execution.
|
7
|
-
# This way one
|
7
|
+
# This way one extension can affect evaluation of another.
|
8
8
|
def extra_flags
|
9
9
|
SCRIPT_VERIFY_P2SH
|
10
10
|
end
|
11
11
|
|
12
|
-
# Every
|
12
|
+
# Every extension gets this callback. If extension return `false`, execution is stopped and interpreter returns `false`.
|
13
13
|
# Default value is `true`.
|
14
14
|
def did_execute_signature_script(interpreter: nil, signature_script: nil)
|
15
15
|
@signature_script = signature_script
|
@@ -15,9 +15,9 @@ module BTC
|
|
15
15
|
include ScriptErrors
|
16
16
|
include Opcodes
|
17
17
|
|
18
|
-
# Flags specified for this interpreter, not including flags added by
|
18
|
+
# Flags specified for this interpreter, not including flags added by extensions.
|
19
19
|
attr_accessor :flags
|
20
|
-
attr_accessor :
|
20
|
+
attr_accessor :extensions
|
21
21
|
attr_accessor :signature_checker
|
22
22
|
attr_accessor :raise_on_failure
|
23
23
|
attr_accessor :max_pushdata_size
|
@@ -36,7 +36,7 @@ module BTC
|
|
36
36
|
# (required if the scripts use signature-checking opcodes).
|
37
37
|
# Checker can be transaction checker or block checker
|
38
38
|
def initialize(flags: SCRIPT_VERIFY_NONE,
|
39
|
-
|
39
|
+
extensions: nil,
|
40
40
|
signature_checker: nil,
|
41
41
|
raise_on_failure: false,
|
42
42
|
max_pushdata_size: MAX_SCRIPT_ELEMENT_SIZE,
|
@@ -46,7 +46,7 @@ module BTC
|
|
46
46
|
integer_max_size: 4,
|
47
47
|
locktime_max_size: 5)
|
48
48
|
@flags = flags
|
49
|
-
@
|
49
|
+
@extensions = extensions || []
|
50
50
|
@signature_checker = signature_checker
|
51
51
|
|
52
52
|
@raise_on_failure = raise_on_failure
|
@@ -69,8 +69,8 @@ module BTC
|
|
69
69
|
return set_error(SCRIPT_ERR_SIG_PUSHONLY)
|
70
70
|
end
|
71
71
|
|
72
|
-
if
|
73
|
-
return
|
72
|
+
if extension = extension_to_handle_scripts(signature_script, output_script)
|
73
|
+
return extension.handle_scripts(
|
74
74
|
interpreter: self,
|
75
75
|
signature_script: signature_script,
|
76
76
|
output_script: output_script
|
@@ -87,13 +87,13 @@ module BTC
|
|
87
87
|
return false
|
88
88
|
end
|
89
89
|
|
90
|
-
# This is implemented in
|
90
|
+
# This is implemented in P2SHExtension
|
91
91
|
# stack_copy = if flag?(SCRIPT_VERIFY_P2SH)
|
92
92
|
# @stack.dup
|
93
93
|
# end
|
94
94
|
|
95
|
-
if
|
96
|
-
return
|
95
|
+
if extension = extension_to_handle_output_script(output_script)
|
96
|
+
return extension.handle_output_script(
|
97
97
|
interpreter: self,
|
98
98
|
output_script: output_script
|
99
99
|
) && verify_clean_stack_if_needed
|
@@ -118,7 +118,7 @@ module BTC
|
|
118
118
|
end
|
119
119
|
|
120
120
|
# Additional validation for pay-to-script-hash (P2SH) transactions:
|
121
|
-
# See
|
121
|
+
# See P2SHExtension#did_execute_output_script.
|
122
122
|
|
123
123
|
return verify_clean_stack_if_needed
|
124
124
|
end
|
@@ -140,7 +140,7 @@ module BTC
|
|
140
140
|
return set_error(SCRIPT_ERR_SCRIPT_SIZE)
|
141
141
|
end
|
142
142
|
|
143
|
-
# Altstack is not shared between individual runs, but we still store it in ivar to make available to the
|
143
|
+
# Altstack is not shared between individual runs, but we still store it in ivar to make available to the extensions.
|
144
144
|
@altstack = []
|
145
145
|
|
146
146
|
number_zero = ScriptNumber.new(integer: 0)
|
@@ -169,10 +169,10 @@ module BTC
|
|
169
169
|
end
|
170
170
|
end
|
171
171
|
|
172
|
-
# Check if there is a
|
173
|
-
|
172
|
+
# Check if there is a extension for this opcode before we check for disabled opcodes.
|
173
|
+
opcode_extension = extension_to_handle_opcode(opcode)
|
174
174
|
|
175
|
-
if !
|
175
|
+
if !opcode_extension
|
176
176
|
if opcode == OP_CAT ||
|
177
177
|
opcode == OP_SUBSTR ||
|
178
178
|
opcode == OP_LEFT ||
|
@@ -200,9 +200,9 @@ module BTC
|
|
200
200
|
end
|
201
201
|
stack_push(chunk.pushdata)
|
202
202
|
|
203
|
-
elsif should_execute &&
|
203
|
+
elsif should_execute && opcode_extension
|
204
204
|
|
205
|
-
if !
|
205
|
+
if !opcode_extension.handle_opcode(interpreter: self, opcode: opcode)
|
206
206
|
# error is set already
|
207
207
|
return false
|
208
208
|
end
|
@@ -224,7 +224,7 @@ module BTC
|
|
224
224
|
when OP_NOP
|
225
225
|
# nothing
|
226
226
|
|
227
|
-
# See
|
227
|
+
# See CLTVExtension
|
228
228
|
# when OP_CHECKLOCKTIMEVERIFY
|
229
229
|
# begin
|
230
230
|
# if !flag?(SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)
|
@@ -896,7 +896,7 @@ module BTC
|
|
896
896
|
end
|
897
897
|
|
898
898
|
def all_flags
|
899
|
-
@
|
899
|
+
@extensions.inject(@flags) do |f, p|
|
900
900
|
f | p.extra_flags
|
901
901
|
end
|
902
902
|
end
|
@@ -929,44 +929,44 @@ module BTC
|
|
929
929
|
|
930
930
|
private
|
931
931
|
|
932
|
-
def
|
933
|
-
@
|
934
|
-
if
|
935
|
-
return
|
932
|
+
def extension_to_handle_scripts(signature_script, output_script)
|
933
|
+
@extensions.each do |extension|
|
934
|
+
if extension.should_handle_scripts(interpreter: self, signature_script: signature_script, output_script: output_script)
|
935
|
+
return extension
|
936
936
|
end
|
937
937
|
end
|
938
938
|
nil
|
939
939
|
end
|
940
940
|
|
941
|
-
def
|
942
|
-
@
|
943
|
-
if
|
944
|
-
return
|
941
|
+
def extension_to_handle_output_script(output_script)
|
942
|
+
@extensions.each do |extension|
|
943
|
+
if extension.should_handle_output_script(interpreter: self, output_script: output_script)
|
944
|
+
return extension
|
945
945
|
end
|
946
946
|
end
|
947
947
|
nil
|
948
948
|
end
|
949
949
|
|
950
|
-
def
|
951
|
-
@
|
952
|
-
if
|
953
|
-
return
|
950
|
+
def extension_to_handle_opcode(opcode)
|
951
|
+
@extensions.each do |extension|
|
952
|
+
if extension.should_handle_opcode(interpreter: self, opcode: opcode)
|
953
|
+
return extension
|
954
954
|
end
|
955
955
|
end
|
956
956
|
nil
|
957
957
|
end
|
958
958
|
|
959
959
|
def did_execute_signature_script(signature_script)
|
960
|
-
@
|
961
|
-
if !
|
960
|
+
@extensions.each do |extension|
|
961
|
+
if !extension.did_execute_signature_script(interpreter: self, signature_script: signature_script)
|
962
962
|
return false
|
963
963
|
end
|
964
964
|
end
|
965
965
|
end
|
966
966
|
|
967
967
|
def did_execute_output_script(output_script)
|
968
|
-
@
|
969
|
-
if !
|
968
|
+
@extensions.each do |extension|
|
969
|
+
if !extension.did_execute_output_script(interpreter: self, output_script: output_script)
|
970
970
|
return false
|
971
971
|
end
|
972
972
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module BTC
|
2
|
-
#
|
2
|
+
# ScriptInterpreterExtension allows adding extensions to the script machinery without requiring source code meddling.
|
3
3
|
# ScriptInterpreter provides several extension points:
|
4
4
|
# - extra flags (e.g. requirement for push-only opcodes in signature script)
|
5
5
|
# - pre-flight hook to completely take control over both scripts' execution
|
@@ -7,19 +7,19 @@ module BTC
|
|
7
7
|
# - interior hook to take control over output script execution after signature script is being executed
|
8
8
|
# - callback after output script execution
|
9
9
|
# - hook for handling the opcodes
|
10
|
-
module
|
10
|
+
module ScriptInterpreterExtension
|
11
11
|
include ScriptFlags
|
12
12
|
include ScriptErrors
|
13
13
|
include Opcodes
|
14
14
|
|
15
15
|
# Returns additional flags to be available to #flag? checks during script execution.
|
16
|
-
# This way one
|
16
|
+
# This way one extension can affect evaluation of another.
|
17
17
|
def extra_flags
|
18
18
|
0
|
19
19
|
end
|
20
20
|
|
21
|
-
# The first
|
22
|
-
# No other callbacks are called for this
|
21
|
+
# The first extension that returns true takes control over both scripts via `handle_scripts`.
|
22
|
+
# No other callbacks are called for this extension or any other.
|
23
23
|
# Default value is `false`.
|
24
24
|
def should_handle_scripts(interpreter: nil, signature_script: nil, output_script: nil)
|
25
25
|
false
|
@@ -30,14 +30,14 @@ module BTC
|
|
30
30
|
false
|
31
31
|
end
|
32
32
|
|
33
|
-
# Every
|
33
|
+
# Every extension gets this callback. If extension return `false`, execution is stopped and interpreter returns `false`.
|
34
34
|
# Default value is `true`.
|
35
35
|
def did_execute_signature_script(interpreter: nil, signature_script: nil)
|
36
36
|
true
|
37
37
|
end
|
38
38
|
|
39
|
-
# The first
|
40
|
-
# No other callbacks are called for this
|
39
|
+
# The first extension that returns true takes control over output script via #handle_output_script.
|
40
|
+
# No other callbacks are called for this extension or any other.
|
41
41
|
# Default value is `false`.
|
42
42
|
def should_handle_output_script(interpreter: nil, output_script: nil)
|
43
43
|
false
|
@@ -48,13 +48,13 @@ module BTC
|
|
48
48
|
false
|
49
49
|
end
|
50
50
|
|
51
|
-
# Every
|
51
|
+
# Every extension gets this callback. If extension return `false`, execution is stopped and interpreter returns `false`.
|
52
52
|
# Default value is `true`.
|
53
53
|
def did_execute_output_script(interpreter: nil, output_script: nil)
|
54
54
|
true
|
55
55
|
end
|
56
56
|
|
57
|
-
# The first
|
57
|
+
# The first extension that returns true takes control over that opcode.
|
58
58
|
# Default value is `false`.
|
59
59
|
def should_handle_opcode(interpreter: nil, opcode: nil)
|
60
60
|
false
|
data/lib/btcruby/version.rb
CHANGED
data/lib/btcruby.rb
CHANGED
@@ -41,9 +41,9 @@ require_relative 'btcruby/script/signature_checker.rb'
|
|
41
41
|
require_relative 'btcruby/script/test_signature_checker.rb'
|
42
42
|
require_relative 'btcruby/script/transaction_signature_checker.rb'
|
43
43
|
|
44
|
-
require_relative 'btcruby/script/
|
45
|
-
require_relative 'btcruby/script/
|
46
|
-
require_relative 'btcruby/script/
|
44
|
+
require_relative 'btcruby/script/script_interpreter_extension.rb'
|
45
|
+
require_relative 'btcruby/script/p2sh_extension.rb'
|
46
|
+
require_relative 'btcruby/script/cltv_extension.rb'
|
47
47
|
|
48
48
|
require_relative 'btcruby/transaction_builder.rb'
|
49
49
|
require_relative 'btcruby/proof_of_work.rb'
|
@@ -10,12 +10,12 @@ describe BTC::ScriptInterpreter do
|
|
10
10
|
def verify_script(sig_script, output_script, flags, expected_result, record)
|
11
11
|
tx = build_spending_transaction(sig_script, build_crediting_transaction(output_script));
|
12
12
|
checker = BTC::TransactionSignatureChecker.new(transaction: tx, input_index: 0)
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
extensions = []
|
14
|
+
extensions << BTC::P2SHExtension.new if (flags & BTC::ScriptFlags::SCRIPT_VERIFY_P2SH) != 0
|
15
|
+
extensions << BTC::CLTVExtension.new if (flags & BTC::ScriptFlags::SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) != 0
|
16
16
|
interpreter = BTC::ScriptInterpreter.new(
|
17
17
|
flags: flags,
|
18
|
-
|
18
|
+
extensions: extensions,
|
19
19
|
signature_checker: checker,
|
20
20
|
raise_on_failure: false,
|
21
21
|
)
|
data/spec/transaction_spec.rb
CHANGED
@@ -75,12 +75,12 @@ describe BTC::Transaction do
|
|
75
75
|
end
|
76
76
|
|
77
77
|
checker = BTC::TransactionSignatureChecker.new(transaction: tx, input_index: txin.index)
|
78
|
-
|
79
|
-
|
80
|
-
|
78
|
+
extensions = []
|
79
|
+
extensions << BTC::P2SHExtension.new if (flags & BTC::ScriptFlags::SCRIPT_VERIFY_P2SH) != 0
|
80
|
+
extensions << BTC::CLTVExtension.new if (flags & BTC::ScriptFlags::SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) != 0
|
81
81
|
interpreter = BTC::ScriptInterpreter.new(
|
82
82
|
flags: flags,
|
83
|
-
|
83
|
+
extensions: extensions,
|
84
84
|
signature_checker: checker,
|
85
85
|
raise_on_failure: expected_result,
|
86
86
|
)
|
@@ -123,12 +123,12 @@ describe BTC::Transaction do
|
|
123
123
|
|
124
124
|
# def verify_script(tx, txin, sig_script, output_script, flags, expected_result, record)
|
125
125
|
# checker = TransactionSignatureChecker.new(transaction: tx, input_index: txin.index)
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
126
|
+
# extensions = []
|
127
|
+
# extensions << P2SHExtension.new if (flags & ScriptFlags::SCRIPT_VERIFY_P2SH) != 0
|
128
|
+
# extensions << CLTVExtension.new if (flags & ScriptFlags::SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) != 0
|
129
129
|
# interpreter = ScriptInterpreter.new(
|
130
130
|
# flags: flags,
|
131
|
-
#
|
131
|
+
# extensions: extensions,
|
132
132
|
# signature_checker: checker,
|
133
133
|
# raise_on_failure: expected_result,
|
134
134
|
# )
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: btcruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: '1.2'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oleg Andreev
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-08
|
12
|
+
date: 2015-09-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
@@ -104,15 +104,15 @@ files:
|
|
104
104
|
- lib/btcruby/outpoint.rb
|
105
105
|
- lib/btcruby/proof_of_work.rb
|
106
106
|
- lib/btcruby/safety.rb
|
107
|
-
- lib/btcruby/script/
|
107
|
+
- lib/btcruby/script/cltv_extension.rb
|
108
108
|
- lib/btcruby/script/opcode.rb
|
109
|
-
- lib/btcruby/script/
|
109
|
+
- lib/btcruby/script/p2sh_extension.rb
|
110
110
|
- lib/btcruby/script/script.rb
|
111
111
|
- lib/btcruby/script/script_chunk.rb
|
112
112
|
- lib/btcruby/script/script_error.rb
|
113
113
|
- lib/btcruby/script/script_flags.rb
|
114
114
|
- lib/btcruby/script/script_interpreter.rb
|
115
|
-
- lib/btcruby/script/
|
115
|
+
- lib/btcruby/script/script_interpreter_extension.rb
|
116
116
|
- lib/btcruby/script/script_number.rb
|
117
117
|
- lib/btcruby/script/signature_checker.rb
|
118
118
|
- lib/btcruby/script/signature_hashtype.rb
|