2
2
3
3
import static org .tron .core .actuator .ActuatorConstant .NOT_EXIST_STR ;
4
4
import static org .tron .core .config .Parameter .ChainConstant .DELEGATE_PERIOD ;
5
+ import static org .tron .core .config .Parameter .ChainConstant .MAX_BLOCK_NUM_DELEGATE_PERIOD ;
5
6
import static org .tron .core .config .Parameter .ChainConstant .TRX_PRECISION ;
7
+ import static org .tron .protos .contract .Common .ResourceCode ;
8
+ import static org .tron .protos .contract .Common .ResourceCode .BANDWIDTH ;
9
+ import static org .tron .protos .contract .Common .ResourceCode .ENERGY ;
6
10
7
11
import com .google .protobuf .ByteString ;
8
12
import com .google .protobuf .InvalidProtocolBufferException ;
@@ -46,8 +50,10 @@ public boolean execute(Object result) throws ContractExeException {
46
50
long fee = calcFee ();
47
51
final DelegateResourceContract delegateResourceContract ;
48
52
AccountStore accountStore = chainBaseManager .getAccountStore ();
53
+ byte [] ownerAddress ;
49
54
try {
50
- delegateResourceContract = any .unpack (DelegateResourceContract .class );
55
+ delegateResourceContract = this .any .unpack (DelegateResourceContract .class );
56
+ ownerAddress = getOwnerAddress ().toByteArray ();
51
57
} catch (InvalidProtocolBufferException e ) {
52
58
logger .debug (e .getMessage (), e );
53
59
ret .setStatus (fee , code .FAILED );
@@ -59,21 +65,21 @@ public boolean execute(Object result) throws ContractExeException {
59
65
60
66
long delegateBalance = delegateResourceContract .getBalance ();
61
67
boolean lock = delegateResourceContract .getLock ();
62
- byte [] ownerAddress = delegateResourceContract .getOwnerAddress (). toByteArray ();
68
+ long lockPeriod = delegateResourceContract .getLockPeriod ();
63
69
byte [] receiverAddress = delegateResourceContract .getReceiverAddress ().toByteArray ();
64
70
65
71
// delegate resource to receiver
66
72
switch (delegateResourceContract .getResource ()) {
67
73
case BANDWIDTH :
68
74
delegateResource (ownerAddress , receiverAddress , true ,
69
- delegateBalance , lock );
75
+ delegateBalance , lock , lockPeriod );
70
76
71
77
ownerCapsule .addDelegatedFrozenV2BalanceForBandwidth (delegateBalance );
72
78
ownerCapsule .addFrozenBalanceForBandwidthV2 (-delegateBalance );
73
79
break ;
74
80
case ENERGY :
75
81
delegateResource (ownerAddress , receiverAddress , false ,
76
- delegateBalance , lock );
82
+ delegateBalance , lock , lockPeriod );
77
83
78
84
ownerCapsule .addDelegatedFrozenV2BalanceForEnergy (delegateBalance );
79
85
ownerCapsule .addFrozenBalanceForEnergyV2 (-delegateBalance );
@@ -100,6 +106,7 @@ public boolean validate() throws ContractValidateException {
100
106
}
101
107
AccountStore accountStore = chainBaseManager .getAccountStore ();
102
108
DynamicPropertiesStore dynamicStore = chainBaseManager .getDynamicPropertiesStore ();
109
+ DelegatedResourceStore delegatedResourceStore = chainBaseManager .getDelegatedResourceStore ();
103
110
if (!any .is (DelegateResourceContract .class )) {
104
111
throw new ContractValidateException (
105
112
"contract type error,expected type [DelegateResourceContract],real type["
@@ -116,13 +123,14 @@ public boolean validate() throws ContractValidateException {
116
123
}
117
124
118
125
final DelegateResourceContract delegateResourceContract ;
126
+ byte [] ownerAddress ;
119
127
try {
120
128
delegateResourceContract = this .any .unpack (DelegateResourceContract .class );
129
+ ownerAddress = getOwnerAddress ().toByteArray ();
121
130
} catch (InvalidProtocolBufferException e ) {
122
131
logger .debug (e .getMessage (), e );
123
132
throw new ContractValidateException (e .getMessage ());
124
133
}
125
- byte [] ownerAddress = delegateResourceContract .getOwnerAddress ().toByteArray ();
126
134
if (!DecodeUtil .addressValid (ownerAddress )) {
127
135
throw new ContractValidateException ("Invalid address" );
128
136
}
@@ -210,6 +218,36 @@ public boolean validate() throws ContractValidateException {
210
218
+ readableOwnerAddress + NOT_EXIST_STR );
211
219
}
212
220
221
+ boolean lock = delegateResourceContract .getLock ();
222
+ if (lock && dynamicStore .supportAllowOptimizeLockDelegateResource ()) {
223
+ long lockPeriod = delegateResourceContract .getLockPeriod ();
224
+ if (lockPeriod < 0 || lockPeriod > MAX_BLOCK_NUM_DELEGATE_PERIOD ) {
225
+ throw new ContractValidateException (
226
+ "The lock period of delegate resource cannot be less than 0 and cannot exceed 1 year!" );
227
+ }
228
+
229
+ byte [] key = DelegatedResourceCapsule .createDbKeyV2 (ownerAddress , receiverAddress , true );
230
+ DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore .get (key );
231
+ long now = dynamicStore .getLatestBlockHeaderTimestamp ();
232
+ if (delegatedResourceCapsule != null ) {
233
+ switch (delegateResourceContract .getResource ()) {
234
+ case BANDWIDTH : {
235
+ validRemainTime (BANDWIDTH , lockPeriod ,
236
+ delegatedResourceCapsule .getExpireTimeForBandwidth (), now );
237
+ }
238
+ break ;
239
+ case ENERGY : {
240
+ validRemainTime (ENERGY , lockPeriod ,
241
+ delegatedResourceCapsule .getExpireTimeForEnergy (), now );
242
+ }
243
+ break ;
244
+ default :
245
+ throw new ContractValidateException (
246
+ "ResourceCode error, valid ResourceCode[BANDWIDTH、ENERGY]" );
247
+ }
248
+ }
249
+ }
250
+
213
251
if (receiverCapsule .getType () == AccountType .Contract ) {
214
252
throw new ContractValidateException (
215
253
"Do not allow delegate resources to contract addresses" );
@@ -218,6 +256,17 @@ public boolean validate() throws ContractValidateException {
218
256
return true ;
219
257
}
220
258
259
+ private void validRemainTime (ResourceCode resourceCode , long lockPeriod , long expireTime ,
260
+ long now ) throws ContractValidateException {
261
+ long remainTime = expireTime - now ;
262
+ if (lockPeriod * 3 * 1000 < remainTime ) {
263
+ throw new ContractValidateException (
264
+ "The lock period for " + resourceCode .name () + " this time cannot be less than the "
265
+ + "remaining time[" + remainTime + "s] of the last lock period for "
266
+ + resourceCode .name () + "!" );
267
+ }
268
+ }
269
+
221
270
@ Override
222
271
public ByteString getOwnerAddress () throws InvalidProtocolBufferException {
223
272
return any .unpack (DelegateResourceContract .class ).getOwnerAddress ();
@@ -229,7 +278,7 @@ public long calcFee() {
229
278
}
230
279
231
280
private void delegateResource (byte [] ownerAddress , byte [] receiverAddress , boolean isBandwidth ,
232
- long balance , boolean lock ) {
281
+ long balance , boolean lock , long lockPeriod ) {
233
282
AccountStore accountStore = chainBaseManager .getAccountStore ();
234
283
DynamicPropertiesStore dynamicPropertiesStore = chainBaseManager .getDynamicPropertiesStore ();
235
284
DelegatedResourceStore delegatedResourceStore = chainBaseManager .getDelegatedResourceStore ();
@@ -241,12 +290,15 @@ private void delegateResource(byte[] ownerAddress, byte[] receiverAddress, boole
241
290
delegatedResourceStore .unLockExpireResource (ownerAddress , receiverAddress , now );
242
291
243
292
//modify DelegatedResourceStore
244
- byte [] key ;
245
293
long expireTime = 0 ;
246
294
if (lock ) {
247
- expireTime = now + DELEGATE_PERIOD ;
295
+ if (dynamicPropertiesStore .supportAllowOptimizeLockDelegateResource ()) {
296
+ expireTime = now + (lockPeriod == 0 ? DELEGATE_PERIOD : lockPeriod * 3 * 1000 );
297
+ } else {
298
+ expireTime = now + DELEGATE_PERIOD ;
299
+ }
248
300
}
249
- key = DelegatedResourceCapsule .createDbKeyV2 (ownerAddress , receiverAddress , lock );
301
+ byte [] key = DelegatedResourceCapsule .createDbKeyV2 (ownerAddress , receiverAddress , lock );
250
302
DelegatedResourceCapsule delegatedResourceCapsule = delegatedResourceStore .get (key );
251
303
if (delegatedResourceCapsule == null ) {
252
304
delegatedResourceCapsule = new DelegatedResourceCapsule (ByteString .copyFrom (ownerAddress ),
0 commit comments