ScriptOp.fromReader constructor

ScriptOp.fromReader(
  1. BytesReader reader, {
  2. bool requireMinimal = false,
})

Reads a single operation from a BytesReader. OutOfData will be thrown if there is not enough data to read. If requireMinimal is true, a pushdata operation must be encoded minimally or else PushDataNotMinimal will be thrown.

Implementation

factory ScriptOp.fromReader(
  BytesReader reader, { bool requireMinimal = false, }
) {

  final code = reader.readUInt8();

  int readN = -1;

  // Push n=code bytes
  if (code > 0 && code < pushData1) readN = code;
  if (code == pushData1) readN = reader.readUInt8();
  if (code == pushData2) readN = reader.readUInt16();
  if (code == pushData4) readN = reader.readUInt32();

  // If not push data, then opcode
  if (readN == -1) return ScriptOpCode(code);

  if (requireMinimal) {
    // Push data opcode should be minimal for length
    if (code == pushData1 && readN < pushData1) throw PushDataNotMinimal();
    if (code == pushData2 && readN <= 0xff) throw PushDataNotMinimal();
    if (code == pushData4 && readN <= 0xffff) throw PushDataNotMinimal();
  }

  // If pushdata is empty, return 0 opcode. If it is one byte between 0-16,
  // return numerical opcode. If it is 0x81, then OP_1NEGATE.

  final bytes = reader.readSlice(readN);

  if (bytes.isEmpty) return ScriptOpCode(0);

  if (bytes.length == 1) {
    final n = bytes[0];
    if (requireMinimal && (n == 0x81 || n == 0x80 || n <= 16)) {
      throw PushDataNotMinimal();
    }
    if (n == 0 || n == 0x80) return ScriptOpCode(0);
    if (n <= 16) return ScriptOpCode(n + op1 - 1);
    if (n == 0x81) return ScriptOpCode(op1Negate);
  }

  return ScriptPushData(bytes);

}