11package org .tron .common .runtime ;
22
3- import static com . google . common . primitives . Longs .max ;
4- import static com . google . common . primitives . Longs .min ;
3+ import static java . lang . Math .max ;
4+ import static java . lang . Math .min ;
55import static org .apache .commons .lang3 .ArrayUtils .isEmpty ;
66import static org .tron .common .runtime .utils .MUtil .convertToTronAddress ;
77import static org .tron .common .runtime .utils .MUtil .transfer ;
88import static org .tron .common .runtime .vm .VMUtils .saveProgramTraceFile ;
99import static org .tron .common .runtime .vm .VMUtils .zipAndEncode ;
10- import static org .tron .common .runtime .vm .program .InternalTransaction .ExecutorType .ET_CONSTANT_TYPE ;
1110import static org .tron .common .runtime .vm .program .InternalTransaction .ExecutorType .ET_NORMAL_TYPE ;
1211import static org .tron .common .runtime .vm .program .InternalTransaction .ExecutorType .ET_PRE_TYPE ;
1312import static org .tron .common .runtime .vm .program .InternalTransaction .ExecutorType .ET_UNKNOWN_TYPE ;
3332import org .tron .common .runtime .vm .program .InternalTransaction .ExecutorType ;
3433import org .tron .common .runtime .vm .program .Program ;
3534import org .tron .common .runtime .vm .program .Program .JVMStackOverFlowException ;
36- import org .tron .common .runtime .vm .program .Program .OutOfResourceException ;
3735import org .tron .common .runtime .vm .program .ProgramPrecompile ;
3836import org .tron .common .runtime .vm .program .ProgramResult ;
3937import org .tron .common .runtime .vm .program .invoke .ProgramInvoke ;
4543import org .tron .core .actuator .Actuator ;
4644import org .tron .core .actuator .ActuatorFactory ;
4745import org .tron .core .capsule .AccountCapsule ;
46+ import org .tron .core .capsule .BlockCapsule ;
4847import org .tron .core .capsule .ContractCapsule ;
4948import org .tron .core .capsule .TransactionCapsule ;
5049import org .tron .core .config .Parameter .ChainConstant ;
50+ import org .tron .core .config .args .Args ;
5151import org .tron .core .db .EnergyProcessor ;
5252import org .tron .core .db .StorageMarket ;
5353import org .tron .core .db .TransactionTrace ;
5454import org .tron .core .exception .ContractExeException ;
5555import org .tron .core .exception .ContractValidateException ;
56- import org .tron .core .exception .OutOfSlotTimeException ;
5756import org .tron .protos .Contract ;
5857import org .tron .protos .Contract .CreateSmartContract ;
5958import org .tron .protos .Contract .TriggerSmartContract ;
6362import org .tron .protos .Protocol .SmartContract .ABI ;
6463import org .tron .protos .Protocol .Transaction ;
6564import org .tron .protos .Protocol .Transaction .Contract .ContractType ;
65+ import org .tron .protos .Protocol .Transaction .Result .contractResult ;
6666
6767@ Slf4j (topic = "Runtime" )
6868public class Runtime {
@@ -71,7 +71,7 @@ public class Runtime {
7171 private SystemProperties config = SystemProperties .getInstance ();
7272
7373 private Transaction trx ;
74- private Block block = null ;
74+ private BlockCapsule blockCap = null ;
7575 private Deposit deposit ;
7676 private ProgramInvokeFactory programInvokeFactory = null ;
7777 private String runtimeError ;
@@ -93,18 +93,18 @@ public class Runtime {
9393
9494
9595 /**
96- * For block 's trx run
96+ * For blockCap 's trx run
9797 */
98- public Runtime (TransactionTrace trace , Block block , Deposit deosit ,
98+ public Runtime (TransactionTrace trace , BlockCapsule block , Deposit deosit ,
9999 ProgramInvokeFactory programInvokeFactory ) {
100100 this .trace = trace ;
101101 this .trx = trace .getTrx ().getInstance ();
102102
103103 if (Objects .nonNull (block )) {
104- this .block = block ;
104+ this .blockCap = block ;
105105 this .executorType = ET_NORMAL_TYPE ;
106106 } else {
107- this .block = Block .newBuilder ().build ();
107+ this .blockCap = new BlockCapsule ( Block .newBuilder ().build () );
108108 this .executorType = ET_PRE_TYPE ;
109109 }
110110 this .deposit = deosit ;
@@ -127,15 +127,15 @@ public Runtime(TransactionTrace trace, Block block, Deposit deosit,
127127
128128
129129 /**
130- * For constant trx with latest block .
130+ * For constant trx with latest blockCap .
131131 */
132- public Runtime (Transaction tx , Block block , DepositImpl deposit ,
132+ public Runtime (Transaction tx , BlockCapsule block , DepositImpl deposit ,
133133 ProgramInvokeFactory programInvokeFactory ) {
134134 this .trx = tx ;
135135 this .deposit = deposit ;
136136 this .programInvokeFactory = programInvokeFactory ;
137137 this .executorType = ET_PRE_TYPE ;
138- this .block = block ;
138+ this .blockCap = block ;
139139 this .energyProcessor = new EnergyProcessor (deposit .getDbManager ());
140140 this .storageMarket = new StorageMarket (deposit .getDbManager ());
141141 Transaction .Contract .ContractType contractType = tx .getRawData ().getContract (0 ).getType ();
@@ -166,10 +166,11 @@ public void precompiled() throws ContractValidateException, ContractExeException
166166
167167 public BigInteger getBlockCPULeftInUs () {
168168
169- // insure block is not null
169+ // insure blockCap is not null
170170 BigInteger curBlockHaveElapsedCPUInUs =
171171 BigInteger .valueOf (
172- 1000 * (DateTime .now ().getMillis () - block .getBlockHeader ().getRawData ()
172+ 1000 * (DateTime .now ().getMillis () - blockCap .getInstance ().getBlockHeader ()
173+ .getRawData ()
173174 .getTimestamp ())); // us
174175 BigInteger curBlockCPULimitInUs = BigInteger .valueOf ((long )
175176 (1000 * ChainConstant .BLOCK_PRODUCED_INTERVAL * 0.5
@@ -180,28 +181,6 @@ public BigInteger getBlockCPULeftInUs() {
180181
181182 }
182183
183- public boolean curCPULimitReachedBlockCPULimit () {
184-
185- if (executorType == ET_NORMAL_TYPE ) {
186- BigInteger blockCPULeftInUs = getBlockCPULeftInUs ();
187- BigInteger oneTxCPULimitInUs = BigInteger
188- .valueOf (Constant .MAX_CPU_TIME_OF_ONE_TX );
189-
190- // TODO get from account
191- BigInteger increasedStorageLimit = BigInteger .valueOf (10000000 );
192-
193- boolean cumulativeCPUReached =
194- oneTxCPULimitInUs .compareTo (blockCPULeftInUs ) > 0 ;
195-
196- if (cumulativeCPUReached ) {
197- logger .error ("cumulative CPU Reached" );
198- return true ;
199- }
200- }
201-
202- return false ;
203- }
204-
205184 public void execute () throws ContractValidateException , ContractExeException {
206185 switch (trxType ) {
207186 case TRX_PRECOMPILED_TYPE :
@@ -285,6 +264,32 @@ private long getEnergyLimit(AccountCapsule creator, AccountCapsule caller,
285264 }
286265 }
287266
267+ private double getThisTxCPULimitInUsRatio () {
268+
269+ double thisTxCPULimitInUsRatio ;
270+
271+ if (ET_NORMAL_TYPE == executorType ) {
272+ // self witness 2
273+ if (this .blockCap != null && blockCap .generatedByMyself &&
274+ this .blockCap .getInstance ().getBlockHeader ().getWitnessSignature ().isEmpty ()) {
275+ thisTxCPULimitInUsRatio = 1.0 ;
276+ } else
277+ // self witness 3, other witness 3, fullnode 2
278+ {
279+ if (trx .getRet (0 ).getContractRet () == contractResult .OUT_OF_TIME ) {
280+ thisTxCPULimitInUsRatio = Args .getInstance ().getMinTimeRatio ();
281+ } else {
282+ thisTxCPULimitInUsRatio = Args .getInstance ().getMaxTimeRatio ();
283+ }
284+ }
285+ } else {
286+ // self witness 1, other witness 1, fullnode 1
287+ thisTxCPULimitInUsRatio = 1.0 ;
288+ }
289+
290+ return thisTxCPULimitInUsRatio ;
291+ }
292+
288293 /*
289294 **/
290295 private void create ()
@@ -328,12 +333,10 @@ private void create()
328333 // thisTxENERGYLimitInUs = Constant.ENERGY_LIMIT_IN_ONE_TX_OF_SMART_CONTRACT;
329334 // }
330335
331- long thisTxCPULimitInUs ;
332- if (ET_NORMAL_TYPE == executorType ) {
333- thisTxCPULimitInUs = Constant .MAX_CPU_TIME_OF_ONE_TX_WHEN_VERIFY_BLOCK ;
334- } else {
335- thisTxCPULimitInUs = Constant .MAX_CPU_TIME_OF_ONE_TX ;
336- }
336+
337+
338+ long thisTxCPULimitInUs =
339+ (long ) (Constant .MAX_CPU_TIME_OF_ONE_TX * getThisTxCPULimitInUsRatio ());
337340 long vmStartInUs = System .nanoTime () / 1000 ;
338341 long vmShouldEndInUs = vmStartInUs + thisTxCPULimitInUs ;
339342
@@ -344,9 +347,9 @@ private void create()
344347
345348 ProgramInvoke programInvoke = programInvokeFactory
346349 .createProgramInvoke (TRX_CONTRACT_CREATION_TYPE , executorType , trx ,
347- block , deposit , vmStartInUs , vmShouldEndInUs , energyLimit );
350+ blockCap . getInstance () , deposit , vmStartInUs , vmShouldEndInUs , energyLimit );
348351 this .vm = new VM (config );
349- this .program = new Program (ops , programInvoke , internalTransaction , config );
352+ this .program = new Program (ops , programInvoke , internalTransaction , config , this . blockCap );
350353 Program .setRootTransactionId (new TransactionCapsule (trx ).getTransactionId ().getBytes ());
351354 Program .resetNonce ();
352355 Program .setRootCallConstant (isCallConstant ());
@@ -400,15 +403,11 @@ private void call()
400403 this .deposit .getContract (contractAddress ).getInstance ()
401404 .getOriginAddress ().toByteArray ());
402405
403- long thisTxENERGYLimitInUs ;
404- if (ET_NORMAL_TYPE == executorType ) {
405- thisTxENERGYLimitInUs = Constant .MAX_CPU_TIME_OF_ONE_TX_WHEN_VERIFY_BLOCK ;
406- } else {
407- thisTxENERGYLimitInUs = Constant .MAX_CPU_TIME_OF_ONE_TX ;
408- }
406+ long thisTxCPULimitInUs =
407+ (long ) (Constant .MAX_CPU_TIME_OF_ONE_TX * getThisTxCPULimitInUsRatio ());
409408
410409 long vmStartInUs = System .nanoTime () / 1000 ;
411- long vmShouldEndInUs = vmStartInUs + thisTxENERGYLimitInUs ;
410+ long vmShouldEndInUs = vmStartInUs + thisTxCPULimitInUs ;
412411
413412 long feeLimit = trx .getRawData ().getFeeLimit ();
414413 long energyLimit ;
@@ -425,10 +424,11 @@ private void call()
425424
426425 ProgramInvoke programInvoke = programInvokeFactory
427426 .createProgramInvoke (TRX_CONTRACT_CALL_TYPE , executorType , trx ,
428- block , deposit , vmStartInUs , vmShouldEndInUs , energyLimit );
427+ blockCap . getInstance () , deposit , vmStartInUs , vmShouldEndInUs , energyLimit );
429428 this .vm = new VM (config );
430429 InternalTransaction internalTransaction = new InternalTransaction (trx );
431- this .program = new Program (null , code , programInvoke , internalTransaction , config );
430+ this .program = new Program (null , code , programInvoke , internalTransaction , config ,
431+ this .blockCap );
432432 Program .setRootTransactionId (new TransactionCapsule (trx ).getTransactionId ().getBytes ());
433433 Program .resetNonce ();
434434 Program .setRootCallConstant (isCallConstant ());
@@ -443,8 +443,7 @@ private void call()
443443
444444 }
445445
446- public void go () throws OutOfSlotTimeException {
447-
446+ public void go () {
448447 try {
449448 if (vm != null ) {
450449 vm .play (program );
@@ -478,15 +477,13 @@ public void go() throws OutOfSlotTimeException {
478477 } else {
479478 deposit .commit ();
480479 }
481- } catch (OutOfResourceException e ) {
482- logger .error ("runtime error is :{}" , e .getMessage ());
483- throw new OutOfSlotTimeException (e .getMessage ());
484- } catch (JVMStackOverFlowException e ){
480+ } catch (JVMStackOverFlowException e ) {
485481 result .setException (e );
486482 runtimeError = result .getException ().getMessage ();
487483 logger .error ("runtime error is :{}" , result .getException ().getMessage ());
488- } catch (Throwable e ) {
484+ } catch (Throwable e ) {
489485 if (Objects .isNull (result .getException ())) {
486+ logger .error (e .getMessage (), e );
490487 result .setException (new RuntimeException ("Unknown Throwable" ));
491488 }
492489 if (StringUtils .isEmpty (runtimeError )) {
@@ -506,7 +503,8 @@ private long getEnergyFee(long callerEnergyUsage, long callerEnergyFrozen,
506503 .divide (BigInteger .valueOf (callerEnergyTotal )).longValue ();
507504 }
508505
509- public boolean isCallConstant () {
506+ public boolean isCallConstant () throws ContractValidateException {
507+
510508 TriggerSmartContract triggerContractFromTransaction = ContractCapsule
511509 .getTriggerContractFromTransaction (trx );
512510 if (TRX_CONTRACT_CALL_TYPE .equals (trxType )) {
@@ -520,7 +518,8 @@ public boolean isCallConstant() {
520518 return false ;
521519 }
522520
523- private boolean isCallConstant (byte [] address ) {
521+ private boolean isCallConstant (byte [] address ) throws ContractValidateException {
522+
524523 if (TRX_CONTRACT_CALL_TYPE .equals (trxType )) {
525524 ABI abi = deposit .getContract (address ).getInstance ().getAbi ();
526525 if (Wallet .isConstant (abi , ContractCapsule .getTriggerContractFromTransaction (trx ))) {
0 commit comments