diff --git a/actuator/src/main/java/org/tron/core/actuator/ProposalCreateActuator.java b/actuator/src/main/java/org/tron/core/actuator/ProposalCreateActuator.java index a3639cca07f..e0044c4958d 100755 --- a/actuator/src/main/java/org/tron/core/actuator/ProposalCreateActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/ProposalCreateActuator.java @@ -9,7 +9,6 @@ import java.util.Map; import java.util.Objects; import lombok.extern.slf4j.Slf4j; -import org.tron.common.parameter.CommonParameter; import org.tron.common.utils.DecodeUtil; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.ProposalCapsule; @@ -53,7 +52,7 @@ public boolean execute(Object result) throws ContractExeException { long currentMaintenanceTime = chainBaseManager.getDynamicPropertiesStore().getNextMaintenanceTime(); - long now3 = now + CommonParameter.getInstance().getProposalExpireTime(); + long now3 = now + chainBaseManager.getDynamicPropertiesStore().getProposalExpireTime(); long round = (now3 - currentMaintenanceTime) / maintenanceTimeInterval; long expirationTime = currentMaintenanceTime + (round + 1) * maintenanceTimeInterval; diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index 0bad940da7e..1df35154d7d 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -4,6 +4,8 @@ import static org.tron.core.Constant.CREATE_ACCOUNT_TRANSACTION_MIN_BYTE_SIZE; import static org.tron.core.Constant.DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE; import static org.tron.core.Constant.DYNAMIC_ENERGY_MAX_FACTOR_RANGE; +import static org.tron.core.Constant.MAX_PROPOSAL_EXPIRE_TIME; +import static org.tron.core.Constant.MIN_PROPOSAL_EXPIRE_TIME; import static org.tron.core.config.Parameter.ChainConstant.ONE_YEAR_BLOCK_NUMBERS; import org.tron.common.utils.ForkController; @@ -839,6 +841,20 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case PROPOSAL_EXPIRE_TIME: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_8_1)) { + throw new ContractValidateException( + "Bad chain parameter id [PROPOSAL_EXPIRE_TIME]"); + } + if (value <= MIN_PROPOSAL_EXPIRE_TIME + || value >= MAX_PROPOSAL_EXPIRE_TIME) { + throw new ContractValidateException( + "This value[PROPOSAL_EXPIRE_TIME] is only allowed to be greater than " + + MIN_PROPOSAL_EXPIRE_TIME + " and less than " + + MAX_PROPOSAL_EXPIRE_TIME + "!"); + } + break; + } default: break; } @@ -921,7 +937,8 @@ public enum ProposalType { // current value, value range ALLOW_TVM_CANCUN(83), // 0, 1 ALLOW_STRICT_MATH(87), // 0, 1 CONSENSUS_LOGIC_OPTIMIZATION(88), // 0, 1 - ALLOW_TVM_BLOB(89); // 0, 1 + ALLOW_TVM_BLOB(89), // 0, 1 + PROPOSAL_EXPIRE_TIME(92); // (0, 31536003000) private long code; diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 91b0cff68a0..bee13782e53 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -1,6 +1,8 @@ package org.tron.core.store; import static org.tron.common.math.Maths.max; +import static org.tron.core.Constant.MAX_PROPOSAL_EXPIRE_TIME; +import static org.tron.core.Constant.MIN_PROPOSAL_EXPIRE_TIME; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL; import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD; @@ -231,6 +233,7 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_TVM_CANCUN = "ALLOW_TVM_CANCUN".getBytes(); private static final byte[] ALLOW_TVM_BLOB = "ALLOW_TVM_BLOB".getBytes(); + private static final byte[] PROPOSAL_EXPIRE_TIME = "PROPOSAL_EXPIRE_TIME".getBytes(); @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { @@ -2946,6 +2949,18 @@ public long getAllowTvmBlob() { .orElse(CommonParameter.getInstance().getAllowTvmBlob()); } + public void saveProposalExpireTime(long proposalExpireTime) { + this.put(PROPOSAL_EXPIRE_TIME, new BytesCapsule(ByteArray.fromLong(proposalExpireTime))); + } + + public long getProposalExpireTime() { + return Optional.ofNullable(getUnchecked(PROPOSAL_EXPIRE_TIME)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .filter(time -> time > MIN_PROPOSAL_EXPIRE_TIME && time < MAX_PROPOSAL_EXPIRE_TIME) + .orElse(CommonParameter.getInstance().getProposalExpireTime()); + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index c5a8a02fb4e..9af085b0464 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -39,6 +39,9 @@ public class Constant { public static final long MAX_CONTRACT_RESULT_SIZE = 2L; public static final long PB_DEFAULT_ENERGY_LIMIT = 0L; public static final long CREATOR_DEFAULT_ENERGY_LIMIT = 1000 * 10_000L; + public static final long MIN_PROPOSAL_EXPIRE_TIME = 0L; // 0 ms + public static final long MAX_PROPOSAL_EXPIRE_TIME = 31536003000L; // ms of 365 days + 3000 ms + public static final long DEFAULT_PROPOSAL_EXPIRE_TIME = 259200000L; // ms of 3 days // Numbers @@ -405,4 +408,5 @@ public class Constant { public static final String COMMITTEE_ALLOW_TVM_CANCUN = "committee.allowTvmCancun"; public static final String COMMITTEE_ALLOW_TVM_BLOB = "committee.allowTvmBlob"; + public static final String COMMITTEE_PROPOSAL_EXPIRE_TIME = "committee.proposalExpireTime"; } diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index a71dc58e8bd..7d0681a9f91 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -26,7 +26,8 @@ public enum ForkBlockVersionEnum { VERSION_4_7_4(29, 1596780000000L, 80), VERSION_4_7_5(30, 1596780000000L, 80), VERSION_4_7_7(31, 1596780000000L, 80), - VERSION_4_8_0(32, 1596780000000L, 80); + VERSION_4_8_0(32, 1596780000000L, 80), + VERSION_4_8_1(33, 1596780000000L, 80); // if add a version, modify BLOCK_VERSION simultaneously @Getter @@ -75,7 +76,7 @@ public class ChainConstant { public static final int SINGLE_REPEAT = 1; public static final int BLOCK_FILLED_SLOTS_NUMBER = 128; public static final int MAX_FROZEN_NUMBER = 1; - public static final int BLOCK_VERSION = 32; + public static final int BLOCK_VERSION = 33; public static final long FROZEN_PERIOD = 86_400_000L; public static final long DELEGATE_PERIOD = 3 * 86_400_000L; public static final long TRX_PRECISION = 1000_000L; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 8dfb18331ff..20a4613295d 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -1387,6 +1387,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getAllowTvmBlob()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getProposalExpireTime") + .setValue(dbManager.getDynamicPropertiesStore().getProposalExpireTime()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 277b3e7bc79..5b4178e6e4c 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -4,8 +4,11 @@ import static org.tron.common.math.Maths.max; import static org.tron.common.math.Maths.min; import static org.tron.core.Constant.ADD_PRE_FIX_BYTE_MAINNET; +import static org.tron.core.Constant.DEFAULT_PROPOSAL_EXPIRE_TIME; import static org.tron.core.Constant.DYNAMIC_ENERGY_INCREASE_FACTOR_RANGE; import static org.tron.core.Constant.DYNAMIC_ENERGY_MAX_FACTOR_RANGE; +import static org.tron.core.Constant.MAX_PROPOSAL_EXPIRE_TIME; +import static org.tron.core.Constant.MIN_PROPOSAL_EXPIRE_TIME; import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCE_TIMEOUT_PERCENT; import static org.tron.core.config.Parameter.ChainConstant.MAX_ACTIVE_WITNESS_NUM; @@ -815,9 +818,7 @@ public static void setParam(final Config config) { config.hasPath(Constant.BLOCK_MAINTENANCE_TIME_INTERVAL) ? config .getInt(Constant.BLOCK_MAINTENANCE_TIME_INTERVAL) : 21600000L; - PARAMETER.proposalExpireTime = - config.hasPath(Constant.BLOCK_PROPOSAL_EXPIRE_TIME) ? config - .getInt(Constant.BLOCK_PROPOSAL_EXPIRE_TIME) : 259200000L; + PARAMETER.proposalExpireTime = getProposalExpirationTime(config); PARAMETER.checkFrozenTime = config.hasPath(Constant.BLOCK_CHECK_FROZEN_TIME) ? config @@ -1300,6 +1301,26 @@ public static void setParam(final Config config) { logConfig(); } + private static long getProposalExpirationTime(final Config config) { + if (config.hasPath(Constant.COMMITTEE_PROPOSAL_EXPIRE_TIME)) { + throw new IllegalArgumentException("It is not allowed to configure " + + "commit.proposalExpireTime in config.conf, please set the value in " + + "block.proposalExpireTime."); + } + if (config.hasPath(Constant.BLOCK_PROPOSAL_EXPIRE_TIME)) { + long proposalExpireTime = config.getLong(Constant.BLOCK_PROPOSAL_EXPIRE_TIME); + if (proposalExpireTime <= MIN_PROPOSAL_EXPIRE_TIME + || proposalExpireTime >= MAX_PROPOSAL_EXPIRE_TIME) { + throw new IllegalArgumentException("The value[block.proposalExpireTime] is only allowed to " + + "be greater than " + MIN_PROPOSAL_EXPIRE_TIME + " and less than " + + MAX_PROPOSAL_EXPIRE_TIME + "!"); + } + return proposalExpireTime; + } else { + return DEFAULT_PROPOSAL_EXPIRE_TIME; + } + } + private static List getWitnessesFromConfig(final com.typesafe.config.Config config) { return config.getObjectList(Constant.GENESIS_BLOCK_WITNESSES).stream() .map(Args::createWitness) diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index b25f0d6fa8d..d6cf0e5fe67 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -384,6 +384,10 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveAllowTvmBlob(entry.getValue()); break; } + case PROPOSAL_EXPIRE_TIME: { + manager.getDynamicPropertiesStore().saveProposalExpireTime(entry.getValue()); + break; + } default: find = false; break; diff --git a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java index 300a38a0916..e81c75948b7 100644 --- a/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java +++ b/framework/src/test/java/org/tron/core/services/ProposalServiceTest.java @@ -1,7 +1,9 @@ package org.tron.core.services; +import static org.tron.core.Constant.MAX_PROPOSAL_EXPIRE_TIME; import static org.tron.core.utils.ProposalUtil.ProposalType.CONSENSUS_LOGIC_OPTIMIZATION; import static org.tron.core.utils.ProposalUtil.ProposalType.ENERGY_FEE; +import static org.tron.core.utils.ProposalUtil.ProposalType.PROPOSAL_EXPIRE_TIME; import static org.tron.core.utils.ProposalUtil.ProposalType.TRANSACTION_FEE; import static org.tron.core.utils.ProposalUtil.ProposalType.WITNESS_127_PAY_PER_BLOCK; @@ -13,6 +15,7 @@ import org.junit.BeforeClass; import org.junit.Test; import org.tron.common.BaseTest; +import org.tron.common.parameter.CommonParameter; import org.tron.core.Constant; import org.tron.core.capsule.ProposalCapsule; import org.tron.core.config.args.Args; @@ -131,4 +134,21 @@ public void testUpdateConsensusLogicOptimization() { Assert.assertTrue(dbManager.getDynamicPropertiesStore().disableJavaLangMath()); } + @Test + public void testProposalExpireTime() { + long defaultWindow = dbManager.getDynamicPropertiesStore().getProposalExpireTime(); + long proposalExpireTime = CommonParameter.getInstance().getProposalExpireTime(); + Assert.assertEquals(proposalExpireTime, defaultWindow); + + Proposal proposal = Proposal.newBuilder().putParameters(PROPOSAL_EXPIRE_TIME.getCode(), + 31536000000L).build(); + ProposalCapsule proposalCapsule = new ProposalCapsule(proposal); + proposalCapsule.setExpirationTime(1627279200000L); + boolean result = ProposalService.process(dbManager, proposalCapsule); + Assert.assertTrue(result); + + long window = dbManager.getDynamicPropertiesStore().getProposalExpireTime(); + Assert.assertEquals(MAX_PROPOSAL_EXPIRE_TIME - 3000, window); + } + } \ No newline at end of file