bitcoinrb 0.0.1
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 +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bitcoinrb.gemspec +32 -0
- data/exe/bitcoinrb-cli +5 -0
- data/exe/bitcoinrbd +49 -0
- data/lib/bitcoin.rb +121 -0
- data/lib/bitcoin/base58.rb +40 -0
- data/lib/bitcoin/block_header.rb +41 -0
- data/lib/bitcoin/chain_params.rb +57 -0
- data/lib/bitcoin/chainparams/mainnet.yml +25 -0
- data/lib/bitcoin/chainparams/regtest.yml +20 -0
- data/lib/bitcoin/chainparams/testnet.yml +24 -0
- data/lib/bitcoin/connection.rb +66 -0
- data/lib/bitcoin/ext_key.rb +205 -0
- data/lib/bitcoin/key.rb +131 -0
- data/lib/bitcoin/logger.rb +18 -0
- data/lib/bitcoin/merkle_tree.rb +120 -0
- data/lib/bitcoin/message.rb +42 -0
- data/lib/bitcoin/message/addr.rb +74 -0
- data/lib/bitcoin/message/base.rb +40 -0
- data/lib/bitcoin/message/block.rb +41 -0
- data/lib/bitcoin/message/error.rb +10 -0
- data/lib/bitcoin/message/fee_filter.rb +27 -0
- data/lib/bitcoin/message/filter_add.rb +28 -0
- data/lib/bitcoin/message/filter_clear.rb +17 -0
- data/lib/bitcoin/message/filter_load.rb +43 -0
- data/lib/bitcoin/message/get_addr.rb +17 -0
- data/lib/bitcoin/message/get_blocks.rb +29 -0
- data/lib/bitcoin/message/get_data.rb +21 -0
- data/lib/bitcoin/message/get_headers.rb +28 -0
- data/lib/bitcoin/message/handler.rb +170 -0
- data/lib/bitcoin/message/headers.rb +34 -0
- data/lib/bitcoin/message/headers_parser.rb +24 -0
- data/lib/bitcoin/message/inv.rb +21 -0
- data/lib/bitcoin/message/inventories_parser.rb +23 -0
- data/lib/bitcoin/message/inventory.rb +47 -0
- data/lib/bitcoin/message/mem_pool.rb +17 -0
- data/lib/bitcoin/message/merkle_block.rb +42 -0
- data/lib/bitcoin/message/not_found.rb +29 -0
- data/lib/bitcoin/message/ping.rb +30 -0
- data/lib/bitcoin/message/pong.rb +26 -0
- data/lib/bitcoin/message/reject.rb +46 -0
- data/lib/bitcoin/message/send_cmpct.rb +43 -0
- data/lib/bitcoin/message/send_headers.rb +16 -0
- data/lib/bitcoin/message/tx.rb +30 -0
- data/lib/bitcoin/message/ver_ack.rb +17 -0
- data/lib/bitcoin/message/version.rb +79 -0
- data/lib/bitcoin/mnemonic.rb +76 -0
- data/lib/bitcoin/mnemonic/wordlist/chinese_simplified.txt +2048 -0
- data/lib/bitcoin/mnemonic/wordlist/chinese_traditional.txt +2048 -0
- data/lib/bitcoin/mnemonic/wordlist/english.txt +2048 -0
- data/lib/bitcoin/mnemonic/wordlist/french.txt +2048 -0
- data/lib/bitcoin/mnemonic/wordlist/italian.txt +2048 -0
- data/lib/bitcoin/mnemonic/wordlist/japanese.txt +2048 -0
- data/lib/bitcoin/mnemonic/wordlist/spanish.txt +2048 -0
- data/lib/bitcoin/nodes.rb +5 -0
- data/lib/bitcoin/nodes/spv.rb +13 -0
- data/lib/bitcoin/nodes/spv/cli.rb +12 -0
- data/lib/bitcoin/nodes/spv/daemon.rb +21 -0
- data/lib/bitcoin/opcodes.rb +172 -0
- data/lib/bitcoin/out_point.rb +31 -0
- data/lib/bitcoin/script/script.rb +347 -0
- data/lib/bitcoin/script/script_error.rb +168 -0
- data/lib/bitcoin/script/script_interpreter.rb +694 -0
- data/lib/bitcoin/script/tx_checker.rb +44 -0
- data/lib/bitcoin/script_witness.rb +29 -0
- data/lib/bitcoin/secp256k1.rb +10 -0
- data/lib/bitcoin/secp256k1/native.rb +22 -0
- data/lib/bitcoin/secp256k1/ruby.rb +96 -0
- data/lib/bitcoin/tx.rb +191 -0
- data/lib/bitcoin/tx_in.rb +45 -0
- data/lib/bitcoin/tx_out.rb +32 -0
- data/lib/bitcoin/util.rb +105 -0
- data/lib/bitcoin/version.rb +3 -0
- metadata +256 -0
@@ -0,0 +1,168 @@
|
|
1
|
+
module Bitcoin
|
2
|
+
|
3
|
+
# bitcoin script error
|
4
|
+
class ScriptError < Exception
|
5
|
+
|
6
|
+
SCRIPT_ERR_OK = 0
|
7
|
+
SCRIPT_ERR_UNKNOWN_ERROR = 1
|
8
|
+
SCRIPT_ERR_EVAL_FALSE = 2
|
9
|
+
SCRIPT_ERR_OP_RETURN = 3
|
10
|
+
|
11
|
+
# Max sizes
|
12
|
+
SCRIPT_ERR_SCRIPT_SIZE = 10
|
13
|
+
SCRIPT_ERR_PUSH_SIZE = 11
|
14
|
+
SCRIPT_ERR_OP_COUNT = 12
|
15
|
+
SCRIPT_ERR_STACK_SIZE = 13
|
16
|
+
SCRIPT_ERR_SIG_COUNT = 14
|
17
|
+
SCRIPT_ERR_PUBKEY_COUNT = 15
|
18
|
+
|
19
|
+
# Failed verify operations
|
20
|
+
SCRIPT_ERR_VERIFY = 20
|
21
|
+
SCRIPT_ERR_EQUALVERIFY = 21
|
22
|
+
SCRIPT_ERR_CHECKMULTISIGVERIFY = 22
|
23
|
+
SCRIPT_ERR_CHECKSIGVERIFY = 23
|
24
|
+
SCRIPT_ERR_NUMEQUALVERIFY = 24
|
25
|
+
|
26
|
+
# Logical/Format/Canonical errors
|
27
|
+
SCRIPT_ERR_BAD_OPCODE = 30
|
28
|
+
SCRIPT_ERR_DISABLED_OPCODE = 31
|
29
|
+
SCRIPT_ERR_INVALID_STACK_OPERATION = 32
|
30
|
+
SCRIPT_ERR_INVALID_ALTSTACK_OPERATION = 33
|
31
|
+
SCRIPT_ERR_UNBALANCED_CONDITIONAL = 34
|
32
|
+
|
33
|
+
# CHECKLOCKTIMEVERIFY and CHECKSEQUENCEVERIFY
|
34
|
+
SCRIPT_ERR_NEGATIVE_LOCKTIME = 40
|
35
|
+
SCRIPT_ERR_UNSATISFIED_LOCKTIME = 41
|
36
|
+
|
37
|
+
# Malleability
|
38
|
+
SCRIPT_ERR_SIG_HASHTYPE = 50
|
39
|
+
SCRIPT_ERR_SIG_DER = 51
|
40
|
+
SCRIPT_ERR_MINIMALDATA = 52
|
41
|
+
SCRIPT_ERR_SIG_PUSHONLY = 53
|
42
|
+
SCRIPT_ERR_SIG_HIGH_S = 54
|
43
|
+
SCRIPT_ERR_SIG_NULLDUMMY = 55
|
44
|
+
SCRIPT_ERR_PUBKEYTYPE = 56
|
45
|
+
SCRIPT_ERR_CLEANSTACK = 56
|
46
|
+
SCRIPT_ERR_MINIMALIF = 57
|
47
|
+
SCRIPT_ERR_SIG_NULLFAIL = 58
|
48
|
+
|
49
|
+
# softfork safeness
|
50
|
+
SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS = 60
|
51
|
+
SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM = 61
|
52
|
+
|
53
|
+
# segregated witness
|
54
|
+
SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH = 70
|
55
|
+
SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY = 71
|
56
|
+
SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH = 72
|
57
|
+
SCRIPT_ERR_WITNESS_MALLEATED = 73
|
58
|
+
SCRIPT_ERR_WITNESS_MALLEATED_P2SH = 74
|
59
|
+
SCRIPT_ERR_WITNESS_UNEXPECTED = 75
|
60
|
+
SCRIPT_ERR_WITNESS_PUBKEYTYPE = 76
|
61
|
+
|
62
|
+
SCRIPT_ERR_ERROR_COUNT = 80
|
63
|
+
|
64
|
+
ERRCODES_MAP = Hash[*constants.grep(/^SCRIPT_ERR_/).map { |c| [const_get(c), c.to_s] }.flatten]
|
65
|
+
NAME_MAP = Hash[*constants.grep(/^SCRIPT_ERR_/).map { |c| [c.to_s, const_get(c)] }.flatten]
|
66
|
+
|
67
|
+
attr_accessor :code
|
68
|
+
attr_accessor :extra_msg
|
69
|
+
|
70
|
+
def initialize(code, extra_msg = '')
|
71
|
+
raise 'invalid error code.' unless ERRCODES_MAP[code]
|
72
|
+
@code = code
|
73
|
+
@extra_msg = extra_msg
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_s
|
77
|
+
case code
|
78
|
+
when SCRIPT_ERR_OK
|
79
|
+
'No error'
|
80
|
+
when SCRIPT_ERR_EVAL_FALSE
|
81
|
+
'Script evaluated without error but finished with a false/empty top stack element'
|
82
|
+
when SCRIPT_ERR_VERIFY
|
83
|
+
'Script failed an OP_VERIFY operation'
|
84
|
+
when SCRIPT_ERR_EQUALVERIFY
|
85
|
+
'Script failed an OP_EQUALVERIFY operation'
|
86
|
+
when SCRIPT_ERR_CHECKMULTISIGVERIFY
|
87
|
+
'Script failed an OP_CHECKMULTISIGVERIFY operation'
|
88
|
+
when SCRIPT_ERR_CHECKSIGVERIFY
|
89
|
+
'Script failed an OP_CHECKSIGVERIFY operation'
|
90
|
+
when SCRIPT_ERR_NUMEQUALVERIFY
|
91
|
+
'Script failed an OP_NUMEQUALVERIFY operation'
|
92
|
+
when SCRIPT_ERR_SCRIPT_SIZE
|
93
|
+
'Script is too big'
|
94
|
+
when SCRIPT_ERR_PUSH_SIZE
|
95
|
+
'Push value size limit exceeded'
|
96
|
+
when SCRIPT_ERR_OP_COUNT
|
97
|
+
'Operation limit exceeded'
|
98
|
+
when SCRIPT_ERR_STACK_SIZE
|
99
|
+
'Stack size limit exceeded'
|
100
|
+
when SCRIPT_ERR_SIG_COUNT
|
101
|
+
'Signature count negative or greater than pubkey count'
|
102
|
+
when SCRIPT_ERR_PUBKEY_COUNT
|
103
|
+
'Pubkey count negative or limit exceeded'
|
104
|
+
when SCRIPT_ERR_BAD_OPCODE
|
105
|
+
'Opcode missing or not understood'
|
106
|
+
when SCRIPT_ERR_DISABLED_OPCODE
|
107
|
+
'Attempted to use a disabled opcode'
|
108
|
+
when SCRIPT_ERR_INVALID_STACK_OPERATION
|
109
|
+
'Operation not valid with the current stack size'
|
110
|
+
when SCRIPT_ERR_INVALID_ALTSTACK_OPERATION
|
111
|
+
'Operation not valid with the current altstack size'
|
112
|
+
when SCRIPT_ERR_OP_RETURN
|
113
|
+
'OP_was encountered'
|
114
|
+
when SCRIPT_ERR_UNBALANCED_CONDITIONAL
|
115
|
+
'Invalid OP_IF construction'
|
116
|
+
when SCRIPT_ERR_NEGATIVE_LOCKTIME
|
117
|
+
'Negative locktime'
|
118
|
+
when SCRIPT_ERR_UNSATISFIED_LOCKTIME
|
119
|
+
'Locktime requirement not satisfied'
|
120
|
+
when SCRIPT_ERR_SIG_HASHTYPE
|
121
|
+
'Signature hash type missing or not understood'
|
122
|
+
when SCRIPT_ERR_SIG_DER
|
123
|
+
'Non-canonical DER signature'
|
124
|
+
when SCRIPT_ERR_MINIMALDATA
|
125
|
+
'Data push larger than necessary'
|
126
|
+
when SCRIPT_ERR_SIG_PUSHONLY
|
127
|
+
'Only non-push operators allowed in signatures'
|
128
|
+
when SCRIPT_ERR_SIG_HIGH_S
|
129
|
+
'Non-canonical signature S value is unnecessarily high'
|
130
|
+
when SCRIPT_ERR_SIG_NULLDUMMY
|
131
|
+
'Dummy CHECKMULTISIG argument must be zero'
|
132
|
+
when SCRIPT_ERR_MINIMALIF
|
133
|
+
'OP_IF/NOTIF argument must be minimal'
|
134
|
+
when SCRIPT_ERR_SIG_NULLFAIL
|
135
|
+
'Signature must be zero for failed CHECK(MULTI)SIG operation'
|
136
|
+
when SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS
|
137
|
+
'NOPx reserved for soft-fork upgrades'
|
138
|
+
when SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM
|
139
|
+
'Witness version reserved for soft-fork upgrades'
|
140
|
+
when SCRIPT_ERR_PUBKEYTYPE
|
141
|
+
'Public key is neither compressed or uncompressed'
|
142
|
+
when SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH
|
143
|
+
'Witness program has incorrect length'
|
144
|
+
when SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY
|
145
|
+
'Witness program was passed an empty witness'
|
146
|
+
when SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH
|
147
|
+
'Witness program hash mismatch'
|
148
|
+
when SCRIPT_ERR_WITNESS_MALLEATED
|
149
|
+
'Witness requires empty scriptSig'
|
150
|
+
when SCRIPT_ERR_WITNESS_MALLEATED_P2SH
|
151
|
+
'Witness requires only-redeemscript scriptSig'
|
152
|
+
when SCRIPT_ERR_WITNESS_UNEXPECTED
|
153
|
+
'Witness provided for non-witness script'
|
154
|
+
when SCRIPT_ERR_WITNESS_PUBKEYTYPE
|
155
|
+
'Using non-compressed keys in segwit'
|
156
|
+
when SCRIPT_ERR_UNKNOWN_ERROR, SCRIPT_ERR_ERROR_COUNT
|
157
|
+
'unknown error'
|
158
|
+
else
|
159
|
+
extra_msg ? extra_msg : 'unknown error'
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.name_to_code(name)
|
164
|
+
NAME_MAP[name]
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,694 @@
|
|
1
|
+
module Bitcoin
|
2
|
+
|
3
|
+
SCRIPT_VERIFY_NONE = 0
|
4
|
+
SCRIPT_VERIFY_P2SH = (1 << 0)
|
5
|
+
SCRIPT_VERIFY_STRICTENC = (1 << 1)
|
6
|
+
SCRIPT_VERIFY_DERSIG = (1 << 2)
|
7
|
+
SCRIPT_VERIFY_LOW_S = (1 << 3)
|
8
|
+
SCRIPT_VERIFY_NULLDUMMY = (1 << 4)
|
9
|
+
SCRIPT_VERIFY_SIGPUSHONLY = (1 << 5)
|
10
|
+
SCRIPT_VERIFY_MINIMALDATA = (1 << 6)
|
11
|
+
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1 << 7)
|
12
|
+
SCRIPT_VERIFY_CLEANSTACK = (1 << 8)
|
13
|
+
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1 << 9) # Verify CHECKLOCKTIMEVERIFY (BIP-65)
|
14
|
+
SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1 << 10) # support CHECKSEQUENCEVERIFY opcode (BIP-112)
|
15
|
+
SCRIPT_VERIFY_WITNESS = (1 << 11) # Support segregated witness
|
16
|
+
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM = (1 << 12) # Making v1-v16 witness program non-standard
|
17
|
+
SCRIPT_VERIFY_MINIMALIF = (1 << 13) # Segwit script only: Require the argument of OP_IF/NOTIF to be exactly 0x01 or empty vector
|
18
|
+
SCRIPT_VERIFY_NULLFAIL = (1 << 14) # Signature(s) must be empty vector if an CHECK(MULTI)SIG operation failed
|
19
|
+
SCRIPT_VERIFY_WITNESS_PUBKEYTYPE = (1 << 15) # Public keys in segregated witness scripts must be compressed
|
20
|
+
|
21
|
+
class ScriptInterpreter
|
22
|
+
|
23
|
+
include Bitcoin::Opcodes
|
24
|
+
|
25
|
+
SIG_VERSION = {base: 0, witness_v0: 1}
|
26
|
+
|
27
|
+
attr_reader :stack
|
28
|
+
attr_reader :debug
|
29
|
+
attr_reader :flags
|
30
|
+
attr_accessor :error
|
31
|
+
attr_reader :checker
|
32
|
+
attr_reader :require_minimal
|
33
|
+
|
34
|
+
DISABLE_OPCODES = [OP_CAT, OP_SUBSTR, OP_LEFT, OP_RIGHT, OP_INVERT, OP_AND, OP_OR, OP_XOR, OP_2MUL, OP_2DIV, OP_DIV, OP_MUL, OP_MOD, OP_LSHIFT, OP_RSHIFT]
|
35
|
+
|
36
|
+
# initialize runner
|
37
|
+
def initialize(flags: [], checker: TxChecker.new)
|
38
|
+
@stack, @debug = [], []
|
39
|
+
@flags = flags
|
40
|
+
@checker = checker
|
41
|
+
@require_minimal = flag?(SCRIPT_VERIFY_MINIMALDATA)
|
42
|
+
end
|
43
|
+
|
44
|
+
# eval script
|
45
|
+
# @param [Bitcoin::Script] script_sig a signature script (unlock script which data push only)
|
46
|
+
# @param [Bitcoin::Script] script_pubkey a script pubkey (locking script)
|
47
|
+
# @param [Bitcoin::ScriptWitness] witness a witness script
|
48
|
+
# @return [Boolean] result
|
49
|
+
def verify(script_sig, script_pubkey, witness = nil)
|
50
|
+
|
51
|
+
return set_error(ScriptError::SCRIPT_ERR_SIG_PUSHONLY) if flag?(SCRIPT_VERIFY_SIGPUSHONLY) && !script_sig.data_only?
|
52
|
+
|
53
|
+
stack_copy = nil
|
54
|
+
had_witness = false
|
55
|
+
|
56
|
+
return false unless eval_script(script_sig, SIG_VERSION[:base])
|
57
|
+
|
58
|
+
stack_copy = stack.dup if flag?(SCRIPT_VERIFY_P2SH)
|
59
|
+
|
60
|
+
return false unless eval_script(script_pubkey, SIG_VERSION[:base])
|
61
|
+
|
62
|
+
return set_error(ScriptError::SCRIPT_ERR_EVAL_FALSE) if stack.empty? || !cast_to_bool(stack.last)
|
63
|
+
|
64
|
+
# Bare witness programs
|
65
|
+
if flag?(SCRIPT_VERIFY_WITNESS) && script_pubkey.witness_program?
|
66
|
+
had_witness = true
|
67
|
+
return set_error(ScriptError::SCRIPT_ERR_WITNESS_MALLEATED) unless script_sig.size == 0
|
68
|
+
version, program = script_pubkey.witness_data
|
69
|
+
stack_copy = stack.dup
|
70
|
+
return false unless verify_witness_program(witness, version, program)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Additional validation for spend-to-script-hash transactions
|
74
|
+
if flag?(SCRIPT_VERIFY_P2SH) && script_pubkey.p2sh?
|
75
|
+
return set_error(ScriptError::SCRIPT_ERR_SIG_PUSHONLY) unless script_sig.data_only?
|
76
|
+
tmp = stack
|
77
|
+
@stack = stack_copy
|
78
|
+
raise 'stack cannot be empty.' if stack.empty?
|
79
|
+
begin
|
80
|
+
redeem_script = Bitcoin::Script.parse_from_payload(stack.pop.htb)
|
81
|
+
rescue Exception => e
|
82
|
+
return set_error(ScriptError::SCRIPT_ERR_BAD_OPCODE, "Failed to parse serialized redeem script for P2SH. #{e.message}")
|
83
|
+
end
|
84
|
+
return false unless eval_script(redeem_script, SIG_VERSION[:base])
|
85
|
+
return set_error(ScriptError::SCRIPT_ERR_EVAL_FALSE) if stack.empty? || !cast_to_bool(stack.last)
|
86
|
+
|
87
|
+
# P2SH witness program
|
88
|
+
if flag?(SCRIPT_VERIFY_WITNESS) && redeem_script.witness_program?
|
89
|
+
had_witness = true
|
90
|
+
# The scriptSig must be _exactly_ a single push of the redeemScript. Otherwise we reintroduce malleability.
|
91
|
+
return set_error(ScriptError::SCRIPT_ERR_WITNESS_MALLEATED_P2SH) unless script_sig == (Bitcoin::Script.new << redeem_script.to_payload.bth)
|
92
|
+
|
93
|
+
version, program = redeem_script.witness_data
|
94
|
+
return false unless verify_witness_program(witness, version, program)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# The CLEANSTACK check is only performed after potential P2SH evaluation,
|
99
|
+
# as the non-P2SH evaluation of a P2SH script will obviously not result in a clean stack (the P2SH inputs remain).
|
100
|
+
# The same holds for witness evaluation.
|
101
|
+
if flag?(SCRIPT_VERIFY_CLEANSTACK)
|
102
|
+
# Disallow CLEANSTACK without P2SH, as otherwise a switch CLEANSTACK->P2SH+CLEANSTACK would be possible,
|
103
|
+
# which is not a softfork (and P2SH should be one).
|
104
|
+
raise 'assert' unless flag?(SCRIPT_VERIFY_P2SH)
|
105
|
+
return set_error(ScriptError::SCRIPT_ERR_CLEANSTACK) unless stack.size == 1
|
106
|
+
end
|
107
|
+
|
108
|
+
if flag?(SCRIPT_VERIFY_WITNESS)
|
109
|
+
raise 'assert' unless flag?(SCRIPT_VERIFY_P2SH)
|
110
|
+
return set_error(ScriptError::SCRIPT_ERR_WITNESS_UNEXPECTED) if !had_witness && !witness.empty?
|
111
|
+
end
|
112
|
+
|
113
|
+
true
|
114
|
+
end
|
115
|
+
|
116
|
+
def set_error(err_code, extra_message = nil)
|
117
|
+
@error = ScriptError.new(err_code, extra_message)
|
118
|
+
false
|
119
|
+
end
|
120
|
+
|
121
|
+
def verify_sig
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
def verify_witness_program(witness, version, program)
|
126
|
+
if version == 0
|
127
|
+
if program.bytesize == 32
|
128
|
+
return set_error(ScriptError::SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY) if witness.stack.size == 0
|
129
|
+
script_pubkey = Bitcoin::Script.parse_from_payload(witness.stack.last)
|
130
|
+
@stack = witness.stack[0..-2]
|
131
|
+
script_hash = Bitcoin.sha256(script_pubkey.to_payload)
|
132
|
+
return set_error(ScriptError::SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH) unless script_hash == program
|
133
|
+
elsif program.bytesize == 20
|
134
|
+
return set_error(ScriptError::SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH) unless witness.stack.size == 2
|
135
|
+
script_pubkey = Bitcoin::Script.to_p2pkh(program.bth)
|
136
|
+
@stack = witness.stack.map{|w|w.bth}
|
137
|
+
else
|
138
|
+
return set_error(ScriptError::SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH)
|
139
|
+
end
|
140
|
+
elsif flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)
|
141
|
+
return set_error(ScriptError::SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH)
|
142
|
+
else
|
143
|
+
return true # Higher version witness scripts return true for future softfork compatibility
|
144
|
+
end
|
145
|
+
|
146
|
+
stack.each do |s| # Disallow stack item size > MAX_SCRIPT_ELEMENT_SIZE in witness stack
|
147
|
+
return set_error(ScriptError::SCRIPT_ERR_PUSH_SIZE) if s.bytesize > Script::MAX_SCRIPT_ELEMENT_SIZE
|
148
|
+
end
|
149
|
+
|
150
|
+
return false unless eval_script(script_pubkey, SIG_VERSION[:witness_v0])
|
151
|
+
|
152
|
+
return set_error(ScriptError::SCRIPT_ERR_EVAL_FALSE) unless stack.size == 1
|
153
|
+
return set_error(ScriptError::SCRIPT_ERR_EVAL_FALSE) unless cast_to_bool(stack.last)
|
154
|
+
true
|
155
|
+
end
|
156
|
+
|
157
|
+
def eval_script(script, sig_version)
|
158
|
+
return set_error(ScriptError::SCRIPT_ERR_SCRIPT_SIZE) if script.size > Script::MAX_SCRIPT_SIZE
|
159
|
+
begin
|
160
|
+
flow_stack = []
|
161
|
+
alt_stack = []
|
162
|
+
last_code_separator_index = 0
|
163
|
+
op_count = 0
|
164
|
+
|
165
|
+
script.chunks.each_with_index do |c, index|
|
166
|
+
need_exec = !flow_stack.include?(false)
|
167
|
+
|
168
|
+
return set_error(ScriptError::SCRIPT_ERR_PUSH_SIZE) if c.pushdata? && c.pushed_data.bytesize > Script::MAX_SCRIPT_ELEMENT_SIZE
|
169
|
+
|
170
|
+
opcode = c.opcode
|
171
|
+
|
172
|
+
if need_exec && c.pushdata?
|
173
|
+
if require_minimal && !minimal_push?(c.pushed_data, opcode)
|
174
|
+
return set_error(ScriptError::SCRIPT_ERR_MINIMALDATA)
|
175
|
+
end
|
176
|
+
return set_error(ScriptError::SCRIPT_ERR_BAD_OPCODE) unless verify_pushdata_length(c)
|
177
|
+
stack << c.pushed_data.bth
|
178
|
+
else
|
179
|
+
if opcode > OP_16 && (op_count += 1) > Script::MAX_OPS_PER_SCRIPT
|
180
|
+
return set_error(ScriptError::SCRIPT_ERR_OP_COUNT)
|
181
|
+
end
|
182
|
+
return set_error(ScriptError::SCRIPT_ERR_DISABLED_OPCODE) if DISABLE_OPCODES.include?(opcode)
|
183
|
+
next unless (need_exec || (OP_IF <= opcode && opcode <= OP_ENDIF))
|
184
|
+
small_int = Opcodes.opcode_to_small_int(opcode)
|
185
|
+
if small_int && opcode != OP_0
|
186
|
+
push_int(small_int)
|
187
|
+
else
|
188
|
+
case opcode
|
189
|
+
when OP_0
|
190
|
+
stack << ''
|
191
|
+
when OP_DEPTH
|
192
|
+
push_int(stack.size)
|
193
|
+
when OP_EQUAL, OP_EQUALVERIFY
|
194
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
195
|
+
a, b = pop_string(2)
|
196
|
+
result = a == b
|
197
|
+
push_int(result ? 1 : 0)
|
198
|
+
if opcode == OP_EQUALVERIFY
|
199
|
+
if result
|
200
|
+
stack.pop
|
201
|
+
else
|
202
|
+
return set_error(ScriptError::SCRIPT_ERR_EQUALVERIFY)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
when OP_0NOTEQUAL
|
206
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
207
|
+
push_int(pop_int == 0 ? 0 : 1)
|
208
|
+
when OP_ADD
|
209
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
210
|
+
a, b = pop_int(2)
|
211
|
+
push_int(a + b)
|
212
|
+
when OP_1ADD
|
213
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
214
|
+
push_int(pop_int + 1)
|
215
|
+
when OP_SUB
|
216
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
217
|
+
a, b = pop_int(2)
|
218
|
+
push_int(a - b)
|
219
|
+
when OP_1SUB
|
220
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
221
|
+
push_int(pop_int - 1)
|
222
|
+
when OP_IF, OP_NOTIF
|
223
|
+
result = false
|
224
|
+
if need_exec
|
225
|
+
return set_error(ScriptError::SCRIPT_ERR_UNBALANCED_CONDITIONAL) if stack.size < 1
|
226
|
+
result = pop_bool
|
227
|
+
result = !result if opcode == OP_NOTIF
|
228
|
+
end
|
229
|
+
flow_stack << result
|
230
|
+
when OP_ELSE
|
231
|
+
return set_error(ScriptError::SCRIPT_ERR_UNBALANCED_CONDITIONAL) if flow_stack.size < 1
|
232
|
+
flow_stack << !flow_stack.pop
|
233
|
+
when OP_ENDIF
|
234
|
+
return set_error(ScriptError::SCRIPT_ERR_UNBALANCED_CONDITIONAL) if flow_stack.empty?
|
235
|
+
flow_stack.pop
|
236
|
+
when OP_NOP
|
237
|
+
when OP_NOP1, OP_NOP4..OP_NOP10
|
238
|
+
return set_error(ScriptError::SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS) if flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
|
239
|
+
when OP_CHECKLOCKTIMEVERIFY
|
240
|
+
unless flag?(SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)
|
241
|
+
return set_error(ScriptError::SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS) if flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
|
242
|
+
next
|
243
|
+
end
|
244
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
245
|
+
locktime = pop_int
|
246
|
+
return set_error(ScriptError::SCRIPT_ERR_NEGATIVE_LOCKTIME) if locktime < 0
|
247
|
+
return set_error(ScriptError::SCRIPT_ERR_UNSATISFIED_LOCKTIME) unless checker.check_locktime(locktime)
|
248
|
+
when OP_CHECKSEQUENCEVERIFY
|
249
|
+
unless flag?(SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)
|
250
|
+
return set_error(ScriptError::SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS) if flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
|
251
|
+
next
|
252
|
+
end
|
253
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
254
|
+
# TODO implement
|
255
|
+
when OP_DUP
|
256
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
257
|
+
stack << stack.last
|
258
|
+
when OP_2DUP
|
259
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
260
|
+
2.times { stack << stack[-2] }
|
261
|
+
when OP_3DUP
|
262
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
|
263
|
+
3.times { stack << stack[-3] }
|
264
|
+
when OP_IFDUP
|
265
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
266
|
+
stack << stack.last if cast_to_bool(stack.last)
|
267
|
+
when OP_RIPEMD160
|
268
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
269
|
+
stack << Digest::RMD160.hexdigest(pop_string.htb)
|
270
|
+
when OP_SHA1
|
271
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
272
|
+
stack << Digest::SHA1.hexdigest(pop_string.htb)
|
273
|
+
when OP_SHA256
|
274
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
275
|
+
stack << Digest::SHA256.hexdigest(pop_string.htb)
|
276
|
+
when OP_HASH160
|
277
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
278
|
+
stack << Bitcoin.hash160(pop_string)
|
279
|
+
when OP_HASH256
|
280
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
281
|
+
stack << Bitcoin.double_sha256(pop_string.htb).bth
|
282
|
+
when OP_VERIFY
|
283
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
284
|
+
return set_error(ScriptError::SCRIPT_ERR_VERIFY) unless pop_bool
|
285
|
+
when OP_TOALTSTACK
|
286
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
287
|
+
alt_stack << stack.pop
|
288
|
+
when OP_FROMALTSTACK
|
289
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_ALTSTACK_OPERATION) if alt_stack.size < 1
|
290
|
+
stack << alt_stack.pop
|
291
|
+
when OP_DROP
|
292
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
293
|
+
stack.pop
|
294
|
+
when OP_2DROP
|
295
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
296
|
+
2.times { stack.pop }
|
297
|
+
when OP_NIP
|
298
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
299
|
+
stack.delete_at(-2)
|
300
|
+
when OP_OVER
|
301
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
302
|
+
stack << stack[-2]
|
303
|
+
when OP_2OVER
|
304
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 4
|
305
|
+
2.times { stack << stack[-4]}
|
306
|
+
when OP_PICK, OP_ROLL
|
307
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
308
|
+
pos = pop_int
|
309
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if pos < 0 || pos >= stack.size
|
310
|
+
stack << stack[-pos - 1]
|
311
|
+
stack.delete_at(-pos - 2) if opcode == OP_ROLL
|
312
|
+
when OP_ROT
|
313
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
|
314
|
+
stack << stack[-3]
|
315
|
+
stack.delete_at(-4)
|
316
|
+
when OP_2ROT
|
317
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 6
|
318
|
+
2.times { stack << stack[-6] }
|
319
|
+
2.times { stack.delete_at(-7) }
|
320
|
+
when OP_SWAP
|
321
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
322
|
+
tmp = stack.last
|
323
|
+
stack[-1] = stack[-2]
|
324
|
+
stack[-2] = tmp
|
325
|
+
when OP_2SWAP
|
326
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 4
|
327
|
+
2.times {stack << stack[-4]}
|
328
|
+
2.times {stack.delete_at(-5)}
|
329
|
+
when OP_TUCK
|
330
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
331
|
+
stack.insert(-3, stack.last)
|
332
|
+
when OP_ABS
|
333
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
334
|
+
v = pop_int
|
335
|
+
push_int(v.abs)
|
336
|
+
when OP_BOOLAND
|
337
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
338
|
+
a, b = pop_int(2)
|
339
|
+
push_int((!a.zero? && !b.zero?) ? 1 : 0)
|
340
|
+
when OP_BOOLOR
|
341
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
342
|
+
a, b = pop_int(2)
|
343
|
+
push_int((!a.zero? || !b.zero?) ? 1 : 0)
|
344
|
+
when OP_NUMEQUAL, OP_NUMEQUALVERIFY
|
345
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
346
|
+
a, b = pop_int(2)
|
347
|
+
result = a == b
|
348
|
+
push_int(result ? 1 : 0)
|
349
|
+
if opcode == OP_NUMEQUALVERIFY
|
350
|
+
if result
|
351
|
+
stack.pop
|
352
|
+
else
|
353
|
+
return set_error(ScriptError::SCRIPT_ERR_NUMEQUALVERIFY)
|
354
|
+
end
|
355
|
+
end
|
356
|
+
when OP_LESSTHAN, OP_LESSTHANOREQUAL
|
357
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
358
|
+
a, b = pop_int(2)
|
359
|
+
push_int(a < b ? 1 : 0) if opcode == OP_LESSTHAN
|
360
|
+
push_int(a <= b ? 1 : 0) if opcode == OP_LESSTHANOREQUAL
|
361
|
+
when OP_GREATERTHAN, OP_GREATERTHANOREQUAL
|
362
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
363
|
+
a, b = pop_int(2)
|
364
|
+
push_int(a > b ? 1 : 0) if opcode == OP_GREATERTHAN
|
365
|
+
push_int(a >= b ? 1 : 0) if opcode == OP_GREATERTHANOREQUAL
|
366
|
+
when OP_MIN
|
367
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
368
|
+
push_int(pop_int(2).min)
|
369
|
+
when OP_MAX
|
370
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
371
|
+
push_int(pop_int(2).max)
|
372
|
+
when OP_WITHIN
|
373
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
|
374
|
+
x, a, b = pop_int(3)
|
375
|
+
push_int((a <= x && x < b) ? 1 : 0)
|
376
|
+
when OP_NOT
|
377
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
378
|
+
push_int(pop_int == 0 ? 1 : 0)
|
379
|
+
when OP_SIZE
|
380
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
381
|
+
item = stack.last
|
382
|
+
item = Bitcoin::Script.encode_number(item) if item.is_a?(Numeric)
|
383
|
+
size = item.htb.bytesize
|
384
|
+
push_int(size)
|
385
|
+
when OP_NEGATE
|
386
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
387
|
+
push_int(-pop_int)
|
388
|
+
when OP_NUMNOTEQUAL
|
389
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
390
|
+
a, b = pop_int(2)
|
391
|
+
push_int(a == b ? 0 : 1)
|
392
|
+
when OP_CODESEPARATOR
|
393
|
+
last_code_separator_index = index + 1
|
394
|
+
when OP_CHECKSIG, OP_CHECKSIGVERIFY
|
395
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
396
|
+
sig, pubkey = pop_string(2)
|
397
|
+
|
398
|
+
subscript = script.subscript(last_code_separator_index..-1)
|
399
|
+
if sig_version == SIG_VERSION[:base]
|
400
|
+
subscript = subscript.find_and_delete(Script.new << sig)
|
401
|
+
end
|
402
|
+
|
403
|
+
return false if !check_pubkey_encoding(pubkey, sig_version) || !check_signature_encoding(sig) # error already set.
|
404
|
+
|
405
|
+
success = checker.check_sig(sig, pubkey, subscript, sig_version)
|
406
|
+
|
407
|
+
# https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki#NULLFAIL
|
408
|
+
if !success && flag?(SCRIPT_VERIFY_NULLFAIL) && sig.bytesize > 0
|
409
|
+
return set_error(ScriptError::SCRIPT_ERR_SIG_NULLFAIL)
|
410
|
+
end
|
411
|
+
|
412
|
+
push_int(success ? 1 : 0)
|
413
|
+
|
414
|
+
if opcode == OP_CHECKSIGVERIFY
|
415
|
+
if success
|
416
|
+
stack.pop
|
417
|
+
else
|
418
|
+
return set_error(SCRIPT_ERR_CHECKSIGVERIFY)
|
419
|
+
end
|
420
|
+
end
|
421
|
+
when OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY
|
422
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
423
|
+
pubkey_count = pop_int
|
424
|
+
unless (0..Script::MAX_PUBKEYS_PER_MULTISIG).include?(pubkey_count)
|
425
|
+
return set_error(ScriptError::SCRIPT_ERR_PUBKEY_COUNT)
|
426
|
+
end
|
427
|
+
|
428
|
+
op_count += pubkey_count
|
429
|
+
return set_error(ScriptError::SCRIPT_ERR_OP_COUNT) if op_count > Script::MAX_OPS_PER_SCRIPT
|
430
|
+
|
431
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < pubkey_count
|
432
|
+
|
433
|
+
pubkeys = pop_string(pubkey_count)
|
434
|
+
pubkeys = [pubkeys] if pubkeys.is_a?(String)
|
435
|
+
|
436
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
437
|
+
|
438
|
+
sig_count = pop_int
|
439
|
+
return set_error(ScriptError::SCRIPT_ERR_SIG_COUNT) if sig_count < 0 || sig_count > pubkey_count
|
440
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < (sig_count)
|
441
|
+
|
442
|
+
sigs = pop_string(sig_count)
|
443
|
+
sigs = [sigs] if sigs.is_a?(String)
|
444
|
+
|
445
|
+
subscript = script.subscript(last_code_separator_index..-1)
|
446
|
+
|
447
|
+
if sig_version == SIG_VERSION[:base]
|
448
|
+
sigs.each do |sig|
|
449
|
+
subscript = subscript.find_and_delete(Script.new << sig)
|
450
|
+
end
|
451
|
+
end
|
452
|
+
|
453
|
+
success = true
|
454
|
+
while success && sig_count > 0
|
455
|
+
sig = sigs.pop
|
456
|
+
pubkey = pubkeys.pop
|
457
|
+
return false if !check_pubkey_encoding(pubkey, sig_version) || !check_signature_encoding(sig) # error already set.
|
458
|
+
ok = checker.check_sig(sig, pubkey, subscript, sig_version)
|
459
|
+
if ok
|
460
|
+
sig_count -= 1
|
461
|
+
else
|
462
|
+
sigs << sig
|
463
|
+
end
|
464
|
+
pubkey_count -= 1
|
465
|
+
success = false if sig_count > pubkey_count
|
466
|
+
end
|
467
|
+
|
468
|
+
if !success && flag?(SCRIPT_VERIFY_NULLFAIL)
|
469
|
+
sigs.each do |sig|
|
470
|
+
# If the operation failed, we require that all signatures must be empty vector
|
471
|
+
return set_error(ScriptError::SCRIPT_ERR_SIG_NULLFAIL) if sig.bytesize > 0
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
# A bug causes CHECKMULTISIG to consume one extra argument whose contents were not checked in any way.
|
476
|
+
# Unfortunately this is a potential source of mutability,
|
477
|
+
# so optionally verify it is exactly equal to zero prior to removing it from the stack.
|
478
|
+
return set_error(ScriptError::SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
479
|
+
if flag?(SCRIPT_VERIFY_NULLDUMMY) && stack[-1].size > 0
|
480
|
+
return set_error(ScriptError::SCRIPT_ERR_SIG_NULLDUMMY)
|
481
|
+
end
|
482
|
+
stack.pop
|
483
|
+
|
484
|
+
push_int(success ? 1 : 0)
|
485
|
+
if opcode == OP_CHECKMULTISIGVERIFY
|
486
|
+
if success
|
487
|
+
stack.pop
|
488
|
+
else
|
489
|
+
return set_error(ScriptError::SCRIPT_ERR_CHECKMULTISIGVERIFY)
|
490
|
+
end
|
491
|
+
end
|
492
|
+
when OP_RETURN
|
493
|
+
return set_error(ScriptError::SCRIPT_ERR_OP_RETURN)
|
494
|
+
else
|
495
|
+
return set_error(ScriptError::SCRIPT_ERR_BAD_OPCODE)
|
496
|
+
end
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
# max stack size check
|
501
|
+
return set_error(ScriptError::SCRIPT_ERR_STACK_SIZE) if stack.size + alt_stack.size > Script::MAX_STACK_SIZE
|
502
|
+
end
|
503
|
+
rescue Exception => e
|
504
|
+
puts e
|
505
|
+
puts e.backtrace
|
506
|
+
return set_error(ScriptError::SCRIPT_ERR_UNKNOWN_ERROR, e.message)
|
507
|
+
end
|
508
|
+
|
509
|
+
return set_error(ScriptError::SCRIPT_ERR_UNBALANCED_CONDITIONAL) unless flow_stack.empty?
|
510
|
+
|
511
|
+
set_error(ScriptError::SCRIPT_ERR_OK)
|
512
|
+
true
|
513
|
+
end
|
514
|
+
|
515
|
+
private
|
516
|
+
|
517
|
+
def flag?(flag)
|
518
|
+
(all_flags & flag) != 0
|
519
|
+
end
|
520
|
+
|
521
|
+
def all_flags
|
522
|
+
result = SCRIPT_VERIFY_NONE
|
523
|
+
flags.each{ |f| result |= f }
|
524
|
+
result
|
525
|
+
end
|
526
|
+
|
527
|
+
# pop the item with the int value for the number specified by +count+ from the stack.
|
528
|
+
def pop_int(count = 1)
|
529
|
+
i = stack.pop(count).map do |s|
|
530
|
+
data = s.htb
|
531
|
+
raise '"script number overflow"' if data.bytesize > Script::DEFAULT_MAX_NUM_SIZE
|
532
|
+
if require_minimal && data.bytesize > 0
|
533
|
+
if data.bytes[-1] & 0x7f == 0 && (data.bytesize <= 1 || data.bytes[data.bytesize - 2] & 0x80 ==0)
|
534
|
+
raise 'non-minimally encoded script number'
|
535
|
+
end
|
536
|
+
end
|
537
|
+
Script.decode_number(s)
|
538
|
+
end
|
539
|
+
count == 1 ? i.first : i
|
540
|
+
end
|
541
|
+
|
542
|
+
# push +i+ into stack as encoded by Script#encode_number
|
543
|
+
def push_int(i)
|
544
|
+
stack << Script.encode_number(i)
|
545
|
+
end
|
546
|
+
|
547
|
+
# pop the item with the string(hex) value for the number specified by +count+ from the stack.
|
548
|
+
def pop_string(count = 1)
|
549
|
+
s = stack.pop(count).map do |s|
|
550
|
+
case s
|
551
|
+
when Numeric
|
552
|
+
Script.encode_number(s)
|
553
|
+
else
|
554
|
+
s
|
555
|
+
end
|
556
|
+
end
|
557
|
+
count == 1 ? s.first : s
|
558
|
+
end
|
559
|
+
|
560
|
+
# pop the item with the boolean value from the stack.
|
561
|
+
def pop_bool
|
562
|
+
cast_to_bool(pop_string.htb)
|
563
|
+
end
|
564
|
+
|
565
|
+
# see https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L36-L49
|
566
|
+
def cast_to_bool(v)
|
567
|
+
case v
|
568
|
+
when Numeric
|
569
|
+
return v != 0
|
570
|
+
when String
|
571
|
+
v.each_byte.with_index do |b, i|
|
572
|
+
return !(i == (v.bytesize - 1) && b == 0x80) unless b == 0
|
573
|
+
end
|
574
|
+
false
|
575
|
+
else
|
576
|
+
false
|
577
|
+
end
|
578
|
+
end
|
579
|
+
|
580
|
+
def check_signature_encoding(sig)
|
581
|
+
return true if sig.size.zero?
|
582
|
+
if (flag?(SCRIPT_VERIFY_DERSIG) || flag?(SCRIPT_VERIFY_LOW_S) || flag?(SCRIPT_VERIFY_STRICTENC)) && !valid_signature_encoding?(sig)
|
583
|
+
return set_error(ScriptError::SCRIPT_ERR_SIG_DER)
|
584
|
+
elsif flag?(SCRIPT_VERIFY_LOW_S) && !low_der_signature?(sig)
|
585
|
+
return false
|
586
|
+
elsif flag?(SCRIPT_VERIFY_STRICTENC) && !defined_hashtype_signature?(sig)
|
587
|
+
return set_error(ScriptError::SCRIPT_ERR_SIG_HASHTYPE)
|
588
|
+
end
|
589
|
+
true
|
590
|
+
end
|
591
|
+
|
592
|
+
# check +sig+ (hex) is correct der encoding.
|
593
|
+
# This function is consensus-critical since BIP66.
|
594
|
+
def valid_signature_encoding?(signature)
|
595
|
+
sig = signature.htb
|
596
|
+
return false if sig.bytesize < 9 || sig.bytesize > 73 # Minimum and maximum size check
|
597
|
+
|
598
|
+
s = sig.unpack('C*')
|
599
|
+
|
600
|
+
return false if s[0] != 0x30 || s[1] != s.size - 3 # A signature is of type 0x30 (compound). Make sure the length covers the entire signature.
|
601
|
+
|
602
|
+
len_r = s[3]
|
603
|
+
return false if 5 + len_r >= s.size # Make sure the length of the S element is still inside the signature.
|
604
|
+
|
605
|
+
len_s = s[5 + len_r]
|
606
|
+
return false unless len_r + len_s + 7 == s.size #Verify that the length of the signature matches the sum of the length of the elements.
|
607
|
+
|
608
|
+
return false unless s[2] == 0x02 # Check whether the R element is an integer.
|
609
|
+
|
610
|
+
return false if len_r == 0 # Zero-length integers are not allowed for R.
|
611
|
+
|
612
|
+
return false unless s[4] & 0x80 == 0 # Negative numbers are not allowed for R.
|
613
|
+
|
614
|
+
# Null bytes at the start of R are not allowed, unless R would otherwise be interpreted as a negative number.
|
615
|
+
return false if len_r > 1 && (s[4] == 0x00) && (s[5] & 0x80 == 0)
|
616
|
+
|
617
|
+
return false unless s[len_r + 4] == 0x02 # Check whether the S element is an integer.
|
618
|
+
|
619
|
+
return false if len_s == 0 # Zero-length integers are not allowed for S.
|
620
|
+
return false unless (s[len_r + 6] & 0x80) == 0 # Negative numbers are not allowed for S.
|
621
|
+
|
622
|
+
# Null bytes at the start of S are not allowed, unless S would otherwise be interpreted as a negative number.
|
623
|
+
return false if len_s > 1 && (s[len_r + 6] == 0x00) && (s[len_r + 7] & 0x80 == 0)
|
624
|
+
|
625
|
+
true
|
626
|
+
end
|
627
|
+
|
628
|
+
def low_der_signature?(sig)
|
629
|
+
return set_error(ScriptError::SCRIPT_ERR_SIG_DER) unless valid_signature_encoding?(sig)
|
630
|
+
return set_error(ScriptError::SCRIPT_ERR_SIG_HIGH_S) unless Key.low_signature?(sig)
|
631
|
+
true
|
632
|
+
end
|
633
|
+
|
634
|
+
def defined_hashtype_signature?(signature)
|
635
|
+
sig = signature.htb
|
636
|
+
return false if sig.empty?
|
637
|
+
s = sig.unpack('C*')
|
638
|
+
hash_type = s[-1] & (~(Script::SIGHASH_TYPE[:anyonecanpay]))
|
639
|
+
return false if hash_type < Script::SIGHASH_TYPE[:all] || hash_type > Script::SIGHASH_TYPE[:single]
|
640
|
+
true
|
641
|
+
end
|
642
|
+
|
643
|
+
def check_pubkey_encoding(pubkey, sig_version)
|
644
|
+
if flag?(SCRIPT_VERIFY_STRICTENC) && !Key.compress_or_uncompress_pubkey?(pubkey)
|
645
|
+
return set_error(ScriptError::SCRIPT_ERR_PUBKEYTYPE)
|
646
|
+
end
|
647
|
+
# Only compressed keys are accepted in segwit
|
648
|
+
if flag?(SCRIPT_VERIFY_WITNESS_PUBKEYTYPE) &&
|
649
|
+
sig_version == SIG_VERSION[:witness_v0] && !Key.compress_pubkey?(pubkey)
|
650
|
+
return set_error(ScriptError::SCRIPT_ERR_WITNESS_PUBKEYTYPE)
|
651
|
+
end
|
652
|
+
true
|
653
|
+
end
|
654
|
+
|
655
|
+
def minimal_push?(data, opcode)
|
656
|
+
if data.bytesize.zero?
|
657
|
+
return opcode == OP_0
|
658
|
+
elsif data.bytesize == 1 && data.bytes[0] >= 1 && data.bytes[0] <= 16
|
659
|
+
return opcode == OP_1 + (data.bytes[0] - 1)
|
660
|
+
elsif data.bytesize == 1 && data.bytes[0] == 0x81
|
661
|
+
return opcode == OP_1NEGATE
|
662
|
+
elsif data.bytesize <= 75
|
663
|
+
return opcode == data.bytesize
|
664
|
+
elsif data.bytesize <= 255
|
665
|
+
return opcode == OP_PUSHDATA1
|
666
|
+
elsif data.bytesize <= 65535
|
667
|
+
return opcode == OP_PUSHDATA2
|
668
|
+
end
|
669
|
+
true
|
670
|
+
end
|
671
|
+
|
672
|
+
def verify_pushdata_length(chunk)
|
673
|
+
buf = StringIO.new(chunk)
|
674
|
+
opcode = buf.read(1).ord
|
675
|
+
offset = 1
|
676
|
+
len = case opcode
|
677
|
+
when OP_PUSHDATA1
|
678
|
+
offset += 1
|
679
|
+
buf.read(1).unpack('C').first
|
680
|
+
when OP_PUSHDATA2
|
681
|
+
offset += 2
|
682
|
+
buf.read(2).unpack('v').first
|
683
|
+
when OP_PUSHDATA4
|
684
|
+
offset += 4
|
685
|
+
buf.read(4).unpack('V').first
|
686
|
+
else
|
687
|
+
opcode
|
688
|
+
end
|
689
|
+
chunk.bytesize == len + offset
|
690
|
+
end
|
691
|
+
|
692
|
+
end
|
693
|
+
|
694
|
+
end
|