String validateCode(
      final Bytes code, final CodeSection thisCodeSection, final EOFLayout eofLayout) {
    final int size = code.size();
    final BitSet rjumpdests = new BitSet(size);
    final BitSet immediates = new BitSet(size);
    final byte[] rawCode = code.toArrayUnsafe();
    OpcodeInfo opcodeInfo = V1_OPCODES[0xfe];
    int pos = 0;
    EOFContainerMode eofContainerMode = eofLayout.containerMode().get();
    boolean hasReturningOpcode = false;
    while (pos < size) {
      final int operationNum = rawCode[pos] & 0xff;
      opcodeInfo = V1_OPCODES[operationNum];
      if (!opcodeInfo.valid()) {
        // undefined instruction
        return format("undefined_instruction 0x%02x", operationNum);
      }
      pos += 1;
      int pcPostInstruction = pos;
      switch (operationNum) {
        case StopOperation.OPCODE, ReturnOperation.OPCODE:
          if (eofContainerMode == null) {
            eofContainerMode = RUNTIME;
            eofLayout.containerMode().set(RUNTIME);
          } else if (!eofContainerMode.equals(RUNTIME)) {
            return format(
                "incompatible_container_kind opcode %s is only valid for runtime.",
                opcodeInfo.name());
          }
          break;
        case PushOperation.PUSH_BASE,
        PushOperation.PUSH_BASE + 1,
        PushOperation.PUSH_BASE + 2,
        PushOperation.PUSH_BASE + 3,
        PushOperation.PUSH_BASE + 4,
        PushOperation.PUSH_BASE + 5,
        PushOperation.PUSH_BASE + 6,
        PushOperation.PUSH_BASE + 7,
        PushOperation.PUSH_BASE + 8,
        PushOperation.PUSH_BASE + 9,
        PushOperation.PUSH_BASE + 10,
        PushOperation.PUSH_BASE + 11,
        PushOperation.PUSH_BASE + 12,
        PushOperation.PUSH_BASE + 13,
        PushOperation.PUSH_BASE + 14,
        PushOperation.PUSH_BASE + 15,
        PushOperation.PUSH_BASE + 16,
        PushOperation.PUSH_BASE + 17,
        PushOperation.PUSH_BASE + 18,
        PushOperation.PUSH_BASE + 19,
        PushOperation.PUSH_BASE + 20,
        PushOperation.PUSH_BASE + 21,
        PushOperation.PUSH_BASE + 22,
        PushOperation.PUSH_BASE + 23,
        PushOperation.PUSH_BASE + 24,
        PushOperation.PUSH_BASE + 25,
        PushOperation.PUSH_BASE + 26,
        PushOperation.PUSH_BASE + 27,
        PushOperation.PUSH_BASE + 28,
        PushOperation.PUSH_BASE + 29,
        PushOperation.PUSH_BASE + 30,
        PushOperation.PUSH_BASE + 31,
        PushOperation.PUSH_BASE + 32:
          final int multiByteDataLen = operationNum - PushOperation.PUSH_BASE;
          pcPostInstruction += multiByteDataLen;
          break;
        case DataLoadNOperation.OPCODE:
          if (pos + 2 > size) {
            return "truncated_instruction DATALOADN";
          }
          pcPostInstruction += 2;
          final int dataLoadOffset = readBigEndianU16(pos, rawCode);
          // only verfy the last byte of the load is within the minimum data
          if (dataLoadOffset > eofLayout.dataLength() - 32) {
            return "invalid_dataloadn_index %d + 32 > %d"
                .formatted(dataLoadOffset, eofLayout.dataLength());
          }
          break;
        case RelativeJumpOperation.OPCODE, RelativeJumpIfOperation.OPCODE:
          if (pos + 2 > size) {
            return "truncated_instruction RJUMP";
          }
          pcPostInstruction += 2;
          final int offset = readBigEndianI16(pos, rawCode);
          final int rjumpdest = pcPostInstruction + offset;
          if (rjumpdest < 0 || rjumpdest >= size) {
            return "invalid_rjump_destination out of bounds";
          }
          rjumpdests.set(rjumpdest);
          break;
        case RelativeJumpVectorOperation.OPCODE:
          pcPostInstruction += 1;
          if (pcPostInstruction > size) {
            return "truncated_instruction RJUMPV";
          }
          int jumpBasis = pcPostInstruction;
          final int jumpTableSize = RelativeJumpVectorOperation.getVectorSize(code, pos);
          pcPostInstruction += 2 * jumpTableSize;
          if (pcPostInstruction > size) {
            return "truncated_instruction RJUMPV";
          }
          for (int offsetPos = jumpBasis; offsetPos < pcPostInstruction; offsetPos += 2) {
            final int rjumpvOffset = readBigEndianI16(offsetPos, rawCode);
            final int rjumpvDest = pcPostInstruction + rjumpvOffset;
            if (rjumpvDest < 0 || rjumpvDest >= size) {
              return "invalid_rjump_destination out of bounds";
            }
            rjumpdests.set(rjumpvDest);
          }
          break;
        case CallFOperation.OPCODE:
          if (pos + 2 > size) {
            return "truncated_instruction CALLF";
          }
          int section = readBigEndianU16(pos, rawCode);
          if (section >= eofLayout.getCodeSectionCount()) {
            return "invalid_code_section_index CALLF to " + Integer.toHexString(section);
          }
          if (!eofLayout.getCodeSection(section).returning) {
            return "CALLF to non-returning section - " + Integer.toHexString(section);
          }
          pcPostInstruction += 2;
          break;
        case RetFOperation.OPCODE:
          hasReturningOpcode = true;
          break;
        case JumpFOperation.OPCODE:
          if (pos + 2 > size) {
            return "truncated_instruction JUMPF";
          }
          int targetSection = readBigEndianU16(pos, rawCode);
          if (targetSection >= eofLayout.getCodeSectionCount()) {
            return "invalid_code_section_index JUMPF - " + Integer.toHexString(targetSection);
          }
          CodeSection targetCodeSection = eofLayout.getCodeSection(targetSection);
          if (targetCodeSection.isReturning() && !thisCodeSection.isReturning()) {
            return "invalid_non_returning_flag non-returning JUMPF source must have non-returning target";
          } else if (thisCodeSection.getOutputs() < targetCodeSection.getOutputs()) {
            return format(
                "jumpf_destination_incompatible_outputs target %2x with more outputs %d than current section's outputs %d",
                targetSection, targetCodeSection.getOutputs(), thisCodeSection.getOutputs());
          }
          hasReturningOpcode |= eofLayout.getCodeSection(targetSection).isReturning();
          pcPostInstruction += 2;
          break;
        case EOFCreateOperation.OPCODE:
          if (pos + 1 > size) {
            return format(
                "truncated_instruction dangling immediate for %s at pc=%d",
                opcodeInfo.name(), pos - opcodeInfo.pcAdvance());
          }
          int subcontainerNum = rawCode[pos] & 0xff;
          if (subcontainerNum >= eofLayout.getSubcontainerCount()) {
            return format(
                "invalid_container_section_index %s refers to non-existent subcontainer %d at pc=%d",
                opcodeInfo.name(), subcontainerNum, pos - opcodeInfo.pcAdvance());
          }
          EOFLayout subContainer = eofLayout.getSubcontainer(subcontainerNum);
          var subcontainerMode = subContainer.containerMode().get();
          if (subcontainerMode == null) {
            subContainer.containerMode().set(INITCODE);
          } else if (subcontainerMode == RUNTIME) {
            return format(
                "incompatible_container_kind subcontainer %d should be initcode", subcontainerNum);
          }
          if (subContainer.dataLength() != subContainer.data().size()) {
            return format(
                "A subcontainer used for %s has a truncated data section, expected %d and is %d.",
                V1_OPCODES[operationNum].name(),
                subContainer.dataLength(),
                subContainer.data().size());
          }
          pcPostInstruction += 1;
          break;
        case ReturnContractOperation.OPCODE:
          if (eofContainerMode == null) {
            eofContainerMode = INITCODE;
            eofLayout.containerMode().set(INITCODE);
          } else if (!eofContainerMode.equals(INITCODE)) {
            return format(
                "incompatible_container_kind opcode %s is only valid for initcode",
                opcodeInfo.name());
          }
          if (pos + 1 > size) {
            return format(
                "truncated_instruction dangling immediate for %s at pc=%d",
                opcodeInfo.name(), pos - opcodeInfo.pcAdvance());
          }
          int returnedContractNum = rawCode[pos] & 0xff;
          if (returnedContractNum >= eofLayout.getSubcontainerCount()) {
            return format(
                "invalid_container_section_index %s refers to non-existent subcontainer %d at pc=%d",
                opcodeInfo.name(), returnedContractNum, pos - opcodeInfo.pcAdvance());
          }
          EOFLayout returnedContract = eofLayout.getSubcontainer(returnedContractNum);
          var returnedContractMode = returnedContract.containerMode().get();
          if (returnedContractMode == null) {
            returnedContract.containerMode().set(RUNTIME);
          } else if (returnedContractMode.equals(INITCODE)) {
            return format(
                "incompatible_container_kind subcontainer %d should be runtime",
                returnedContractNum);
          }
          pcPostInstruction += 1;
          break;
        default:
          // a few opcodes have potentially dangling immediates
          if (opcodeInfo.pcAdvance() > 1) {
            pcPostInstruction += opcodeInfo.pcAdvance() - 1;
            if (pcPostInstruction > size) {
              return format(
                  "truncated_instruction dangling immediate for %s at pc=%d",
                  opcodeInfo.name(), pos - opcodeInfo.pcAdvance());
            }
          }
          break;
      }
      immediates.set(pos, pcPostInstruction);
      pos = pcPostInstruction;
    }
    if (thisCodeSection.isReturning() != hasReturningOpcode) {
      return thisCodeSection.isReturning()
          ? "unreachable_code_sections no RETF or qualifying JUMPF"
          : "invalid_non_returning_flag RETF or JUMPF into returning section";
    }
    if (!opcodeInfo.terminal()) {
      return "missing_stop_opcode No terminating instruction";
    }
    if (rjumpdests.intersects(immediates)) {
      return "invalid_rjump_destination targets immediate data";
    }
    return null;
  }
validates the code section

@param code the code section code
@return null if valid, otherwise a string containing an error reason.
evm/src/main/java/org/hyperledger/besu/evm/code/CodeV1Validation.java