Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions yarn-project/txe/src/oracle/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,21 @@ export interface ITxeExecutionOracle {
args: Fr[],
argsHash: Fr,
isStaticCall: boolean,
jobId: string,
): Promise<Fr[]>;
txeExecuteUtilityFunction(
targetContractAddress: AztecAddress,
functionSelector: FunctionSelector,
args: Fr[],
jobId: string,
): Promise<Fr[]>;
txePublicCallNewFlow(
from: AztecAddress,
targetContractAddress: AztecAddress,
calldata: Fr[],
isStaticCall: boolean,
): Promise<Fr[]>;
// TODO(F-335): Drop this from here as it's not a real oracle handler - it's only called from
// RPCTranslator::txeGetPrivateEvents and never from Noir.
syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string): Promise<void>;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I needed this to be able to trigger contract sync from txeGetPrivateEvents in RPCTranslator. It was not possible to do it from txeGetPrivateEvents in TXEOracleTopLevelContext because there we don't have access to the stateMachine and hence it's impossible to commit there after the sync is done.

}
44 changes: 34 additions & 10 deletions yarn-project/txe/src/oracle/txe_oracle_top_level_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
private senderAddressBookStore: SenderAddressBookStore,
private capsuleStore: CapsuleStore,
private privateEventStore: PrivateEventStore,
private jobId: string,
private nextBlockTimestamp: bigint,
private version: Fr,
private chainId: Fr,
Expand Down Expand Up @@ -172,6 +171,25 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
}

async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
if (contractAddress.equals(DEFAULT_ADDRESS)) {
this.logger.debug(`Skipping sync in txeGetPrivateEvents because the events correspond to the default address.`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this exception needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because these tests work in top level context and have there address set to DEFAULT_ADDRESS. DEFAULT_ADDRESS is some kind of fake address and is set to the number of 42.

This is pretty messy but a lot of TXE is pretty messy so would not bother with this now (and until we are sure that the current TXE model makes sense).

return;
}

const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
await this.stateMachine.contractSyncService.ensureContractSynced(
contractAddress,
null,
async (call, execScopes) => {
await this.executeUtilityCall(call, execScopes, jobId);
},
blockHeader,
jobId,
[scope],
);
}

async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
return (
await this.privateEventStore.getPrivateEvents(selector, {
Expand Down Expand Up @@ -285,6 +303,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
args: Fr[],
argsHash: Fr = Fr.zero(),
isStaticCall: boolean = false,
jobId: string,
) {
this.logger.verbose(
`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
Expand All @@ -304,7 +323,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl

// Sync notes before executing private function to discover notes from previous transactions
const utilityExecutor = async (call: FunctionCall, execScopes: AccessScopes) => {
await this.executeUtilityCall(call, execScopes);
await this.executeUtilityCall(call, execScopes, jobId);
};

const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
Expand All @@ -313,7 +332,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
functionSelector,
utilityExecutor,
blockHeader,
this.jobId,
jobId,
effectiveScopes,
);

Expand Down Expand Up @@ -360,7 +379,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
capsuleStore: this.capsuleStore,
privateEventStore: this.privateEventStore,
contractSyncService: this.stateMachine.contractSyncService,
jobId: this.jobId,
jobId,
totalPublicCalldataCount: 0,
sideEffectCounter: minRevertibleSideEffectCounter,
scopes: effectiveScopes,
Expand Down Expand Up @@ -659,7 +678,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
return returnValues ?? [];
}

async txeExecuteUtilityFunction(targetContractAddress: AztecAddress, functionSelector: FunctionSelector, args: Fr[]) {
async txeExecuteUtilityFunction(
targetContractAddress: AztecAddress,
functionSelector: FunctionSelector,
args: Fr[],
jobId: string,
) {
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
if (!artifact) {
throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
Expand All @@ -671,10 +695,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
targetContractAddress,
functionSelector,
async (call, execScopes) => {
await this.executeUtilityCall(call, execScopes);
await this.executeUtilityCall(call, execScopes, jobId);
},
blockHeader,
this.jobId,
jobId,
'ALL_SCOPES',
);

Expand All @@ -689,10 +713,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
returnTypes: [],
});

return this.executeUtilityCall(call, 'ALL_SCOPES');
return this.executeUtilityCall(call, 'ALL_SCOPES', jobId);
}

private async executeUtilityCall(call: FunctionCall, scopes: AccessScopes): Promise<Fr[]> {
private async executeUtilityCall(call: FunctionCall, scopes: AccessScopes, jobId: string): Promise<Fr[]> {
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
Expand All @@ -719,7 +743,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
senderAddressBookStore: this.senderAddressBookStore,
capsuleStore: this.capsuleStore,
privateEventStore: this.privateEventStore,
jobId: this.jobId,
jobId,
scopes,
});
const acirExecutionResult = await new WASMSimulator()
Expand Down
15 changes: 15 additions & 0 deletions yarn-project/txe/src/rpc_translator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,13 @@ export class RPCTranslator {
const contractAddress = addressFromSingle(foreignContractAddress);
const scope = addressFromSingle(foreignScope);

// TODO(F-335): Avoid doing the following 2 calls here.
{
await this.handlerAsTxe().syncContractNonOracleMethod(contractAddress, scope, this.stateHandler.getCurrentJob());
// We cycle job to commit the stores after the contract sync.
await this.stateHandler.cycleJob();
}

const events = await this.handlerAsTxe().txeGetPrivateEvents(selector, contractAddress, scope);

if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
Expand Down Expand Up @@ -1038,8 +1045,11 @@ export class RPCTranslator {
args,
argsHash,
isStaticCall,
this.stateHandler.getCurrentJob(),
);

// TODO(F-335): Avoid doing the following call here.
await this.stateHandler.cycleJob();
return toForeignCallResult([toArray(returnValues)]);
}

Expand All @@ -1056,8 +1066,11 @@ export class RPCTranslator {
targetContractAddress,
functionSelector,
args,
this.stateHandler.getCurrentJob(),
);

// TODO(F-335): Avoid doing the following call here.
await this.stateHandler.cycleJob();
return toForeignCallResult([toArray(returnValues)]);
}

Expand All @@ -1074,6 +1087,8 @@ export class RPCTranslator {

const returnValues = await this.handlerAsTxe().txePublicCallNewFlow(from, address, calldata, isStaticCall);

// TODO(F-335): Avoid doing the following call here.
await this.stateHandler.cycleJob();
return toForeignCallResult([toArray(returnValues)]);
}

Expand Down
20 changes: 16 additions & 4 deletions yarn-project/txe/src/txe_session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ export interface TXESessionStateHandler {
enterPublicState(contractAddress?: AztecAddress): Promise<void>;
enterPrivateState(contractAddress?: AztecAddress, anchorBlockNumber?: BlockNumber): Promise<PrivateContextInputs>;
enterUtilityState(contractAddress?: AztecAddress): Promise<void>;

// TODO(F-335): Exposing the job info is abstraction breakage - drop the following 2 functions.
cycleJob(): Promise<string>;
getCurrentJob(): string;
}

/**
Expand Down Expand Up @@ -193,7 +197,6 @@ export class TXESession implements TXESessionStateHandler {
senderAddressBookStore,
capsuleStore,
privateEventStore,
initialJobId,
nextBlockTimestamp,
version,
chainId,
Expand Down Expand Up @@ -254,6 +257,17 @@ export class TXESession implements TXESessionStateHandler {
}
}

getCurrentJob(): string {
return this.currentJobId;
}

/** Commits the current job and begins a new one. Returns the new job ID. */
async cycleJob(): Promise<string> {
await this.jobCoordinator.commitJob(this.currentJobId);
this.currentJobId = this.jobCoordinator.beginJob();
return this.currentJobId;
}

async enterTopLevelState() {
switch (this.state.name) {
case 'PRIVATE': {
Expand All @@ -277,8 +291,7 @@ export class TXESession implements TXESessionStateHandler {
}

// Commit all staged stores from the job that was just completed, then begin a new job
await this.jobCoordinator.commitJob(this.currentJobId);
this.currentJobId = this.jobCoordinator.beginJob();
await this.cycleJob();

this.oracleHandler = new TXEOracleTopLevelContext(
this.stateMachine,
Expand All @@ -292,7 +305,6 @@ export class TXESession implements TXESessionStateHandler {
this.senderAddressBookStore,
this.capsuleStore,
this.privateEventStore,
this.currentJobId,
this.nextBlockTimestamp,
this.version,
this.chainId,
Expand Down
Loading