Skip to content

Commit

Permalink
feat(freezeV2): optimize usage merging
Browse files Browse the repository at this point in the history
Signed-off-by: liuxincheng <[email protected]>
  • Loading branch information
lxcmyf committed Oct 18, 2022
1 parent 9a4be62 commit 5f9307b
Show file tree
Hide file tree
Showing 18 changed files with 174 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public boolean validate() throws ContractValidateException {
throw new ContractValidateException("No support for resource delegate");
}

if (dynamicStore.getUnfreezeDelayDays() == 0) {
if (!dynamicStore.supportUnfreezeDelay()) {
throw new ContractValidateException("Not support Delegate resource transaction,"
+ " need to be opened by the committee");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ public boolean validate() throws ContractValidateException {

}

if (dynamicStore.getUnfreezeDelayDays() > 0) {
if (dynamicStore.supportUnfreezeDelay()) {
throw new ContractValidateException(
"freeze v2 is open, old freeze is closed");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public boolean validate() throws ContractValidateException {
.getClass() + "]");
}

if (dynamicStore.getUnfreezeDelayDays() == 0) {
if (!dynamicStore.supportUnfreezeDelay()) {
throw new ContractValidateException("Not support FreezeV2 transaction,"
+ " need to be opened by the committee");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import static org.tron.core.actuator.ActuatorConstant.ACCOUNT_EXCEPTION_STR;
import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION;
import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH;
import static org.tron.protos.contract.Common.ResourceCode.ENERGY;

import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
Expand Down Expand Up @@ -135,10 +137,16 @@ public boolean execute(Object result) throws ContractExeException {
ownerCapsule.addFrozenBalanceForBandwidthV2(unDelegateBalance);

BandwidthProcessor processor = new BandwidthProcessor(chainBaseManager);
processor.updateUsage(ownerCapsule);
long newNetUsage = ownerCapsule.getNetUsage() + transferUsage;
ownerCapsule.setNetUsage(newNetUsage);
ownerCapsule.setLatestConsumeTime(chainBaseManager.getHeadSlot());

long now = chainBaseManager.getHeadSlot();
if (Objects.nonNull(receiverCapsule)) {
ownerCapsule.setNetUsage(processor.increase(ownerCapsule, receiverCapsule,
transferUsage, BANDWIDTH, now));
} else {
long newNetUsage = ownerCapsule.getNetUsage() + transferUsage;
ownerCapsule.setNetUsage(newNetUsage);
}
ownerCapsule.setLatestConsumeTime(now);
}
break;
case ENERGY: {
Expand All @@ -148,10 +156,16 @@ public boolean execute(Object result) throws ContractExeException {
ownerCapsule.addFrozenBalanceForEnergyV2(unDelegateBalance);

EnergyProcessor processor = new EnergyProcessor(dynamicStore, accountStore);
processor.updateUsage(ownerCapsule);
long newEnergyUsage = ownerCapsule.getEnergyUsage() + transferUsage;
ownerCapsule.setEnergyUsage(newEnergyUsage);
ownerCapsule.setLatestConsumeTimeForEnergy(chainBaseManager.getHeadSlot());

long now = chainBaseManager.getHeadSlot();
if (Objects.nonNull(receiverCapsule)) {
ownerCapsule.setEnergyUsage(processor.increase(ownerCapsule, receiverCapsule,
transferUsage, ENERGY, now));
} else {
long newEnergyUsage = ownerCapsule.getEnergyUsage() + transferUsage;
ownerCapsule.setEnergyUsage(newEnergyUsage);
}
ownerCapsule.setLatestConsumeTimeForEnergy(now);
}
break;
default:
Expand Down Expand Up @@ -215,7 +229,7 @@ public boolean validate() throws ContractValidateException {
throw new ContractValidateException("No support for resource delegate");
}

if (dynamicStore.getUnfreezeDelayDays() == 0) {
if (!dynamicStore.supportUnfreezeDelay()) {
throw new ContractValidateException("Not support Delegate resource transaction,"
+ " need to be opened by the committee");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public boolean validate() throws ContractValidateException {
.getClass() + "]");
}

if (dynamicStore.getUnfreezeDelayDays() == 0) {
if (!dynamicStore.supportUnfreezeDelay()) {
throw new ContractValidateException("Not support UnfreezeV2 transaction,"
+ " need to be opened by the committee");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public boolean validate() throws ContractValidateException {
.getClass() + "]");
}

if (dynamicStore.getUnfreezeDelayDays() == 0) {
if (!dynamicStore.supportUnfreezeDelay()) {
throw new ContractValidateException("Not support WithdrawExpireUnfreeze transaction,"
+ " need to be opened by the committee");
}
Expand Down
37 changes: 37 additions & 0 deletions chainbase/src/main/java/org/tron/core/capsule/AccountCapsule.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,12 @@
import java.util.Map;
import java.util.Objects;

import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL;
import static org.tron.core.config.Parameter.ChainConstant.WINDOW_SIZE_MS;
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 static org.tron.protos.contract.Common.ResourceCode;

@Slf4j(topic = "capsule")
public class AccountCapsule implements ProtoCapsule<Account>, Comparable<AccountCapsule> {
Expand Down Expand Up @@ -969,6 +972,14 @@ public long getNetUsage() {
return this.account.getNetUsage();
}

public long getUsage(ResourceCode resourceCode) {
if (resourceCode == BANDWIDTH) {
return this.account.getNetUsage();
} else {
return this.account.getAccountResource().getEnergyUsage();
}
}

public void setNetUsage(long netUsage) {
this.account = this.account.toBuilder()
.setNetUsage(netUsage).build();
Expand Down Expand Up @@ -1262,4 +1273,30 @@ public void clearUnfrozenV2() {
this.account = this.account.toBuilder().clearUnfrozenV2().build();
}

public void setNewWindowSize(ResourceCode resourceCode, long newWindowSize) {
if (resourceCode == BANDWIDTH) {
this.account = this.account.toBuilder().setNetWindowSize(newWindowSize).build();
} else {
this.account = this.account.toBuilder().setAccountResource(this.account.getAccountResource()
.toBuilder().setEnergyWindowSize(newWindowSize).build()).build();
}
}

public long getWindowSize(ResourceCode resourceCode) {
long windowSize;
if (resourceCode == BANDWIDTH) {
windowSize = this.account.getNetWindowSize();
} else {
windowSize = this.account.getAccountResource().getEnergyWindowSize();
}
return windowSize == 0 ? WINDOW_SIZE_MS / BLOCK_PRODUCED_INTERVAL : windowSize;
}

public long getLastConsumeTime(ResourceCode resourceCode) {
if (resourceCode == BANDWIDTH) {
return this.account.getLatestConsumeTime();
} else {
return this.account.getAccountResource().getLatestConsumeTimeForEnergy();
}
}
}
20 changes: 13 additions & 7 deletions chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract;
import org.tron.protos.contract.BalanceContract.TransferContract;

import static org.tron.protos.contract.Common.ResourceCode.BANDWIDTH;

@Slf4j(topic = "DB")
public class BandwidthProcessor extends ResourceProcessor {

Expand All @@ -42,7 +44,8 @@ public void updateUsage(AccountCapsule accountCapsule) {
private void updateUsage(AccountCapsule accountCapsule, long now) {
long oldNetUsage = accountCapsule.getNetUsage();
long latestConsumeTime = accountCapsule.getLatestConsumeTime();
accountCapsule.setNetUsage(increase(oldNetUsage, 0, latestConsumeTime, now));
accountCapsule.setNetUsage(increase(accountCapsule, BANDWIDTH,
oldNetUsage, 0, latestConsumeTime, now));
long oldFreeNetUsage = accountCapsule.getFreeNetUsage();
long latestConsumeFreeTime = accountCapsule.getLatestConsumeFreeTime();
accountCapsule.setFreeNetUsage(increase(oldFreeNetUsage, 0, latestConsumeFreeTime, now));
Expand Down Expand Up @@ -183,13 +186,14 @@ public boolean consumeBandwidthForCreateNewAccount(AccountCapsule accountCapsule
long netUsage = accountCapsule.getNetUsage();
long latestConsumeTime = accountCapsule.getLatestConsumeTime();
long netLimit = calculateGlobalNetLimit(accountCapsule);
long newNetUsage = increase(netUsage, 0, latestConsumeTime, now);
long newNetUsage = increase(accountCapsule, BANDWIDTH, netUsage, 0, latestConsumeTime, now);

long netCost = bytes * createNewAccountBandwidthRatio;
if (netCost <= (netLimit - newNetUsage)) {
latestConsumeTime = now;
long latestOperationTime = chainBaseManager.getHeadBlockTimeStamp();
newNetUsage = increase(newNetUsage, netCost, latestConsumeTime, now);
newNetUsage = increase(accountCapsule, BANDWIDTH,
newNetUsage, netCost, latestConsumeTime, now);
accountCapsule.setLatestConsumeTime(latestConsumeTime);
accountCapsule.setLatestOperationTime(latestOperationTime);
accountCapsule.setNetUsage(newNetUsage);
Expand Down Expand Up @@ -313,7 +317,8 @@ private boolean useAssetAccountNet(Contract contract, AccountCapsule accountCaps
long latestConsumeTime = issuerAccountCapsule.getLatestConsumeTime();
long issuerNetLimit = calculateGlobalNetLimit(issuerAccountCapsule);

long newIssuerNetUsage = increase(issuerNetUsage, 0, latestConsumeTime, now);
long newIssuerNetUsage = increase(issuerAccountCapsule, BANDWIDTH,
issuerNetUsage, 0, latestConsumeTime, now);

if (bytes > (issuerNetLimit - newIssuerNetUsage)) {
logger.debug("The " + tokenID + " issuer's bandwidth is not enough");
Expand All @@ -325,7 +330,8 @@ private boolean useAssetAccountNet(Contract contract, AccountCapsule accountCaps
publicLatestFreeNetTime = now;
long latestOperationTime = chainBaseManager.getHeadBlockTimeStamp();

newIssuerNetUsage = increase(newIssuerNetUsage, bytes, latestConsumeTime, now);
newIssuerNetUsage = increase(issuerAccountCapsule, BANDWIDTH,
newIssuerNetUsage, bytes, latestConsumeTime, now);
newFreeAssetNetUsage = increase(newFreeAssetNetUsage,
bytes, latestAssetOperationTime, now);
newPublicFreeAssetNetUsage = increase(newPublicFreeAssetNetUsage, bytes,
Expand Down Expand Up @@ -390,7 +396,7 @@ private boolean useAccountNet(AccountCapsule accountCapsule, long bytes, long no
long latestConsumeTime = accountCapsule.getLatestConsumeTime();
long netLimit = calculateGlobalNetLimit(accountCapsule);

long newNetUsage = increase(netUsage, 0, latestConsumeTime, now);
long newNetUsage = increase(accountCapsule, BANDWIDTH, netUsage, 0, latestConsumeTime, now);

if (bytes > (netLimit - newNetUsage)) {
logger.debug("net usage is running out, now use free net usage");
Expand All @@ -399,7 +405,7 @@ private boolean useAccountNet(AccountCapsule accountCapsule, long bytes, long no

latestConsumeTime = now;
long latestOperationTime = chainBaseManager.getHeadBlockTimeStamp();
newNetUsage = increase(newNetUsage, bytes, latestConsumeTime, now);
newNetUsage = increase(accountCapsule, BANDWIDTH, newNetUsage, bytes, latestConsumeTime, now);
accountCapsule.setNetUsage(newNetUsage);
accountCapsule.setLatestOperationTime(latestOperationTime);
accountCapsule.setLatestConsumeTime(latestConsumeTime);
Expand Down
12 changes: 8 additions & 4 deletions chainbase/src/main/java/org/tron/core/db/EnergyProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import org.tron.core.store.DynamicPropertiesStore;
import org.tron.protos.Protocol.Account.AccountResource;

import static org.tron.protos.contract.Common.ResourceCode.ENERGY;

@Slf4j(topic = "DB")
public class EnergyProcessor extends ResourceProcessor {

Expand All @@ -41,7 +43,8 @@ private void updateUsage(AccountCapsule accountCapsule, long now) {
long oldEnergyUsage = accountResource.getEnergyUsage();
long latestConsumeTime = accountResource.getLatestConsumeTimeForEnergy();

accountCapsule.setEnergyUsage(increase(oldEnergyUsage, 0, latestConsumeTime, now));
accountCapsule.setEnergyUsage(increase(accountCapsule, ENERGY,
oldEnergyUsage, 0, latestConsumeTime, now));
}

public void updateTotalEnergyAverageUsage() {
Expand Down Expand Up @@ -101,7 +104,7 @@ public boolean useEnergy(AccountCapsule accountCapsule, long energy, long now) {
long latestConsumeTime = accountCapsule.getAccountResource().getLatestConsumeTimeForEnergy();
long energyLimit = calculateGlobalEnergyLimit(accountCapsule);

long newEnergyUsage = increase(energyUsage, 0, latestConsumeTime, now);
long newEnergyUsage = increase(accountCapsule, ENERGY, energyUsage, 0, latestConsumeTime, now);

if (energy > (energyLimit - newEnergyUsage)
&& dynamicPropertiesStore.getAllowTvmFreeze() == 0) {
Expand All @@ -110,7 +113,8 @@ public boolean useEnergy(AccountCapsule accountCapsule, long energy, long now) {

latestConsumeTime = now;
long latestOperationTime = dynamicPropertiesStore.getLatestBlockHeaderTimestamp();
newEnergyUsage = increase(newEnergyUsage, energy, latestConsumeTime, now);
newEnergyUsage = increase(accountCapsule, ENERGY,
newEnergyUsage, energy, latestConsumeTime, now);
accountCapsule.setEnergyUsage(newEnergyUsage);
accountCapsule.setLatestOperationTime(latestOperationTime);
accountCapsule.setLatestConsumeTimeForEnergy(latestConsumeTime);
Expand Down Expand Up @@ -146,7 +150,7 @@ public long getAccountLeftEnergyFromFreeze(AccountCapsule accountCapsule) {
long latestConsumeTime = accountCapsule.getAccountResource().getLatestConsumeTimeForEnergy();
long energyLimit = calculateGlobalEnergyLimit(accountCapsule);

long newEnergyUsage = increase(energyUsage, 0, latestConsumeTime, now);
long newEnergyUsage = increase(accountCapsule, ENERGY, energyUsage, 0, latestConsumeTime, now);

return max(energyLimit - newEnergyUsage, 0); // us
}
Expand Down
65 changes: 65 additions & 0 deletions chainbase/src/main/java/org/tron/core/db/ResourceProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.tron.core.exception.TooBigTransactionResultException;
import org.tron.core.store.AccountStore;
import org.tron.core.store.DynamicPropertiesStore;
import org.tron.protos.contract.Common.ResourceCode;

abstract class ResourceProcessor {

Expand Down Expand Up @@ -59,6 +60,70 @@ protected long increase(long lastUsage, long usage, long lastTime, long now, lon
return getUsage(averageLastUsage, windowSize);
}

protected 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;
averageLastUsage = Math.round(averageLastUsage * decay);
} else {
averageLastUsage = 0;
}
}
/* new logic */
long newUsage = getUsage(averageLastUsage, oldWindowSize) +
getUsage(averageUsage, this.windowSize);
if (dynamicPropertiesStore.supportUnfreezeDelay()) {
long remainUsage = getUsage(averageLastUsage, oldWindowSize);
if (remainUsage == 0) {
accountCapsule.setNewWindowSize(resourceCode, this.windowSize);
return newUsage;
}
long remainWindowSize = oldWindowSize - (now - lastTime);
long newWindowSize = (remainWindowSize * remainUsage + this.windowSize * usage)
/ newUsage;
accountCapsule.setNewWindowSize(resourceCode, newWindowSize);
}
return newUsage;
}

public long increase(AccountCapsule owner, AccountCapsule receiver,
long transferUsage, ResourceCode resourceCode, long now) {
long lastOwnerTime = owner.getLastConsumeTime(resourceCode);
long lastReceiverTime = receiver.getLastConsumeTime(resourceCode);
long ownerWindowSize = owner.getWindowSize(resourceCode);
long receiverWindowSize = receiver.getWindowSize(resourceCode);
long ownerUsage = owner.getUsage(resourceCode);
// Update itself first
ownerUsage = increase(owner, resourceCode, ownerUsage, 0, lastOwnerTime, now);
owner.setEnergyUsage(ownerUsage);

long remainOwnerWindowSize = ownerWindowSize - (now - lastOwnerTime);
long remainReceiverWindowSize = receiverWindowSize - (now - lastReceiverTime);
remainOwnerWindowSize = remainOwnerWindowSize < 0 ? 0 : remainOwnerWindowSize;
remainReceiverWindowSize = remainReceiverWindowSize < 0 ? 0 : remainReceiverWindowSize;

long newOwnerUsage = ownerUsage + transferUsage;
// mean ownerUsage == 0 and transferUsage == 0
if (newOwnerUsage == 0) {
owner.setNewWindowSize(resourceCode, this.windowSize);
return newOwnerUsage;
}
// calculate new windowSize
long newOwnerWindowSize = (ownerUsage * remainOwnerWindowSize +
transferUsage * remainReceiverWindowSize)
/ newOwnerUsage;
owner.setNewWindowSize(resourceCode, newOwnerWindowSize);
return newOwnerUsage;
}

private long divideCeil(long numerator, long denominator) {
return (numerator / denominator) + ((numerator % denominator) > 0 ? 1 : 0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2533,6 +2533,10 @@ public long getUnfreezeDelayDays() {
.orElseThrow(() -> new IllegalArgumentException("not found UNFREEZE_DELAY_DAYS"));
}

public boolean supportUnfreezeDelay() {
return getUnfreezeDelayDays() > 0;
}

public void saveUnfreezeDelayDays(long value) {
this.put(UNFREEZE_DELAY_DAYS, new BytesCapsule(ByteArray.fromLong(value)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,9 @@ private TVMTestResult freezeForOther(byte[] callerAddr,
if (oldReceiver != null) {
newReceiver.setBalance(oldReceiver.getBalance());
oldReceiver.setEnergyUsage(0);
oldReceiver.setEnergyWindowSize(28800);
newReceiver.setEnergyUsage(0);
newReceiver.setEnergyWindowSize(28800);
if (res == 0) {
oldReceiver.setAcquiredDelegatedFrozenBalanceForBandwidth(0);
newReceiver.setAcquiredDelegatedFrozenBalanceForBandwidth(0);
Expand Down Expand Up @@ -912,7 +914,9 @@ private TVMTestResult unfreezeForOther(byte[] callerAddr,
|| acquiredBalance - newAcquiredBalance == delegatedFrozenBalance);
newReceiver.setBalance(oldReceiver.getBalance());
newReceiver.setEnergyUsage(0);
newReceiver.setEnergyWindowSize(28800);
oldReceiver.setEnergyUsage(0);
oldReceiver.setEnergyWindowSize(28800);
if (res == 0) {
oldReceiver.setAcquiredDelegatedFrozenBalanceForBandwidth(0);
newReceiver.setAcquiredDelegatedFrozenBalanceForBandwidth(0);
Expand Down
Loading

0 comments on commit 5f9307b

Please sign in to comment.