diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c81587501f3..d8dc83ad51b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -103,12 +103,12 @@ If you want to contribute codes to java-tron, please follow the following steps: Submit a pull request (PR) from your repository to `tronprotocol/java-tron`. Please be sure to click on the link in the red box shown below. Select the base branch for tronprotocol and the compare branch for your personal fork repository. - ![](https://codimd.s3.shivering-isles.com/demo/uploads/e24435ab42e4287d9369a2136.png) + ![image](https://raw.githubusercontent.com/tronprotocol/documentation-en/master/images/javatron_pr.png) ## Code Review Guidelines -The only way to get code into java-tron is to send a pull request. Those pull requests need to be reviewed by someone. there a guide that explains our expectations around PRs for both authors and reviewers. +The only way to get code into java-tron is to send a pull request. Those pull requests need to be reviewed by someone. The following guide explains our expectations around PRs for both authors and reviewers. ### Terminology - The author of a pull request is the entity who wrote the diff and submitted it to GitHub. diff --git a/actuator/src/main/java/org/tron/core/actuator/ClearABIContractActuator.java b/actuator/src/main/java/org/tron/core/actuator/ClearABIContractActuator.java index 5e0b2367dc5..7ce96d3318c 100755 --- a/actuator/src/main/java/org/tron/core/actuator/ClearABIContractActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/ClearABIContractActuator.java @@ -1,5 +1,7 @@ package org.tron.core.actuator; +import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; + import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import java.util.Arrays; @@ -16,13 +18,10 @@ import org.tron.core.store.AbiStore; import org.tron.core.store.AccountStore; import org.tron.core.store.ContractStore; -import org.tron.core.vm.config.VMConfig; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.code; -import org.tron.protos.contract.SmartContractOuterClass.SmartContract.ABI; import org.tron.protos.contract.SmartContractOuterClass.ClearABIContract; - -import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; +import org.tron.protos.contract.SmartContractOuterClass.SmartContract.ABI; @Slf4j(topic = "actuator") public class ClearABIContractActuator extends AbstractActuator { @@ -57,17 +56,16 @@ public boolean execute(Object result) throws ContractExeException { @Override public boolean validate() throws ContractValidateException { - if (!VMConfig.allowTvmConstantinople()) { - throw new ContractValidateException( - "contract type error,unexpected type [ClearABIContract]"); - } - if (this.any == null) { throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); } if (chainBaseManager == null) { throw new ContractValidateException("No account store or contract store!"); } + if (chainBaseManager.getDynamicPropertiesStore().getAllowTvmConstantinople() == 0) { + throw new ContractValidateException( + "contract type error,unexpected type [ClearABIContract]"); + } AccountStore accountStore = chainBaseManager.getAccountStore(); ContractStore contractStore = chainBaseManager.getContractStore(); if (!this.any.is(ClearABIContract.class)) { diff --git a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java index 5d630d0f115..0cfd981217f 100755 --- a/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java @@ -3,6 +3,10 @@ import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR; import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; +import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; @@ -72,44 +76,48 @@ public boolean execute(Object result) throws ContractExeException { byte[] ownerAddress = freezeBalanceContract.getOwnerAddress().toByteArray(); byte[] receiverAddress = freezeBalanceContract.getReceiverAddress().toByteArray(); + long increment; switch (freezeBalanceContract.getResource()) { case BANDWIDTH: if (!ArrayUtils.isEmpty(receiverAddress) && dynamicStore.supportDR()) { - delegateResource(ownerAddress, receiverAddress, true, - frozenBalance, expireTime); + increment = delegateResource(ownerAddress, receiverAddress, true, + frozenBalance, expireTime); accountCapsule.addDelegatedFrozenBalanceForBandwidth(frozenBalance); } else { + long oldNetWeight = accountCapsule.getFrozenBalance() / TRX_PRECISION; long newFrozenBalanceForBandwidth = frozenBalance + accountCapsule.getFrozenBalance(); accountCapsule.setFrozenForBandwidth(newFrozenBalanceForBandwidth, expireTime); + long newNetWeight = accountCapsule.getFrozenBalance() / TRX_PRECISION; + increment = newNetWeight - oldNetWeight; } - dynamicStore - .addTotalNetWeight(frozenBalance / TRX_PRECISION); + addTotalWeight(BANDWIDTH, dynamicStore, frozenBalance, increment); break; case ENERGY: if (!ArrayUtils.isEmpty(receiverAddress) && dynamicStore.supportDR()) { - delegateResource(ownerAddress, receiverAddress, false, - frozenBalance, expireTime); + increment = delegateResource(ownerAddress, receiverAddress, false, + frozenBalance, expireTime); accountCapsule.addDelegatedFrozenBalanceForEnergy(frozenBalance); } else { + long oldEnergyWeight = accountCapsule.getEnergyFrozenBalance() / TRX_PRECISION; long newFrozenBalanceForEnergy = - frozenBalance + accountCapsule.getAccountResource() - .getFrozenBalanceForEnergy() - .getFrozenBalance(); + frozenBalance + accountCapsule.getEnergyFrozenBalance(); accountCapsule.setFrozenForEnergy(newFrozenBalanceForEnergy, expireTime); + long newEnergyWeight = accountCapsule.getEnergyFrozenBalance() / TRX_PRECISION; + increment = newEnergyWeight - oldEnergyWeight; } - dynamicStore - .addTotalEnergyWeight(frozenBalance / TRX_PRECISION); + addTotalWeight(ENERGY, dynamicStore, frozenBalance, increment); break; case TRON_POWER: + long oldTPWeight = accountCapsule.getTronPowerFrozenBalance() / TRX_PRECISION; long newFrozenBalanceForTronPower = frozenBalance + accountCapsule.getTronPowerFrozenBalance(); accountCapsule.setFrozenForTronPower(newFrozenBalanceForTronPower, expireTime); - - dynamicStore - .addTotalTronPowerWeight(frozenBalance / TRX_PRECISION); + long newTPWeight = accountCapsule.getTronPowerFrozenBalance() / TRX_PRECISION; + increment = newTPWeight - oldTPWeight; + addTotalWeight(TRON_POWER, dynamicStore, frozenBalance, increment); break; default: logger.debug("Resource Code Error."); @@ -123,6 +131,23 @@ public boolean execute(Object result) throws ContractExeException { return true; } + private void addTotalWeight(ResourceCode resourceCode, DynamicPropertiesStore dynamicStore, + long frozenBalance, long increment) { + long weight = dynamicStore.allowNewReward() ? increment : frozenBalance / TRX_PRECISION; + switch (resourceCode) { + case BANDWIDTH: + dynamicStore.addTotalNetWeight(weight); + break; + case ENERGY: + dynamicStore.addTotalEnergyWeight(weight); + break; + case TRON_POWER: + dynamicStore.addTotalTronPowerWeight(weight); + break; + default: + logger.debug("Resource Code Error."); + } + } @Override public boolean validate() throws ContractValidateException { @@ -175,11 +200,6 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("frozenBalance must be less than accountBalance"); } -// long maxFrozenNumber = dbManager.getDynamicPropertiesStore().getMaxFrozenNumber(); -// if (accountCapsule.getFrozenCount() >= maxFrozenNumber) { -// throw new ContractValidateException("max frozen number is: " + maxFrozenNumber); -// } - long frozenDuration = freezeBalanceContract.getFrozenDuration(); long minFrozenTime = dynamicStore.getMinFrozenTime(); long maxFrozenTime = dynamicStore.getMaxFrozenTime(); @@ -224,8 +244,7 @@ public boolean validate() throws ContractValidateException { //If the receiver is included in the contract, the receiver will receive the resource. if (!ArrayUtils.isEmpty(receiverAddress) && dynamicStore.supportDR()) { if (Arrays.equals(receiverAddress, ownerAddress)) { - throw new ContractValidateException( - "receiverAddress must not be the same as ownerAddress"); + throw new ContractValidateException("receiverAddress must not be the same as ownerAddress"); } if (!DecodeUtil.addressValid(receiverAddress)) { @@ -267,9 +286,10 @@ public long calcFee() { return 0; } - private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boolean isBandwidth, + private long delegateResource(byte[] ownerAddress, byte[] receiverAddress, boolean isBandwidth, long balance, long expireTime) { AccountStore accountStore = chainBaseManager.getAccountStore(); + DynamicPropertiesStore dynamicPropertiesStore = chainBaseManager.getDynamicPropertiesStore(); DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore(); DelegatedResourceAccountIndexStore delegatedResourceAccountIndexStore = chainBaseManager .getDelegatedResourceAccountIndexStore(); @@ -297,46 +317,56 @@ private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole delegatedResourceStore.put(key, delegatedResourceCapsule); //modify DelegatedResourceAccountIndexStore - { - DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = delegatedResourceAccountIndexStore - .get(ownerAddress); - if (delegatedResourceAccountIndexCapsule == null) { - delegatedResourceAccountIndexCapsule = new DelegatedResourceAccountIndexCapsule( + if (!dynamicPropertiesStore.supportAllowDelegateOptimization()) { + + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = + delegatedResourceAccountIndexStore.get(ownerAddress); + if (ownerIndexCapsule == null) { + ownerIndexCapsule = new DelegatedResourceAccountIndexCapsule( ByteString.copyFrom(ownerAddress)); } - List toAccountsList = delegatedResourceAccountIndexCapsule.getToAccountsList(); + List toAccountsList = ownerIndexCapsule.getToAccountsList(); if (!toAccountsList.contains(ByteString.copyFrom(receiverAddress))) { - delegatedResourceAccountIndexCapsule.addToAccount(ByteString.copyFrom(receiverAddress)); + ownerIndexCapsule.addToAccount(ByteString.copyFrom(receiverAddress)); } - delegatedResourceAccountIndexStore - .put(ownerAddress, delegatedResourceAccountIndexCapsule); - } + delegatedResourceAccountIndexStore.put(ownerAddress, ownerIndexCapsule); - { - DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = delegatedResourceAccountIndexStore - .get(receiverAddress); - if (delegatedResourceAccountIndexCapsule == null) { - delegatedResourceAccountIndexCapsule = new DelegatedResourceAccountIndexCapsule( + DelegatedResourceAccountIndexCapsule receiverIndexCapsule + = delegatedResourceAccountIndexStore.get(receiverAddress); + if (receiverIndexCapsule == null) { + receiverIndexCapsule = new DelegatedResourceAccountIndexCapsule( ByteString.copyFrom(receiverAddress)); } - List fromAccountsList = delegatedResourceAccountIndexCapsule + List fromAccountsList = receiverIndexCapsule .getFromAccountsList(); if (!fromAccountsList.contains(ByteString.copyFrom(ownerAddress))) { - delegatedResourceAccountIndexCapsule.addFromAccount(ByteString.copyFrom(ownerAddress)); + receiverIndexCapsule.addFromAccount(ByteString.copyFrom(ownerAddress)); } - delegatedResourceAccountIndexStore - .put(receiverAddress, delegatedResourceAccountIndexCapsule); + delegatedResourceAccountIndexStore.put(receiverAddress, receiverIndexCapsule); + + } else { + // modify DelegatedResourceAccountIndexStore new + delegatedResourceAccountIndexStore.convert(ownerAddress); + delegatedResourceAccountIndexStore.convert(receiverAddress); + delegatedResourceAccountIndexStore.delegate(ownerAddress, receiverAddress, + dynamicPropertiesStore.getLatestBlockHeaderTimestamp()); } //modify AccountStore AccountCapsule receiverCapsule = accountStore.get(receiverAddress); + long oldWeight; + long newWeight; if (isBandwidth) { + oldWeight = receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() / TRX_PRECISION; receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(balance); + newWeight = receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() / TRX_PRECISION; } else { + oldWeight = receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() / TRX_PRECISION; receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(balance); + newWeight = receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() / TRX_PRECISION; } - accountStore.put(receiverCapsule.createDbKey(), receiverCapsule); + return newWeight - oldWeight; } } diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java index 93dcd61e044..80334f1fc49 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java @@ -38,6 +38,9 @@ @Slf4j(topic = "actuator") public class UnfreezeBalanceActuator extends AbstractActuator { + private static final String INVALID_RESOURCE_CODE = + "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"; + public UnfreezeBalanceActuator() { super(ContractType.UnfreezeBalanceContract, UnfreezeBalanceContract.class); } @@ -83,6 +86,7 @@ public boolean execute(Object result) throws ContractExeException { byte[] receiverAddress = unfreezeBalanceContract.getReceiverAddress().toByteArray(); //If the receiver is not included in the contract, unfreeze frozen balance for this account. //otherwise,unfreeze delegated frozen balance provided this account. + long decrease = 0; if (!ArrayUtils.isEmpty(receiverAddress) && dynamicStore.supportDR()) { byte[] key = DelegatedResourceCapsule .createDbKey(unfreezeBalanceContract.getOwnerAddress().toByteArray(), @@ -107,31 +111,46 @@ public boolean execute(Object result) throws ContractExeException { } AccountCapsule receiverCapsule = accountStore.get(receiverAddress); + if (dynamicStore.getAllowTvmConstantinople() == 0 || (receiverCapsule != null && receiverCapsule.getType() != AccountType.Contract)) { switch (unfreezeBalanceContract.getResource()) { case BANDWIDTH: + long oldNetWeight = receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() / + TRX_PRECISION; if (dynamicStore.getAllowTvmSolidity059() == 1 && receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() < unfreezeBalance) { + oldNetWeight = unfreezeBalance / TRX_PRECISION; receiverCapsule.setAcquiredDelegatedFrozenBalanceForBandwidth(0); } else { receiverCapsule.addAcquiredDelegatedFrozenBalanceForBandwidth(-unfreezeBalance); } + long newNetWeight = receiverCapsule.getAcquiredDelegatedFrozenBalanceForBandwidth() / + TRX_PRECISION; + decrease = newNetWeight - oldNetWeight; break; case ENERGY: + long oldEnergyWeight = receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() / + TRX_PRECISION; if (dynamicStore.getAllowTvmSolidity059() == 1 && receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() < unfreezeBalance) { + oldEnergyWeight = unfreezeBalance / TRX_PRECISION; receiverCapsule.setAcquiredDelegatedFrozenBalanceForEnergy(0); } else { receiverCapsule.addAcquiredDelegatedFrozenBalanceForEnergy(-unfreezeBalance); } + long newEnergyWeight = receiverCapsule.getAcquiredDelegatedFrozenBalanceForEnergy() / + TRX_PRECISION; + decrease = newEnergyWeight - oldEnergyWeight; break; default: //this should never happen break; } accountStore.put(receiverCapsule.createDbKey(), receiverCapsule); + } else { + decrease = -unfreezeBalance / TRX_PRECISION; } accountCapsule.setBalance(oldBalance + unfreezeBalance); @@ -141,39 +160,39 @@ public boolean execute(Object result) throws ContractExeException { delegatedResourceStore.delete(key); //modify DelegatedResourceAccountIndexStore - { - DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = delegatedResourceAccountIndexStore - .get(ownerAddress); - if (delegatedResourceAccountIndexCapsule != null) { - List toAccountsList = new ArrayList<>(delegatedResourceAccountIndexCapsule + if (!dynamicStore.supportAllowDelegateOptimization()) { + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = + delegatedResourceAccountIndexStore.get(ownerAddress); + if (ownerIndexCapsule != null) { + List toAccountsList = new ArrayList<>(ownerIndexCapsule .getToAccountsList()); toAccountsList.remove(ByteString.copyFrom(receiverAddress)); - delegatedResourceAccountIndexCapsule.setAllToAccounts(toAccountsList); - delegatedResourceAccountIndexStore - .put(ownerAddress, delegatedResourceAccountIndexCapsule); + ownerIndexCapsule.setAllToAccounts(toAccountsList); + delegatedResourceAccountIndexStore.put(ownerAddress, ownerIndexCapsule); } - } - { - DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = delegatedResourceAccountIndexStore - .get(receiverAddress); - if (delegatedResourceAccountIndexCapsule != null) { - List fromAccountsList = new ArrayList<>(delegatedResourceAccountIndexCapsule + DelegatedResourceAccountIndexCapsule receiverIndexCapsule = + delegatedResourceAccountIndexStore.get(receiverAddress); + if (receiverIndexCapsule != null) { + List fromAccountsList = new ArrayList<>(receiverIndexCapsule .getFromAccountsList()); fromAccountsList.remove(ByteString.copyFrom(ownerAddress)); - delegatedResourceAccountIndexCapsule.setAllFromAccounts(fromAccountsList); - delegatedResourceAccountIndexStore - .put(receiverAddress, delegatedResourceAccountIndexCapsule); + receiverIndexCapsule.setAllFromAccounts(fromAccountsList); + delegatedResourceAccountIndexStore.put(receiverAddress, receiverIndexCapsule); } + } else { + //modify DelegatedResourceAccountIndexStore new + delegatedResourceAccountIndexStore.convert(ownerAddress); + delegatedResourceAccountIndexStore.convert(receiverAddress); + delegatedResourceAccountIndexStore.unDelegate(ownerAddress, receiverAddress); } - } else { delegatedResourceStore.put(key, delegatedResourceCapsule); } } else { switch (unfreezeBalanceContract.getResource()) { case BANDWIDTH: - + long oldNetWeight = accountCapsule.getFrozenBalance() / TRX_PRECISION; List frozenList = Lists.newArrayList(); frozenList.addAll(accountCapsule.getFrozenList()); Iterator iterator = frozenList.iterator(); @@ -189,9 +208,11 @@ public boolean execute(Object result) throws ContractExeException { accountCapsule.setInstance(accountCapsule.getInstance().toBuilder() .setBalance(oldBalance + unfreezeBalance) .clearFrozen().addAllFrozen(frozenList).build()); - + long newNetWeight = accountCapsule.getFrozenBalance() / TRX_PRECISION; + decrease = newNetWeight - oldNetWeight; break; case ENERGY: + long oldEnergyWeight = accountCapsule.getEnergyFrozenBalance() / TRX_PRECISION; unfreezeBalance = accountCapsule.getAccountResource().getFrozenBalanceForEnergy() .getFrozenBalance(); @@ -200,12 +221,17 @@ public boolean execute(Object result) throws ContractExeException { accountCapsule.setInstance(accountCapsule.getInstance().toBuilder() .setBalance(oldBalance + unfreezeBalance) .setAccountResource(newAccountResource).build()); + long newEnergyWeight = accountCapsule.getEnergyFrozenBalance() / TRX_PRECISION; + decrease = newEnergyWeight - oldEnergyWeight; break; case TRON_POWER: + long oldTPWeight = accountCapsule.getTronPowerFrozenBalance() / TRX_PRECISION; unfreezeBalance = accountCapsule.getTronPowerFrozenBalance(); accountCapsule.setInstance(accountCapsule.getInstance().toBuilder() .setBalance(oldBalance + unfreezeBalance) .clearTronPower().build()); + long newTPWeight = accountCapsule.getTronPowerFrozenBalance() / TRX_PRECISION; + decrease = newTPWeight - oldTPWeight; break; default: //this should never happen @@ -213,19 +239,20 @@ public boolean execute(Object result) throws ContractExeException { } } - + + long weight = dynamicStore.allowNewReward() ? decrease : -unfreezeBalance / TRX_PRECISION; switch (unfreezeBalanceContract.getResource()) { case BANDWIDTH: dynamicStore - .addTotalNetWeight(-unfreezeBalance / TRX_PRECISION); + .addTotalNetWeight(weight); break; case ENERGY: dynamicStore - .addTotalEnergyWeight(-unfreezeBalance / TRX_PRECISION); + .addTotalEnergyWeight(weight); break; case TRON_POWER: dynamicStore - .addTotalTronPowerWeight(-unfreezeBalance / TRX_PRECISION); + .addTotalTronPowerWeight(weight); break; default: //this should never happen @@ -402,8 +429,7 @@ public boolean validate() throws ContractValidateException { } break; default: - throw new ContractValidateException( - "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + throw new ContractValidateException(INVALID_RESOURCE_CODE); } } else { @@ -440,8 +466,7 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException("It's not time to unfreeze(TronPower)."); } } else { - throw new ContractValidateException( - "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + throw new ContractValidateException(INVALID_RESOURCE_CODE); } break; default: @@ -449,8 +474,7 @@ public boolean validate() throws ContractValidateException { throw new ContractValidateException( "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy、TRON_POWER]"); } else { - throw new ContractValidateException( - "ResourceCode error.valid ResourceCode[BANDWIDTH、Energy]"); + throw new ContractValidateException(INVALID_RESOURCE_CODE); } } diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java index 416f861d2da..b43b614b8a6 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -3,6 +3,10 @@ import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR; import static org.tron.core.config.Parameter.ChainConstant.FROZEN_PERIOD; import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION; +import static org.tron.protos.contract.Common.ResourceCode; +import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH; +import static org.tron.protos.contract.Common.ResourceCode.ENERGY; +import static org.tron.protos.contract.Common.ResourceCode.TRON_POWER; import com.google.common.collect.Lists; import com.google.protobuf.ByteString; @@ -24,11 +28,12 @@ import org.tron.core.store.DynamicPropertiesStore; import org.tron.core.store.VotesStore; import org.tron.protos.Protocol; +import org.tron.protos.Protocol.Account.FreezeV2; +import org.tron.protos.Protocol.Account.UnFreezeV2; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result.code; import org.tron.protos.Protocol.Vote; import org.tron.protos.contract.BalanceContract.UnfreezeBalanceV2Contract; -import org.tron.protos.contract.Common; @Slf4j(topic = "actuator") public class UnfreezeBalanceV2Actuator extends AbstractActuator { @@ -73,7 +78,7 @@ public boolean execute(Object result) throws ContractExeException { accountCapsule.initializeOldTronPower(); } - Common.ResourceCode freezeType = unfreezeBalanceV2Contract.getResource(); + ResourceCode freezeType = unfreezeBalanceV2Contract.getResource(); this.updateAccountFrozenInfo(freezeType, accountCapsule, unfreezeBalance); @@ -140,18 +145,18 @@ public boolean validate() throws ContractValidateException { long now = dynamicStore.getLatestBlockHeaderTimestamp(); switch (unfreezeBalanceV2Contract.getResource()) { case BANDWIDTH: - if (!this.checkExistFreezedBalance(accountCapsule, Common.ResourceCode.BANDWIDTH)) { + if (!checkExistFrozenBalance(accountCapsule, BANDWIDTH)) { throw new ContractValidateException("no frozenBalance(BANDWIDTH)"); } break; case ENERGY: - if (!this.checkExistFreezedBalance(accountCapsule, Common.ResourceCode.ENERGY)) { + if (!checkExistFrozenBalance(accountCapsule, ENERGY)) { throw new ContractValidateException("no frozenBalance(Energy)"); } break; case TRON_POWER: if (dynamicStore.supportAllowNewResourceModel()) { - if (!this.checkExistFreezedBalance(accountCapsule, Common.ResourceCode.TRON_POWER)) { + if (!checkExistFrozenBalance(accountCapsule, TRON_POWER)) { throw new ContractValidateException("no frozenBalance(TronPower)"); } } else { @@ -190,32 +195,24 @@ public long calcFee() { return 0; } - public boolean checkExistFreezedBalance(AccountCapsule accountCapsule, Common.ResourceCode freezeType) { - boolean checkOk = false; - - long frozenAmount = 0; - List frozenV2List = accountCapsule.getFrozenV2List(); - for (Protocol.Account.FreezeV2 frozenV2 : frozenV2List) { - if (frozenV2.getType().equals(freezeType)) { - frozenAmount = frozenV2.getAmount(); - if (frozenAmount > 0) { - checkOk = true; - break; - } + public boolean checkExistFrozenBalance(AccountCapsule accountCapsule, ResourceCode freezeType) { + List frozenV2List = accountCapsule.getFrozenV2List(); + for (FreezeV2 frozenV2 : frozenV2List) { + if (frozenV2.getType().equals(freezeType) && frozenV2.getAmount() > 0) { + return true; } } - - return checkOk; + return false; } public boolean checkUnfreezeBalance(AccountCapsule accountCapsule, final UnfreezeBalanceV2Contract unfreezeBalanceV2Contract, - Common.ResourceCode freezeType) { + ResourceCode freezeType) { boolean checkOk = false; long frozenAmount = 0L; - List freezeV2List = accountCapsule.getFrozenV2List(); - for (Protocol.Account.FreezeV2 freezeV2 : freezeV2List) { + List freezeV2List = accountCapsule.getFrozenV2List(); + for (FreezeV2 freezeV2 : freezeV2List) { if (freezeV2.getType().equals(freezeType)) { frozenAmount = freezeV2.getAmount(); break; @@ -237,11 +234,11 @@ public long calcUnfreezeExpireTime(long now) { return now + unfreezeDelayDays * FROZEN_PERIOD; } - public void updateAccountFrozenInfo(Common.ResourceCode freezeType, AccountCapsule accountCapsule, long unfreezeBalance) { - List freezeV2List = accountCapsule.getFrozenV2List(); + public void updateAccountFrozenInfo(ResourceCode freezeType, AccountCapsule accountCapsule, long unfreezeBalance) { + List freezeV2List = accountCapsule.getFrozenV2List(); for (int i = 0; i < freezeV2List.size(); i++) { if (freezeV2List.get(i).getType().equals(freezeType)) { - Protocol.Account.FreezeV2 freezeV2 = Protocol.Account.FreezeV2.newBuilder() + FreezeV2 freezeV2 = FreezeV2.newBuilder() .setAmount(freezeV2List.get(i).getAmount() - unfreezeBalance) .setType(freezeV2List.get(i).getType()) .build(); @@ -254,12 +251,12 @@ public void updateAccountFrozenInfo(Common.ResourceCode freezeType, AccountCapsu public long unfreezeExpire(AccountCapsule accountCapsule, long now) { long unfreezeBalance = 0L; - List unFrozenV2List = Lists.newArrayList(); + List unFrozenV2List = Lists.newArrayList(); unFrozenV2List.addAll(accountCapsule.getUnfrozenV2List()); - Iterator iterator = unFrozenV2List.iterator(); + Iterator iterator = unFrozenV2List.iterator(); while (iterator.hasNext()) { - Protocol.Account.UnFreezeV2 next = iterator.next(); + UnFreezeV2 next = iterator.next(); if (next.getUnfreezeExpireTime() <= now) { unfreezeBalance += next.getUnfreezeAmount(); iterator.remove(); diff --git a/actuator/src/main/java/org/tron/core/actuator/UpdateEnergyLimitContractActuator.java b/actuator/src/main/java/org/tron/core/actuator/UpdateEnergyLimitContractActuator.java index 369b936a527..f6b67e02891 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UpdateEnergyLimitContractActuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UpdateEnergyLimitContractActuator.java @@ -6,10 +6,10 @@ import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.tron.common.utils.DecodeUtil; -import org.tron.common.utils.StorageUtils; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.AccountCapsule; import org.tron.core.capsule.ContractCapsule; +import org.tron.core.capsule.ReceiptCapsule; import org.tron.core.capsule.TransactionResultCapsule; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; @@ -58,16 +58,16 @@ public boolean execute(Object object) throws ContractExeException { @Override public boolean validate() throws ContractValidateException { - if (!StorageUtils.getEnergyLimitHardFork()) { - throw new ContractValidateException( - "contract type error, unexpected type [UpdateEnergyLimitContract]"); - } if (this.any == null) { throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST); } if (chainBaseManager == null) { throw new ContractValidateException(ActuatorConstant.STORE_NOT_EXIST); } + if (!ReceiptCapsule.checkForEnergyLimit(chainBaseManager.getDynamicPropertiesStore())) { + throw new ContractValidateException( + "contract type error, unexpected type [UpdateEnergyLimitContract]"); + } AccountStore accountStore = chainBaseManager.getAccountStore(); ContractStore contractStore = chainBaseManager.getContractStore(); if (!this.any.is(UpdateEnergyLimitContract.class)) { 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 44376dcd223..ca5691d25ee 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -560,18 +560,40 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } - case ALLOW_NEW_REWARD_ALGO: { + case ALLOW_NEW_REWARD: { if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_6)) { throw new ContractValidateException( - "Bad chain parameter id [ALLOW_NEW_REWARD_ALGO]"); + "Bad chain parameter id [ALLOW_NEW_REWARD]"); } - if (dynamicPropertiesStore.useNewRewardAlgorithm()) { + if (dynamicPropertiesStore.allowNewReward()) { throw new ContractValidateException( - "New reward algorithm has been valid."); + "New reward has been valid."); } if (value != 1) { throw new ContractValidateException( - "This value[ALLOW_NEW_REWARD_ALGO] is only allowed to be 1"); + "This value[ALLOW_NEW_REWARD] is only allowed to be 1"); + } + break; + } + case MEMO_FEE: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_6)) { + throw new ContractValidateException( + "Bad chain parameter id [MEMO_FEE]"); + } + if (value < 0 || value > 1_000_000_000) { + throw new ContractValidateException( + "This value[MEMO_FEE] is only allowed to be in the range 0-1000_000_000"); + } + break; + } + case ALLOW_DELEGATE_OPTIMIZATION: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_6)) { + throw new ContractValidateException( + "Bad chain parameter id [ALLOW_DELEGATE_OPTIMIZATION]"); + } + if (value != 1) { + throw new ContractValidateException( + "This value[ALLOW_DELEGATE_OPTIMIZATION] is only allowed to be 1"); } break; } @@ -651,8 +673,10 @@ public enum ProposalType { // current value, value range ALLOW_TVM_LONDON(63), // 0, 1 ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX(65), // 0, 1 ALLOW_ASSET_OPTIMIZATION(66), // 0, 1 - ALLOW_NEW_REWARD_ALGO(67), // 0, 1 - UNFREEZE_DELAY_DAYS(68); // 0, [1, 365] + ALLOW_NEW_REWARD(67), // 0, 1 + MEMO_FEE(68), // 0, [0, 1000_000_000] + ALLOW_DELEGATE_OPTIMIZATION(69), + UNFREEZE_DELAY_DAYS(70); // 0, [1, 365] private long code; diff --git a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java index a1e40878173..d2ab55a7032 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java @@ -36,7 +36,6 @@ import org.tron.protos.Protocol.Vote; import org.tron.protos.contract.AccountContract.AccountCreateContract; import org.tron.protos.contract.AccountContract.AccountUpdateContract; -import org.tron.protos.contract.Common; import java.util.List; import java.util.Map; @@ -453,7 +452,7 @@ public void addFrozenBalanceForEnergyV2(long balance) { this.addFrozenBalanceForResource(ENERGY, balance); } - private void addFrozenBalanceForResource(Common.ResourceCode type, long balance) { + private void addFrozenBalanceForResource(ResourceCode type, long balance) { boolean doUpdate = false; for (int i = 0; i < this.account.getFrozenV2List().size(); i++) { if (this.account.getFrozenV2List().get(i).getType().equals(type)) { @@ -564,9 +563,10 @@ public List getUnfrozenV2List() { } public void updateFrozenV2List(int index, FreezeV2 frozenV2) { - this.account = this.account.toBuilder() - .setFrozenV2(index, frozenV2) - .build(); + if (Objects.isNull(frozenV2)) { + return; + } + this.account = this.account.toBuilder().setFrozenV2(index, frozenV2).build(); } public void addFrozenV2List(FreezeV2 frozenV2) { @@ -750,9 +750,8 @@ public boolean addAssetV2(byte[] key, long value) { return true; } - public boolean addAssetMapV2(Map assetMap) { + public void addAssetMapV2(Map assetMap) { this.account = this.account.toBuilder().putAllAssetV2(assetMap).build(); - return true; } public Long getAsset(DynamicPropertiesStore dynamicStore, String key) { @@ -799,9 +798,8 @@ public Map getAssetV2MapForTest() { /*************************** end asset ****************************************/ - public boolean addAllLatestAssetOperationTimeV2(Map map) { + public void addAllLatestAssetOperationTimeV2(Map map) { this.account = this.account.toBuilder().putAllLatestAssetOperationTimeV2(map).build(); - return true; } public Map getLatestAssetOperationTimeMap() { @@ -1097,9 +1095,8 @@ public void setFreeNetUsage(long freeNetUsage) { this.account = this.account.toBuilder().setFreeNetUsage(freeNetUsage).build(); } - public boolean addAllFreeAssetNetUsageV2(Map map) { + public void addAllFreeAssetNetUsageV2(Map map) { this.account = this.account.toBuilder().putAllFreeAssetNetUsageV2(map).build(); - return true; } public long getFreeAssetNetUsage(String assetName) { diff --git a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java index 2ff6495b2cf..9628f193b5e 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java @@ -93,6 +93,15 @@ public void removeToAccount(ByteString toAccount) { } } + public void setTimestamp(long time) { + this.delegatedResourceAccountIndex = this.delegatedResourceAccountIndex.toBuilder() + .setTimestamp(time) + .build(); + } + + public long getTimestamp() { + return this.delegatedResourceAccountIndex.getTimestamp(); + } public byte[] createDbKey() { return getAccount().toByteArray(); diff --git a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java index b33e47a2406..fbb398a4b44 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceCapsule.java @@ -76,17 +76,26 @@ public long getFrozenBalanceForBandwidth() { return this.delegatedResource.getFrozenBalanceForBandwidth(); } - public void setFrozenBalanceForBandwidth(long Bandwidth, long expireTime) { + public long getFrozenBalance(boolean isBandwidth) { + if (isBandwidth) { + return getFrozenBalanceForBandwidth(); + } else { + return getFrozenBalanceForEnergy(); + } + + } + + public void setFrozenBalanceForBandwidth(long bandwidth, long expireTime) { this.delegatedResource = this.delegatedResource.toBuilder() - .setFrozenBalanceForBandwidth(Bandwidth) + .setFrozenBalanceForBandwidth(bandwidth) .setExpireTimeForBandwidth(expireTime) .build(); } - public void addFrozenBalanceForBandwidth(long Bandwidth, long expireTime) { + public void addFrozenBalanceForBandwidth(long bandwidth, long expireTime) { this.delegatedResource = this.delegatedResource.toBuilder() .setFrozenBalanceForBandwidth(this.delegatedResource.getFrozenBalanceForBandwidth() - + Bandwidth) + + bandwidth) .setExpireTimeForBandwidth(expireTime) .build(); } @@ -99,9 +108,9 @@ public long getExpireTimeForEnergy() { return this.delegatedResource.getExpireTimeForEnergy(); } - public void setExpireTimeForBandwidth(long ExpireTime) { + public void setExpireTimeForBandwidth(long expireTime) { this.delegatedResource = this.delegatedResource.toBuilder() - .setExpireTimeForBandwidth(ExpireTime) + .setExpireTimeForBandwidth(expireTime) .build(); } @@ -113,9 +122,9 @@ public long getExpireTimeForEnergy(DynamicPropertiesStore dynamicPropertiesStore } } - public void setExpireTimeForEnergy(long ExpireTime) { + public void setExpireTimeForEnergy(long expireTime) { this.delegatedResource = this.delegatedResource.toBuilder() - .setExpireTimeForEnergy(ExpireTime) + .setExpireTimeForEnergy(expireTime) .build(); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java index e86d1f627ab..5b362fae120 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/ReceiptCapsule.java @@ -24,6 +24,9 @@ public class ReceiptCapsule { @Setter private long multiSignFee; + @Getter + @Setter + private long memoFee; /** * Available energy of contract deployer before executing transaction */ diff --git a/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java b/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java index d1126b23674..d31b5009401 100644 --- a/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java +++ b/chainbase/src/main/java/org/tron/core/capsule/utils/TransactionUtil.java @@ -72,9 +72,9 @@ public static TransactionInfoCapsule buildTransactionInfoInstance(TransactionCap } builder.setId(ByteString.copyFrom(trxCap.getTransactionId().getBytes())); ProgramResult programResult = trace.getRuntimeResult(); - long fee = - programResult.getRet().getFee() + traceReceipt.getEnergyFee() - + traceReceipt.getNetFee() + traceReceipt.getMultiSignFee(); + long fee = programResult.getRet().getFee() + traceReceipt.getEnergyFee() + + traceReceipt.getNetFee() + traceReceipt.getMultiSignFee() + + traceReceipt.getMemoFee(); boolean supportTransactionFeePool = trace.getTransactionContext().getStoreFactory() .getChainBaseManager().getDynamicPropertiesStore().supportTransactionFeePool(); diff --git a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java index c98b553ba3f..d9cb61825e9 100644 --- a/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java @@ -36,7 +36,6 @@ public BandwidthProcessor(ChainBaseManager chainBaseManager) { this.chainBaseManager = chainBaseManager; } - @Override public void updateUsage(AccountCapsule accountCapsule) { long now = chainBaseManager.getHeadSlot(); updateUsage(accountCapsule, now); @@ -61,8 +60,7 @@ private void updateUsage(AccountCapsule accountCapsule, long now) { }); } Map assetMapV2 = accountCapsule.getAssetMapV2(); - Map map = new HashMap<>(); - map.putAll(assetMapV2); + Map map = new HashMap<>(assetMapV2); accountCapsule.getAllFreeAssetNetUsageV2().forEach((k, v) -> { if (!map.containsKey(k)) { map.put(k, 0L); @@ -399,6 +397,9 @@ public long calculateGlobalNetLimit(AccountCapsule accountCapsule) { long netWeight = frozeBalance / TRX_PRECISION; long totalNetLimit = chainBaseManager.getDynamicPropertiesStore().getTotalNetLimit(); long totalNetWeight = chainBaseManager.getDynamicPropertiesStore().getTotalNetWeight(); + if (dynamicPropertiesStore.allowNewReward() && totalNetWeight <= 0) { + return 0; + } if (totalNetWeight == 0) { return 0; } diff --git a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java index beca72fad63..362cb9e9392 100644 --- a/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java @@ -31,7 +31,6 @@ public static long getHeadSlot(DynamicPropertiesStore dynamicPropertiesStore) { / BLOCK_PRODUCED_INTERVAL; } - @Override public void updateUsage(AccountCapsule accountCapsule) { long now = getHeadSlot(); updateUsage(accountCapsule, now); @@ -141,9 +140,11 @@ public long calculateGlobalEnergyLimit(AccountCapsule accountCapsule) { long energyWeight = frozeBalance / TRX_PRECISION; long totalEnergyLimit = dynamicPropertiesStore.getTotalEnergyCurrentLimit(); long totalEnergyWeight = dynamicPropertiesStore.getTotalEnergyWeight(); - - assert totalEnergyWeight > 0; - + if (dynamicPropertiesStore.allowNewReward() && totalEnergyWeight <= 0) { + return 0; + } else { + assert totalEnergyWeight > 0; + } return (long) (energyWeight * ((double) totalEnergyLimit / totalEnergyWeight)); } diff --git a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java index eb0ab0eba7a..c3a0b56221a 100644 --- a/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java +++ b/chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java @@ -33,8 +33,6 @@ public ResourceProcessor(DynamicPropertiesStore dynamicPropertiesStore, AdaptiveResourceLimitConstants.PERIODS_MS / BLOCK_PRODUCED_INTERVAL; } - abstract void updateUsage(AccountCapsule accountCapsule); - abstract void consume(TransactionCapsule trx, TransactionTrace trace) throws ContractValidateException, AccountResourceInsufficientException, TooBigTransactionResultException; @@ -63,12 +61,10 @@ protected long increase(long lastUsage, long usage, long lastTime, long now, lon public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, long lastUsage, long usage, long lastTime, long now) { long oldWindowSize = accountCapsule.getWindowSize(resourceCode); - /* old logic */ long averageLastUsage = divideCeil(lastUsage * this.precision, oldWindowSize); long averageUsage = divideCeil(usage * this.precision, this.windowSize); if (lastTime != now) { - assert now > lastTime; if (lastTime + oldWindowSize > now) { long delta = now - lastTime; double decay = (oldWindowSize - delta) / (double) oldWindowSize; @@ -77,7 +73,7 @@ public long increase(AccountCapsule accountCapsule, ResourceCode resourceCode, averageLastUsage = 0; } } - /* new logic */ + long newUsage = getUsage(averageLastUsage, oldWindowSize) + getUsage(averageUsage, this.windowSize); if (dynamicPropertiesStore.supportUnfreezeDelay()) { @@ -150,7 +146,6 @@ protected boolean consumeFeeForBandwidth(AccountCapsule accountCapsule, long fee } } - protected boolean consumeFeeForNewAccount(AccountCapsule accountCapsule, long fee) { try { long latestOperationTime = dynamicPropertiesStore.getLatestBlockHeaderTimestamp(); diff --git a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java index d1bbed934d5..be005a1da76 100644 --- a/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java +++ b/chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java @@ -11,6 +11,7 @@ import java.util.Iterator; import java.util.Map; import java.util.Objects; +import java.util.stream.Collectors; import javax.annotation.PostConstruct; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -29,6 +30,7 @@ import org.tron.core.db2.common.IRevokingDB; import org.tron.core.db2.common.LevelDB; import org.tron.core.db2.common.RocksDB; +import org.tron.core.db2.common.WrappedByteArray; import org.tron.core.db2.core.Chainbase; import org.tron.core.db2.core.ITronChainBase; import org.tron.core.db2.core.RevokingDBWithCachingOldValue; @@ -234,4 +236,16 @@ public long size() { public void setCursor(Chainbase.Cursor cursor) { revokingDB.setCursor(cursor); } + + public Map prefixQuery(byte[] key) { + return revokingDB.prefixQuery(key).entrySet().stream().collect( + Collectors.toMap(Map.Entry::getKey, e -> { + try { + return of(e.getValue()); + } catch (BadItemException e1) { + throw new RuntimeException(e1); + } + } + )); + } } diff --git a/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java b/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java index b3eb5675873..e9b7be47792 100644 --- a/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java @@ -1,5 +1,10 @@ package org.tron.core.store; +import com.google.protobuf.ByteString; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -11,6 +16,9 @@ public class DelegatedResourceAccountIndexStore extends TronStoreWithRevoking { + private static final byte[] FROM_PREFIX = {0x01}; + private static final byte[] TO_PREFIX = {0x02}; + @Autowired public DelegatedResourceAccountIndexStore(@Value("DelegatedResourceAccountIndex") String dbName) { super(dbName); @@ -23,4 +31,85 @@ public DelegatedResourceAccountIndexCapsule get(byte[] key) { return ArrayUtils.isEmpty(value) ? null : new DelegatedResourceAccountIndexCapsule(value); } + private byte[] createKey(byte[] prefix, byte[] address1, byte[] address2) { + byte[] key = new byte[prefix.length + address1.length + address2.length]; + System.arraycopy(prefix, 0, key, 0, prefix.length); + System.arraycopy(address1, 0, key, prefix.length, address1.length); + System.arraycopy(address2, 0, key, prefix.length + address1.length, address2.length); + return key; + } + + public void convert(byte[] address) { + DelegatedResourceAccountIndexCapsule indexCapsule = this.get(address); + if (indexCapsule == null) { + // convert complete or have no delegate + return; + } + // convert old data + List toList = indexCapsule.getToAccountsList(); + for (int i = 0; i < toList.size(); i++) { + // use index as the timestamp, just to keep index in order + this.delegate(address, toList.get(i).toByteArray(), i + 1L); + } + + List fromList = indexCapsule.getFromAccountsList(); + for (int i = 0; i < fromList.size(); i++) { + // use index as the timestamp, just to keep index in order + this.delegate(fromList.get(i).toByteArray(), address, i + 1L); + } + this.delete(address); + } + + public void delegate(byte[] from, byte[] to, long time) { + byte[] fromKey = createKey(FROM_PREFIX, from, to); + DelegatedResourceAccountIndexCapsule toIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(to)); + toIndexCapsule.setTimestamp(time); + this.put(fromKey, toIndexCapsule); + + byte[] toKey = createKey(TO_PREFIX, to, from); + DelegatedResourceAccountIndexCapsule fromIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(from)); + fromIndexCapsule.setTimestamp(time); + this.put(toKey, fromIndexCapsule); + } + + public void unDelegate(byte[] from, byte[] to) { + byte[] fromKey = createKey(FROM_PREFIX, from, to); + this.delete(fromKey); + byte[] toKey = createKey(TO_PREFIX, to, from); + this.delete(toKey); + } + + public DelegatedResourceAccountIndexCapsule getIndex(byte[] address) { + DelegatedResourceAccountIndexCapsule indexCapsule = get(address); + if (indexCapsule != null) { + return indexCapsule; + } + + DelegatedResourceAccountIndexCapsule tmpIndexCapsule = + new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(address)); + byte[] key = new byte[FROM_PREFIX.length + address.length]; + + System.arraycopy(FROM_PREFIX, 0, key, 0, FROM_PREFIX.length); + System.arraycopy(address, 0, key, FROM_PREFIX.length, address.length); + List tmpToList = + new ArrayList<>(this.prefixQuery(key).values()); + + tmpToList.sort(Comparator.comparing(DelegatedResourceAccountIndexCapsule::getTimestamp)); + List list = tmpToList.stream() + .map(DelegatedResourceAccountIndexCapsule::getAccount).collect(Collectors.toList()); + tmpIndexCapsule.setAllToAccounts(list); + + System.arraycopy(TO_PREFIX, 0, key, 0, TO_PREFIX.length); + System.arraycopy(address, 0, key, TO_PREFIX.length, address.length); + List tmpFromList = + new ArrayList<>(this.prefixQuery(key).values()); + tmpFromList.sort(Comparator.comparing(DelegatedResourceAccountIndexCapsule::getTimestamp)); + list = tmpFromList.stream().map(DelegatedResourceAccountIndexCapsule::getAccount).collect( + Collectors.toList()); + tmpIndexCapsule.setAllFromAccounts(list); + return tmpIndexCapsule; + } + } \ No newline at end of file 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 7227c97f9bf..b417a3b283f 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -187,6 +187,13 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX = "ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX".getBytes(); + private static final byte[] ALLOW_NEW_REWARD = "ALLOW_NEW_REWARD".getBytes(); + private static final byte[] MEMO_FEE = "MEMO_FEE".getBytes(); + private static final byte[] MEMO_FEE_HISTORY = "MEMO_FEE_HISTORY".getBytes(); + private static final byte[] ALLOW_DELEGATE_OPTIMIZATION = + "ALLOW_DELEGATE_OPTIMIZATION".getBytes(); + + private static final byte[] UNFREEZE_DELAY_DAYS = "UNFREEZE_DELAY_DAYS".getBytes(); @Autowired @@ -860,6 +867,31 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { } } + try { + this.getAllowNewReward(); + } catch (IllegalArgumentException e) { + this.saveAllowNewReward(CommonParameter.getInstance().getAllowNewReward()); + if (CommonParameter.getInstance().getAllowNewReward() == 1) { + this.put(NEW_REWARD_ALGORITHM_EFFECTIVE_CYCLE, + new BytesCapsule(ByteArray.fromLong(getCurrentCycleNumber()))); + } + } + + try { + this.getMemoFee(); + } catch (IllegalArgumentException e) { + long memoFee = CommonParameter.getInstance().getMemoFee(); + this.saveMemoFee(memoFee); + this.saveMemoFeeHistory("0:" + memoFee); + } + + try { + this.getAllowDelegateOptimization(); + } catch (IllegalArgumentException e) { + this.saveAllowDelegateOptimization( + CommonParameter.getInstance().getAllowDelegateOptimization()); + } + try { this.getUnfreezeDelayDays(); } catch (IllegalArgumentException e) { @@ -2144,6 +2176,9 @@ public void updateNextMaintenanceTime(long blockTime) { public void addTotalNetWeight(long amount) { long totalNetWeight = getTotalNetWeight(); totalNetWeight += amount; + if (allowNewReward()) { + totalNetWeight = Math.max(0, totalNetWeight); + } saveTotalNetWeight(totalNetWeight); } @@ -2151,6 +2186,9 @@ public void addTotalNetWeight(long amount) { public void addTotalEnergyWeight(long amount) { long totalEnergyWeight = getTotalEnergyWeight(); totalEnergyWeight += amount; + if (allowNewReward()) { + totalEnergyWeight = Math.max(0, totalEnergyWeight); + } saveTotalEnergyWeight(totalEnergyWeight); } @@ -2158,6 +2196,9 @@ public void addTotalEnergyWeight(long amount) { public void addTotalTronPowerWeight(long amount) { long totalWeight = getTotalTronPowerWeight(); totalWeight += amount; + if (allowNewReward()) { + totalWeight = Math.max(0, totalWeight); + } saveTotalTronPowerWeight(totalWeight); } @@ -2538,6 +2579,59 @@ public long getAllowHigherLimitForMaxCpuTimeOfOneTx() { () -> new IllegalArgumentException(msg)); } + public long getMemoFee() { + return Optional.ofNullable(getUnchecked(MEMO_FEE)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow(() -> new IllegalArgumentException("not found MEMO_FEE")); + } + + public void saveMemoFee(long value) { + this.put(MEMO_FEE, new BytesCapsule(ByteArray.fromLong(value))); + } + + public String getMemoFeeHistory() { + return Optional.ofNullable(getUnchecked(MEMO_FEE_HISTORY)) + .map(BytesCapsule::getData) + .map(ByteArray::toStr) + .orElseThrow(() -> new IllegalArgumentException("not found MEMO_FEE_HISTORY")); + } + + public void saveMemoFeeHistory(String value) { + this.put(MEMO_FEE_HISTORY, new BytesCapsule(ByteArray.fromString(value))); + } + + public long getAllowNewReward() { + return Optional.ofNullable(getUnchecked(ALLOW_NEW_REWARD)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow(() -> new IllegalArgumentException("not found AllowNewReward")); + } + + public void saveAllowNewReward(long newReward) { + this.put(ALLOW_NEW_REWARD, new BytesCapsule(ByteArray.fromLong(newReward))); + } + + public long getAllowDelegateOptimization() { + return Optional.ofNullable(getUnchecked(ALLOW_DELEGATE_OPTIMIZATION)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException("not found ALLOW_DELEGATE_OPTIMIZATION")); + } + + public boolean supportAllowDelegateOptimization() { + return getAllowDelegateOptimization() == 1L; + } + + public void saveAllowDelegateOptimization(long value) { + this.put(ALLOW_DELEGATE_OPTIMIZATION, new BytesCapsule(ByteArray.fromLong(value))); + } + + public boolean allowNewReward() { + return getAllowNewReward() == 1; + } + public long getUnfreezeDelayDays() { return Optional.ofNullable(getUnchecked(UNFREEZE_DELAY_DAYS)) .map(BytesCapsule::getData) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 91325d44a9d..7569de58da1 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -561,6 +561,18 @@ public class CommonParameter { @Setter public long allowNewRewardAlgorithm; + @Getter + @Setter + public long allowNewReward = 0L; + + @Getter + @Setter + public long memoFee = 0L; + + @Getter + @Setter + public long allowDelegateOptimization = 0L; + @Getter @Setter public long unfreezeDelayDays = 0L; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 130395d1f5e..f91d04074ad 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -308,6 +308,9 @@ public class Constant { public static final String ALLOW_ACCOUNT_ASSET_OPTIMIZATION = "committee.allowAccountAssetOptimization"; public static final String ALLOW_ASSET_OPTIMIZATION = "committee.allowAssetOptimization"; + public static final String ALLOW_NEW_REWARD = "committee.allowNewReward"; + public static final String MEMO_FEE = "committee.memoFee"; + public static final String ALLOW_DELEGATE_OPTIMIZATION = "committee.allowDelegateOptimization"; public static final String LOCAL_HOST = "127.0.0.1"; diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index d4bff49fea3..cae83378ab0 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -344,13 +344,9 @@ public Account getAccount(Account account) { private void sortFrozenV2List(AccountCapsule accountCapsule) { List oldFreezeV2List = accountCapsule.getFrozenV2List(); accountCapsule.clearFrozenV2(); - ResourceCode[] codes = ResourceCode.values(); - for (ResourceCode code : codes) { + for (ResourceCode code : ResourceCode.values()) { if (ResourceCode.UNRECOGNIZED != code) { - accountCapsule.addFrozenV2List(FreezeV2.newBuilder() - .setType(code) - .setAmount(0) - .build()); + accountCapsule.addFrozenV2List(FreezeV2.newBuilder().setType(code).setAmount(0).build()); } } List newFreezeV2List = accountCapsule.getFrozenV2List(); @@ -359,7 +355,9 @@ private void sortFrozenV2List(AccountCapsule accountCapsule) { ResourceCode code = freezeV2.getType(); Optional optional = oldFreezeV2List .stream().filter(o -> o.getType() == code).findFirst(); - accountCapsule.updateFrozenV2List(i, optional.orElse(freezeV2)); + if (optional.isPresent()) { + accountCapsule.updateFrozenV2List(i, optional.get()); + } } } @@ -698,7 +696,7 @@ public long getTransactionCountByBlockNum(long blockNum) { Block block = chainBaseManager.getBlockByNum(blockNum).getInstance(); count = block.getTransactionsCount(); } catch (StoreException e) { - logger.error(e.getMessage()); + logger.warn(e.getMessage()); } return count; @@ -899,7 +897,7 @@ public long calcCanDelegatedEnergyMaxSize(ByteString ownerAddress) { public DelegatedResourceAccountIndex getDelegatedResourceAccountIndex(ByteString address) { DelegatedResourceAccountIndexCapsule accountIndexCapsule = - chainBaseManager.getDelegatedResourceAccountIndexStore().get(address.toByteArray()); + chainBaseManager.getDelegatedResourceAccountIndexStore().getIndex(address.toByteArray()); if (accountIndexCapsule != null) { return accountIndexCapsule.getInstance(); } else { @@ -1256,8 +1254,18 @@ public Protocol.ChainParameters getChainParameters() { .build()); builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() - .setKey("getNewRewardAlgorithm") - .setValue(dbManager.getDynamicPropertiesStore().useNewRewardAlgorithm() ? 1 : 0) + .setKey("getAllowNewReward") + .setValue(dbManager.getDynamicPropertiesStore().getAllowNewReward()) + .build()); + + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getMemoFee") + .setValue(dbManager.getDynamicPropertiesStore().getMemoFee()) + .build()); + + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowDelegateOptimization") + .setValue(dbManager.getDynamicPropertiesStore().getAllowDelegateOptimization()) .build()); builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() @@ -1571,7 +1579,7 @@ public Block getBlockById(ByteString blockId) { try { block = chainBaseManager.getBlockStore().get(blockId.toByteArray()).getInstance(); } catch (StoreException e) { - logger.error(e.getMessage()); + logger.warn(e.getMessage()); } return block; } @@ -4242,5 +4250,13 @@ public Block getBlock(GrpcAPI.BlockReq request) { return block.toBuilder().clearTransactions().build(); } + public String getMemoFeePrices() { + try { + return chainBaseManager.getDynamicPropertiesStore().getMemoFeeHistory(); + } catch (Exception e) { + logger.error("getMemoFeePrices failed, error is {}", e.getMessage()); + } + return null; + } } 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 6e159052e38..d5f835f85c4 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 @@ -215,6 +215,8 @@ public static void clearParam() { PARAMETER.shutdownBlockCount = -1; PARAMETER.blockCacheTimeout = 60; PARAMETER.allowNewRewardAlgorithm = 0; + PARAMETER.allowNewReward = 0; + PARAMETER.memoFee = 0; } /** @@ -1034,6 +1036,32 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.blockCacheTimeout = config.getLong(Constant.BLOCK_CACHE_TIMEOUT); } + if (config.hasPath(Constant.ALLOW_NEW_REWARD)) { + PARAMETER.allowNewReward = config.getLong(Constant.ALLOW_NEW_REWARD); + if (PARAMETER.allowNewReward > 1) { + PARAMETER.allowNewReward = 1; + } + if (PARAMETER.allowNewReward < 0) { + PARAMETER.allowNewReward = 0; + } + } + + if (config.hasPath(Constant.MEMO_FEE)) { + PARAMETER.memoFee = config.getLong(Constant.MEMO_FEE); + if (PARAMETER.memoFee > 1_000_000_000) { + PARAMETER.memoFee = 1_000_000_000; + } + if (PARAMETER.memoFee < 0) { + PARAMETER.memoFee = 0; + } + } + + if (config.hasPath(Constant.ALLOW_DELEGATE_OPTIMIZATION)) { + PARAMETER.allowDelegateOptimization = config.getLong(Constant.ALLOW_DELEGATE_OPTIMIZATION); + PARAMETER.allowDelegateOptimization = Math.min(PARAMETER.allowDelegateOptimization, 1); + PARAMETER.allowDelegateOptimization = Math.max(PARAMETER.allowDelegateOptimization, 0); + } + if (config.hasPath(Constant.COMMITTEE_UNFREEZE_DELAY_DAYS)) { PARAMETER.unfreezeDelayDays = config.getLong(Constant.COMMITTEE_UNFREEZE_DELAY_DAYS); if (PARAMETER.unfreezeDelayDays > 365) { 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 f54d59f2b3b..9b5c6dfb975 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -286,8 +286,17 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().setAllowAssetOptimization(entry.getValue()); break; } - case ALLOW_NEW_REWARD_ALGO: { + case ALLOW_NEW_REWARD: { manager.getDynamicPropertiesStore().saveNewRewardAlgorithmEffectiveCycle(); + manager.getDynamicPropertiesStore().saveAllowNewReward(entry.getValue()); + break; + } + case MEMO_FEE: { + manager.getDynamicPropertiesStore().saveMemoFee(entry.getValue()); + // update memo fee history + manager.getDynamicPropertiesStore().saveMemoFeeHistory( + manager.getDynamicPropertiesStore().getMemoFeeHistory() + + "," + proposalCapsule.getExpirationTime() + ":" + entry.getValue()); break; } case UNFREEZE_DELAY_DAYS: { @@ -305,6 +314,10 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) ContractType.UnDelegateResourceContract_VALUE); break; } + case ALLOW_DELEGATE_OPTIMIZATION: { + manager.getDynamicPropertiesStore().saveAllowDelegateOptimization(entry.getValue()); + break; + } default: find = false; break; diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 80be86403ba..a9d11133866 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -85,7 +85,6 @@ import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.BlockCapsule.BlockId; import org.tron.core.capsule.BytesCapsule; -import org.tron.core.capsule.ReceiptCapsule; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.capsule.TransactionInfoCapsule; import org.tron.core.capsule.TransactionRetCapsule; @@ -155,7 +154,6 @@ import org.tron.core.store.WitnessScheduleStore; import org.tron.core.store.WitnessStore; import org.tron.core.utils.TransactionRegister; -import org.tron.core.vm.config.VMConfig; import org.tron.protos.Protocol.AccountType; import org.tron.protos.Protocol.Permission; import org.tron.protos.Protocol.Transaction; @@ -537,9 +535,6 @@ public void init() { //initActuatorCreator ActuatorCreator.init(); TransactionRegister.registerActuator(); - //initEnergyLimitHardFork - VMConfig.initVmHardFork(ReceiptCapsule.checkForEnergyLimit( - chainBaseManager.getDynamicPropertiesStore())); long exitHeight = CommonParameter.getInstance().getShutdownBlockHeight(); long exitCount = CommonParameter.getInstance().getShutdownBlockCount(); @@ -855,6 +850,42 @@ public void consumeMultiSignFee(TransactionCapsule trx, TransactionTrace trace) } } + public void consumeMemoFee(TransactionCapsule trx, TransactionTrace trace) + throws AccountResourceInsufficientException { + if (trx.getInstance().getRawData().getData().isEmpty()) { + // no memo + return; + } + + long fee = getDynamicPropertiesStore().getMemoFee(); + if (fee == 0) { + return; + } + + List contracts = trx.getInstance().getRawData().getContractList(); + for (Contract contract : contracts) { + byte[] address = TransactionCapsule.getOwner(contract); + AccountCapsule accountCapsule = getAccountStore().get(address); + try { + if (accountCapsule != null) { + adjustBalance(getAccountStore(), accountCapsule, -fee); + + if (getDynamicPropertiesStore().supportBlackHoleOptimization()) { + getDynamicPropertiesStore().burnTrx(fee); + } else { + adjustBalance(getAccountStore(), this.getAccountStore().getBlackhole(), +fee); + } + } + } catch (BalanceInsufficientException e) { + throw new AccountResourceInsufficientException( + String.format("account %s insufficient balance[%d] to memo fee", + StringUtil.encode58Check(address), fee)); + } + } + + trace.getReceipt().setMemoFee(fee); + } + public void consumeBandwidth(TransactionCapsule trx, TransactionTrace trace) throws ContractValidateException, AccountResourceInsufficientException, TooBigTransactionResultException { @@ -1338,6 +1369,7 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block consumeBandwidth(trxCap, trace); consumeMultiSignFee(trxCap, trace); + consumeMemoFee(trxCap, trace); trace.init(blockCap, eventPluginLoaded); trace.checkIsConstant(); diff --git a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java index b4479eafdea..c2b201cb787 100644 --- a/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java +++ b/framework/src/main/java/org/tron/core/services/http/FullNodeHttpApiService.java @@ -303,6 +303,8 @@ public class FullNodeHttpApiService implements Service { private GetBandwidthPricesServlet getBandwidthPricesServlet; @Autowired private GetBlockServlet getBlockServlet; + @Autowired + private GetMemoFeePricesServlet getMemoFeePricesServlet; @Autowired private FreezeBalanceV2Servlet freezeBalanceV2Servlet; @@ -574,6 +576,7 @@ public void start() { context.addServlet(new ServletHolder(getBandwidthPricesServlet), "/wallet/getbandwidthprices"); context.addServlet(new ServletHolder(getBlockServlet), "/wallet/getblock"); + context.addServlet(new ServletHolder(getMemoFeePricesServlet), "/wallet/getmemofee"); context.addServlet(new ServletHolder(freezeBalanceV2Servlet), "/wallet/freezebalancev2"); diff --git a/framework/src/main/java/org/tron/core/services/http/GetMemoFeePricesServlet.java b/framework/src/main/java/org/tron/core/services/http/GetMemoFeePricesServlet.java new file mode 100644 index 00000000000..8d5f46d8236 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/http/GetMemoFeePricesServlet.java @@ -0,0 +1,37 @@ +package org.tron.core.services.http; + +import com.alibaba.fastjson.JSONObject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.Wallet; + + +@Component +@Slf4j(topic = "API") +public class GetMemoFeePricesServlet extends RateLimiterServlet { + + @Autowired + private Wallet wallet; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + try { + String reply = wallet.getMemoFeePrices(); + if (reply != null) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("prices", reply); + response.getWriter().println(jsonObject); + } else { + response.getWriter().println("{}"); + } + } catch (Exception e) { + Util.processError(e, response); + } + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + doGet(request, response); + } +} diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java index 565ce922572..a25bedc577d 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java @@ -35,8 +35,10 @@ import org.tron.protos.contract.AssetIssueContractOuterClass.ParticipateAssetIssueContract; import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract; import org.tron.protos.contract.AssetIssueContractOuterClass.UnfreezeAssetContract; +import org.tron.protos.contract.BalanceContract.DelegateResourceContract; import org.tron.protos.contract.BalanceContract.FreezeBalanceContract; import org.tron.protos.contract.BalanceContract.TransferContract; +import org.tron.protos.contract.BalanceContract.UnDelegateResourceContract; import org.tron.protos.contract.BalanceContract.UnfreezeBalanceContract; import org.tron.protos.contract.ExchangeContract.ExchangeInjectContract; import org.tron.protos.contract.ExchangeContract.ExchangeTransactionContract; @@ -114,7 +116,7 @@ public static byte[] getToAddress(Transaction transaction) { if (!toAddressList.isEmpty()) { return toAddressList.get(0).toByteArray(); } else { - return null; + return new byte[0]; } } @@ -158,6 +160,20 @@ public static List getTo(Transaction transaction) { list.add(receiverAddress); } break; + case DelegateResourceContract: + receiverAddress = contractParameter.unpack(DelegateResourceContract.class) + .getReceiverAddress(); + if (!receiverAddress.isEmpty()) { + list.add(receiverAddress); + } + break; + case UnDelegateResourceContract: + receiverAddress = contractParameter.unpack(UnDelegateResourceContract.class) + .getReceiverAddress(); + if (!receiverAddress.isEmpty()) { + list.add(receiverAddress); + } + break; case TriggerSmartContract: list.add(contractParameter.unpack(TriggerSmartContract.class).getContractAddress()); break; @@ -205,7 +221,7 @@ public static long getTransactionAmount(Transaction.Contract contract, String ha amount = getAmountFromTransactionInfo(hash, contract.getType(), transactionInfo); break; default: - amount = getTransactionAmount(contract, hash, 0, null, wallet); + amount = getTransactionAmount(contract, hash, null, wallet); break; } } catch (Exception e) { @@ -217,7 +233,7 @@ public static long getTransactionAmount(Transaction.Contract contract, String ha } public static long getTransactionAmount(Transaction.Contract contract, String hash, - long blockNum, TransactionInfo transactionInfo, Wallet wallet) { + TransactionInfo transactionInfo, Wallet wallet) { long amount = 0; try { Any contractParameter = contract.getParameter(); diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java b/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java index 5dd46d71235..389c58505cd 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java @@ -137,8 +137,8 @@ public TransactionResult(BlockCapsule blockCapsule, int index, Protocol.Transact public TransactionResult(Transaction tx, Wallet wallet) { TransactionCapsule capsule = new TransactionCapsule(tx); - byte[] txid = capsule.getTransactionId().getBytes(); - hash = ByteArray.toJsonHex(txid); + byte[] txId = capsule.getTransactionId().getBytes(); + hash = ByteArray.toJsonHex(txId); nonce = ByteArray.toJsonHex(new byte[8]); // no value blockHash = "0x"; blockNumber = "0x"; diff --git a/framework/src/main/java/org/tron/program/Version.java b/framework/src/main/java/org/tron/program/Version.java index 4296f5daf1a..93ee7a52818 100644 --- a/framework/src/main/java/org/tron/program/Version.java +++ b/framework/src/main/java/org/tron/program/Version.java @@ -4,7 +4,7 @@ public class Version { public static final String VERSION_NAME = "GreatVoyage-v4.5.1-125-ga9809b5bb"; public static final String VERSION_CODE = "17071"; - private static final String VERSION = "4.5.2"; + private static final String VERSION = "4.6.0"; public static String getVersion() { return VERSION; diff --git a/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java index a5341c22c3c..de6a426f1ef 100644 --- a/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ClearABIContractActuatorTest.java @@ -26,7 +26,6 @@ import org.tron.core.db.Manager; import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; -import org.tron.core.vm.config.VMConfig; import org.tron.protos.Protocol; import org.tron.protos.contract.AssetIssueContractOuterClass; import org.tron.protos.contract.SmartContractOuterClass.ClearABIContract; @@ -68,8 +67,8 @@ public class ClearABIContractActuatorTest { */ @BeforeClass public static void init() { - VMConfig.initAllowTvmConstantinople(1); dbManager = context.getBean(Manager.class); + dbManager.getDynamicPropertiesStore().saveAllowTvmConstantinople(1); } /** diff --git a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java index b2e84d39095..3494ddb0624 100644 --- a/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/FreezeBalanceActuatorTest.java @@ -6,6 +6,7 @@ import com.google.protobuf.Any; import com.google.protobuf.ByteString; import java.io.File; +import java.util.List; import lombok.extern.slf4j.Slf4j; import org.junit.AfterClass; import org.junit.Assert; @@ -13,8 +14,10 @@ import org.junit.BeforeClass; import org.junit.Test; import org.tron.common.application.TronApplicationContext; +import org.tron.common.crypto.ECKey; import org.tron.common.utils.ByteArray; import org.tron.common.utils.FileUtil; +import org.tron.common.utils.Utils; import org.tron.core.ChainBaseManager; import org.tron.core.Constant; import org.tron.core.Wallet; @@ -313,6 +316,70 @@ public void testFreezeDelegatedBalanceForBandwidth() { } } + @Test + public void testMultiFreezeDelegatedBalanceForBandwidth() { + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + dbManager.getDynamicPropertiesStore().saveAllowDelegateOptimization(1L); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(10000L); + long frozenBalance = 1_000_000_000L; + long duration = 3; + final int RECEIVE_COUNT = 100; + String[] RECEIVE_ADDRESSES = new String[RECEIVE_COUNT + 1]; + + DelegatedResourceAccountIndexCapsule ownerIndexCapsule = + new DelegatedResourceAccountIndexCapsule( + ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + for (int i = 0; i < RECEIVE_COUNT + 1; i++) { + ECKey ecKey = new ECKey(Utils.getRandom()); + RECEIVE_ADDRESSES[i] = ByteArray.toHexString(ecKey.getAddress()); + if (i != RECEIVE_COUNT) { + ownerIndexCapsule.addToAccount(ByteString.copyFrom(ecKey.getAddress())); + } + } + dbManager.getDelegatedResourceAccountIndexStore().put( + ByteArray.fromHexString(OWNER_ADDRESS), ownerIndexCapsule); + AccountCapsule receiverCapsule = + new AccountCapsule( + ByteString.copyFromUtf8("receiver"), + ByteString.copyFrom(ByteArray.fromHexString(RECEIVE_ADDRESSES[RECEIVE_COUNT])), + AccountType.Normal, + initBalance); + dbManager.getAccountStore().put(receiverCapsule.getAddress().toByteArray(), receiverCapsule); + + TransactionResultCapsule ret = new TransactionResultCapsule(); + FreezeBalanceActuator actuator = new FreezeBalanceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForBandwidth( + OWNER_ADDRESS, RECEIVE_ADDRESSES[RECEIVE_COUNT], frozenBalance, duration)); + try { + ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().getIndex(ByteArray.fromHexString(OWNER_ADDRESS)); + List beforeList = ownerIndexCapsule.getToAccountsList(); + actuator.validate(); + actuator.execute(ret); + + //check DelegatedResourceAccountIndex convert + ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertNull(ownerIndexCapsule); + + ownerIndexCapsule = dbManager + .getDelegatedResourceAccountIndexStore().getIndex(ByteArray.fromHexString(OWNER_ADDRESS)); + Assert.assertEquals(0, ownerIndexCapsule.getFromAccountsList().size()); + List tmpList = ownerIndexCapsule.getToAccountsList(); + Assert.assertEquals(RECEIVE_COUNT + 1, ownerIndexCapsule.getToAccountsList().size()); + for (int i = 0; i < RECEIVE_COUNT; i++) { + Assert.assertEquals(beforeList.get(i), tmpList.get(i)); + } + Assert.assertEquals(RECEIVE_ADDRESSES[RECEIVE_COUNT], + ByteArray.toHexString(tmpList.get(RECEIVE_COUNT).toByteArray())); + } catch (ContractValidateException | ContractExeException e) { + Assert.fail("con not reach here"); + } + dbManager.getDynamicPropertiesStore().saveAllowDelegateOptimization(0L); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(10000L); + } + @Test public void testFreezeDelegatedBalanceForCpuSameNameTokenActive() { dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java index 9dd1b026d08..de24f581c04 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceActuatorTest.java @@ -140,6 +140,7 @@ private Any getContract(String ownerAddress, ResourceCode resourceCode) { @Test public void testUnfreezeBalanceForBandwidth() { long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveAllowNewReward(0); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); AccountCapsule accountCapsule = dbManager.getAccountStore() @@ -178,10 +179,98 @@ public void testUnfreezeBalanceForBandwidth() { } } + @Test + public void testUnfreezeSelfAndOthersForBandwidth() { + dbManager.getDynamicPropertiesStore().saveAllowDelegateResource(1); + dbManager.getDynamicPropertiesStore().saveAllowNewReward(1); + long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); + + AccountCapsule owner = dbManager.getAccountStore().get(ByteArray.fromHexString(OWNER_ADDRESS)); + owner.setDelegatedFrozenBalanceForBandwidth(150_0000L); + owner.setFrozen(150_0000L, now); + dbManager.getDynamicPropertiesStore().saveTotalNetWeight(2L); + long beforeWeight = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); + Assert.assertEquals(2, beforeWeight); + + AccountCapsule receiver = dbManager.getAccountStore() + .get(ByteArray.fromHexString(RECEIVER_ADDRESS)); + receiver.setAcquiredDelegatedFrozenBalanceForBandwidth(150_0000L); + + dbManager.getAccountStore().put(owner.createDbKey(), owner); + dbManager.getAccountStore().put(receiver.createDbKey(), receiver); + + //init DelegatedResourceCapsule + DelegatedResourceCapsule delegatedResourceCapsule = new DelegatedResourceCapsule( + owner.getAddress(), receiver.getAddress()); + delegatedResourceCapsule.setFrozenBalanceForBandwidth(150_0000L, now - 100L); + dbManager.getDelegatedResourceStore().put(DelegatedResourceCapsule + .createDbKey(ByteArray.fromHexString(OWNER_ADDRESS), + ByteArray.fromHexString(RECEIVER_ADDRESS)), delegatedResourceCapsule); + + //init DelegatedResourceAccountIndex + { + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndex = + new DelegatedResourceAccountIndexCapsule( + owner.getAddress()); + delegatedResourceAccountIndex + .addToAccount(ByteString.copyFrom(ByteArray.fromHexString(RECEIVER_ADDRESS))); + dbManager.getDelegatedResourceAccountIndexStore() + .put(ByteArray.fromHexString(OWNER_ADDRESS), delegatedResourceAccountIndex); + } + + { + DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndex = + new DelegatedResourceAccountIndexCapsule( + receiver.getAddress()); + delegatedResourceAccountIndex + .addFromAccount(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS))); + dbManager.getDelegatedResourceAccountIndexStore() + .put(ByteArray.fromHexString(RECEIVER_ADDRESS), delegatedResourceAccountIndex); + } + + + + UnfreezeBalanceActuator actuator1 = new UnfreezeBalanceActuator(); + actuator1.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getContractForBandwidth(OWNER_ADDRESS)); + TransactionResultCapsule ret1 = new TransactionResultCapsule(); + try { + actuator1.validate(); + actuator1.execute(ret1); + long afterWeight1 = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); + Assert.assertEquals(1, afterWeight1); + Assert.assertEquals(ret1.getInstance().getRet(), code.SUCESS); + } catch (ContractValidateException e) { + logger.error("ContractValidateException", e); + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + + UnfreezeBalanceActuator actuator = new UnfreezeBalanceActuator(); + actuator.setChainBaseManager(dbManager.getChainBaseManager()) + .setAny(getDelegatedContractForBandwidth(OWNER_ADDRESS, RECEIVER_ADDRESS)); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + long afterWeight = dbManager.getDynamicPropertiesStore().getTotalNetWeight(); + Assert.assertEquals(0, afterWeight); + Assert.assertEquals(ret.getInstance().getRet(), code.SUCESS); + } catch (ContractValidateException e) { + Assert.assertFalse(e instanceof ContractValidateException); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + dbManager.getDynamicPropertiesStore().saveAllowNewReward(0); + } @Test public void testUnfreezeBalanceForEnergy() { long now = System.currentTimeMillis(); + dbManager.getDynamicPropertiesStore().saveAllowNewReward(0); dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderTimestamp(now); AccountCapsule accountCapsule = dbManager.getAccountStore() @@ -304,6 +393,7 @@ public void testUnfreezeDelegatedBalanceForBandwidth() { } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); } + } @Test diff --git a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java index 07d7f3a6def..d1aa0820c6e 100644 --- a/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UnfreezeBalanceV2ActuatorTest.java @@ -43,7 +43,6 @@ public class UnfreezeBalanceV2ActuatorTest { private static final String OWNER_ACCOUNT_INVALID; private static final long initBalance = 10_000_000_000L; private static final long frozenBalance = 1_000_000_000L; - private static final long smallTatalResource = 100L; private static Manager dbManager; private static TronApplicationContext context; @@ -541,7 +540,7 @@ public void testUnfreezeBalanceForTronPowerWithOldTronPowerAfterNewResourceModel try { actuator.validate(); //Assert.fail(); - } catch (ContractValidateException e) { + } catch (Exception e) { Assert.assertTrue(e instanceof ContractValidateException); } } @@ -566,15 +565,15 @@ public void testUnfreezeBalanceCheckExistFreezedBalance() { actuator.setChainBaseManager(dbManager.getChainBaseManager()) .setAny(getContractForBandwidthV2(OWNER_ADDRESS, unfreezeBalance)); - boolean bret1 = actuator.checkExistFreezedBalance( + boolean bret1 = actuator.checkExistFrozenBalance( accountCapsule, ResourceCode.BANDWIDTH); - Assert.assertTrue(true == bret1); - boolean bret2 = actuator.checkExistFreezedBalance( + Assert.assertTrue(bret1); + boolean bret2 = actuator.checkExistFrozenBalance( accountCapsule, ResourceCode.ENERGY); - Assert.assertTrue(true == bret2); - boolean bret3 = actuator.checkExistFreezedBalance( + Assert.assertTrue(bret2); + boolean bret3 = actuator.checkExistFrozenBalance( accountCapsule, ResourceCode.TRON_POWER); - Assert.assertTrue(true == bret3); + Assert.assertTrue(bret3); } @@ -603,7 +602,7 @@ public void testUnfreezeBalanceCheckUnfreezeBalance() { boolean bret1 = actuator.checkUnfreezeBalance( accountCapsule, unfreezeBalanceV2Contract, ResourceCode.BANDWIDTH ); - Assert.assertTrue(true == bret1); + Assert.assertTrue(bret1); } @@ -633,7 +632,7 @@ public void testUnfreezeBalanceGetFreezeType() { ResourceCode freezeType = unfreezeBalanceV2Contract.getResource(); - Assert.assertTrue(ResourceCode.TRON_POWER.equals(freezeType)); + Assert.assertEquals(ResourceCode.TRON_POWER, freezeType); } @Test @@ -695,7 +694,7 @@ public void testUnfreezeBalanceUpdateAccountFrozenInfo() { ResourceCode.BANDWIDTH, accountCapsule, unfreezeBalance ); - Assert.assertTrue(accountCapsule.getAllFrozenBalanceForBandwidth() == 1); + Assert.assertEquals(1, accountCapsule.getAllFrozenBalanceForBandwidth()); } diff --git a/framework/src/test/java/org/tron/core/actuator/UpdateEnergyLimitContractActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/UpdateEnergyLimitContractActuatorTest.java index 7dfcbee8824..9a662e15834 100644 --- a/framework/src/test/java/org/tron/core/actuator/UpdateEnergyLimitContractActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/UpdateEnergyLimitContractActuatorTest.java @@ -30,7 +30,6 @@ import org.tron.core.exception.ContractExeException; import org.tron.core.exception.ContractValidateException; import org.tron.core.exception.TronException; -import org.tron.core.vm.config.VMConfig; import org.tron.protos.Protocol; import org.tron.protos.contract.AssetIssueContractOuterClass; import org.tron.protos.contract.SmartContractOuterClass.SmartContract; @@ -78,7 +77,7 @@ public static void init() { Arrays.fill(stats, (byte) 1); dbManager.getDynamicPropertiesStore() .statsByVersion(ForkBlockVersionConsts.ENERGY_LIMIT, stats); - VMConfig.initVmHardFork(true); + CommonParameter.getInstance().setBlockNumForEnergyLimit(0); } /** @@ -93,7 +92,6 @@ public static void destroy() { } else { logger.info("Release resources failure."); } - CommonParameter.setENERGY_LIMIT_HARD_FORK(false); } /** diff --git a/protocol/src/main/protos/core/Tron.proto b/protocol/src/main/protos/core/Tron.proto index 632dcc157ce..780b5b71e84 100644 --- a/protocol/src/main/protos/core/Tron.proto +++ b/protocol/src/main/protos/core/Tron.proto @@ -474,7 +474,7 @@ message TransactionInfo { repeated MarketOrderDetail orderDetails = 26; int64 packingFee = 27; - int64 withdraw_Expire_amount = 28; + int64 withdraw_expire_amount = 28; } message TransactionRet { @@ -642,6 +642,7 @@ message DelegatedResourceAccountIndex { bytes account = 1; repeated bytes fromAccounts = 2; repeated bytes toAccounts = 3; + int64 timestamp = 4; } message NodeInfo {