2121import java .util .Arrays ;
2222import java .util .List ;
2323import java .util .Objects ;
24+ import lombok .Getter ;
25+ import lombok .Setter ;
2426import lombok .extern .slf4j .Slf4j ;
2527import org .apache .commons .lang3 .StringUtils ;
2628import org .joda .time .DateTime ;
@@ -88,6 +90,8 @@ public class Runtime {
8890 private VM vm = null ;
8991 private Program program = null ;
9092
93+ @ Getter
94+ @ Setter
9195 private InternalTransaction .TrxType trxType = TRX_UNKNOWN_TYPE ;
9296 private ExecutorType executorType = ET_UNKNOWN_TYPE ;
9397
@@ -132,6 +136,13 @@ public Runtime(TransactionTrace trace, BlockCapsule block, Deposit deposit,
132136 /**
133137 * For constant trx with latest blockCap.
134138 */
139+ private boolean isStaticCall = false ;
140+ public Runtime (Transaction tx , BlockCapsule block , DepositImpl deposit ,
141+ ProgramInvokeFactory programInvokeFactory , boolean isStaticCall ) {
142+ this (tx , block , deposit , programInvokeFactory );
143+ this .isStaticCall = isStaticCall ;
144+ }
145+
135146 public Runtime (Transaction tx , BlockCapsule block , DepositImpl deposit ,
136147 ProgramInvokeFactory programInvokeFactory ) {
137148 this .trx = tx ;
@@ -177,32 +188,26 @@ public BigInteger getBlockCPULeftInUs() {
177188 .getTimestamp ())); // us
178189 BigInteger curBlockCPULimitInUs = BigInteger .valueOf ((long )
179190 (1000 * ChainConstant .BLOCK_PRODUCED_INTERVAL * 0.5
180- * ChainConstant . BLOCK_PRODUCED_TIME_OUT
191+ * Args . getInstance (). getBlockProducedTimeOut ()
181192 / 100 )); // us
182193
183194 return curBlockCPULimitInUs .subtract (curBlockHaveElapsedCPUInUs );
184195
185196 }
186197
187198 public void execute () throws ContractValidateException , ContractExeException {
188- try {
189- switch (trxType ) {
190- case TRX_PRECOMPILED_TYPE :
191- precompiled ();
192- break ;
193- case TRX_CONTRACT_CREATION_TYPE :
194- create ();
195- break ;
196- case TRX_CONTRACT_CALL_TYPE :
197- call ();
198- break ;
199- default :
200- throw new ContractValidateException ("Unknown contract type" );
201- }
202- } catch (ContractExeException | ContractValidateException e ) {
203- throw e ;
204- } catch (Exception e ) {
205- throw new ContractValidateException ("Unknown contract error" );
199+ switch (trxType ) {
200+ case TRX_PRECOMPILED_TYPE :
201+ precompiled ();
202+ break ;
203+ case TRX_CONTRACT_CREATION_TYPE :
204+ create ();
205+ break ;
206+ case TRX_CONTRACT_CALL_TYPE :
207+ call ();
208+ break ;
209+ default :
210+ throw new ContractValidateException ("Unknown contract type" );
206211 }
207212 }
208213
@@ -255,18 +260,15 @@ private long getEnergyLimit(AccountCapsule creator, AccountCapsule caller,
255260 // creatorEnergyFromFreeze
256261 long creatorEnergyLimit = energyProcessor .getAccountLeftEnergyFromFreeze (creator );
257262
263+
258264 SmartContract smartContract = this .deposit
259265 .getContract (contract .getContractAddress ().toByteArray ()).getInstance ();
260266 long consumeUserResourcePercent = smartContract .getConsumeUserResourcePercent ();
261267
262268 consumeUserResourcePercent = max (0 , min (consumeUserResourcePercent , 100 ));
263269
264- if (consumeUserResourcePercent <= 0 ) {
265- return creatorEnergyLimit ;
266- }
267-
268270 if (creatorEnergyLimit * consumeUserResourcePercent
269- >= (100 - consumeUserResourcePercent ) * callerEnergyLimit ) {
271+ > (100 - consumeUserResourcePercent ) * callerEnergyLimit ) {
270272 return Math .floorDiv (callerEnergyLimit * 100 , consumeUserResourcePercent );
271273 } else {
272274 return Math .addExact (callerEnergyLimit , creatorEnergyLimit );
@@ -309,6 +311,9 @@ private void create()
309311 }
310312
311313 CreateSmartContract contract = ContractCapsule .getSmartContractFromTransaction (trx );
314+ if (contract == null ) {
315+ throw new ContractValidateException ("Cannot get CreateSmartContract from transaction" );
316+ }
312317 SmartContract newSmartContract = contract .getNewContract ();
313318 if (!contract .getOwnerAddress ().equals (newSmartContract .getOriginAddress ())) {
314319 logger .error ("OwnerAddress not equals OriginAddress" );
@@ -317,6 +322,12 @@ private void create()
317322 byte [] code = newSmartContract .getBytecode ().toByteArray ();
318323 byte [] contractAddress = Wallet .generateContractAddress (trx );
319324 byte [] ownerAddress = contract .getOwnerAddress ().toByteArray ();
325+ byte [] contractName = newSmartContract .getName ().getBytes ();
326+
327+ if (contractName .length > 32 ) {
328+ logger .error ("contractName's length mustn't be greater than 32" );
329+ throw new ContractValidateException ("contractName's length mustn't be greater than 32" );
330+ }
320331
321332 long percent = contract .getNewContract ().getConsumeUserResourcePercent ();
322333 if (percent < 0 || percent > 100 ) {
@@ -374,7 +385,6 @@ private void create()
374385 this .vm = new VM (config );
375386 this .program = new Program (ops , programInvoke , internalTransaction , config , this .blockCap );
376387 this .program .setRootTransactionId (new TransactionCapsule (trx ).getTransactionId ().getBytes ());
377- this .program .resetNonce ();
378388 this .program .setRootCallConstant (isCallConstant ());
379389 } catch (Exception e ) {
380390 logger .error (e .getMessage ());
@@ -415,7 +425,17 @@ private void call()
415425 return ;
416426 }
417427
428+ if (contract .getContractAddress () == null ){
429+ throw new ContractValidateException ("Cannot get contract address from TriggerContract" );
430+ }
431+
418432 byte [] contractAddress = contract .getContractAddress ().toByteArray ();
433+
434+ ContractCapsule deployedContract = this .deposit .getContract (contractAddress );
435+ if (null == deployedContract ) {
436+ logger .error ("No contract or not a smart contract" );
437+ throw new ContractValidateException ("No contract or not a smart contract" );
438+ }
419439 byte [] code = this .deposit .getCode (contractAddress );
420440 long callValue = contract .getCallValue ();
421441 if (isEmpty (code )) {
@@ -424,7 +444,7 @@ private void call()
424444
425445 AccountCapsule caller = this .deposit .getAccount (contract .getOwnerAddress ().toByteArray ());
426446 AccountCapsule creator = this .deposit .getAccount (
427- this . deposit . getContract ( contractAddress ) .getInstance ()
447+ deployedContract .getInstance ()
428448 .getOriginAddress ().toByteArray ());
429449
430450 long MAX_CPU_TIME_OF_ONE_TX = deposit .getDbManager ().getDynamicPropertiesStore ()
@@ -443,6 +463,7 @@ private void call()
443463 }
444464 long energyLimit ;
445465 if (isCallConstant (contractAddress )) {
466+ isStaticCall = true ;
446467 energyLimit = Constant .MAX_ENERGY_IN_TX ;
447468 } else {
448469 energyLimit = getEnergyLimit (creator , caller , contract , feeLimit , callValue );
@@ -451,12 +472,14 @@ private void call()
451472 ProgramInvoke programInvoke = programInvokeFactory
452473 .createProgramInvoke (TRX_CONTRACT_CALL_TYPE , executorType , trx ,
453474 blockCap .getInstance (), deposit , vmStartInUs , vmShouldEndInUs , energyLimit );
475+ if (isStaticCall ) {
476+ programInvoke .setStaticCall ();
477+ }
454478 this .vm = new VM (config );
455479 InternalTransaction internalTransaction = new InternalTransaction (trx );
456480 this .program = new Program (null , code , programInvoke , internalTransaction , config ,
457481 this .blockCap );
458482 this .program .setRootTransactionId (new TransactionCapsule (trx ).getTransactionId ().getBytes ());
459- this .program .resetNonce ();
460483 this .program .setRootCallConstant (isCallConstant ());
461484 }
462485
@@ -473,7 +496,8 @@ public void go() {
473496 try {
474497
475498 TransactionCapsule trxCap = new TransactionCapsule (trx );
476- if (null != trxCap .getContractRet () && contractResult .OUT_OF_TIME
499+ if (null != blockCap && blockCap .generatedByMyself && null != trxCap .getContractRet ()
500+ && contractResult .OUT_OF_TIME
477501 .equals (trxCap .getContractRet ())) {
478502 result = program .getResult ();
479503 program .spendAllEnergy ();
@@ -485,7 +509,6 @@ public void go() {
485509 if (vm != null ) {
486510 vm .play (program );
487511
488- program .getResult ().setRet (result .getRet ());
489512 result = program .getResult ();
490513
491514 if (isCallConstant ()) {
@@ -533,16 +556,19 @@ public void go() {
533556 }
534557 } catch (JVMStackOverFlowException e ) {
535558 program .spendAllEnergy ();
559+ result = program .getResult ();
536560 result .setException (e );
537561 runtimeError = result .getException ().getMessage ();
538562 logger .error ("runtime error is :{}" , result .getException ().getMessage ());
539563 } catch (OutOfResourceException e ) {
540564 program .spendAllEnergy ();
565+ result = program .getResult ();
541566 result .setException (e );
542567 runtimeError = result .getException ().getMessage ();
543568 logger .error ("runtime error is :{}" , result .getException ().getMessage ());
544569 } catch (Throwable e ) {
545570 program .spendAllEnergy ();
571+ result = program .getResult ();
546572 if (Objects .isNull (result .getException ())) {
547573 logger .error (e .getMessage (), e );
548574 result .setException (new RuntimeException ("Unknown Throwable" ));
0 commit comments