bitcoinrb 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|