Skip to content

Commit 2c2c137

Browse files
authored
Merge pull request #4788 from tronprotocol/feature/optimize_delegates
Optimize delegates
2 parents aeb108e + 5ac7f0c commit 2c2c137

14 files changed

Lines changed: 282 additions & 39 deletions

File tree

actuator/src/main/java/org/tron/core/actuator/FreezeBalanceActuator.java

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ public long calcFee() {
285285
private long delegateResource(byte[] ownerAddress, byte[] receiverAddress, boolean isBandwidth,
286286
long balance, long expireTime) {
287287
AccountStore accountStore = chainBaseManager.getAccountStore();
288+
DynamicPropertiesStore dynamicPropertiesStore = chainBaseManager.getDynamicPropertiesStore();
288289
DelegatedResourceStore delegatedResourceStore = chainBaseManager.getDelegatedResourceStore();
289290
DelegatedResourceAccountIndexStore delegatedResourceAccountIndexStore = chainBaseManager
290291
.getDelegatedResourceAccountIndexStore();
@@ -312,35 +313,39 @@ private long delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole
312313
delegatedResourceStore.put(key, delegatedResourceCapsule);
313314

314315
//modify DelegatedResourceAccountIndexStore
315-
{
316-
DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = delegatedResourceAccountIndexStore
317-
.get(ownerAddress);
318-
if (delegatedResourceAccountIndexCapsule == null) {
319-
delegatedResourceAccountIndexCapsule = new DelegatedResourceAccountIndexCapsule(
316+
if (!dynamicPropertiesStore.supportAllowDelegateOptimization()) {
317+
318+
DelegatedResourceAccountIndexCapsule ownerIndexCapsule =
319+
delegatedResourceAccountIndexStore.get(ownerAddress);
320+
if (ownerIndexCapsule == null) {
321+
ownerIndexCapsule = new DelegatedResourceAccountIndexCapsule(
320322
ByteString.copyFrom(ownerAddress));
321323
}
322-
List<ByteString> toAccountsList = delegatedResourceAccountIndexCapsule.getToAccountsList();
324+
List<ByteString> toAccountsList = ownerIndexCapsule.getToAccountsList();
323325
if (!toAccountsList.contains(ByteString.copyFrom(receiverAddress))) {
324-
delegatedResourceAccountIndexCapsule.addToAccount(ByteString.copyFrom(receiverAddress));
326+
ownerIndexCapsule.addToAccount(ByteString.copyFrom(receiverAddress));
325327
}
326-
delegatedResourceAccountIndexStore
327-
.put(ownerAddress, delegatedResourceAccountIndexCapsule);
328-
}
328+
delegatedResourceAccountIndexStore.put(ownerAddress, ownerIndexCapsule);
329329

330-
{
331-
DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = delegatedResourceAccountIndexStore
332-
.get(receiverAddress);
333-
if (delegatedResourceAccountIndexCapsule == null) {
334-
delegatedResourceAccountIndexCapsule = new DelegatedResourceAccountIndexCapsule(
330+
DelegatedResourceAccountIndexCapsule receiverIndexCapsule
331+
= delegatedResourceAccountIndexStore.get(receiverAddress);
332+
if (receiverIndexCapsule == null) {
333+
receiverIndexCapsule = new DelegatedResourceAccountIndexCapsule(
335334
ByteString.copyFrom(receiverAddress));
336335
}
337-
List<ByteString> fromAccountsList = delegatedResourceAccountIndexCapsule
336+
List<ByteString> fromAccountsList = receiverIndexCapsule
338337
.getFromAccountsList();
339338
if (!fromAccountsList.contains(ByteString.copyFrom(ownerAddress))) {
340-
delegatedResourceAccountIndexCapsule.addFromAccount(ByteString.copyFrom(ownerAddress));
339+
receiverIndexCapsule.addFromAccount(ByteString.copyFrom(ownerAddress));
341340
}
342-
delegatedResourceAccountIndexStore
343-
.put(receiverAddress, delegatedResourceAccountIndexCapsule);
341+
delegatedResourceAccountIndexStore.put(receiverAddress, receiverIndexCapsule);
342+
343+
} else {
344+
// modify DelegatedResourceAccountIndexStore new
345+
delegatedResourceAccountIndexStore.convert(ownerAddress);
346+
delegatedResourceAccountIndexStore.convert(receiverAddress);
347+
delegatedResourceAccountIndexStore.delegate(ownerAddress, receiverAddress,
348+
dynamicPropertiesStore.getLatestBlockHeaderTimestamp());
344349
}
345350

346351
//modify AccountStore

actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceActuator.java

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -157,32 +157,32 @@ public boolean execute(Object result) throws ContractExeException {
157157
delegatedResourceStore.delete(key);
158158

159159
//modify DelegatedResourceAccountIndexStore
160-
{
161-
DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = delegatedResourceAccountIndexStore
162-
.get(ownerAddress);
163-
if (delegatedResourceAccountIndexCapsule != null) {
164-
List<ByteString> toAccountsList = new ArrayList<>(delegatedResourceAccountIndexCapsule
160+
if (!dynamicStore.supportAllowDelegateOptimization()) {
161+
DelegatedResourceAccountIndexCapsule ownerIndexCapsule =
162+
delegatedResourceAccountIndexStore.get(ownerAddress);
163+
if (ownerIndexCapsule != null) {
164+
List<ByteString> toAccountsList = new ArrayList<>(ownerIndexCapsule
165165
.getToAccountsList());
166166
toAccountsList.remove(ByteString.copyFrom(receiverAddress));
167-
delegatedResourceAccountIndexCapsule.setAllToAccounts(toAccountsList);
168-
delegatedResourceAccountIndexStore
169-
.put(ownerAddress, delegatedResourceAccountIndexCapsule);
167+
ownerIndexCapsule.setAllToAccounts(toAccountsList);
168+
delegatedResourceAccountIndexStore.put(ownerAddress, ownerIndexCapsule);
170169
}
171-
}
172170

173-
{
174-
DelegatedResourceAccountIndexCapsule delegatedResourceAccountIndexCapsule = delegatedResourceAccountIndexStore
175-
.get(receiverAddress);
176-
if (delegatedResourceAccountIndexCapsule != null) {
177-
List<ByteString> fromAccountsList = new ArrayList<>(delegatedResourceAccountIndexCapsule
171+
DelegatedResourceAccountIndexCapsule receiverIndexCapsule =
172+
delegatedResourceAccountIndexStore.get(receiverAddress);
173+
if (receiverIndexCapsule != null) {
174+
List<ByteString> fromAccountsList = new ArrayList<>(receiverIndexCapsule
178175
.getFromAccountsList());
179176
fromAccountsList.remove(ByteString.copyFrom(ownerAddress));
180-
delegatedResourceAccountIndexCapsule.setAllFromAccounts(fromAccountsList);
181-
delegatedResourceAccountIndexStore
182-
.put(receiverAddress, delegatedResourceAccountIndexCapsule);
177+
receiverIndexCapsule.setAllFromAccounts(fromAccountsList);
178+
delegatedResourceAccountIndexStore.put(receiverAddress, receiverIndexCapsule);
183179
}
180+
} else {
181+
//modify DelegatedResourceAccountIndexStore new
182+
delegatedResourceAccountIndexStore.convert(ownerAddress);
183+
delegatedResourceAccountIndexStore.convert(receiverAddress);
184+
delegatedResourceAccountIndexStore.unDelegate(ownerAddress, receiverAddress);
184185
}
185-
186186
} else {
187187
delegatedResourceStore.put(key, delegatedResourceCapsule);
188188
}

actuator/src/main/java/org/tron/core/utils/ProposalUtil.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,17 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore,
586586
}
587587
break;
588588
}
589+
case ALLOW_DELEGATE_OPTIMIZATION: {
590+
if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_6)) {
591+
throw new ContractValidateException(
592+
"Bad chain parameter id [ALLOW_DELEGATE_OPTIMIZATION]");
593+
}
594+
if (value != 1) {
595+
throw new ContractValidateException(
596+
"This value[ALLOW_DELEGATE_OPTIMIZATION] is only allowed to be 1");
597+
}
598+
break;
599+
}
589600
default:
590601
break;
591602
}
@@ -651,7 +662,8 @@ public enum ProposalType { // current value, value range
651662
ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX(65), // 0, 1
652663
ALLOW_ASSET_OPTIMIZATION(66), // 0, 1
653664
ALLOW_NEW_REWARD(67), // 0, 1
654-
MEMO_FEE(68); // 0, [0, 1000_000_000]
665+
MEMO_FEE(68), // 0, [0, 1000_000_000]
666+
ALLOW_DELEGATE_OPTIMIZATION(69); // 0, 1
655667

656668
private long code;
657669

chainbase/src/main/java/org/tron/core/capsule/DelegatedResourceAccountIndexCapsule.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,15 @@ public void removeToAccount(ByteString toAccount) {
9393
}
9494
}
9595

96+
public void setTimestamp(long time) {
97+
this.delegatedResourceAccountIndex = this.delegatedResourceAccountIndex.toBuilder()
98+
.setTimestamp(time)
99+
.build();
100+
}
101+
102+
public long getTimestamp() {
103+
return this.delegatedResourceAccountIndex.getTimestamp();
104+
}
96105

97106
public byte[] createDbKey() {
98107
return getAccount().toByteArray();

chainbase/src/main/java/org/tron/core/db/TronStoreWithRevoking.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.util.Iterator;
1212
import java.util.Map;
1313
import java.util.Objects;
14+
import java.util.stream.Collectors;
1415
import javax.annotation.PostConstruct;
1516
import lombok.Getter;
1617
import lombok.extern.slf4j.Slf4j;
@@ -29,6 +30,7 @@
2930
import org.tron.core.db2.common.IRevokingDB;
3031
import org.tron.core.db2.common.LevelDB;
3132
import org.tron.core.db2.common.RocksDB;
33+
import org.tron.core.db2.common.WrappedByteArray;
3234
import org.tron.core.db2.core.Chainbase;
3335
import org.tron.core.db2.core.ITronChainBase;
3436
import org.tron.core.db2.core.RevokingDBWithCachingOldValue;
@@ -234,4 +236,16 @@ public long size() {
234236
public void setCursor(Chainbase.Cursor cursor) {
235237
revokingDB.setCursor(cursor);
236238
}
239+
240+
public Map<WrappedByteArray, T> prefixQuery(byte[] key) {
241+
return revokingDB.prefixQuery(key).entrySet().stream().collect(
242+
Collectors.toMap(Map.Entry::getKey, e -> {
243+
try {
244+
return of(e.getValue());
245+
} catch (BadItemException e1) {
246+
throw new RuntimeException(e1);
247+
}
248+
}
249+
));
250+
}
237251
}

chainbase/src/main/java/org/tron/core/store/DelegatedResourceAccountIndexStore.java

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package org.tron.core.store;
22

3+
import com.google.protobuf.ByteString;
4+
import java.util.ArrayList;
5+
import java.util.Comparator;
6+
import java.util.List;
7+
import java.util.stream.Collectors;
38
import org.apache.commons.lang3.ArrayUtils;
49
import org.springframework.beans.factory.annotation.Autowired;
510
import org.springframework.beans.factory.annotation.Value;
@@ -11,6 +16,9 @@
1116
public class DelegatedResourceAccountIndexStore extends
1217
TronStoreWithRevoking<DelegatedResourceAccountIndexCapsule> {
1318

19+
private static final byte[] FROM_PREFIX = {0x01};
20+
private static final byte[] TO_PREFIX = {0x02};
21+
1422
@Autowired
1523
public DelegatedResourceAccountIndexStore(@Value("DelegatedResourceAccountIndex") String dbName) {
1624
super(dbName);
@@ -23,4 +31,85 @@ public DelegatedResourceAccountIndexCapsule get(byte[] key) {
2331
return ArrayUtils.isEmpty(value) ? null : new DelegatedResourceAccountIndexCapsule(value);
2432
}
2533

34+
private byte[] createKey(byte[] prefix, byte[] address1, byte[] address2) {
35+
byte[] key = new byte[prefix.length + address1.length + address2.length];
36+
System.arraycopy(prefix, 0, key, 0, prefix.length);
37+
System.arraycopy(address1, 0, key, prefix.length, address1.length);
38+
System.arraycopy(address2, 0, key, prefix.length + address1.length, address2.length);
39+
return key;
40+
}
41+
42+
public void convert(byte[] address) {
43+
DelegatedResourceAccountIndexCapsule indexCapsule = this.get(address);
44+
if (indexCapsule == null) {
45+
// convert complete or have no delegate
46+
return;
47+
}
48+
// convert old data
49+
List<ByteString> toList = indexCapsule.getToAccountsList();
50+
for (int i = 0; i < toList.size(); i++) {
51+
// use index as the timestamp, just to keep index in order
52+
this.delegate(address, toList.get(i).toByteArray(), i + 1L);
53+
}
54+
55+
List<ByteString> fromList = indexCapsule.getFromAccountsList();
56+
for (int i = 0; i < fromList.size(); i++) {
57+
// use index as the timestamp, just to keep index in order
58+
this.delegate(fromList.get(i).toByteArray(), address, i + 1L);
59+
}
60+
this.delete(address);
61+
}
62+
63+
public void delegate(byte[] from, byte[] to, long time) {
64+
byte[] fromKey = createKey(FROM_PREFIX, from, to);
65+
DelegatedResourceAccountIndexCapsule toIndexCapsule =
66+
new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(to));
67+
toIndexCapsule.setTimestamp(time);
68+
this.put(fromKey, toIndexCapsule);
69+
70+
byte[] toKey = createKey(TO_PREFIX, to, from);
71+
DelegatedResourceAccountIndexCapsule fromIndexCapsule =
72+
new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(from));
73+
fromIndexCapsule.setTimestamp(time);
74+
this.put(toKey, fromIndexCapsule);
75+
}
76+
77+
public void unDelegate(byte[] from, byte[] to) {
78+
byte[] fromKey = createKey(FROM_PREFIX, from, to);
79+
this.delete(fromKey);
80+
byte[] toKey = createKey(TO_PREFIX, to, from);
81+
this.delete(toKey);
82+
}
83+
84+
public DelegatedResourceAccountIndexCapsule getIndex(byte[] address) {
85+
DelegatedResourceAccountIndexCapsule indexCapsule = get(address);
86+
if (indexCapsule != null) {
87+
return indexCapsule;
88+
}
89+
90+
DelegatedResourceAccountIndexCapsule tmpIndexCapsule =
91+
new DelegatedResourceAccountIndexCapsule(ByteString.copyFrom(address));
92+
byte[] key = new byte[FROM_PREFIX.length + address.length];
93+
94+
System.arraycopy(FROM_PREFIX, 0, key, 0, FROM_PREFIX.length);
95+
System.arraycopy(address, 0, key, FROM_PREFIX.length, address.length);
96+
List<DelegatedResourceAccountIndexCapsule> tmpToList =
97+
new ArrayList<>(this.prefixQuery(key).values());
98+
99+
tmpToList.sort(Comparator.comparing(DelegatedResourceAccountIndexCapsule::getTimestamp));
100+
List<ByteString> list = tmpToList.stream()
101+
.map(DelegatedResourceAccountIndexCapsule::getAccount).collect(Collectors.toList());
102+
tmpIndexCapsule.setAllToAccounts(list);
103+
104+
System.arraycopy(TO_PREFIX, 0, key, 0, TO_PREFIX.length);
105+
System.arraycopy(address, 0, key, TO_PREFIX.length, address.length);
106+
List<DelegatedResourceAccountIndexCapsule> tmpFromList =
107+
new ArrayList<>(this.prefixQuery(key).values());
108+
tmpFromList.sort(Comparator.comparing(DelegatedResourceAccountIndexCapsule::getTimestamp));
109+
list = tmpFromList.stream().map(DelegatedResourceAccountIndexCapsule::getAccount).collect(
110+
Collectors.toList());
111+
tmpIndexCapsule.setAllFromAccounts(list);
112+
return tmpIndexCapsule;
113+
}
114+
26115
}

chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking<BytesCapsule>
190190
private static final byte[] ALLOW_NEW_REWARD = "ALLOW_NEW_REWARD".getBytes();
191191
private static final byte[] MEMO_FEE = "MEMO_FEE".getBytes();
192192
private static final byte[] MEMO_FEE_HISTORY = "MEMO_FEE_HISTORY".getBytes();
193+
private static final byte[] ALLOW_DELEGATE_OPTIMIZATION =
194+
"ALLOW_DELEGATE_OPTIMIZATION".getBytes();
195+
193196

194197
@Autowired
195198
private DynamicPropertiesStore(@Value("properties") String dbName) {
@@ -879,6 +882,13 @@ private DynamicPropertiesStore(@Value("properties") String dbName) {
879882
this.saveMemoFee(memoFee);
880883
this.saveMemoFeeHistory("0:" + memoFee);
881884
}
885+
886+
try {
887+
this.getAllowDelegateOptimization();
888+
} catch (IllegalArgumentException e) {
889+
this.saveAllowDelegateOptimization(
890+
CommonParameter.getInstance().getAllowDelegateOptimization());
891+
}
882892
}
883893

884894
public String intArrayToString(int[] a) {
@@ -2592,6 +2602,22 @@ public void saveAllowNewReward(long newReward) {
25922602
this.put(ALLOW_NEW_REWARD, new BytesCapsule(ByteArray.fromLong(newReward)));
25932603
}
25942604

2605+
public long getAllowDelegateOptimization() {
2606+
return Optional.ofNullable(getUnchecked(ALLOW_DELEGATE_OPTIMIZATION))
2607+
.map(BytesCapsule::getData)
2608+
.map(ByteArray::toLong)
2609+
.orElseThrow(
2610+
() -> new IllegalArgumentException("not found ALLOW_DELEGATE_OPTIMIZATION"));
2611+
}
2612+
2613+
public boolean supportAllowDelegateOptimization() {
2614+
return getAllowDelegateOptimization() == 1L;
2615+
}
2616+
2617+
public void saveAllowDelegateOptimization(long value) {
2618+
this.put(ALLOW_DELEGATE_OPTIMIZATION, new BytesCapsule(ByteArray.fromLong(value)));
2619+
}
2620+
25952621
public boolean allowNewReward() {
25962622
return getAllowNewReward() == 1;
25972623
}

common/src/main/java/org/tron/common/parameter/CommonParameter.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,10 @@ public class CommonParameter {
569569
@Setter
570570
public long memoFee = 0L;
571571

572+
@Getter
573+
@Setter
574+
public long allowDelegateOptimization = 0L;
575+
572576
private static double calcMaxTimeRatio() {
573577
//return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1)));
574578
return 5.0;

common/src/main/java/org/tron/core/Constant.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ public class Constant {
309309
public static final String ALLOW_ASSET_OPTIMIZATION = "committee.allowAssetOptimization";
310310
public static final String ALLOW_NEW_REWARD = "committee.allowNewReward";
311311
public static final String MEMO_FEE = "committee.memoFee";
312+
public static final String ALLOW_DELEGATE_OPTIMIZATION = "committee.allowDelegateOptimization";
312313

313314
public static final String LOCAL_HOST = "127.0.0.1";
314315

framework/src/main/java/org/tron/core/Wallet.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ public DelegatedResourceList getDelegatedResource(ByteString fromAddress, ByteSt
753753

754754
public DelegatedResourceAccountIndex getDelegatedResourceAccountIndex(ByteString address) {
755755
DelegatedResourceAccountIndexCapsule accountIndexCapsule =
756-
chainBaseManager.getDelegatedResourceAccountIndexStore().get(address.toByteArray());
756+
chainBaseManager.getDelegatedResourceAccountIndexStore().getIndex(address.toByteArray());
757757
if (accountIndexCapsule != null) {
758758
return accountIndexCapsule.getInstance();
759759
} else {
@@ -1108,6 +1108,11 @@ public Protocol.ChainParameters getChainParameters() {
11081108
.setValue(dbManager.getDynamicPropertiesStore().getMemoFee())
11091109
.build());
11101110

1111+
builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder()
1112+
.setKey("getAllowDelegateOptimization")
1113+
.setValue(dbManager.getDynamicPropertiesStore().getAllowDelegateOptimization())
1114+
.build());
1115+
11111116
return builder.build();
11121117
}
11131118

0 commit comments

Comments
 (0)