diff --git a/src/contract/InnerWritesEvaluator.ts b/src/contract/InnerWritesEvaluator.ts index a09f9985..2b84ae13 100644 --- a/src/contract/InnerWritesEvaluator.ts +++ b/src/contract/InnerWritesEvaluator.ts @@ -11,7 +11,7 @@ export class InnerWritesEvaluator { return result; } - private evalForeignCalls(rootContractTxId: string, interaction: InteractionCall, result: Array) { + evalForeignCalls(rootContractTxId: string, interaction: InteractionCall, result: Array) { Object.keys(interaction.interactionInput.foreignContractCalls).forEach((foreignContractCallKey) => { const foreignContractCall = interaction.interactionInput.foreignContractCalls[foreignContractCallKey]; if (foreignContractCall.innerCallType == 'write') { diff --git a/src/core/modules/impl/DefaultStateEvaluator.ts b/src/core/modules/impl/DefaultStateEvaluator.ts index 4046afee..e235b0f7 100644 --- a/src/core/modules/impl/DefaultStateEvaluator.ts +++ b/src/core/modules/impl/DefaultStateEvaluator.ts @@ -13,6 +13,7 @@ import { ContractInteraction, HandlerApi, InteractionResult } from './HandlerExe import { TagsParser } from './TagsParser'; import { VrfPluginFunctions } from '../../WarpPlugin'; import { BasicSortKeyCache } from '../../../cache/BasicSortKeyCache'; +import { InnerWritesEvaluator } from '../../../contract/InnerWritesEvaluator'; type EvaluationProgressInput = { contractTxId: string; @@ -239,22 +240,40 @@ export abstract class DefaultStateEvaluator implements StateEvaluator { this.logger.debug(`${indent(depth)}Interaction evaluation`, singleInteractionBenchmark.elapsed()); + if (result.type === 'exception' && ignoreExceptions !== true) { + throw new Error(`Exception while processing ${JSON.stringify(interaction)}:\n${result.errorMessage}`); + } + + if (internalWrites && contract.isRoot()) { + const innerWritesEvaluator = new InnerWritesEvaluator(); + const iwEvaluatorResult = []; + innerWritesEvaluator.evalForeignCalls(contract.txId(), interactionCall, iwEvaluatorResult); + const tagsInnerWrites = this.tagsParser.getInteractWritesContracts(missingInteraction); + if ( + iwEvaluatorResult.length == tagsInnerWrites.length && + tagsInnerWrites.every((elem) => iwEvaluatorResult.includes(elem)) + ) { + validity[missingInteraction.id] = result.type === 'ok'; + currentState = result.state; + } else { + validity[missingInteraction.id] = false; + errorMessage = `[SDK] Inner writes do not match - tags:${tagsInnerWrites}, evaluated: ${iwEvaluatorResult}`; + errorMessages[missingInteraction.id] = errorMessage; + } + } else { + validity[missingInteraction.id] = result.type === 'ok'; + currentState = result.state; + } + interactionCall.update({ cacheHit: false, outputState: stackTrace.saveState ? currentState : undefined, executionTime: singleInteractionBenchmark.elapsed(true) as number, valid: validity[missingInteraction.id], - errorMessage: errorMessage, + errorMessage, gasUsed: result.gasUsed }); - if (result.type === 'exception' && ignoreExceptions !== true) { - throw new Error(`Exception while processing ${JSON.stringify(interaction)}:\n${result.errorMessage}`); - } - - validity[missingInteraction.id] = result.type === 'ok'; - currentState = result.state; - const toCache = new EvalStateResult(currentState, validity, errorMessages); if (canBeCached(missingInteraction)) { lastConfirmedTxState = {