fix: CIS should return null if nothing found

This commit is contained in:
Tadeuchi
2023-07-20 11:47:20 +02:00
committed by just_ppe
parent b321456db8
commit d21d1213a6
5 changed files with 40 additions and 32 deletions

View File

@@ -130,17 +130,31 @@ describe('Testing deep internal reads', () => {
}); });
it('root contract should have the latest balance', async () => { it('root contract should have the latest balance', async () => {
await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 200 }); await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 25 });
await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 25 });
await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 50 });
await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 50 });
await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 50 });
await mineBlock(warp); await mineBlock(warp);
await node20Contract.writeInteraction({ function: 'readBalanceFrom', tokenAddress: leafId, contractTxId: 'asd' }); await node20Contract.writeInteraction({ function: 'readBalanceFrom', tokenAddress: leafId, contractTxId: 'asd' });
await mineBlock(warp); await mineBlock(warp);
await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 400 }); await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 200 });
await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 100 });
await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 100 });
await mineBlock(warp); await mineBlock(warp);
await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 400 }); await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 100 });
await mineBlock(warp);
await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 100 });
await mineBlock(warp);
await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 100 });
await mineBlock(warp);
await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 100 });
await mineBlock(warp); await mineBlock(warp);
await node22Contract.writeInteraction({ function: 'readBalanceFrom', tokenAddress: leafId, contractTxId: 'asd' }); await node22Contract.writeInteraction({ function: 'readBalanceFrom', tokenAddress: leafId, contractTxId: 'asd' });
await mineBlock(warp); await mineBlock(warp);
await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 250 }); await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 50 });
await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 100 });
await leafContract.writeInteraction({ function: 'increase', target: 'asd', qty: 100 });
await mineBlock(warp); await mineBlock(warp);
await node21Contract.writeInteraction({ function: 'readBalanceFrom', tokenAddress: leafId, contractTxId: 'asd' }); await node21Contract.writeInteraction({ function: 'readBalanceFrom', tokenAddress: leafId, contractTxId: 'asd' });
await mineBlock(warp); await mineBlock(warp);
@@ -154,7 +168,10 @@ describe('Testing deep internal reads', () => {
await mineBlock(warp); await mineBlock(warp);
const rootResult = await warp.pst(rootId).readState(); const rootResult = await warp.pst(rootId)
.setEvaluationOptions({
cacheEveryNInteractions: 1,
}).readState();
expect(rootResult.cachedValue.state.balances['asd']).toEqual(1100); expect(rootResult.cachedValue.state.balances['asd']).toEqual(1100);
const node20Result = await warp.pst(node20Id).readState(); const node20Result = await warp.pst(node20Id).readState();

View File

@@ -30,7 +30,9 @@ export class ContractInteractionState implements InteractionState {
} }
keys = keys.sort((a, b) => a.localeCompare(b)); keys = keys.sort((a, b) => a.localeCompare(b));
const resultSortKey = keys[keys.length - 1]; const resultSortKey = keys[keys.length - 1];
return new SortKeyCacheResult<EvalStateResult<unknown>>(resultSortKey, states.get(resultSortKey)); if (states.get(resultSortKey)) {
return new SortKeyCacheResult<EvalStateResult<unknown>>(resultSortKey, states.get(resultSortKey));
}
} }
return null; return null;
} }
@@ -87,9 +89,9 @@ export class ContractInteractionState implements InteractionState {
this._kv.clear(); this._kv.clear();
} }
async rollback(interaction: GQLNodeInterface): Promise<void> { async rollback(interaction: GQLNodeInterface, forceStateStoreToCache: boolean): Promise<void> {
try { try {
await this.doStoreJson(this._initialJson, interaction); await this.doStoreJson(this._initialJson, interaction, forceStateStoreToCache);
await this.rollbackKVs(); await this.rollbackKVs();
} finally { } finally {
this.reset(); this.reset();

View File

@@ -38,7 +38,7 @@ export interface InteractionState {
* - IFF the result.type != 'ok'. * - IFF the result.type != 'ok'.
* This ensures atomicity of state changes withing any given interaction - also in case of internal contract calls. * This ensures atomicity of state changes withing any given interaction - also in case of internal contract calls.
*/ */
rollback(interaction: GQLNodeInterface): Promise<void>; rollback(interaction: GQLNodeInterface, forceStateStoreToCache: boolean): Promise<void>;
has(contractTxId: string, sortKey: string): boolean; has(contractTxId: string, sortKey: string): boolean;

View File

@@ -86,11 +86,6 @@ export class CacheableStateEvaluator extends DefaultStateEvaluator {
); );
} }
// {
// contractTxId: this.contractDefinition.txId,
// interactionTxId: this.swGlobal.transaction.id
// }
async onStateEvaluated<State>( async onStateEvaluated<State>(
transaction: GQLNodeInterface, transaction: GQLNodeInterface,
executionContext: ExecutionContext<State>, executionContext: ExecutionContext<State>,

View File

@@ -14,7 +14,6 @@ import { TagsParser } from './TagsParser';
import { VrfPluginFunctions } from '../../WarpPlugin'; import { VrfPluginFunctions } from '../../WarpPlugin';
import { BasicSortKeyCache } from '../../../cache/BasicSortKeyCache'; import { BasicSortKeyCache } from '../../../cache/BasicSortKeyCache';
import { KnownErrors } from './handler/JsHandlerApi'; import { KnownErrors } from './handler/JsHandlerApi';
import { genesisSortKey } from "./LexicographicalInteractionsSorter";
type EvaluationProgressInput = { type EvaluationProgressInput = {
contractTxId: string; contractTxId: string;
@@ -91,17 +90,12 @@ export abstract class DefaultStateEvaluator implements StateEvaluator {
break; break;
} }
const missingInteraction = missingInteractions[i];
currentSortKey = missingInteraction.sortKey;
contract contract
.interactionState() .interactionState()
.setInitial( .setInitial(contract.txId(), new EvalStateResult(currentState, validity, errorMessages), currentSortKey);
contract.txId(),
new EvalStateResult(currentState, validity, errorMessages),
lastConfirmedTxState?.tx?.sortKey || executionContext.cachedState?.sortKey || genesisSortKey
);
const missingInteraction = missingInteractions[i];
const singleInteractionBenchmark = Benchmark.measure(); const singleInteractionBenchmark = Benchmark.measure();
currentSortKey = missingInteraction.sortKey;
if (missingInteraction.vrf) { if (missingInteraction.vrf) {
if (!vrfPlugin) { if (!vrfPlugin) {
@@ -311,27 +305,27 @@ export abstract class DefaultStateEvaluator implements StateEvaluator {
} }
} }
const forceStateStoreToCache =
executionContext.evaluationOptions.cacheEveryNInteractions > 0 &&
i % executionContext.evaluationOptions.cacheEveryNInteractions === 0;
// if that's the end of the root contract's interaction - commit all the uncommitted states to cache. // if that's the end of the root contract's interaction - commit all the uncommitted states to cache.
if (contract.isRoot()) { if (contract.isRoot()) {
contract.clearChildren(); contract.clearChildren();
// update the uncommitted state of the root contract // update the uncommitted state of the root contract
if (lastConfirmedTxState) { if (lastConfirmedTxState) {
contract.interactionState().update(contract.txId(), lastConfirmedTxState.state, lastConfirmedTxState.tx.sortKey); contract
.interactionState()
.update(contract.txId(), lastConfirmedTxState.state, lastConfirmedTxState.tx.sortKey);
if (validity[missingInteraction.id]) { if (validity[missingInteraction.id]) {
let forceStateStoreToCache = false;
if (executionContext.evaluationOptions.cacheEveryNInteractions > 0) {
forceStateStoreToCache = i % executionContext.evaluationOptions.cacheEveryNInteractions === 0;
}
await contract.interactionState().commit(missingInteraction, forceStateStoreToCache); await contract.interactionState().commit(missingInteraction, forceStateStoreToCache);
} else { } else {
await contract.interactionState().rollback(missingInteraction); await contract.interactionState().rollback(missingInteraction, forceStateStoreToCache);
} }
} }
} else { } else {
// if that's an inner contract call - only update the state in the uncommitted states // if that's an inner contract call - only update the state in the uncommitted states
contract const interactionState = new EvalStateResult(currentState, validity, errorMessages);
.interactionState() contract.interactionState().update(contract.txId(), interactionState, currentSortKey);
.update(contract.txId(), new EvalStateResult(currentState, validity, errorMessages), currentSortKey);
} }
} }
const evalStateResult = new EvalStateResult<State>(currentState, validity, errorMessages); const evalStateResult = new EvalStateResult<State>(currentState, validity, errorMessages);