Class: Tapyrus::ScriptDebugger

Inherits:
Object
  • Object
show all
Defined in:
lib/tapyrus/script/debugger.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(script_pubkey:, script_sig:, tx: nil, index: nil) ⇒ ScriptDebugger

Returns a new instance of ScriptDebugger.

Parameters:

Raises:

  • (ArgumentError)


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/tapyrus/script/debugger.rb', line 20

def initialize(script_pubkey:, script_sig:, tx: nil, index: nil)
  @script_pubkey = script_pubkey
  @script_sig = script_sig
  if tx
    raise ArgumentError, "index should be specified" if index.nil?
    @tx_checker = Tapyrus::TxChecker.new(tx: tx, input_index: index)
    if (tx_checker.tx.in.size - 1) < tx_checker.input_index
      raise ArgumentError, "Tx does not have #{tx_checker.input_index}-th input."
    end
  else
    @tx_checker = EmptyTxChecker.new
  end
  @interpreter = Tapyrus::ScriptInterpreter.new(checker: tx_checker)
  @interpreter.reset_params
  @chunk_index = 0
  @target_script = script_sig
  @chunks = target_script.chunks.each
  @chunk_size = target_script.chunks.length
  @stack_copy = nil
end

Instance Attribute Details

#chunk_indexObject

Returns the value of attribute chunk_index.



10
11
12
# File 'lib/tapyrus/script/debugger.rb', line 10

def chunk_index
  @chunk_index
end

#chunk_sizeObject

Returns the value of attribute chunk_size.



11
12
13
# File 'lib/tapyrus/script/debugger.rb', line 11

def chunk_size
  @chunk_size
end

#chunksObject

Returns the value of attribute chunks.



12
13
14
# File 'lib/tapyrus/script/debugger.rb', line 12

def chunks
  @chunks
end

#interpreterObject (readonly)

Returns the value of attribute interpreter.



6
7
8
# File 'lib/tapyrus/script/debugger.rb', line 6

def interpreter
  @interpreter
end

#is_redeemObject

Returns the value of attribute is_redeem.



9
10
11
# File 'lib/tapyrus/script/debugger.rb', line 9

def is_redeem
  @is_redeem
end

#script_pubkeyObject (readonly)

Returns the value of attribute script_pubkey.



3
4
5
# File 'lib/tapyrus/script/debugger.rb', line 3

def script_pubkey
  @script_pubkey
end

#script_sigObject (readonly)

Returns the value of attribute script_sig.



4
5
6
# File 'lib/tapyrus/script/debugger.rb', line 4

def script_sig
  @script_sig
end

#stack_copyObject

Returns the value of attribute stack_copy.



13
14
15
# File 'lib/tapyrus/script/debugger.rb', line 13

def stack_copy
  @stack_copy
end

#target_scriptObject

Returns the value of attribute target_script.



8
9
10
# File 'lib/tapyrus/script/debugger.rb', line 8

def target_script
  @target_script
end

#tx_checkerObject (readonly)

Returns the value of attribute tx_checker.



5
6
7
# File 'lib/tapyrus/script/debugger.rb', line 5

def tx_checker
  @tx_checker
end

Instance Method Details

#stepObject



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
72
73
74
75
76
77
# File 'lib/tapyrus/script/debugger.rb', line 41

def step
  if chunk_size == chunk_index
    if target_script == script_sig
      @stack_copy = interpreter.stack.dup
      @target_script = script_pubkey
      @interpreter.reset_params
      @chunks = target_script.chunks.each
      @chunk_index = 0
      @chunk_size = target_script.chunks.length
    elsif target_script == script_pubkey
      if interpreter.stack.empty? || !interpreter.cast_to_bool(interpreter.stack.last.htb)
        return(
          StepResult.error(
            current_stack: interpreter.stack.dup,
            error: "Script evaluated without error but finished with a false/empty top stack element"
          )
        )
      end
      if script_pubkey.p2sh?
        interpreter.stack = stack_copy
        redeem_script = Tapyrus::Script.parse_from_payload(interpreter.stack.pop.htb)
        @target_script = redeem_script
        @chunks = target_script.chunks.each
        @chunk_index = 0
        @chunk_size = target_script.chunks.length
      else
        return StepResult.finished(current_stack: interpreter.stack.dup)
      end
    else
      return StepResult.finished(current_stack: interpreter.stack.dup)
    end
  end
  result = step_process(interpreter, target_script, chunks.next, chunk_index, is_redeem)
  return result if result.is_a?(StepResult)
  @chunk_index += 1
  StepResult.success(current_stack: interpreter.stack.dup, message: result)
end