private static FlatTrace.Context handleCall(
      final TransactionTrace transactionTrace,
      final TraceFrame traceFrame,
      final Optional<TraceFrame> nextTraceFrame,
      final List<FlatTrace.Builder> flatTraces,
      final long cumulativeGasCost,
      final Deque<FlatTrace.Context> tracesContexts,
      final String opcodeString) {
    final Bytes[] stack = traceFrame.getStack().orElseThrow();
    final FlatTrace.Context lastContext = tracesContexts.peekLast();

    final String callingAddress = calculateCallingAddress(lastContext);

    if (traceFrame.getDepth() >= nextTraceFrame.map(TraceFrame::getDepth).orElse(0)) {
      // don't log calls to calls that don't execute, such as insufficient value and precompiles
      return tracesContexts.peekLast();
    }

    final FlatTrace.Builder subTraceBuilder =
        FlatTrace.builder()
            .traceAddress(calculateTraceAddress(tracesContexts))
            .resultBuilder(Result.builder());
    final Action.Builder subTraceActionBuilder =
        Action.builder()
            .from(callingAddress)
            .input(
                nextTraceFrame.map(TraceFrame::getInputData).map(Bytes::toHexString).orElse(null))
            .gas(
                "0x" + Long.toHexString(nextTraceFrame.map(TraceFrame::getGasRemaining).orElse(0L)))
            .callType(opcodeString.toLowerCase(Locale.US))
            .value(Quantity.create(traceFrame.getValue()));

    if (stack.length > 1) {
      subTraceActionBuilder.to(toAddress(stack[stack.length - 2]).toString());
    }

    nextTraceFrame.ifPresent(
        nextFrame -> {
          if (hasRevertInSubCall(transactionTrace, nextFrame)) {
            subTraceBuilder.error(Optional.of("Reverted"));
          }
        });

    final FlatTrace.Context currentContext =
        new FlatTrace.Context(subTraceBuilder.actionBuilder(subTraceActionBuilder));
    currentContext.decGasUsed(cumulativeGasCost);

    tracesContexts.addLast(currentContext);
    flatTraces.add(currentContext.getBuilder());
    return currentContext;
  }
Generates a stream of {@link Trace} from the passed {@link TransactionTrace} and {@link Block}
data with additional Transaction Information added to FlatTrace

@param protocolSchedule the current {@link ProtocolSchedule} to use
@param transactionTrace the {@link TransactionTrace} to use
@param block the {@link Block} to use
@return a stream of generated traces {@link Trace}
ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/tracing/flat/FlatTraceGenerator.java