fix: CIS should return null if nothing found
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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>,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user