Class: BTC::P2SHExtension

Inherits:
Object
  • Object
show all
Includes:
ScriptInterpreterExtension
Defined in:
lib/btcruby/script/p2sh_extension.rb

Overview

Performs Pay-to-Script-Hash (BIP16) evaluation

Constant Summary

Constants included from Opcodes

Opcodes::OPCODE_NAME_TO_VALUE, Opcodes::OPCODE_VALUE_TO_NAME, Opcodes::OP_0, Opcodes::OP_0NOTEQUAL, Opcodes::OP_1, Opcodes::OP_10, Opcodes::OP_11, Opcodes::OP_12, Opcodes::OP_13, Opcodes::OP_14, Opcodes::OP_15, Opcodes::OP_16, Opcodes::OP_1ADD, Opcodes::OP_1NEGATE, Opcodes::OP_1SUB, Opcodes::OP_2, Opcodes::OP_2DIV, Opcodes::OP_2DROP, Opcodes::OP_2DUP, Opcodes::OP_2MUL, Opcodes::OP_2OVER, Opcodes::OP_2ROT, Opcodes::OP_2SWAP, Opcodes::OP_3, Opcodes::OP_3DUP, Opcodes::OP_4, Opcodes::OP_5, Opcodes::OP_6, Opcodes::OP_7, Opcodes::OP_8, Opcodes::OP_9, Opcodes::OP_ABS, Opcodes::OP_ADD, Opcodes::OP_AND, Opcodes::OP_BOOLAND, Opcodes::OP_BOOLOR, Opcodes::OP_CAT, Opcodes::OP_CHECKLOCKTIMEVERIFY, Opcodes::OP_CHECKMULTISIG, Opcodes::OP_CHECKMULTISIGVERIFY, Opcodes::OP_CHECKSIG, Opcodes::OP_CHECKSIGVERIFY, Opcodes::OP_CODESEPARATOR, Opcodes::OP_DEPTH, Opcodes::OP_DIV, Opcodes::OP_DROP, Opcodes::OP_DUP, Opcodes::OP_ELSE, Opcodes::OP_ENDIF, Opcodes::OP_EQUAL, Opcodes::OP_EQUALVERIFY, Opcodes::OP_FALSE, Opcodes::OP_FROMALTSTACK, Opcodes::OP_GREATERTHAN, Opcodes::OP_GREATERTHANOREQUAL, Opcodes::OP_HASH160, Opcodes::OP_HASH256, Opcodes::OP_IF, Opcodes::OP_IFDUP, Opcodes::OP_INVALIDOPCODE, Opcodes::OP_INVERT, Opcodes::OP_LEFT, Opcodes::OP_LESSTHAN, Opcodes::OP_LESSTHANOREQUAL, Opcodes::OP_LSHIFT, Opcodes::OP_MAX, Opcodes::OP_MIN, Opcodes::OP_MOD, Opcodes::OP_MUL, Opcodes::OP_NEGATE, Opcodes::OP_NIP, Opcodes::OP_NOP, Opcodes::OP_NOP1, Opcodes::OP_NOP10, Opcodes::OP_NOP2, Opcodes::OP_NOP3, Opcodes::OP_NOP4, Opcodes::OP_NOP5, Opcodes::OP_NOP6, Opcodes::OP_NOP7, Opcodes::OP_NOP8, Opcodes::OP_NOP9, Opcodes::OP_NOT, Opcodes::OP_NOTIF, Opcodes::OP_NUMEQUAL, Opcodes::OP_NUMEQUALVERIFY, Opcodes::OP_NUMNOTEQUAL, Opcodes::OP_OR, Opcodes::OP_OVER, Opcodes::OP_PICK, Opcodes::OP_PUSHDATA1, Opcodes::OP_PUSHDATA2, Opcodes::OP_PUSHDATA4, Opcodes::OP_RESERVED, Opcodes::OP_RESERVED1, Opcodes::OP_RESERVED2, Opcodes::OP_RETURN, Opcodes::OP_RIGHT, Opcodes::OP_RIPEMD160, Opcodes::OP_ROLL, Opcodes::OP_ROT, Opcodes::OP_RSHIFT, Opcodes::OP_SHA1, Opcodes::OP_SHA256, Opcodes::OP_SIZE, Opcodes::OP_SUB, Opcodes::OP_SUBSTR, Opcodes::OP_SWAP, Opcodes::OP_TOALTSTACK, Opcodes::OP_TRUE, Opcodes::OP_TUCK, Opcodes::OP_VER, Opcodes::OP_VERIF, Opcodes::OP_VERIFY, Opcodes::OP_VERNOTIF, Opcodes::OP_WITHIN, Opcodes::OP_XOR

Constants included from ScriptErrors

ScriptErrors::SCRIPT_ERR_BAD_OPCODE, ScriptErrors::SCRIPT_ERR_CHECKMULTISIGVERIFY, ScriptErrors::SCRIPT_ERR_CHECKSIGVERIFY, ScriptErrors::SCRIPT_ERR_CLEANSTACK, ScriptErrors::SCRIPT_ERR_DISABLED_OPCODE, ScriptErrors::SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, ScriptErrors::SCRIPT_ERR_EQUALVERIFY, ScriptErrors::SCRIPT_ERR_EVAL_FALSE, ScriptErrors::SCRIPT_ERR_INVALID_ALTSTACK_OPERATION, ScriptErrors::SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrors::SCRIPT_ERR_MINIMALDATA, ScriptErrors::SCRIPT_ERR_NEGATIVE_LOCKTIME, ScriptErrors::SCRIPT_ERR_NUMEQUALVERIFY, ScriptErrors::SCRIPT_ERR_OK, ScriptErrors::SCRIPT_ERR_OP_COUNT, ScriptErrors::SCRIPT_ERR_OP_RETURN, ScriptErrors::SCRIPT_ERR_PUBKEYTYPE, ScriptErrors::SCRIPT_ERR_PUBKEY_COUNT, ScriptErrors::SCRIPT_ERR_PUSH_SIZE, ScriptErrors::SCRIPT_ERR_SCRIPT_SIZE, ScriptErrors::SCRIPT_ERR_SIG_COUNT, ScriptErrors::SCRIPT_ERR_SIG_DER, ScriptErrors::SCRIPT_ERR_SIG_HASHTYPE, ScriptErrors::SCRIPT_ERR_SIG_HIGH_S, ScriptErrors::SCRIPT_ERR_SIG_NULLDUMMY, ScriptErrors::SCRIPT_ERR_SIG_PUSHONLY, ScriptErrors::SCRIPT_ERR_STACK_SIZE, ScriptErrors::SCRIPT_ERR_UNBALANCED_CONDITIONAL, ScriptErrors::SCRIPT_ERR_UNKNOWN_ERROR, ScriptErrors::SCRIPT_ERR_UNSATISFIED_LOCKTIME, ScriptErrors::SCRIPT_ERR_VERIFY

Constants included from ScriptFlags

ScriptFlags::SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, ScriptFlags::SCRIPT_VERIFY_CLEANSTACK, ScriptFlags::SCRIPT_VERIFY_DERSIG, ScriptFlags::SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS, ScriptFlags::SCRIPT_VERIFY_LOW_S, ScriptFlags::SCRIPT_VERIFY_MINIMALDATA, ScriptFlags::SCRIPT_VERIFY_NONE, ScriptFlags::SCRIPT_VERIFY_NULLDUMMY, ScriptFlags::SCRIPT_VERIFY_P2SH, ScriptFlags::SCRIPT_VERIFY_SIGPUSHONLY, ScriptFlags::SCRIPT_VERIFY_STRICTENC

Instance Method Summary collapse

Methods included from ScriptInterpreterExtension

#handle_opcode, #handle_output_script, #handle_scripts, #should_handle_opcode, #should_handle_output_script, #should_handle_scripts

Instance Method Details

#did_execute_output_script(interpreter: nil, output_script: nil) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/btcruby/script/p2sh_extension.rb', line 20

def did_execute_output_script(interpreter: nil, output_script: nil)
  # Cleanup ivars
  stack_copy = @stack_copy
  @stack_copy = nil

  signature_script = @signature_script
  @signature_script = nil

  # NOTE: check for empty stack or "false" item happens
  # in ScriptInterpreter before this callback is invoked.

  # If output script is not P2SH, do nothing.
  return true if !output_script.p2sh?

  # Additional validation for pay-to-script-hash (P2SH) transactions:

  # scriptSig must be literals-only or validation fails
  if !signature_script.data_only?
    return interpreter.set_error(SCRIPT_ERR_SIG_PUSHONLY)
  end

  # Restore stack.
  interpreter.stack = stack_copy

  # stack cannot be empty here, because if it was the
  # P2SH  HASH <> EQUAL  scriptPubKey would be evaluated with
  # an empty stack and the EvalScript above would return false.
  raise "Stack cannot be empty" if stack_copy.empty?

  serialized_redeem_script = interpreter.stack.pop
  begin
    redeem_script = BTC::Script.new(data: serialized_redeem_script)
  rescue => e
    return interpreter.set_error(SCRIPT_ERR_BAD_OPCODE, "Failed to parse serialized redeem script for P2SH. #{e.message}")
  end

  # Actually execute the script.
  if !interpreter.run_script(redeem_script)
    # error is set in run_script
    return false
  end

  if interpreter.stack.empty?
    return interpreter.set_error(SCRIPT_ERR_EVAL_FALSE)
  end

  if interpreter.cast_to_bool(interpreter.stack.last) == false
    return interpreter.set_error(SCRIPT_ERR_EVAL_FALSE)
  end

  return true
end

#did_execute_signature_script(interpreter: nil, signature_script: nil) ⇒ Object

Every extension gets this callback. If extension return false, execution is stopped and interpreter returns false. Default value is true.



14
15
16
17
18
# File 'lib/btcruby/script/p2sh_extension.rb', line 14

def did_execute_signature_script(interpreter: nil, signature_script: nil)
  @signature_script = signature_script
  @stack_copy = interpreter.stack.dup
  true
end

#extra_flagsObject

Returns additional flags to be available to #flag? checks during script execution. This way one extension can affect evaluation of another.



8
9
10
# File 'lib/btcruby/script/p2sh_extension.rb', line 8

def extra_flags
  SCRIPT_VERIFY_P2SH
end