Class: BSV::Script::Chunk

Inherits:
Object
  • Object
show all
Defined in:
lib/bsv/script/chunk.rb

Overview

A single element of a parsed script — either an opcode or a data push.

Scripts are composed of a sequence of chunks. Each chunk is either a bare opcode (e.g. OP_DUP) or a data push (opcode + data payload).

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opcode:, data: nil) ⇒ Chunk

Returns a new instance of Chunk.

Parameters:

  • opcode (Integer)

    the opcode byte value

  • data (String, nil) (defaults to: nil)

    data payload for push operations



18
19
20
21
# File 'lib/bsv/script/chunk.rb', line 18

def initialize(opcode:, data: nil)
  @opcode = opcode
  @data = data&.b
end

Instance Attribute Details

#dataString? (readonly)

Returns the pushed data bytes, or nil for bare opcodes.

Returns:

  • (String, nil)

    the pushed data bytes, or nil for bare opcodes



14
15
16
# File 'lib/bsv/script/chunk.rb', line 14

def data
  @data
end

#opcodeInteger (readonly)

Returns the opcode byte.

Returns:

  • (Integer)

    the opcode byte



11
12
13
# File 'lib/bsv/script/chunk.rb', line 11

def opcode
  @opcode
end

Instance Method Details

#==(other) ⇒ Boolean

Returns true if both chunks have equal opcode and data.

Parameters:

  • other (Object)

    the object to compare

Returns:

  • (Boolean)

    true if both chunks have equal opcode and data



87
88
89
# File 'lib/bsv/script/chunk.rb', line 87

def ==(other)
  other.is_a?(Chunk) && @opcode == other.opcode && @data == other.data
end

#data?Boolean

Whether this chunk carries a data payload.

Returns:

  • (Boolean)

    true if this is a data push chunk



26
27
28
# File 'lib/bsv/script/chunk.rb', line 26

def data?
  !@data.nil?
end

#to_asmString

Render this chunk as human-readable ASM.

Data pushes are shown as hex strings; opcodes are shown by name. Opcodes with no defined name are rendered as OP_UNKNOWN<n> (e.g. OP_UNKNOWN186) so that the output is unambiguous and round-trippable via from_asm.

The OP_RETURN opcode is special: it carries the raw tail bytes as its data payload (absorbed during parsing). To preserve round-trip fidelity with from_asm, the tail is re-parsed into individual push items and each is rendered as a hex token after OP_RETURN.

Returns:

  • (String)

    ASM representation



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/bsv/script/chunk.rb', line 66

def to_asm
  if @opcode == Opcodes::OP_RETURN && @data
    return 'OP_RETURN' if @data.empty?

    # Re-parse the tail bytes into individual chunks (without OP_RETURN
    # termination) so each push renders as a separate hex token.
    tail_script = BSV::Script::Script.new(@data)
    tail_chunks = tail_script.send(:parse_chunks, terminate_on_op_return: false)
    parts = ['OP_RETURN'] + tail_chunks.map do |ch|
      ch.data? ? ch.data.unpack1('H*') : (Opcodes.name_for(ch.opcode) || "OP_UNKNOWN#{ch.opcode}")
    end
    parts.join(' ')
  elsif @data
    @data.unpack1('H*')
  else
    Opcodes.name_for(@opcode) || "OP_UNKNOWN#{@opcode}"
  end
end

#to_binaryString

Serialise this chunk back to raw script bytes.

Preserves the original push encoding (including non-minimal pushes) so that round-tripping through parse/serialise does not alter the script bytes. This is critical for sighash computation.

Returns:

  • (String)

    binary script bytes for this chunk



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/bsv/script/chunk.rb', line 37

def to_binary
  return [@opcode].pack('C') unless @data

  case @opcode
  when Opcodes::OP_PUSHDATA1
    [Opcodes::OP_PUSHDATA1, @data.bytesize].pack('CC') + @data
  when Opcodes::OP_PUSHDATA2
    [Opcodes::OP_PUSHDATA2].pack('C') + [@data.bytesize].pack('v') + @data
  when Opcodes::OP_PUSHDATA4
    [Opcodes::OP_PUSHDATA4].pack('C') + [@data.bytesize].pack('V') + @data
  else
    # Direct push: opcode IS the length (0x01..0x4b)
    [@opcode].pack('C') + @data
  end
end