LIMB
Вход Регистрация

тема

Делаем локальный TRON тестнет

3p49jv1a · · 1 ответов · 427 просмотров

TRON - это почти EVM сеть. Иногда это "почти" заставляет целые классы инструментов характерных для EVM-сетей внезапно ломаться, не поддерживать или отсутствовать, когда дело касается именно сети TRON.
Тот же простой реплей транзакции с дебаг-трейсом я в свое время не нашел как получить. Такого метода нет ни в HTTP, ни в JSON_RPC апи движка java-tron. Единственный способ - это иметь локальный доступ к ноде, так как трейсы сохраняются только на диск с включенным флагом в конфиге:
Code:
vm = {
  vmTrace = true
}
Это не значит, что метода для получения дебаг-трейса через публичные ноды TRON нет в принципе, очевидно его реализовать можно. Скорее всего это я плохо искал. В любом случае, тут я показываю как поднять свою ноду локально. Это надежно, приватно и убережет от потенциальных технических проблем. Начнем.

Сперва про готовые решения. На докерхабе существуют уже обертки tronbox/tre и старый trontools/quickstart. Советую про них сразу забыть, они время не сэкономят. 
Я покажу как сделать свою обертку в несколько шагов. По ходу создания решим еще 2 важные проблемы с которыми вы столкнетесь:

Проблема 1: Нетворк параметры
Это своего рода фича-тоглы, нужны чтобы все ноды сети могли обновиться мгновенно. Без их включения голая java-tron даже дебаг-трейса не даст.

Хорошая новость - часть их можно включить через конфиг:
Code:
committee = {
  allowCreationOfContracts = 1
  allowUpdateAccountName = 1
  allowSameTokenName = 1
  ...
}

Плохая новость - некоторые важные параметры с конфига не считываются. Например, getMaxCpuTimeOfOneTx очень важный параметр от которого зависит выполнится ли твоя транзакция или уйдет в OUT_OF_TIME, что частый случай при включенном vmTrace = true, который замедляет.
Вот как подобные параметры включать:


1. Качаем java-tron
Code:
git clone https://github.com/tronprotocol/java-tron
2. Меняем /java-tron/framework/src/main/java/org/tron/core/consensus/ProposalService.java на:

Спойлер: ProposalService.java
Code:
package org.tron.core.consensus;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.tron.core.capsule.ProposalCapsule;
import org.tron.core.config.Parameter.ForkBlockVersionEnum;
import org.tron.core.db.HistoryBlockHashUtil;
import org.tron.core.db.Manager;
import org.tron.core.store.DynamicPropertiesStore;
import org.tron.core.utils.ProposalUtil;
import org.tron.protos.Protocol.Transaction.Contract.ContractType;
/**
 * Notice:
 * <p>
 * if you want to add a proposal,you just should add a enum ProposalType and add the valid in the
 * validator method, add the process in the process method
 */
@Slf4j
@Component
public class ProposalService extends ProposalUtil implements ApplicationContextAware {
  private static ApplicationContext context;
  private Manager manager;
  private ProposalCapsule proposalCapsule;
  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    context = applicationContext;
  }
  private static Manager getManagerFromContext() {
    return context.getBean(Manager.class);
  }
  public static boolean process(Manager manager, ProposalCapsule proposalCapsule) {
    Map<Long, Long> parameters = proposalCapsule.getInstance().getParametersMap();
    boolean success = true;
    ProposalService service = new ProposalService();
    service.manager = manager;
    service.proposalCapsule = proposalCapsule;
    for (Map.Entry<Long, Long> entry : parameters.entrySet()) {
      ProposalType proposalType = ProposalType.getEnumOrNull(entry.getKey());
      if (proposalType == null) {
        success = false;
        continue;
      }
      service.apply(proposalType, entry.getValue());
    }
    return success;
  }
  /**
   * Public static entry point for external callers (e.g. HTTP API, debugger) that want to apply
   * a single dynamic parameter directly, outside of the normal on-chain proposal flow. There is
   * no ProposalCapsule in this context, so any case that logs a price/fee history entry keyed by
   * proposal expiration time will skip that history write and only persist the value itself.
   */
  public static void apply(ProposalType proposalType, Long value) {
    ProposalService service = new ProposalService();
    service.manager = getManagerFromContext();
    service.proposalCapsule = null;
    service.applyInternal(proposalType, value);
  }
  private void applyInternal(ProposalType proposalType, Long value) {
    DynamicPropertiesStore dynamicStore = manager.getDynamicPropertiesStore();
    switch (proposalType) {
      case MAINTENANCE_TIME_INTERVAL: {
        dynamicStore.saveMaintenanceTimeInterval(value);
        break;
      }
      case ACCOUNT_UPGRADE_COST: {
        dynamicStore.saveAccountUpgradeCost(value);
        break;
      }
      case CREATE_ACCOUNT_FEE: {
        dynamicStore.saveCreateAccountFee(value);
        break;
      }
      case TRANSACTION_FEE: {
        dynamicStore.saveTransactionFee(value);
        // update bandwidth price history
        if (proposalCapsule != null) {
          dynamicStore.saveBandwidthPriceHistory(
              dynamicStore.getBandwidthPriceHistory()
                  + "," + proposalCapsule.getExpirationTime() + ":" + value);
        }
        break;
      }
      case ASSET_ISSUE_FEE: {
        dynamicStore.saveAssetIssueFee(value);
        break;
      }
      case WITNESS_PAY_PER_BLOCK: {
        dynamicStore.saveWitnessPayPerBlock(value);
        break;
      }
      case WITNESS_STANDBY_ALLOWANCE: {
        dynamicStore.saveWitnessStandbyAllowance(value);
        break;
      }
      case CREATE_NEW_ACCOUNT_FEE_IN_SYSTEM_CONTRACT: {
        dynamicStore
            .saveCreateNewAccountFeeInSystemContract(value);
        break;
      }
      case CREATE_NEW_ACCOUNT_BANDWIDTH_RATE: {
        dynamicStore.saveCreateNewAccountBandwidthRate(value);
        break;
      }
      case ALLOW_CREATION_OF_CONTRACTS: {
        dynamicStore.saveAllowCreationOfContracts(value);
        break;
      }
      case REMOVE_THE_POWER_OF_THE_GR: {
        if (dynamicStore.getRemoveThePowerOfTheGr() == 0) {
          dynamicStore.saveRemoveThePowerOfTheGr(value);
        }
        break;
      }
      case ENERGY_FEE: {
        dynamicStore.saveEnergyFee(value);
        // update energy price history
        if (proposalCapsule != null) {
          dynamicStore.saveEnergyPriceHistory(
              dynamicStore.getEnergyPriceHistory()
                  + "," + proposalCapsule.getExpirationTime() + ":" + value);
        }
        break;
      }
      case EXCHANGE_CREATE_FEE: {
        dynamicStore.saveExchangeCreateFee(value);
        break;
      }
      case MAX_CPU_TIME_OF_ONE_TX: {
        dynamicStore.saveMaxCpuTimeOfOneTx(value);
        break;
      }
      case ALLOW_UPDATE_ACCOUNT_NAME: {
        dynamicStore.saveAllowUpdateAccountName(value);
        break;
      }
      case ALLOW_SAME_TOKEN_NAME: {
        dynamicStore.saveAllowSameTokenName(value);
        break;
      }
      case ALLOW_DELEGATE_RESOURCE: {
        dynamicStore.saveAllowDelegateResource(value);
        break;
      }
      case TOTAL_ENERGY_LIMIT: {
        dynamicStore.saveTotalEnergyLimit(value);
        break;
      }
      case ALLOW_TVM_TRANSFER_TRC10: {
        dynamicStore.saveAllowTvmTransferTrc10(value);
        break;
      }
      case TOTAL_CURRENT_ENERGY_LIMIT: {
        dynamicStore.saveTotalEnergyLimit2(value);
        break;
      }
      case ALLOW_MULTI_SIGN: {
        if (dynamicStore.getAllowMultiSign() == 0) {
          dynamicStore.saveAllowMultiSign(value);
        }
        break;
      }
      case ALLOW_ADAPTIVE_ENERGY: {
        if (dynamicStore.getAllowAdaptiveEnergy() == 0) {
          dynamicStore.saveAllowAdaptiveEnergy(value);
          if (manager.getChainBaseManager()
              .getForkController().pass(ForkBlockVersionEnum.VERSION_3_6_5)) {
            //24 * 60 * 2 . one minute,1/2 total limit.
            dynamicStore.saveAdaptiveResourceLimitTargetRatio(2880);
            dynamicStore.saveTotalEnergyTargetLimit(
                dynamicStore.getTotalEnergyLimit() / 2880);
            dynamicStore.saveAdaptiveResourceLimitMultiplier(50);
          }
        }
        break;
      }
      case UPDATE_ACCOUNT_PERMISSION_FEE: {
        dynamicStore.saveUpdateAccountPermissionFee(value);
        break;
      }
      case MULTI_SIGN_FEE: {
        dynamicStore.saveMultiSignFee(value);
        break;
      }
      case ALLOW_PROTO_FILTER_NUM: {
        dynamicStore.saveAllowProtoFilterNum(value);
        break;
      }
      case ALLOW_ACCOUNT_STATE_ROOT: {
        dynamicStore.saveAllowAccountStateRoot(value);
        break;
      }
      case ALLOW_TVM_CONSTANTINOPLE: {
        dynamicStore.saveAllowTvmConstantinople(value);
        dynamicStore.addSystemContractAndSetPermission(48);
        break;
      }
      case ALLOW_TVM_SOLIDITY_059: {
        dynamicStore.saveAllowTvmSolidity059(value);
        break;
      }
      case ADAPTIVE_RESOURCE_LIMIT_TARGET_RATIO: {
        long ratio = 24 * 60 * value;
        dynamicStore.saveAdaptiveResourceLimitTargetRatio(ratio);
        dynamicStore.saveTotalEnergyTargetLimit(
            dynamicStore.getTotalEnergyLimit() / ratio);
        break;
      }
      case ADAPTIVE_RESOURCE_LIMIT_MULTIPLIER: {
        dynamicStore.saveAdaptiveResourceLimitMultiplier(value);
        break;
      }
      case ALLOW_CHANGE_DELEGATION: {
        dynamicStore.saveChangeDelegation(value);
        dynamicStore.addSystemContractAndSetPermission(49);
        break;
      }
      case WITNESS_127_PAY_PER_BLOCK: {
        dynamicStore.saveWitness127PayPerBlock(value);
        break;
      }
      case FORBID_TRANSFER_TO_CONTRACT: {
        dynamicStore.saveForbidTransferToContract(value);
        break;
      }
      case ALLOW_PBFT: {
        dynamicStore.saveAllowPBFT(value);
        break;
      }
      case ALLOW_TVM_ISTANBUL: {
        dynamicStore.saveAllowTvmIstanbul(value);
        break;
      }
      case ALLOW_SHIELDED_TRC20_TRANSACTION: {
        dynamicStore.saveAllowShieldedTRC20Transaction(value);
        break;
      }
      case ALLOW_MARKET_TRANSACTION: {
        if (dynamicStore.getAllowMarketTransaction() == 0) {
          dynamicStore.saveAllowMarketTransaction(value);
          dynamicStore.addSystemContractAndSetPermission(52);
          dynamicStore.addSystemContractAndSetPermission(53);
        }
        break;
      }
      case MARKET_SELL_FEE: {
        dynamicStore.saveMarketSellFee(value);
        break;
      }
      case MARKET_CANCEL_FEE: {
        dynamicStore.saveMarketCancelFee(value);
        break;
      }
      case MAX_FEE_LIMIT: {
        dynamicStore.saveMaxFeeLimit(value);
        break;
      }
      case ALLOW_TRANSACTION_FEE_POOL: {
        dynamicStore.saveAllowTransactionFeePool(value);
        break;
      }
      case ALLOW_BLACKHOLE_OPTIMIZATION: {
        dynamicStore.saveAllowBlackHoleOptimization(value);
        break;
      }
      case ALLOW_NEW_RESOURCE_MODEL: {
        dynamicStore.saveAllowNewResourceModel(value);
        break;
      }
      case ALLOW_TVM_FREEZE: {
        dynamicStore.saveAllowTvmFreeze(value);
        break;
      }
      case ALLOW_TVM_VOTE: {
        dynamicStore.saveNewRewardAlgorithmEffectiveCycle();
        dynamicStore.saveAllowTvmVote(value);
        break;
      }
      case ALLOW_TVM_LONDON: {
        dynamicStore.saveAllowTvmLondon(value);
        break;
      }
      case ALLOW_TVM_COMPATIBLE_EVM: {
        dynamicStore.saveAllowTvmCompatibleEvm(value);
        break;
      }
      case FREE_NET_LIMIT: {
        dynamicStore.saveFreeNetLimit(value);
        break;
      }
      case TOTAL_NET_LIMIT: {
        dynamicStore.saveTotalNetLimit(value);
        break;
      }
      case ALLOW_ACCOUNT_ASSET_OPTIMIZATION: {
        dynamicStore.setAllowAccountAssetOptimization(value);
        break;
      }
      case ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX: {
        dynamicStore.saveAllowHigherLimitForMaxCpuTimeOfOneTx(
            value);
        break;
      }
      case ALLOW_ASSET_OPTIMIZATION: {
        dynamicStore.setAllowAssetOptimization(value);
        break;
      }
      case ALLOW_NEW_REWARD: {
        dynamicStore.saveNewRewardAlgorithmEffectiveCycle();
        dynamicStore.saveAllowNewReward(value);
        break;
      }
      case MEMO_FEE: {
        dynamicStore.saveMemoFee(value);
        // update memo fee history
        if (proposalCapsule != null) {
          dynamicStore.saveMemoFeeHistory(
              dynamicStore.getMemoFeeHistory()
                  + "," + proposalCapsule.getExpirationTime() + ":" + value);
        }
        break;
      }
      case UNFREEZE_DELAY_DAYS: {
        dynamicStore.saveUnfreezeDelayDays(value);
        dynamicStore.addSystemContractAndSetPermission(
            ContractType.FreezeBalanceV2Contract_VALUE);
        dynamicStore.addSystemContractAndSetPermission(
            ContractType.UnfreezeBalanceV2Contract_VALUE);
        dynamicStore.addSystemContractAndSetPermission(
            ContractType.WithdrawExpireUnfreezeContract_VALUE);
        dynamicStore.addSystemContractAndSetPermission(
            ContractType.DelegateResourceContract_VALUE);
        dynamicStore.addSystemContractAndSetPermission(
            ContractType.UnDelegateResourceContract_VALUE);
        break;
      }
      case ALLOW_DELEGATE_OPTIMIZATION: {
        dynamicStore.saveAllowDelegateOptimization(value);
        break;
      }
      case ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID: {
        dynamicStore
            .saveAllowOptimizedReturnValueOfChainId(value);
        break;
      }
      case ALLOW_DYNAMIC_ENERGY: {
        dynamicStore.saveAllowDynamicEnergy(value);
        break;
      }
      case DYNAMIC_ENERGY_THRESHOLD: {
        dynamicStore.saveDynamicEnergyThreshold(value);
        break;
      }
      case DYNAMIC_ENERGY_INCREASE_FACTOR: {
        dynamicStore.saveDynamicEnergyIncreaseFactor(value);
        break;
      }
      case DYNAMIC_ENERGY_MAX_FACTOR: {
        dynamicStore.saveDynamicEnergyMaxFactor(value);
        break;
      }
      case ALLOW_TVM_SHANGHAI: {
        dynamicStore.saveAllowTvmShangHai(value);
        break;
      }
      case ALLOW_CANCEL_ALL_UNFREEZE_V2: {
        if (dynamicStore.getAllowCancelAllUnfreezeV2() == 0) {
          dynamicStore.saveAllowCancelAllUnfreezeV2(value);
          dynamicStore.addSystemContractAndSetPermission(
              ContractType.CancelAllUnfreezeV2Contract_VALUE);
        }
        break;
      }
      case MAX_DELEGATE_LOCK_PERIOD: {
        dynamicStore.saveMaxDelegateLockPeriod(value);
        break;
      }
      case ALLOW_OLD_REWARD_OPT: {
        dynamicStore.saveAllowOldRewardOpt(value);
        break;
      }
      case ALLOW_ENERGY_ADJUSTMENT: {
        dynamicStore.saveAllowEnergyAdjustment(value);
        break;
      }
      case MAX_CREATE_ACCOUNT_TX_SIZE: {
        dynamicStore.saveMaxCreateAccountTxSize(value);
        break;
      }
      case ALLOW_STRICT_MATH: {
        dynamicStore.saveAllowStrictMath(value);
        break;
      }
      case CONSENSUS_LOGIC_OPTIMIZATION: {
        dynamicStore
            .saveConsensusLogicOptimization(value);
        break;
      }
      case ALLOW_TVM_CANCUN: {
        dynamicStore.saveAllowTvmCancun(value);
        break;
      }
      case ALLOW_TVM_BLOB: {
        dynamicStore.saveAllowTvmBlob(value);
        break;
      }
      case ALLOW_TVM_SELFDESTRUCT_RESTRICTION: {
        dynamicStore.saveAllowTvmSelfdestructRestriction(value);
        break;
      }
      case PROPOSAL_EXPIRE_TIME: {
        dynamicStore.saveProposalExpireTime(value);
        break;
      }
      case ALLOW_TVM_OSAKA: {
        dynamicStore.saveAllowTvmOsaka(value);
        break;
      }
      case ALLOW_TVM_PRAGUE: {
        dynamicStore.saveAllowTvmPrague(value);
        HistoryBlockHashUtil.deploy(manager);
        break;
      }
      case ALLOW_HARDEN_RESOURCE_CALCULATION: {
        dynamicStore
            .saveAllowHardenResourceCalculation(value);
        break;
      }
      case ALLOW_HARDEN_EXCHANGE_CALCULATION: {
        dynamicStore
            .saveAllowHardenExchangeCalculation(value);
        break;
      }
      default:
        break;
    }
  }
}
3. Создаем /java-tron/framework/src/main/java/org/tron/core/services/http/UpdateProposalParameterServlet.java

Спойлер: UpdateProposalParameterServlet.java
Code:
package org.tron.core.services.http;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.tron.core.consensus.ProposalService;
import org.tron.core.utils.ProposalUtil.ProposalType;
import org.tron.json.JSONObject;
@Slf4j(topic = "API")
@Component
public class UpdateProposalParameterServlet extends RateLimiterServlet {
  protected void doGet(HttpServletRequest request, HttpServletResponse response) {
    doPost(request, response);
  }
  protected void doPost(HttpServletRequest request, HttpServletResponse response) {
    try {
      String body = request.getReader().lines().reduce("", (a, b) -> a + b);
      JSONObject json = JSONObject.parseObject(body);
      String key = json.getString("key");
      long value = json.getLongValue("value");
      ProposalType proposalType;
      try {
        proposalType = ProposalType.valueOf(key);
      } catch (IllegalArgumentException e) {
        response.getWriter().println("{\"result\":false,\"error\":\"unknown key: " + key + "\"}");
        return;
      }
      ProposalService.apply(proposalType, value);
      response.getWriter().println("{\"result\":true}");
    } catch (Exception e) {
      logger.error("UpdateProposalParameterServlet error", e);
      try {
        response.getWriter().println("{\"result\":false,\"error\":\"" + e.getMessage() + "\"}");
      } catch (IOException ex) {
        logger.error("IOException", ex);
      }
    }
  }
}
3. Регистрируем в /java-tron/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java
Code:
@Autowired
private UpdateProposalParameterServlet updateProposalParameterServlet;
...
context.addServlet(new ServletHolder(updateProposalParameterServlet), 
  "/wallet/updateproposalparameter");
4. Собираем
Спойлер: Dockefile
Code:
FROM tronprotocol/centos7:0.2
ENV TMP_DIR="/tron-build"
ENV JDK_TAR="jdk-8u202-linux-x64.tar.gz"
ENV JDK_DIR="jdk1.8.0_202"
ENV JDK_MD5="0029351f7a946f6c05b582100c7d45b7"
ENV BASE_DIR="/java-tron"
# исходники копируются из локального контекста сборки
COPY . $TMP_DIR/java-tron
RUN set -o errexit -o nounset \
    && yum -y install git wget \
    && wget -P /usr/local https://github.com/frekele/oracle-java/releases/download/8u202-b08/$JDK_TAR \
    && echo "$JDK_MD5 /usr/local/$JDK_TAR" | md5sum -c \
    && tar -zxf /usr/local/$JDK_TAR -C /usr/local \
    && rm /usr/local/$JDK_TAR \
    && export JAVA_HOME=/usr/local/$JDK_DIR \
    && export CLASSPATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar \
    && export PATH=$PATH:$JAVA_HOME/bin \
    && cd $TMP_DIR/java-tron \
    && chmod +x gradlew \
    && ./gradlew build -x test \
    && cd build/distributions \
    && 7za x -y java-tron-1.0.0.zip  \
    && mv java-tron-1.0.0 $BASE_DIR \
    && rm -rf $TMP_DIR \
    && rm -rf ~/.gradle \
    && mv $JAVA_HOME/jre /usr/local \
    && rm -rf $JAVA_HOME \
    && yum clean all
RUN wget -P $BASE_DIR/config https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/main_net_config.conf
ENV JAVA_HOME="/usr/local/jre"
ENV PATH=$PATH:$JAVA_HOME/bin
WORKDIR $BASE_DIR
ENTRYPOINT ["./bin/FullNode"]
5. Запускаем

Спойлер: docker-compose.yml
Code:
services:
  tron-witness1:
    # image: tronprotocol/java-tron:latest
    image: mine/java-tron
    container_name: tron-witness1
    networks:
      - tron_private_network
    deploy:
      resources:
        limits:
          memory: 12g
    ports:
      - "8545:8545"
      - "8090:8090" # for external http API request
      - "50051:50051" # for external rpc API request
    volumes:
      - ./conf/:/java-tron/conf/
      # - ./datadir:/java-tron/data # mount a local directory to make the blocks data persistent.
      # - ./logs/tron-witness1:/java-tron/logs # map to host logs
    command: >
      -jvm "{-Xmx12g -Xmn2g -XX:+UseConcMarkSweepGC}" -c /java-tron/conf/private_net_config_witness1.conf -d /java-tron/data -w

networks:
  tron_private_network:
    driver: bridge
6. Проверяем 
Code:
curl -X POST http://localhost:8090/wallet/updateproposalparameter \
  -d '{"key": "ALLOW_CANCEL_ALL_UNFREEZE_V2", "value": 1}'
Code:
curl -X POST http://localhost:8090/wallet/getchainparameters
Спойлер: mainet_chainparameters.json
Code:
{
  "chainParameter": [
    {
      "key": "getMaintenanceTimeInterval",
      "value": 21600000
    },
    {
      "key": "getAccountUpgradeCost",
      "value": 9999000000
    },
    {
      "key": "getCreateAccountFee",
      "value": 100000
    },
    {
      "key": "getTransactionFee",
      "value": 1000
    },
    {
      "key": "getAssetIssueFee",
      "value": 1024000000
    },
    {
      "key": "getWitnessPayPerBlock",
      "value": 8000000
    },
    {
      "key": "getWitnessStandbyAllowance",
      "value": 115200000000
    },
    {
      "key": "getCreateNewAccountFeeInSystemContract",
      "value": 1000000
    },
    {
      "key": "getCreateNewAccountBandwidthRate",
      "value": 1
    },
    {
      "key": "getAllowCreationOfContracts",
      "value": 1
    },
    {
      "key": "getRemoveThePowerOfTheGr",
      "value": -1
    },
    {
      "key": "getEnergyFee",
      "value": 100
    },
    {
      "key": "getExchangeCreateFee",
      "value": 1024000000
    },
    {
      "key": "getMaxCpuTimeOfOneTx",
      "value": 800
    },
    {
      "key": "getAllowUpdateAccountName"
    },
    {
      "key": "getAllowSameTokenName",
      "value": 1
    },
    {
      "key": "getAllowDelegateResource",
      "value": 1
    },
    {
      "key": "getTotalEnergyLimit",
      "value": 180000000000
    },
    {
      "key": "getAllowTvmTransferTrc10",
      "value": 1
    },
    {
      "key": "getTotalEnergyCurrentLimit",
      "value": 180000000000
    },
    {
      "key": "getAllowMultiSign",
      "value": 1
    },
    {
      "key": "getAllowAdaptiveEnergy"
    },
    {
      "key": "getTotalEnergyTargetLimit",
      "value": 12500000
    },
    {
      "key": "getTotalEnergyAverageUsage"
    },
    {
      "key": "getUpdateAccountPermissionFee",
      "value": 100000000
    },
    {
      "key": "getMultiSignFee",
      "value": 1000000
    },
    {
      "key": "getAllowAccountStateRoot"
    },
    {
      "key": "getAllowProtoFilterNum"
    },
    {
      "key": "getAllowTvmConstantinople",
      "value": 1
    },
    {
      "key": "getAllowTvmSolidity059",
      "value": 1
    },
    {
      "key": "getAllowTvmIstanbul",
      "value": 1
    },
    {
      "key": "getAllowShieldedTRC20Transaction",
      "value": 1
    },
    {
      "key": "getForbidTransferToContract"
    },
    {
      "key": "getAdaptiveResourceLimitTargetRatio",
      "value": 10
    },
    {
      "key": "getAdaptiveResourceLimitMultiplier",
      "value": 1000
    },
    {
      "key": "getChangeDelegation",
      "value": 1
    },
    {
      "key": "getWitness127PayPerBlock",
      "value": 128000000
    },
    {
      "key": "getAllowMarketTransaction"
    },
    {
      "key": "getMarketSellFee"
    },
    {
      "key": "getMarketCancelFee"
    },
    {
      "key": "getAllowPBFT"
    },
    {
      "key": "getAllowTransactionFeePool"
    },
    {
      "key": "getMaxFeeLimit",
      "value": 15000000000
    },
    {
      "key": "getAllowOptimizeBlackHole",
      "value": 1
    },
    {
      "key": "getAllowNewResourceModel"
    },
    {
      "key": "getAllowTvmFreeze"
    },
    {
      "key": "getAllowTvmVote",
      "value": 1
    },
    {
      "key": "getAllowTvmLondon",
      "value": 1
    },
    {
      "key": "getAllowTvmCompatibleEvm"
    },
    {
      "key": "getAllowAccountAssetOptimization"
    },
    {
      "key": "getFreeNetLimit",
      "value": 600
    },
    {
      "key": "getTotalNetLimit",
      "value": 43200000000
    },
    {
      "key": "getAllowHigherLimitForMaxCpuTimeOfOneTx",
      "value": 1
    },
    {
      "key": "getAllowAssetOptimization",
      "value": 1
    },
    {
      "key": "getAllowNewReward",
      "value": 1
    },
    {
      "key": "getMemoFee",
      "value": 1000000
    },
    {
      "key": "getAllowDelegateOptimization",
      "value": 1
    },
    {
      "key": "getUnfreezeDelayDays",
      "value": 14
    },
    {
      "key": "getAllowOptimizedReturnValueOfChainId",
      "value": 1
    },
    {
      "key": "getAllowDynamicEnergy",
      "value": 1
    },
    {
      "key": "getDynamicEnergyThreshold",
      "value": 5000000000
    },
    {
      "key": "getDynamicEnergyIncreaseFactor",
      "value": 2000
    },
    {
      "key": "getDynamicEnergyMaxFactor",
      "value": 34000
    },
    {
      "key": "getAllowTvmShangHai",
      "value": 1
    },
    {
      "key": "getAllowCancelAllUnfreezeV2",
      "value": 1
    },
    {
      "key": "getMaxDelegateLockPeriod",
      "value": 864000
    },
    {
      "key": "getAllowOldRewardOpt",
      "value": 1
    },
    {
      "key": "getAllowEnergyAdjustment",
      "value": 1
    },
    {
      "key": "getMaxCreateAccountTxSize",
      "value": 1000
    },
    {
      "key": "getAllowStrictMath",
      "value": 1
    },
    {
      "key": "getConsensusLogicOptimization",
      "value": 1
    },
    {
      "key": "getAllowTvmCancun",
      "value": 1
    },
    {
      "key": "getAllowTvmBlob",
      "value": 1
    },
    {
      "key": "getAllowTvmSelfdestructRestriction",
      "value": 1
    },
    {
      "key": "getProposalExpireTime",
      "value": 259200000
    },
    {
      "key": "getAllowTvmOsaka"
    },
    {
      "key": "getAllowTvmPrague"
    },
    {
      "key": "getAllowHardenResourceCalculation"
    },
    {
      "key": "getAllowHardenExchangeCalculation"
    }
  ]
}

Спойлер: getter_key_mapping.json
Code:
{
  "getAbiMoveDone": {
    "key": "ABI_MOVE_DONE",
    "setter": "saveAbiMoveDone"
  },
  "getAccountUpgradeCost": {
    "key": "ACCOUNT_UPGRADE_COST",
    "setter": "saveAccountUpgradeCost"
  },
  "getAllowAccountAssetOptimizationFromRoot": {
    "key": "ALLOW_ACCOUNT_ASSET_OPTIMIZATION",
    "setter": null
  },
  "getAllowAccountStateRoot": {
    "key": "ALLOW_ACCOUNT_STATE_ROOT",
    "setter": "saveAllowAccountStateRoot"
  },
  "getAllowAdaptiveEnergy": {
    "key": "ALLOW_ADAPTIVE_ENERGY",
    "setter": "saveAllowAdaptiveEnergy"
  },
  "getAllowAssetOptimization": {
    "key": "ALLOW_ASSET_OPTIMIZATION",
    "setter": null
  },
  "getAllowBlackHoleOptimization": {
    "key": "ALLOW_BLACKHOLE_OPTIMIZATION",
    "setter": "saveAllowBlackHoleOptimization"
  },
  "getAllowCancelAllUnfreezeV2": {
    "key": "ALLOW_CANCEL_ALL_UNFREEZE_V2",
    "setter": "saveAllowCancelAllUnfreezeV2"
  },
  "getAllowCreationOfContracts": {
    "key": "ALLOW_CREATION_OF_CONTRACTS",
    "setter": "saveAllowCreationOfContracts"
  },
  "getAllowDelegateOptimization": {
    "key": "ALLOW_DELEGATE_OPTIMIZATION",
    "setter": "saveAllowDelegateOptimization"
  },
  "getAllowDelegateResource": {
    "key": "ALLOW_DELEGATE_RESOURCE",
    "setter": "saveAllowDelegateResource"
  },
  "getAllowDynamicEnergy": {
    "key": "ALLOW_DYNAMIC_ENERGY",
    "setter": "saveAllowDynamicEnergy"
  },
  "getAllowEnergyAdjustment": {
    "key": "ALLOW_ENERGY_ADJUSTMENT",
    "setter": "saveAllowEnergyAdjustment"
  },
  "getAllowHardenExchangeCalculation": {
    "key": "ALLOW_HARDEN_EXCHANGE_CALCULATION",
    "setter": "saveAllowHardenExchangeCalculation"
  },
  "getAllowHardenResourceCalculation": {
    "key": "ALLOW_HARDEN_RESOURCE_CALCULATION",
    "setter": "saveAllowHardenResourceCalculation"
  },
  "getAllowHigherLimitForMaxCpuTimeOfOneTx": {
    "key": "ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX",
    "setter": "saveAllowHigherLimitForMaxCpuTimeOfOneTx"
  },
  "getAllowMarketTransaction": {
    "key": "ALLOW_MARKET_TRANSACTION",
    "setter": "saveAllowMarketTransaction"
  },
  "getAllowMultiSign": {
    "key": "ALLOW_MULTI_SIGN",
    "setter": "saveAllowMultiSign"
  },
  "getAllowNewResourceModel": {
    "key": "ALLOW_NEW_RESOURCE_MODEL",
    "setter": "saveAllowNewResourceModel"
  },
  "getAllowNewReward": {
    "key": "ALLOW_NEW_REWARD",
    "setter": "saveAllowNewReward"
  },
  "getAllowOldRewardOpt": {
    "key": "ALLOW_OLD_REWARD_OPT",
    "setter": "saveAllowOldRewardOpt"
  },
  "getAllowOptimizedReturnValueOfChainId": {
    "key": "ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID",
    "setter": "saveAllowOptimizedReturnValueOfChainId"
  },
  "getAllowPBFT": {
    "key": "ALLOW_PBFT",
    "setter": "saveAllowPBFT"
  },
  "getAllowProtoFilterNum": {
    "key": "ALLOW_PROTO_FILTER_NUM",
    "setter": "saveAllowProtoFilterNum"
  },
  "getAllowSameTokenName": {
    "key": "ALLOW_SAME_TOKEN_NAME",
    "setter": "saveAllowSameTokenName"
  },
  "getAllowShieldedTRC20Transaction": {
    "key": "ALLOW_SHIELDED_TRC20_TRANSACTION",
    "setter": "saveAllowShieldedTRC20Transaction"
  },
  "getAllowShieldedTransaction": {
    "key": "ALLOW_SHIELDED_TRANSACTION",
    "setter": "saveAllowShieldedTransaction"
  },
  "getAllowStrictMath": {
    "key": "ALLOW_STRICT_MATH",
    "setter": "saveAllowStrictMath"
  },
  "getAllowTransactionFeePool": {
    "key": "ALLOW_TRANSACTION_FEE_POOL",
    "setter": "saveAllowTransactionFeePool"
  },
  "getAllowTvmBlob": {
    "key": "ALLOW_TVM_BLOB",
    "setter": "saveAllowTvmBlob"
  },
  "getAllowTvmCancun": {
    "key": "ALLOW_TVM_CANCUN",
    "setter": "saveAllowTvmCancun"
  },
  "getAllowTvmCompatibleEvm": {
    "key": "ALLOW_TVM_COMPATIBLE_EVM",
    "setter": "saveAllowTvmCompatibleEvm"
  },
  "getAllowTvmConstantinople": {
    "key": "ALLOW_TVM_CONSTANTINOPLE",
    "setter": "saveAllowTvmConstantinople"
  },
  "getAllowTvmFreeze": {
    "key": "ALLOW_TVM_FREEZE",
    "setter": "saveAllowTvmFreeze"
  },
  "getAllowTvmIstanbul": {
    "key": "ALLOW_TVM_ISTANBUL",
    "setter": "saveAllowTvmIstanbul"
  },
  "getAllowTvmLondon": {
    "key": "ALLOW_TVM_LONDON",
    "setter": "saveAllowTvmLondon"
  },
  "getAllowTvmOsaka": {
    "key": "ALLOW_TVM_OSAKA",
    "setter": "saveAllowTvmOsaka"
  },
  "getAllowTvmPrague": {
    "key": "ALLOW_TVM_PRAGUE",
    "setter": "saveAllowTvmPrague"
  },
  "getAllowTvmSelfdestructRestriction": {
    "key": "ALLOW_TVM_SELFDESTRUCT_RESTRICTION",
    "setter": "saveAllowTvmSelfdestructRestriction"
  },
  "getAllowTvmShangHai": {
    "key": "ALLOW_TVM_SHANGHAI",
    "setter": "saveAllowTvmShangHai"
  },
  "getAllowTvmSolidity059": {
    "key": "ALLOW_TVM_SOLIDITY_059",
    "setter": "saveAllowTvmSolidity059"
  },
  "getAllowTvmTransferTrc10": {
    "key": "ALLOW_TVM_TRANSFER_TRC10",
    "setter": "saveAllowTvmTransferTrc10"
  },
  "getAllowTvmVote": {
    "key": "ALLOW_TVM_VOTE",
    "setter": "saveAllowTvmVote"
  },
  "getAllowUpdateAccountName": {
    "key": "ALLOW_UPDATE_ACCOUNT_NAME",
    "setter": "saveAllowUpdateAccountName"
  },
  "getAssetIssueFee": {
    "key": "ASSET_ISSUE_FEE",
    "setter": "saveAssetIssueFee"
  },
  "getBandwidthPriceHistory": {
    "key": "BANDWIDTH_PRICE_HISTORY",
    "setter": "saveBandwidthPriceHistory"
  },
  "getBandwidthPriceHistoryDone": {
    "key": "BANDWIDTH_PRICE_HISTORY_DONE",
    "setter": "saveBandwidthPriceHistoryDone"
  },
  "getBlockFilledSlotsIndex": {
    "key": "BLOCK_FILLED_SLOTS_INDEX",
    "setter": "saveBlockFilledSlotsIndex"
  },
  "getBlockFilledSlotsNumber": {
    "key": "LATEST_SOLIDIFIED_BLOCK_NUM",
    "setter": null
  },
  "getBlockHashHistoryInstalled": {
    "key": "BLOCK_HASH_HISTORY_INSTALLED",
    "setter": "saveBlockHashHistoryInstalled"
  },
  "getBurnTrxAmount": {
    "key": "BURN_TRX_AMOUNT",
    "setter": null
  },
  "getChangeDelegation": {
    "key": "ALLOW_CHANGE_DELEGATION",
    "setter": "saveChangeDelegation"
  },
  "getConsensusLogicOptimization": {
    "key": "CONSENSUS_LOGIC_OPTIMIZATION",
    "setter": "saveConsensusLogicOptimization"
  },
  "getCreateAccountFee": {
    "key": "CREATE_ACCOUNT_FEE",
    "setter": "saveCreateAccountFee"
  },
  "getCreateNewAccountBandwidthRate": {
    "key": "CREATE_NEW_ACCOUNT_BANDWIDTH_RATE",
    "setter": "saveCreateNewAccountBandwidthRate"
  },
  "getCreateNewAccountFeeInSystemContract": {
    "key": "CREATE_NEW_ACCOUNT_FEE_IN_SYSTEM_CONTRACT",
    "setter": "saveCreateNewAccountFeeInSystemContract"
  },
  "getCurrentCycleNumber": {
    "key": "CURRENT_CYCLE_NUMBER",
    "setter": "saveCurrentCycleNumber"
  },
  "getDynamicEnergyIncreaseFactor": {
    "key": "DYNAMIC_ENERGY_INCREASE_FACTOR",
    "setter": "saveDynamicEnergyIncreaseFactor"
  },
  "getDynamicEnergyMaxFactor": {
    "key": "DYNAMIC_ENERGY_MAX_FACTOR",
    "setter": "saveDynamicEnergyMaxFactor"
  },
  "getDynamicEnergyThreshold": {
    "key": "DYNAMIC_ENERGY_THRESHOLD",
    "setter": "saveDynamicEnergyThreshold"
  },
  "getEnergyPriceHistory": {
    "key": "ENERGY_PRICE_HISTORY",
    "setter": "saveEnergyPriceHistory"
  },
  "getEnergyPriceHistoryDone": {
    "key": "ENERGY_PRICE_HISTORY_DONE",
    "setter": "saveEnergyPriceHistoryDone"
  },
  "getExchangeBalanceLimit": {
    "key": "EXCHANGE_BALANCE_LIMIT",
    "setter": "saveExchangeBalanceLimit"
  },
  "getExchangeCreateFee": {
    "key": "EXCHANGE_CREATE_FEE",
    "setter": "saveExchangeCreateFee"
  },
  "getForbidTransferToContract": {
    "key": "FORBID_TRANSFER_TO_CONTRACT",
    "setter": "saveForbidTransferToContract"
  },
  "getLatestBlockHeaderHash": {
    "key": "LATEST_BLOCK_HEADER_HASH",
    "setter": "saveLatestBlockHeaderHash"
  },
  "getLatestBlockHeaderNumber": {
    "key": "LATEST_BLOCK_HEADER_NUMBER",
    "setter": "saveLatestBlockHeaderNumber"
  },
  "getLatestBlockHeaderNumberFromDB": {
    "key": "STATE_FLAG",
    "setter": null
  },
  "getLatestBlockHeaderTimestamp": {
    "key": "LATEST_BLOCK_HEADER_TIMESTAMP",
    "setter": "saveLatestBlockHeaderTimestamp"
  },
  "getLatestExchangeNum": {
    "key": "LATEST_EXCHANGE_NUM",
    "setter": "saveLatestExchangeNum"
  },
  "getLatestProposalNum": {
    "key": "LATEST_PROPOSAL_NUM",
    "setter": "saveLatestProposalNum"
  },
  "getMaintenanceSkipSlots": {
    "key": "VERSION_NUMBER",
    "setter": null
  },
  "getMaintenanceTimeInterval": {
    "key": "MAINTENANCE_TIME_INTERVAL",
    "setter": "saveMaintenanceTimeInterval"
  },
  "getMarketCancelFee": {
    "key": "MARKET_CANCEL_FEE",
    "setter": "saveMarketCancelFee"
  },
  "getMarketQuantityLimit": {
    "key": "MARKET_QUANTITY_LIMIT",
    "setter": "saveMarketQuantityLimit"
  },
  "getMarketSellFee": {
    "key": "MARKET_SELL_FEE",
    "setter": "saveMarketSellFee"
  },
  "getMaxCpuTimeOfOneTx": {
    "key": "MAX_CPU_TIME_OF_ONE_TX",
    "setter": "saveMaxCpuTimeOfOneTx"
  },
  "getMaxCreateAccountTxSize": {
    "key": "MAX_CREATE_ACCOUNT_TX_SIZE",
    "setter": "saveMaxCreateAccountTxSize"
  },
  "getMaxDelegateLockPeriod": {
    "key": "MAX_DELEGATE_LOCK_PERIOD",
    "setter": "saveMaxDelegateLockPeriod"
  },
  "getMaxFeeLimit": {
    "key": "MAX_FEE_LIMIT",
    "setter": "saveMaxFeeLimit"
  },
  "getMaxFrozenSupplyNumber": {
    "key": "MAX_FROZEN_SUPPLY_NUMBER",
    "setter": "saveMaxFrozenSupplyNumber"
  },
  "getMaxFrozenSupplyTime": {
    "key": "MAX_FROZEN_SUPPLY_TIME",
    "setter": "saveMaxFrozenSupplyTime"
  },
  "getMaxFrozenTime": {
    "key": "MAX_FROZEN_TIME",
    "setter": "saveMaxFrozenTime"
  },
  "getMemoFee": {
    "key": "MEMO_FEE",
    "setter": "saveMemoFee"
  },
  "getMemoFeeHistory": {
    "key": "MEMO_FEE_HISTORY",
    "setter": "saveMemoFeeHistory"
  },
  "getMinFrozenSupplyTime": {
    "key": "MIN_FROZEN_SUPPLY_TIME",
    "setter": "saveMinFrozenSupplyTime"
  },
  "getMinFrozenTime": {
    "key": "MIN_FROZEN_TIME",
    "setter": "saveMinFrozenTime"
  },
  "getMultiSignFee": {
    "key": "MULTI_SIGN_FEE",
    "setter": "saveMultiSignFee"
  },
  "getNewRewardAlgorithmEffectiveCycle": {
    "key": "NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE",
    "setter": "saveNewRewardAlgorithmEffectiveCycle"
  },
  "getNextMaintenanceTime": {
    "key": "NEXT_MAINTENANCE_TIME",
    "setter": "saveNextMaintenanceTime"
  },
  "getOneDayNetLimit": {
    "key": "ENERGY_FEE",
    "setter": "saveOneDayNetLimit"
  },
  "getProposalExpireTime": {
    "key": "PROPOSAL_EXPIRE_TIME",
    "setter": "saveProposalExpireTime"
  },
  "getRemoveThePowerOfTheGr": {
    "key": "REMOVE_THE_POWER_OF_THE_GR",
    "setter": "saveRemoveThePowerOfTheGr"
  },
  "getSetBlackholeAccountPermission": {
    "key": "SET_BLACKHOLE_ACCOUNT_PERMISSION",
    "setter": null
  },
  "getShieldedTransactionCreateAccountFee": {
    "key": "SHIELDED_TRANSACTION_CREATE_ACCOUNT_FEE",
    "setter": "saveShieldedTransactionCreateAccountFee"
  },
  "getShieldedTransactionFee": {
    "key": "SHIELDED_TRANSACTION_FEE",
    "setter": "saveShieldedTransactionFee"
  },
  "getStorageExchangeTaxRate": {
    "key": "STORAGE_EXCHANGE_TAX_RATE",
    "setter": "saveStorageExchangeTaxRate"
  },
  "getTokenIdNum": {
    "key": "TOKEN_ID_NUM",
    "setter": "saveTokenIdNum"
  },
  "getTokenUpdateDone": {
    "key": "TOKEN_UPDATE_DONE",
    "setter": "saveTokenUpdateDone"
  },
  "getTotalCreateAccountCost": {
    "key": "TOTAL_CREATE_ACCOUNT_COST",
    "setter": null
  },
  "getTotalCreateWitnessCost": {
    "key": "TOTAL_CREATE_WITNESS_COST",
    "setter": null
  },
  "getTotalShieldedPoolValue": {
    "key": "TOTAL_SHIELDED_POOL_VALUE",
    "setter": "saveTotalShieldedPoolValue"
  },
  "getTotalSignNum": {
    "key": "TOTAL_SIGN_NUM",
    "setter": "saveTotalSignNum"
  },
  "getTotalStoragePool": {
    "key": "TOTAL_STORAGE_POOL",
    "setter": "saveTotalStoragePool"
  },
  "getTotalStorageReserved": {
    "key": "TOTAL_STORAGE_RESERVED",
    "setter": "saveTotalStorageReserved"
  },
  "getTotalStorageTax": {
    "key": "TOTAL_STORAGE_TAX",
    "setter": "saveTotalStorageTax"
  },
  "getTotalTransactionCost": {
    "key": "TOTAL_TRANSACTION_COST",
    "setter": "saveTotalTransactionCost"
  },
  "getTransactionFee": {
    "key": "TRANSACTION_FEE",
    "setter": "saveTransactionFee"
  },
  "getTransactionFeePool": {
    "key": "TRANSACTION_FEE_POOL",
    "setter": "saveTransactionFeePool"
  },
  "getTurkishKeyMigrationDone": {
    "key": "TURKISH_KEY_MIGRATION_DONE",
    "setter": "saveTurkishKeyMigrationDone"
  },
  "getUnfreezeDelayDays": {
    "key": "UNFREEZE_DELAY_DAYS",
    "setter": "saveUnfreezeDelayDays"
  },
  "getUpdateAccountPermissionFee": {
    "key": "UPDATE_ACCOUNT_PERMISSION_FEE",
    "setter": "saveUpdateAccountPermissionFee"
  },
  "getWitness127PayPerBlock": {
    "key": "WITNESS_127_PAY_PER_BLOCK",
    "setter": "saveWitness127PayPerBlock"
  },
  "getWitnessAllowanceFrozenTime": {
    "key": "WITNESS_ALLOWANCE_FROZEN_TIME",
    "setter": "saveWitnessAllowanceFrozenTime"
  },
  "getWitnessPayPerBlock": {
    "key": "WITNESS_PAY_PER_BLOCK",
    "setter": "saveWitnessPayPerBlock"
  },
  "getWitnessStandbyAllowance": {
    "key": "WITNESS_STANDBY_ALLOWANCE",
    "setter": "saveWitnessStandbyAllowance"
  },
  "getAdaptiveResourceLimitMultiplier": {
    "key": "ADAPTIVE_RESOURCE_LIMIT_MULTIPLIER",
    "setter": "saveAdaptiveResourceLimitMultiplier"
  },
  "getAdaptiveResourceLimitTargetRatio": {
    "key": "ADAPTIVE_RESOURCE_LIMIT_TARGET_RATIO",
    "setter": "saveAdaptiveResourceLimitTargetRatio"
  },
  "getAllowAccountAssetOptimization": {
    "key": "ALLOW_ACCOUNT_ASSET_OPTIMIZATION",
    "setter": "saveAllowAccountAssetOptimization"
  },
  "getAllowOptimizeBlackHole": {
    "key": "ALLOW_BLACKHOLE_OPTIMIZATION",
    "setter": "saveAllowBlackHoleOptimization"
  },
  "getEnergyFee": {
    "key": "ENERGY_FEE",
    "setter": "saveEnergyFee"
  },
  "getFreeNetLimit": {
    "key": "FREE_NET_LIMIT",
    "setter": "saveFreeNetLimit"
  },
  "getTotalEnergyAverageUsage": {
    "key": "TOTAL_ENERGY_AVERAGE_USAGE",
    "setter": "saveTotalEnergyAverageUsage"
  },
  "getTotalEnergyCurrentLimit": {
    "key": "TOTAL_ENERGY_CURRENT_LIMIT",
    "setter": "saveTotalEnergyCurrentLimit"
  },
  "getTotalEnergyLimit": {
    "key": "TOTAL_ENERGY_LIMIT",
    "setter": "saveTotalEnergyLimit"
  },
  "getTotalEnergyTargetLimit": {
    "key": "TOTAL_ENERGY_TARGET_LIMIT",
    "setter": "saveTotalEnergyTargetLimit"
  },
  "getTotalNetLimit": {
    "key": "TOTAL_NET_LIMIT",
    "setter": "saveTotalNetLimit"
  }
}
Спойлер: updateparams.py
Code:
import json
import os
import requests
# Пути к файлам конфигурации относительно текущей директории
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
CHAIN_PARAMS_PATH = os.path.join(BASE_DIR, "../data/mainet_chainparameters.json")
MAPPING_PATH = os.path.join(BASE_DIR, "../data/getter_key_mapping.json")
# URL эндпоинта java-tron
URL = "http://localhost:8090/wallet/updateproposalparameter"
HEADERS = {"Content-Type": "application/json"}

def load_json(file_path: str) -> dict:
    if not os.path.exists(file_path):
        raise FileNotFoundError(f"Файл не найден по пути: {file_path}")
    with open(file_path, "r", encoding="utf-8") as f:
        return json.load(f)

def main():
    chain_params_data = load_json(CHAIN_PARAMS_PATH)
    mapping_data = load_json(MAPPING_PATH)
    chain_parameters = chain_params_data.get("chainParameter", [])
    print(f"Загружено {len(chain_parameters)} параметров из {CHAIN_PARAMS_PATH}\n")
    success_count = 0
    skipped_count = 0
    error_count = 0
    for item in chain_parameters:
        getter_name = item.get("key")
        value = item.get("value")
        if not getter_name:
            continue
        # Ищем соответствие геттера (например, "getAccountUpgradeCost") в маппинге
        mapping_info = mapping_data.get(getter_name)
        if not mapping_info or not mapping_info.get("key"):
            print(f"[SKIPPED] Пропущен геттер '{getter_name}': не найден ключ в getter_key_mapping.json")
            skipped_count += 1
            continue
        proposal_key = mapping_info["key"]
        payload = {"key": proposal_key, "value": value}
        try:
            response = requests.post(URL, json=payload, headers=HEADERS, timeout=10)
            
            if response.status_code == 200:
                print(f"[OK] {getter_name} -> '{proposal_key}': {value} | Ответ: {response.text.strip()}")
                success_count += 1
            else:
                print(f"[ERROR] {getter_name} -> '{proposal_key}': {value} | HTTP {response.status_code}: {response.text.strip()}")
                error_count += 1
        except requests.exceptions.RequestException as e:
            print(f"[FAIL] Ошибка при отправке {proposal_key}: {e}")
            error_count += 1
    print("\n" + "=" * 40)
    print(f"Итог: Успешно: {success_count} | Пропущено: {skipped_count} | Ошибок: {error_count}")

if __name__ == "__main__":
    main()


Потом советую добавить HTTP прокси-логгер. Будет удобно.

Спойлер: docker-compose.yml
Code:
  tron-proxy:
    image: mitmproxy/mitmproxy:latest
    container_name: tron-proxy
    networks:
      - tron_private_network
    ports:
      - "9090:8080"
    volumes:
      - ./logger/log_compact.py:/log_compact.py:ro
    command: ["mitmdump", "-q", "--mode", "reverse:http://tron-witness1:8090", "-s", "/log_compact.py"]
    depends_on:
      - tron-witness1

Спойлер: logger.py
Code:
import json
from mitmproxy import http
MAX_STRING_LEN = 100  # Максимальная длина строки
# ANSI-коды для цветов
COLOR_GREEN = "\033[92m"
COLOR_PINK = "\033[95m"
COLOR_RESET = "\033[0m"

def truncate_strings(data, max_len=MAX_STRING_LEN):
    """Рекурсивно обрезает слишком длинные строки в JSON-структуре."""
    if isinstance(data, dict):
        return {k: truncate_strings(v, max_len) for k, v in data.items()}
    elif isinstance(data, list):
        return [truncate_strings(item, max_len) for item in data]
    elif isinstance(data, str) and len(data) > max_len:
        return data[:max_len] + "..."
    return data

def format_body(content: bytes) -> str:
    """Парсит body, рекурсивно обрезает длинные поля и форматирует обратно в JSON."""
    if not content:
        return "EMPTY"
    text = content.decode("utf-8", errors="replace").strip()
    if not text:
        return "EMPTY"
    try:
        data = json.loads(text)
        truncated_data = truncate_strings(data)
        return json.dumps(truncated_data, ensure_ascii=False)
    except Exception:
        # Если тело запроса/ответа — не JSON, а обычный текст
        if len(text) > MAX_STRING_LEN:
            return text[:MAX_STRING_LEN] + "..."
        return text

def response(flow: http.HTTPFlow) -> None:
    req_body = format_body(flow.request.content)
    resp_body = format_body(flow.response.content)
    path = flow.request.path
    method = flow.request.method
    status = flow.response.status_code
    req_out = f"{COLOR_GREEN}REQ:  {req_body}{COLOR_RESET}"
    resp_out = f"{COLOR_PINK}RESP: {resp_body}{COLOR_RESET}"
    print(
        f"{method} {path} -> {status}\n"
        f"{req_out}\n"
        f"{resp_out}",
        flush=True,
    )

Проблема 2: А как деплоить?
Теперь когда тестнет готов остается только вопрос - "через какой интерфейс его использовать?". Никакого кода я тут давать не буду, просто обрисую как это должно выглядеть по-человечески.
Мы хотим писать наши плэйбуки/тесты/эксперименты (в общем то, что подразумевает под собой множественный деплой и вызов самрт-контрактов) декларативно через удобный формат типо .yaml. Мы хотим видеть IaC интерфейс со своим стейтом, чтобы шаги не выполнялись заново при каждом новом вызове. 
В общем, что-то типо Terraform или Hardhat Ignition.
Архитектура примерно такая:
java-tron node <-- client (TronWeb) <-- playbook engine <-- .yaml



На этом всё. Давайте фидбек кто чем занимается, какие проблемы, какие успехи. Тут мало кто про крипту пишет.
👍41 ❤️7 👏3 😢12
разве это не везде написано?
В чем изюм? 

=без иронии
👍2

Гостевой просмотр. Чтобы отвечать и ставить реакции, войдите или зарегистрируйтесь.