private void migrateVariables() {
    final var blockchainUpdater = updater();
    final var variablesUpdater = variablesStorage.updater();

    get(VARIABLES_PREFIX, CHAIN_HEAD_HASH.getBytes())
        .map(this::bytesToHash)
        .ifPresent(
            bch ->
                variablesStorage
                    .getChainHead()
                    .ifPresentOrElse(
                        vch -> {
                          if (!vch.equals(bch)) {
                            logInconsistencyAndFail(CHAIN_HEAD_HASH, bch, vch);
                          }
                        },
                        () -> {
                          variablesUpdater.setChainHead(bch);
                          LOG.info("Migrated key {} to variables storage", CHAIN_HEAD_HASH);
                        }));

    get(VARIABLES_PREFIX, FINALIZED_BLOCK_HASH.getBytes())
        .map(this::bytesToHash)
        .ifPresent(
            bfh -> {
              variablesStorage
                  .getFinalized()
                  .ifPresentOrElse(
                      vfh -> {
                        if (!vfh.equals(bfh)) {
                          logInconsistencyAndFail(FINALIZED_BLOCK_HASH, bfh, vfh);
                        }
                      },
                      () -> {
                        variablesUpdater.setFinalized(bfh);
                        LOG.info("Migrated key {} to variables storage", FINALIZED_BLOCK_HASH);
                      });
            });

    get(VARIABLES_PREFIX, SAFE_BLOCK_HASH.getBytes())
        .map(this::bytesToHash)
        .ifPresent(
            bsh -> {
              variablesStorage
                  .getSafeBlock()
                  .ifPresentOrElse(
                      vsh -> {
                        if (!vsh.equals(bsh)) {
                          logInconsistencyAndFail(SAFE_BLOCK_HASH, bsh, vsh);
                        }
                      },
                      () -> {
                        variablesUpdater.setSafeBlock(bsh);
                        LOG.info("Migrated key {} to variables storage", SAFE_BLOCK_HASH);
                      });
            });

    get(VARIABLES_PREFIX, FORK_HEADS.getBytes())
        .map(bytes -> RLP.input(bytes).readList(in -> this.bytesToHash(in.readBytes32())))
        .ifPresent(
            bfh -> {
              final var vfh = variablesStorage.getForkHeads();
              if (vfh.isEmpty()) {
                variablesUpdater.setForkHeads(bfh);
                LOG.info("Migrated key {} to variables storage", FORK_HEADS);
              } else if (!List.copyOf(vfh).equals(bfh)) {
                logInconsistencyAndFail(FORK_HEADS, bfh, vfh);
              }
            });

    get(Bytes.EMPTY, SEQ_NO_STORE.getBytes())
        .ifPresent(
            bsns -> {
              variablesStorage
                  .getLocalEnrSeqno()
                  .ifPresentOrElse(
                      vsns -> {
                        if (!vsns.equals(bsns)) {
                          logInconsistencyAndFail(SEQ_NO_STORE, bsns, vsns);
                        }
                      },
                      () -> {
                        variablesUpdater.setLocalEnrSeqno(bsns);
                        LOG.info("Migrated key {} to variables storage", SEQ_NO_STORE);
                      });
            });

    blockchainUpdater.removeVariables();

    variablesUpdater.commit();
    blockchainUpdater.commit();
  }
One time migration of variables from the blockchain storage to the dedicated variable storage.
To avoid state inconsistency in case of a downgrade done without running the storage
revert-variables subcommand it fails giving the possibility to retry the downgrade procedure.
ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStoragePrefixedKeyBlockchainStorage.java