Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(freezeV2): optimize delegate resource lock period #5255

Merged
merged 12 commits into from
Jun 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import static org.tron.core.actuator.ActuatorConstant.NOT_EXIST_STR;
import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_PERIOD;
import static org.tron.core.config.Parameter.ChainConstant.MAX_BLOCK_NUM_DELEGATE_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 com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
Expand Down Expand Up @@ -46,8 +50,10 @@ public boolean execute(Object result) throws ContractExeException {
long fee = calcFee();
final DelegateResourceContract delegateResourceContract;
AccountStore accountStore = chainBaseManager.getAccountStore();
byte[] ownerAddress;
try {
delegateResourceContract = any.unpack(DelegateResourceContract.class);
delegateResourceContract = this.any.unpack(DelegateResourceContract.class);
ownerAddress = getOwnerAddress().toByteArray();
} catch (InvalidProtocolBufferException e) {
logger.debug(e.getMessage(), e);
ret.setStatus(fee, code.FAILED);
Expand All @@ -59,21 +65,21 @@ public boolean execute(Object result) throws ContractExeException {

long delegateBalance = delegateResourceContract.getBalance();
boolean lock = delegateResourceContract.getLock();
byte[] ownerAddress = delegateResourceContract.getOwnerAddress().toByteArray();
long lockPeriod = delegateResourceContract.getLockPeriod();
byte[] receiverAddress = delegateResourceContract.getReceiverAddress().toByteArray();

// delegate resource to receiver
switch (delegateResourceContract.getResource()) {
case BANDWIDTH:
delegateResource(ownerAddress, receiverAddress, true,
delegateBalance, lock);
delegateBalance, lock, lockPeriod);

ownerCapsule.addDelegatedFrozenV2BalanceForBandwidth(delegateBalance);
ownerCapsule.addFrozenBalanceForBandwidthV2(-delegateBalance);
break;
case ENERGY:
delegateResource(ownerAddress, receiverAddress, false,
delegateBalance, lock);
delegateBalance, lock, lockPeriod);

ownerCapsule.addDelegatedFrozenV2BalanceForEnergy(delegateBalance);
ownerCapsule.addFrozenBalanceForEnergyV2(-delegateBalance);
Expand All @@ -100,6 +106,7 @@ public boolean validate() throws ContractValidateException {
}
AccountStore accountStore = chainBaseManager.getAccountStore();
DynamicPropertiesStore dynamicStore = chainBaseManager.getDynamicPropertiesStore();
DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore();
if (!any.is(DelegateResourceContract.class)) {
throw new ContractValidateException(
"contract type error,expected type [DelegateResourceContract],real type["
Expand All @@ -116,13 +123,14 @@ public boolean validate() throws ContractValidateException {
}

final DelegateResourceContract delegateResourceContract;
byte[] ownerAddress;
try {
delegateResourceContract = this.any.unpack(DelegateResourceContract.class);
ownerAddress = getOwnerAddress().toByteArray();
} catch (InvalidProtocolBufferException e) {
logger.debug(e.getMessage(), e);
throw new ContractValidateException(e.getMessage());
}
byte[] ownerAddress = delegateResourceContract.getOwnerAddress().toByteArray();
if (!DecodeUtil.addressValid(ownerAddress)) {
throw new ContractValidateException("Invalid address");
}
Expand Down Expand Up @@ -210,6 +218,36 @@ public boolean validate() throws ContractValidateException {
+ readableOwnerAddress + NOT_EXIST_STR);
}

boolean lock = delegateResourceContract.getLock();
if (lock && dynamicStore.supportAllowOptimizeLockDelegateResource()) {
long lockPeriod = delegateResourceContract.getLockPeriod();
if (lockPeriod < 0 || lockPeriod > MAX_BLOCK_NUM_DELEGATE_PERIOD) {
throw new ContractValidateException(
"The lock period of delegate resource cannot be less than 0 and cannot exceed 1 year!");
}

byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, true);
DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore.get(key);
long now = dynamicStore.getLatestBlockHeaderTimestamp();
if (delegatedResourceCapsule != null) {
switch (delegateResourceContract.getResource()) {
case BANDWIDTH: {
validRemainTime(BANDWIDTH, lockPeriod,
delegatedResourceCapsule.getExpireTimeForBandwidth(), now);
}
break;
case ENERGY: {
validRemainTime(ENERGY, lockPeriod,
delegatedResourceCapsule.getExpireTimeForEnergy(), now);
}
break;
default:
throw new ContractValidateException(
"ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]");
}
}
}

if (receiverCapsule.getType() == AccountType.Contract) {
throw new ContractValidateException(
"Do not allow delegate resources to contract addresses");
Expand All @@ -218,6 +256,17 @@ public boolean validate() throws ContractValidateException {
return true;
}

private void validRemainTime(ResourceCode resourceCode, long lockPeriod, long expireTime,
long now) throws ContractValidateException {
long remainTime = expireTime - now;
if (lockPeriod * 3 * 1000 < remainTime) {
throw new ContractValidateException(
"The lock period for " + resourceCode.name() + " this time cannot be less than the "
+ "remaining time[" + remainTime + "s] of the last lock period for "
+ resourceCode.name() + "!");
}
}

@Override
public ByteString getOwnerAddress() throws InvalidProtocolBufferException {
return any.unpack(DelegateResourceContract.class).getOwnerAddress();
Expand All @@ -229,7 +278,7 @@ public long calcFee() {
}

private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boolean isBandwidth,
long balance, boolean lock) {
long balance, boolean lock, long lockPeriod) {
AccountStore accountStore = chainBaseManager.getAccountStore();
DynamicPropertiesStore dynamicPropertiesStore = chainBaseManager.getDynamicPropertiesStore();
DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore();
Expand All @@ -241,12 +290,15 @@ private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole
delegatedResourceStore.unLockExpireResource(ownerAddress, receiverAddress, now);

//modify DelegatedResourceStore
byte[] key;
long expireTime = 0;
if (lock) {
expireTime = now + DELEGATE_PERIOD;
if (dynamicPropertiesStore.supportAllowOptimizeLockDelegateResource()) {
expireTime = now + (lockPeriod == 0 ? DELEGATE_PERIOD : lockPeriod * 3 * 1000);
} else {
expireTime = now + DELEGATE_PERIOD;
}
}
key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, lock);
byte[] key = DelegatedResourceCapsule.createDbKeyV2(ownerAddress, receiverAddress, lock);
DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore.get(key);
if (delegatedResourceCapsule == null) {
delegatedResourceCapsule = new DelegatedResourceCapsule(ByteString.copyFrom(ownerAddress),
Expand Down
19 changes: 18 additions & 1 deletion actuator/src/main/java/org/tron/core/utils/ProposalUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,22 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore,
}
break;
}
case ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE: {
if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7_2)) {
throw new ContractValidateException(
"Bad chain parameter id [ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE]");
}
if (value != 1) {
throw new ContractValidateException(
"This value[ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE] is only allowed to be 1");
}
if (dynamicPropertiesStore.getUnfreezeDelayDays() == 0) {
throw new ContractValidateException(
"[UNFREEZE_DELAY_DAYS] proposal must be approved "
+ "before [ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE] can be proposed");
}
break;
}
default:
break;
}
Expand Down Expand Up @@ -782,7 +798,8 @@ public enum ProposalType { // current value, value range
DYNAMIC_ENERGY_INCREASE_FACTOR(74), // 0, [0, 10_000]
DYNAMIC_ENERGY_MAX_FACTOR(75), // 0, [0, 100_000]
ALLOW_TVM_SHANGHAI(76), // 0, 1
ALLOW_CANCEL_UNFREEZE_V2(77); // 0, 1
ALLOW_CANCEL_UNFREEZE_V2(77), // 0, 1
ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE(78); // 0, 1

private long code;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import static org.tron.common.crypto.Hash.sha3omit12;
import static org.tron.core.config.Parameter.ChainConstant.DELEGATE_COST_BASE_SIZE;
import static org.tron.core.config.Parameter.ChainConstant.MAX_BLOCK_NUM_DELEGATE_PERIOD;
import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION;

import com.google.common.base.CaseFormat;
Expand Down Expand Up @@ -279,11 +280,11 @@ public static long consumeBandWidthSize(
}


public static long estimateConsumeBandWidthSize(
final AccountCapsule ownerCapsule,
ChainBaseManager chainBaseManager) {
public static long estimateConsumeBandWidthSize(final AccountCapsule ownerCapsule,
ChainBaseManager chainBaseManager) {
DelegateResourceContract.Builder builder = DelegateResourceContract.newBuilder()
.setLock(true)
.setLockPeriod(MAX_BLOCK_NUM_DELEGATE_PERIOD)
.setBalance(ownerCapsule.getFrozenV2BalanceForBandwidth());
TransactionCapsule fakeTransactionCapsule = new TransactionCapsule(builder.build()
, ContractType.DelegateResourceContract);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking<BytesCapsule>
private static final byte[] ALLOW_CANCEL_UNFREEZE_V2 = "ALLOW_CANCEL_UNFREEZE_V2"
.getBytes();

private static final byte[] ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE =
"ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE".getBytes();

@Autowired
private DynamicPropertiesStore(@Value("properties") String dbName) {
super(dbName);
Expand Down Expand Up @@ -2796,6 +2799,22 @@ public boolean supportAllowCancelUnfreezeV2() {
return getAllowCancelUnfreezeV2() == 1L && getUnfreezeDelayDays() > 0;
}

public void saveAllowOptimizeLockDelegateResource(long allowOptimizeLockDelegateResource) {
this.put(DynamicPropertiesStore.ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE,
new BytesCapsule(ByteArray.fromLong(allowOptimizeLockDelegateResource)));
}

public long getAllowOptimizeLockDelegateResource() {
return Optional.ofNullable(getUnchecked(ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE))
.map(BytesCapsule::getData)
.map(ByteArray::toLong)
.orElse(CommonParameter.getInstance().getAllowOptimizeLockDelegateResource());
}

public boolean supportAllowOptimizeLockDelegateResource() {
return getAllowOptimizeLockDelegateResource() == 1L && getUnfreezeDelayDays() > 0;
}

private static class DynamicResourceProperties {

private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,10 @@ public class CommonParameter {
@Setter
public long allowCancelUnfreezeV2;

@Getter
@Setter
public long allowOptimizeLockDelegateResource;

private static double calcMaxTimeRatio() {
//return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1)));
return 5.0;
Expand Down
1 change: 1 addition & 0 deletions common/src/main/java/org/tron/core/config/Parameter.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public class ChainConstant {
public static final int BLOCK_VERSION = 28;
public static final long FROZEN_PERIOD = 86_400_000L;
public static final long DELEGATE_PERIOD = 3 * 86_400_000L;
public static final long MAX_BLOCK_NUM_DELEGATE_PERIOD = 10512000L;
public static final long TRX_PRECISION = 1000_000L;
public static final long DELEGATE_COST_BASE_SIZE = 275L;
}
Expand Down
5 changes: 5 additions & 0 deletions framework/src/main/java/org/tron/core/Wallet.java
Original file line number Diff line number Diff line change
Expand Up @@ -1330,6 +1330,11 @@ public Protocol.ChainParameters getChainParameters() {
.setValue(dbManager.getDynamicPropertiesStore().getAllowCancelUnfreezeV2())
.build());

builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder()
.setKey("getAllowOptimizeLockDelegateResource")
.setValue(dbManager.getDynamicPropertiesStore().getAllowOptimizeLockDelegateResource())
.build());

return builder.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,13 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule)
}
break;
}
case ALLOW_OPTIMIZE_LOCK_DELEGATE_RESOURCE: {
if (manager.getDynamicPropertiesStore().getAllowOptimizeLockDelegateResource() == 0) {
manager.getDynamicPropertiesStore()
.saveAllowOptimizeLockDelegateResource(entry.getValue());
}
break;
}
default:
find = false;
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.tron.core.services.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
Expand All @@ -18,6 +19,7 @@ public class DelegateResourceServlet extends RateLimiterServlet {
@Autowired
private Wallet wallet;

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
try {
PostParams params = PostParams.getPostParams(request);
Expand All @@ -26,7 +28,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response)
Transaction tx = wallet
.createTransactionCapsule(build.build(), ContractType.DelegateResourceContract)
.getInstance();
JSONObject jsonObject = JSONObject.parseObject(params.getParams());
JSONObject jsonObject = JSON.parseObject(params.getParams());
tx = Util.setTransactionPermissionId(jsonObject, tx);
response.getWriter().println(Util.printCreateTransaction(tx, params.isVisible()));
} catch (Exception e) {
Expand Down
17 changes: 7 additions & 10 deletions framework/src/test/java/org/tron/core/WalletTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ public void testGetEcKey() {
public void ss() {
for (int i = 0; i < 4; i++) {
ECKey ecKey = new ECKey(Utils.getRandom());
assertNotNull(ecKey);
System.out.println(i + 1);
System.out.println("privateKey:" + ByteArray.toHexString(ecKey.getPrivKeyBytes()));
System.out.println("publicKey:" + ByteArray.toHexString(ecKey.getPubKey()));
Expand Down Expand Up @@ -483,14 +484,14 @@ public void getPaginatedAssetIssueList() {
AssetIssueList assetList1 = wallet.getAssetIssueList(0, 100);
assertEquals("get Asset1", assetList1.getAssetIssue(0).getName(), Asset1.getName());
try {
assetList1.getAssetIssue(1);
assertNotNull(assetList1.getAssetIssue(1));
} catch (Exception e) {
Assert.assertTrue("AssetIssueList1 size should be 1", true);
}

AssetIssueList assetList2 = wallet.getAssetIssueList(0, 0);
try {
assetList2.getAssetIssue(0);
assertNotNull(assetList2.getAssetIssue(0));
} catch (Exception e) {
Assert.assertTrue("AssetIssueList2 size should be 0", true);
}
Expand Down Expand Up @@ -615,12 +616,8 @@ public void testGetDelegatedResource() {
delegatedResourceList.getDelegatedResource(0).getFrozenBalanceForBandwidth());
Assert.assertEquals(0L,
delegatedResourceList.getDelegatedResource(0).getExpireTimeForBandwidth());
} catch (ContractValidateException e) {
Assert.assertFalse(e instanceof ContractValidateException);
} catch (ContractExeException e) {
Assert.assertFalse(e instanceof ContractExeException);
} catch (Exception e) {
Assert.assertEquals(false, true);
Assert.fail();
}
}

Expand Down Expand Up @@ -794,7 +791,7 @@ public void testGetCanDelegatedMaxSizeBandWidth() {
GrpcAPI.CanDelegatedMaxSizeResponseMessage message = wallet.getCanDelegatedMaxSize(
ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)),
BANDWIDTH.getNumber());
Assert.assertEquals(initBalance - 280L, message.getMaxSize());
Assert.assertEquals(initBalance - 285L, message.getMaxSize());

}

Expand Down Expand Up @@ -1054,13 +1051,13 @@ public void testEstimateEnergyOutOfTime() {
@Test
public void testListNodes() {
try {
GrpcAPI.NodeList nodeList = wallet.listNodes();
wallet.listNodes();
} catch (Exception e) {
Assert.assertTrue(e instanceof NullPointerException);
}
Args.getInstance().setP2pDisable(true);
GrpcAPI.NodeList nodeList = wallet.listNodes();
Assert.assertTrue(nodeList.getNodesList().size() == 0);
assertEquals(0, nodeList.getNodesList().size());
}
}

Loading