@aztec/pxe 0.0.1-commit.7cf39cb55 → 0.0.1-commit.808bf7f90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/access_scopes.d.ts +9 -0
- package/dest/access_scopes.d.ts.map +1 -0
- package/dest/access_scopes.js +6 -0
- package/dest/config/package_info.js +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.d.ts +5 -4
- package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.js +6 -6
- package/dest/contract_function_simulator/noir-structs/event_validation_request.js +1 -1
- package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +2 -2
- package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/note_validation_request.js +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +3 -2
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.js +2 -10
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +4 -3
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +5 -8
- package/dest/contract_logging.d.ts +22 -0
- package/dest/contract_logging.d.ts.map +1 -0
- package/dest/contract_logging.js +23 -0
- package/dest/contract_sync/contract_sync_service.d.ts +4 -3
- package/dest/contract_sync/contract_sync_service.d.ts.map +1 -1
- package/dest/contract_sync/contract_sync_service.js +10 -10
- package/dest/contract_sync/helpers.d.ts +3 -2
- package/dest/contract_sync/helpers.d.ts.map +1 -1
- package/dest/contract_sync/helpers.js +3 -3
- package/dest/debug/pxe_debug_utils.d.ts +5 -4
- package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
- package/dest/debug/pxe_debug_utils.js +4 -4
- package/dest/entrypoints/client/bundle/index.d.ts +4 -1
- package/dest/entrypoints/client/bundle/index.d.ts.map +1 -1
- package/dest/entrypoints/client/bundle/index.js +3 -0
- package/dest/entrypoints/client/lazy/index.d.ts +4 -1
- package/dest/entrypoints/client/lazy/index.d.ts.map +1 -1
- package/dest/entrypoints/client/lazy/index.js +3 -0
- package/dest/entrypoints/server/index.d.ts +3 -1
- package/dest/entrypoints/server/index.d.ts.map +1 -1
- package/dest/entrypoints/server/index.js +2 -0
- package/dest/logs/log_service.d.ts +3 -2
- package/dest/logs/log_service.d.ts.map +1 -1
- package/dest/logs/log_service.js +1 -1
- package/dest/notes/note_service.d.ts +4 -3
- package/dest/notes/note_service.d.ts.map +1 -1
- package/dest/notes/note_service.js +3 -2
- package/dest/notes_filter.d.ts +25 -0
- package/dest/notes_filter.d.ts.map +1 -0
- package/dest/notes_filter.js +4 -0
- package/dest/private_kernel/hints/compute_tx_expiration_timestamp.d.ts +4 -0
- package/dest/private_kernel/hints/compute_tx_expiration_timestamp.d.ts.map +1 -0
- package/dest/private_kernel/hints/{compute_tx_include_by_timestamp.js → compute_tx_expiration_timestamp.js} +12 -12
- package/dest/private_kernel/hints/index.d.ts +1 -1
- package/dest/private_kernel/hints/index.js +1 -1
- package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.js +4 -4
- package/dest/private_kernel/private_kernel_execution_prover.js +6 -6
- package/dest/private_kernel/private_kernel_oracle.d.ts +6 -2
- package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_oracle.js +7 -3
- package/dest/pxe.d.ts +12 -11
- package/dest/pxe.d.ts.map +1 -1
- package/dest/pxe.js +30 -24
- package/dest/storage/contract_store/contract_store.d.ts +42 -15
- package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
- package/dest/storage/contract_store/contract_store.js +140 -64
- package/dest/storage/note_store/note_store.d.ts +3 -2
- package/dest/storage/note_store/note_store.d.ts.map +1 -1
- package/dest/storage/note_store/note_store.js +2 -2
- package/dest/tagging/get_all_logs_by_tags.d.ts +1 -1
- package/dest/tagging/get_all_logs_by_tags.d.ts.map +1 -1
- package/dest/tagging/get_all_logs_by_tags.js +17 -3
- package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.js +4 -4
- package/dest/tagging/recipient_sync/utils/find_highest_indexes.js +2 -2
- package/package.json +16 -16
- package/src/access_scopes.ts +9 -0
- package/src/config/package_info.ts +1 -1
- package/src/contract_function_simulator/contract_function_simulator.ts +17 -11
- package/src/contract_function_simulator/noir-structs/event_validation_request.ts +1 -1
- package/src/contract_function_simulator/noir-structs/note_validation_request.ts +1 -1
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +5 -13
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +12 -10
- package/src/contract_logging.ts +39 -0
- package/src/contract_sync/contract_sync_service.ts +19 -12
- package/src/contract_sync/helpers.ts +7 -2
- package/src/debug/pxe_debug_utils.ts +9 -8
- package/src/entrypoints/client/bundle/index.ts +3 -0
- package/src/entrypoints/client/lazy/index.ts +3 -0
- package/src/entrypoints/server/index.ts +2 -0
- package/src/logs/log_service.ts +3 -6
- package/src/notes/note_service.ts +4 -3
- package/src/notes_filter.ts +26 -0
- package/src/private_kernel/hints/{compute_tx_include_by_timestamp.ts → compute_tx_expiration_timestamp.ts} +13 -13
- package/src/private_kernel/hints/index.ts +1 -1
- package/src/private_kernel/hints/private_kernel_reset_private_inputs_builder.ts +7 -7
- package/src/private_kernel/private_kernel_execution_prover.ts +6 -6
- package/src/private_kernel/private_kernel_oracle.ts +7 -7
- package/src/pxe.ts +43 -39
- package/src/storage/contract_store/contract_store.ts +170 -71
- package/src/storage/note_store/note_store.ts +7 -3
- package/src/tagging/get_all_logs_by_tags.ts +28 -4
- package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +4 -4
- package/src/tagging/recipient_sync/utils/find_highest_indexes.ts +2 -2
- package/dest/private_kernel/hints/compute_tx_include_by_timestamp.d.ts +0 -4
- package/dest/private_kernel/hints/compute_tx_include_by_timestamp.d.ts.map +0 -1
|
@@ -2,11 +2,8 @@ import {
|
|
|
2
2
|
AVM_EMITNOTEHASH_BASE_L2_GAS,
|
|
3
3
|
AVM_EMITNULLIFIER_BASE_L2_GAS,
|
|
4
4
|
AVM_SENDL2TOL1MSG_BASE_L2_GAS,
|
|
5
|
-
|
|
6
|
-
DA_GAS_PER_BYTE,
|
|
5
|
+
DA_GAS_PER_FIELD,
|
|
7
6
|
FIXED_AVM_STARTUP_L2_GAS,
|
|
8
|
-
FIXED_DA_GAS,
|
|
9
|
-
FIXED_L2_GAS,
|
|
10
7
|
L2_GAS_PER_CONTRACT_CLASS_LOG,
|
|
11
8
|
L2_GAS_PER_L2_TO_L1_MSG,
|
|
12
9
|
L2_GAS_PER_NOTE_HASH,
|
|
@@ -20,6 +17,9 @@ import {
|
|
|
20
17
|
MAX_NULLIFIERS_PER_TX,
|
|
21
18
|
MAX_NULLIFIER_READ_REQUESTS_PER_TX,
|
|
22
19
|
MAX_PRIVATE_LOGS_PER_TX,
|
|
20
|
+
PRIVATE_TX_L2_GAS_OVERHEAD,
|
|
21
|
+
PUBLIC_TX_L2_GAS_OVERHEAD,
|
|
22
|
+
TX_DA_GAS_OVERHEAD,
|
|
23
23
|
} from '@aztec/constants';
|
|
24
24
|
import { arrayNonEmptyLength, padArrayEnd } from '@aztec/foundation/collection';
|
|
25
25
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
@@ -87,6 +87,7 @@ import {
|
|
|
87
87
|
getFinalMinRevertibleSideEffectCounter,
|
|
88
88
|
} from '@aztec/stdlib/tx';
|
|
89
89
|
|
|
90
|
+
import type { AccessScopes } from '../access_scopes.js';
|
|
90
91
|
import type { ContractSyncService } from '../contract_sync/contract_sync_service.js';
|
|
91
92
|
import type { AddressStore } from '../storage/address_store/address_store.js';
|
|
92
93
|
import type { CapsuleStore } from '../storage/capsule_store/capsule_store.js';
|
|
@@ -117,8 +118,8 @@ export type ContractSimulatorRunOpts = {
|
|
|
117
118
|
anchorBlockHeader: BlockHeader;
|
|
118
119
|
/** The address used as a tagging sender when emitting private logs. */
|
|
119
120
|
senderForTags?: AztecAddress;
|
|
120
|
-
/** The accounts whose notes we can access in this call.
|
|
121
|
-
scopes
|
|
121
|
+
/** The accounts whose notes we can access in this call. */
|
|
122
|
+
scopes: AccessScopes;
|
|
122
123
|
/** The job ID for staged writes. */
|
|
123
124
|
jobId: string;
|
|
124
125
|
};
|
|
@@ -311,7 +312,7 @@ export class ContractFunctionSimulator {
|
|
|
311
312
|
call: FunctionCall,
|
|
312
313
|
authwits: AuthWitness[],
|
|
313
314
|
anchorBlockHeader: BlockHeader,
|
|
314
|
-
scopes:
|
|
315
|
+
scopes: AccessScopes,
|
|
315
316
|
jobId: string,
|
|
316
317
|
): Promise<Fr[]> {
|
|
317
318
|
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
@@ -360,7 +361,7 @@ export class ContractFunctionSimulator {
|
|
|
360
361
|
);
|
|
361
362
|
});
|
|
362
363
|
|
|
363
|
-
this.log.verbose(`Utility
|
|
364
|
+
this.log.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
|
|
364
365
|
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
365
366
|
} catch (err) {
|
|
366
367
|
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
@@ -653,9 +654,14 @@ export async function generateSimulatedProvingResult(
|
|
|
653
654
|
|
|
654
655
|
const publicInputs = new PrivateKernelTailCircuitPublicInputs(
|
|
655
656
|
constantData,
|
|
656
|
-
/*gasUsed=*/ gasUsed.add(
|
|
657
|
+
/*gasUsed=*/ gasUsed.add(
|
|
658
|
+
Gas.from({
|
|
659
|
+
l2Gas: isPrivateOnlyTx ? PRIVATE_TX_L2_GAS_OVERHEAD : PUBLIC_TX_L2_GAS_OVERHEAD,
|
|
660
|
+
daGas: TX_DA_GAS_OVERHEAD,
|
|
661
|
+
}),
|
|
662
|
+
),
|
|
657
663
|
/*feePayer=*/ AztecAddress.zero(),
|
|
658
|
-
/*
|
|
664
|
+
/*expirationTimestamp=*/ 0n,
|
|
659
665
|
hasPublicCalls ? inputsForPublic : undefined,
|
|
660
666
|
!hasPublicCalls ? inputsForRollup : undefined,
|
|
661
667
|
);
|
|
@@ -817,7 +823,7 @@ function meterGasUsed(data: PrivateToRollupAccumulatedData | PrivateToPublicAccu
|
|
|
817
823
|
);
|
|
818
824
|
meteredL2Gas += numContractClassLogs * L2_GAS_PER_CONTRACT_CLASS_LOG;
|
|
819
825
|
|
|
820
|
-
const meteredDAGas = meteredDAFields *
|
|
826
|
+
const meteredDAGas = meteredDAFields * DA_GAS_PER_FIELD;
|
|
821
827
|
|
|
822
828
|
if ((data as PrivateToPublicAccumulatedData).publicCallRequests) {
|
|
823
829
|
const dataForPublic = data as PrivateToPublicAccumulatedData;
|
|
@@ -5,7 +5,7 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
|
5
5
|
import { TxHash } from '@aztec/stdlib/tx';
|
|
6
6
|
|
|
7
7
|
// TODO(#14617): should we compute this from constants? This value is aztec-nr specific.
|
|
8
|
-
const MAX_EVENT_SERIALIZED_LEN =
|
|
8
|
+
const MAX_EVENT_SERIALIZED_LEN = 11;
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Intermediate struct used to perform batch event validation by PXE. The `utilityValidateAndStoreEnqueuedNotesAndEvents` oracle
|
|
@@ -4,7 +4,7 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
|
4
4
|
import { TxHash } from '@aztec/stdlib/tx';
|
|
5
5
|
|
|
6
6
|
// TODO(#14617): should we compute this from constants? This value is aztec-nr specific.
|
|
7
|
-
export const MAX_NOTE_PACKED_LEN =
|
|
7
|
+
export const MAX_NOTE_PACKED_LEN = 9;
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Intermediate struct used to perform batch note validation by PXE. The `utilityValidateAndStoreEnqueuedNotesAndEvents` oracle
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
type TxContext,
|
|
26
26
|
} from '@aztec/stdlib/tx';
|
|
27
27
|
|
|
28
|
+
import type { AccessScopes } from '../../access_scopes.js';
|
|
28
29
|
import type { ContractSyncService } from '../../contract_sync/contract_sync_service.js';
|
|
29
30
|
import { NoteService } from '../../notes/note_service.js';
|
|
30
31
|
import type { SenderTaggingStore } from '../../storage/tagging_store/sender_tagging_store.js';
|
|
@@ -43,7 +44,7 @@ export type PrivateExecutionOracleArgs = Omit<UtilityExecutionOracleArgs, 'contr
|
|
|
43
44
|
txContext: TxContext;
|
|
44
45
|
callContext: CallContext;
|
|
45
46
|
/** Needed to trigger contract synchronization before nested calls */
|
|
46
|
-
utilityExecutor: (call: FunctionCall, scopes:
|
|
47
|
+
utilityExecutor: (call: FunctionCall, scopes: AccessScopes) => Promise<void>;
|
|
47
48
|
executionCache: HashedValuesCache;
|
|
48
49
|
noteCache: ExecutionNoteCache;
|
|
49
50
|
taggingIndexCache: ExecutionTaggingIndexCache;
|
|
@@ -78,7 +79,7 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
|
|
|
78
79
|
private readonly argsHash: Fr;
|
|
79
80
|
private readonly txContext: TxContext;
|
|
80
81
|
private readonly callContext: CallContext;
|
|
81
|
-
private readonly utilityExecutor: (call: FunctionCall, scopes:
|
|
82
|
+
private readonly utilityExecutor: (call: FunctionCall, scopes: AccessScopes) => Promise<void>;
|
|
82
83
|
private readonly executionCache: HashedValuesCache;
|
|
83
84
|
private readonly noteCache: ExecutionNoteCache;
|
|
84
85
|
private readonly taggingIndexCache: ExecutionTaggingIndexCache;
|
|
@@ -526,22 +527,13 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
|
|
|
526
527
|
|
|
527
528
|
isStaticCall = isStaticCall || this.callContext.isStaticCall;
|
|
528
529
|
|
|
529
|
-
// When scopes are set and the target contract is a registered account (has keys in the keyStore),
|
|
530
|
-
// expand scopes to include it so nested private calls can sync and read the contract's own notes.
|
|
531
|
-
// We only expand for registered accounts because the log service needs the recipient's keys to derive
|
|
532
|
-
// tagging secrets, which are only available for registered accounts.
|
|
533
|
-
const expandedScopes =
|
|
534
|
-
this.scopes && (await this.keyStore.hasAccount(targetContractAddress))
|
|
535
|
-
? [...this.scopes, targetContractAddress]
|
|
536
|
-
: this.scopes;
|
|
537
|
-
|
|
538
530
|
await this.contractSyncService.ensureContractSynced(
|
|
539
531
|
targetContractAddress,
|
|
540
532
|
functionSelector,
|
|
541
533
|
this.utilityExecutor,
|
|
542
534
|
this.anchorBlockHeader,
|
|
543
535
|
this.jobId,
|
|
544
|
-
|
|
536
|
+
this.scopes,
|
|
545
537
|
);
|
|
546
538
|
|
|
547
539
|
const targetArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(
|
|
@@ -579,7 +571,7 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
|
|
|
579
571
|
totalPublicCalldataCount: this.totalPublicCalldataCount,
|
|
580
572
|
sideEffectCounter,
|
|
581
573
|
log: this.log,
|
|
582
|
-
scopes:
|
|
574
|
+
scopes: this.scopes,
|
|
583
575
|
senderForTags: this.senderForTags,
|
|
584
576
|
simulator: this.simulator!,
|
|
585
577
|
});
|
|
@@ -3,7 +3,7 @@ import type { BlockNumber } from '@aztec/foundation/branded-types';
|
|
|
3
3
|
import { Aes128 } from '@aztec/foundation/crypto/aes128';
|
|
4
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
5
|
import { Point } from '@aztec/foundation/curves/grumpkin';
|
|
6
|
-
import { LogLevels, type Logger,
|
|
6
|
+
import { LogLevels, type Logger, createLogger } from '@aztec/foundation/log';
|
|
7
7
|
import type { MembershipWitness } from '@aztec/foundation/trees';
|
|
8
8
|
import type { KeyStore } from '@aztec/key-store';
|
|
9
9
|
import type { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
@@ -20,6 +20,8 @@ import type { NoteStatus } from '@aztec/stdlib/note';
|
|
|
20
20
|
import { MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
|
|
21
21
|
import type { BlockHeader, Capsule } from '@aztec/stdlib/tx';
|
|
22
22
|
|
|
23
|
+
import type { AccessScopes } from '../../access_scopes.js';
|
|
24
|
+
import { createContractLogger, logContractMessage } from '../../contract_logging.js';
|
|
23
25
|
import { EventService } from '../../events/event_service.js';
|
|
24
26
|
import { LogService } from '../../logs/log_service.js';
|
|
25
27
|
import { NoteService } from '../../notes/note_service.js';
|
|
@@ -58,7 +60,7 @@ export type UtilityExecutionOracleArgs = {
|
|
|
58
60
|
privateEventStore: PrivateEventStore;
|
|
59
61
|
jobId: string;
|
|
60
62
|
log?: ReturnType<typeof createLogger>;
|
|
61
|
-
scopes
|
|
63
|
+
scopes: AccessScopes;
|
|
62
64
|
};
|
|
63
65
|
|
|
64
66
|
/**
|
|
@@ -85,7 +87,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
85
87
|
protected readonly privateEventStore: PrivateEventStore;
|
|
86
88
|
protected readonly jobId: string;
|
|
87
89
|
protected log: ReturnType<typeof createLogger>;
|
|
88
|
-
protected readonly scopes
|
|
90
|
+
protected readonly scopes: AccessScopes;
|
|
89
91
|
|
|
90
92
|
constructor(args: UtilityExecutionOracleArgs) {
|
|
91
93
|
this.contractAddress = args.contractAddress;
|
|
@@ -129,7 +131,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
129
131
|
*/
|
|
130
132
|
public async utilityGetKeyValidationRequest(pkMHash: Fr): Promise<KeyValidationRequest> {
|
|
131
133
|
// If scopes are defined, check that the key belongs to an account in the scopes.
|
|
132
|
-
if (this.scopes && this.scopes.length > 0) {
|
|
134
|
+
if (this.scopes !== 'ALL_SCOPES' && this.scopes.length > 0) {
|
|
133
135
|
let hasAccess = false;
|
|
134
136
|
for (let i = 0; i < this.scopes.length && !hasAccess; i++) {
|
|
135
137
|
if (await this.keyStore.accountHasKey(this.scopes[i], pkMHash)) {
|
|
@@ -401,12 +403,13 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
401
403
|
*/
|
|
402
404
|
async #getContractLogger(): Promise<Logger> {
|
|
403
405
|
if (!this.contractLogger) {
|
|
404
|
-
const addrAbbrev = this.contractAddress.toString().slice(0, 10);
|
|
405
|
-
const name = await this.contractStore.getDebugContractName(this.contractAddress);
|
|
406
|
-
const module = name ? `contract_log::${name}(${addrAbbrev})` : `contract_log::${addrAbbrev}`;
|
|
407
406
|
// Purpose of instanceId is to distinguish logs from different instances of the same component. It makes sense
|
|
408
407
|
// to re-use jobId as instanceId here as executions of different PXE jobs are isolated.
|
|
409
|
-
this.contractLogger =
|
|
408
|
+
this.contractLogger = await createContractLogger(
|
|
409
|
+
this.contractAddress,
|
|
410
|
+
addr => this.contractStore.getDebugContractName(addr),
|
|
411
|
+
{ instanceId: this.jobId },
|
|
412
|
+
);
|
|
410
413
|
}
|
|
411
414
|
return this.contractLogger;
|
|
412
415
|
}
|
|
@@ -415,9 +418,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
415
418
|
if (!LogLevels[level]) {
|
|
416
419
|
throw new Error(`Invalid log level: ${level}`);
|
|
417
420
|
}
|
|
418
|
-
const levelName = LogLevels[level];
|
|
419
421
|
const logger = await this.#getContractLogger();
|
|
420
|
-
logger[
|
|
422
|
+
logContractMessage(logger, LogLevels[level], message, fields);
|
|
421
423
|
}
|
|
422
424
|
|
|
423
425
|
public async utilityFetchTaggedLogs(pendingTaggedLogArrayBaseSlot: Fr) {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
|
+
import { type LogLevel, type Logger, applyStringFormatting, createLogger } from '@aztec/foundation/log';
|
|
3
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
4
|
+
import type { DebugLog } from '@aztec/stdlib/logs';
|
|
5
|
+
|
|
6
|
+
/** Resolves a contract address to a human-readable name, if available. */
|
|
7
|
+
export type ContractNameResolver = (address: AztecAddress) => Promise<string | undefined>;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates a logger whose output is prefixed with `contract_log::<name>(<addrAbbrev>)`.
|
|
11
|
+
*/
|
|
12
|
+
export async function createContractLogger(
|
|
13
|
+
contractAddress: AztecAddress,
|
|
14
|
+
getContractName: ContractNameResolver,
|
|
15
|
+
options?: { instanceId?: string },
|
|
16
|
+
): Promise<Logger> {
|
|
17
|
+
const addrAbbrev = contractAddress.toString().slice(0, 10);
|
|
18
|
+
const name = await getContractName(contractAddress);
|
|
19
|
+
const module = name ? `contract_log::${name}(${addrAbbrev})` : `contract_log::Unknown(${addrAbbrev})`;
|
|
20
|
+
return createLogger(module, options);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Formats and emits a single contract log message through the given logger.
|
|
25
|
+
*/
|
|
26
|
+
export function logContractMessage(logger: Logger, level: LogLevel, message: string, fields: Fr[]): void {
|
|
27
|
+
logger[level](applyStringFormatting(message, fields));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Displays debug logs collected during public function simulation,
|
|
32
|
+
* using the `contract_log::` prefixed logger format.
|
|
33
|
+
*/
|
|
34
|
+
export async function displayDebugLogs(debugLogs: DebugLog[], getContractName: ContractNameResolver): Promise<void> {
|
|
35
|
+
for (const log of debugLogs) {
|
|
36
|
+
const logger = await createContractLogger(log.contractAddress, getContractName);
|
|
37
|
+
logContractMessage(logger, log.level, log.message, log.fields);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -4,6 +4,7 @@ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
|
4
4
|
import type { AztecNode } from '@aztec/stdlib/interfaces/client';
|
|
5
5
|
import type { BlockHeader } from '@aztec/stdlib/tx';
|
|
6
6
|
|
|
7
|
+
import type { AccessScopes } from '../access_scopes.js';
|
|
7
8
|
import type { StagedStore } from '../job_coordinator/job_coordinator.js';
|
|
8
9
|
import type { ContractStore } from '../storage/contract_store/contract_store.js';
|
|
9
10
|
import type { NoteStore } from '../storage/note_store/note_store.js';
|
|
@@ -45,15 +46,15 @@ export class ContractSyncService implements StagedStore {
|
|
|
45
46
|
* @param functionToInvokeAfterSync - The function selector that will be called after sync (used to validate it's
|
|
46
47
|
* not sync_state itself).
|
|
47
48
|
* @param utilityExecutor - Executor function for running the sync_state utility function.
|
|
48
|
-
* @param scopes -
|
|
49
|
+
* @param scopes - Access scopes to pass through to the utility executor (affects whose account's private state is discovered).
|
|
49
50
|
*/
|
|
50
51
|
async ensureContractSynced(
|
|
51
52
|
contractAddress: AztecAddress,
|
|
52
53
|
functionToInvokeAfterSync: FunctionSelector | null,
|
|
53
|
-
utilityExecutor: (call: FunctionCall, scopes:
|
|
54
|
+
utilityExecutor: (call: FunctionCall, scopes: AccessScopes) => Promise<any>,
|
|
54
55
|
anchorBlockHeader: BlockHeader,
|
|
55
56
|
jobId: string,
|
|
56
|
-
scopes:
|
|
57
|
+
scopes: AccessScopes,
|
|
57
58
|
): Promise<void> {
|
|
58
59
|
// Skip sync if this contract has an override for this job (overrides are keyed by contract address only)
|
|
59
60
|
const overrides = this.overriddenContracts.get(jobId);
|
|
@@ -62,13 +63,16 @@ export class ContractSyncService implements StagedStore {
|
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
// Skip sync if we already synced for "all scopes", or if we have an empty list of scopes
|
|
65
|
-
const allScopesKey = toKey(contractAddress,
|
|
66
|
+
const allScopesKey = toKey(contractAddress, 'ALL_SCOPES');
|
|
66
67
|
const allScopesExisting = this.syncedContracts.get(allScopesKey);
|
|
67
|
-
if (allScopesExisting || (scopes && scopes.length == 0)) {
|
|
68
|
+
if (allScopesExisting || (scopes !== 'ALL_SCOPES' && scopes.length == 0)) {
|
|
68
69
|
return;
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
const unsyncedScopes =
|
|
72
|
+
const unsyncedScopes =
|
|
73
|
+
scopes === 'ALL_SCOPES'
|
|
74
|
+
? scopes
|
|
75
|
+
: scopes.filter(scope => !this.syncedContracts.has(toKey(contractAddress, scope)));
|
|
72
76
|
const unsyncedScopesKeys = toKeys(contractAddress, unsyncedScopes);
|
|
73
77
|
|
|
74
78
|
if (unsyncedScopesKeys.length > 0) {
|
|
@@ -76,9 +80,10 @@ export class ContractSyncService implements StagedStore {
|
|
|
76
80
|
const promise = this.#doSync(
|
|
77
81
|
contractAddress,
|
|
78
82
|
functionToInvokeAfterSync,
|
|
79
|
-
|
|
83
|
+
utilityExecutor,
|
|
80
84
|
anchorBlockHeader,
|
|
81
85
|
jobId,
|
|
86
|
+
unsyncedScopes,
|
|
82
87
|
).catch(err => {
|
|
83
88
|
// There was an error syncing the contract, so we remove it from the cache so that it can be retried.
|
|
84
89
|
unsyncedScopesKeys.forEach(key => this.syncedContracts.delete(key));
|
|
@@ -94,9 +99,10 @@ export class ContractSyncService implements StagedStore {
|
|
|
94
99
|
async #doSync(
|
|
95
100
|
contractAddress: AztecAddress,
|
|
96
101
|
functionToInvokeAfterSync: FunctionSelector | null,
|
|
97
|
-
utilityExecutor: (call: FunctionCall) => Promise<any>,
|
|
102
|
+
utilityExecutor: (call: FunctionCall, scopes: AccessScopes) => Promise<any>,
|
|
98
103
|
anchorBlockHeader: BlockHeader,
|
|
99
104
|
jobId: string,
|
|
105
|
+
scopes: AccessScopes,
|
|
100
106
|
): Promise<void> {
|
|
101
107
|
this.log.debug(`Syncing contract ${contractAddress}`);
|
|
102
108
|
await Promise.all([
|
|
@@ -109,6 +115,7 @@ export class ContractSyncService implements StagedStore {
|
|
|
109
115
|
this.aztecNode,
|
|
110
116
|
anchorBlockHeader,
|
|
111
117
|
jobId,
|
|
118
|
+
scopes,
|
|
112
119
|
),
|
|
113
120
|
verifyCurrentClassId(contractAddress, this.aztecNode, this.contractStore, anchorBlockHeader),
|
|
114
121
|
]);
|
|
@@ -136,10 +143,10 @@ export class ContractSyncService implements StagedStore {
|
|
|
136
143
|
}
|
|
137
144
|
}
|
|
138
145
|
|
|
139
|
-
function toKeys(contract: AztecAddress, scopes:
|
|
140
|
-
return scopes ===
|
|
146
|
+
function toKeys(contract: AztecAddress, scopes: AccessScopes) {
|
|
147
|
+
return scopes === 'ALL_SCOPES' ? [toKey(contract, scopes)] : scopes.map(scope => toKey(contract, scope));
|
|
141
148
|
}
|
|
142
149
|
|
|
143
|
-
function toKey(contract: AztecAddress, scope: AztecAddress |
|
|
144
|
-
return scope ===
|
|
150
|
+
function toKey(contract: AztecAddress, scope: AztecAddress | 'ALL_SCOPES') {
|
|
151
|
+
return scope === 'ALL_SCOPES' ? `${contract.toString()}:*` : `${contract.toString()}:${scope.toString()}`;
|
|
145
152
|
}
|
|
@@ -6,6 +6,7 @@ import { DelayedPublicMutableValues, DelayedPublicMutableValuesWithHash } from '
|
|
|
6
6
|
import type { AztecNode } from '@aztec/stdlib/interfaces/client';
|
|
7
7
|
import type { BlockHeader } from '@aztec/stdlib/tx';
|
|
8
8
|
|
|
9
|
+
import type { AccessScopes } from '../access_scopes.js';
|
|
9
10
|
import { NoteService } from '../notes/note_service.js';
|
|
10
11
|
import type { ContractStore } from '../storage/contract_store/contract_store.js';
|
|
11
12
|
import type { NoteStore } from '../storage/note_store/note_store.js';
|
|
@@ -42,11 +43,12 @@ export async function syncState(
|
|
|
42
43
|
contractAddress: AztecAddress,
|
|
43
44
|
contractStore: ContractStore,
|
|
44
45
|
functionToInvokeAfterSync: FunctionSelector | null,
|
|
45
|
-
utilityExecutor: (privateSyncCall: FunctionCall) => Promise<any>,
|
|
46
|
+
utilityExecutor: (privateSyncCall: FunctionCall, scopes: AccessScopes) => Promise<any>,
|
|
46
47
|
noteStore: NoteStore,
|
|
47
48
|
aztecNode: AztecNode,
|
|
48
49
|
anchorBlockHeader: BlockHeader,
|
|
49
50
|
jobId: string,
|
|
51
|
+
scopes: AccessScopes,
|
|
50
52
|
) {
|
|
51
53
|
// Protocol contracts don't have private state to sync
|
|
52
54
|
if (!isProtocolContract(contractAddress)) {
|
|
@@ -61,7 +63,10 @@ export async function syncState(
|
|
|
61
63
|
|
|
62
64
|
// Both sync_state and syncNoteNullifiers interact with the note store, but running them in parallel is safe
|
|
63
65
|
// because note store is designed to handle concurrent operations.
|
|
64
|
-
await Promise.all([
|
|
66
|
+
await Promise.all([
|
|
67
|
+
utilityExecutor(syncStateFunctionCall, scopes),
|
|
68
|
+
noteService.syncNoteNullifiers(contractAddress, scopes),
|
|
69
|
+
]);
|
|
65
70
|
}
|
|
66
71
|
}
|
|
67
72
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { FunctionCall } from '@aztec/stdlib/abi';
|
|
2
2
|
import type { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
3
|
-
import type {
|
|
4
|
-
import type { NoteDao, NotesFilter } from '@aztec/stdlib/note';
|
|
3
|
+
import type { NoteDao } from '@aztec/stdlib/note';
|
|
5
4
|
import type { ContractOverrides } from '@aztec/stdlib/tx';
|
|
6
5
|
|
|
6
|
+
import type { AccessScopes } from '../access_scopes.js';
|
|
7
7
|
import type { BlockSynchronizer } from '../block_synchronizer/block_synchronizer.js';
|
|
8
8
|
import type { ContractFunctionSimulator } from '../contract_function_simulator/contract_function_simulator.js';
|
|
9
9
|
import type { ContractSyncService } from '../contract_sync/contract_sync_service.js';
|
|
10
|
+
import type { NotesFilter } from '../notes_filter.js';
|
|
10
11
|
import type { AnchorBlockStore } from '../storage/index.js';
|
|
11
12
|
import type { NoteStore } from '../storage/note_store/note_store.js';
|
|
12
13
|
|
|
@@ -17,11 +18,11 @@ import type { NoteStore } from '../storage/note_store/note_store.js';
|
|
|
17
18
|
export class PXEDebugUtils {
|
|
18
19
|
#putJobInQueue!: <T>(job: (jobId: string) => Promise<T>) => Promise<T>;
|
|
19
20
|
#getSimulatorForTx!: (overrides?: { contracts?: ContractOverrides }) => ContractFunctionSimulator;
|
|
20
|
-
#
|
|
21
|
+
#executeUtility!: (
|
|
21
22
|
contractFunctionSimulator: ContractFunctionSimulator,
|
|
22
23
|
call: FunctionCall,
|
|
23
24
|
authWitnesses: AuthWitness[] | undefined,
|
|
24
|
-
scopes:
|
|
25
|
+
scopes: AccessScopes,
|
|
25
26
|
jobId: string,
|
|
26
27
|
) => Promise<any>;
|
|
27
28
|
|
|
@@ -36,17 +37,17 @@ export class PXEDebugUtils {
|
|
|
36
37
|
public setPXEHelpers(
|
|
37
38
|
putJobInQueue: <T>(job: (jobId: string) => Promise<T>) => Promise<T>,
|
|
38
39
|
getSimulatorForTx: (overrides?: { contracts?: ContractOverrides }) => ContractFunctionSimulator,
|
|
39
|
-
|
|
40
|
+
executeUtility: (
|
|
40
41
|
contractFunctionSimulator: ContractFunctionSimulator,
|
|
41
42
|
call: FunctionCall,
|
|
42
43
|
authWitnesses: AuthWitness[] | undefined,
|
|
43
|
-
scopes:
|
|
44
|
+
scopes: AccessScopes,
|
|
44
45
|
jobId: string,
|
|
45
46
|
) => Promise<any>,
|
|
46
47
|
) {
|
|
47
48
|
this.#putJobInQueue = putJobInQueue;
|
|
48
49
|
this.#getSimulatorForTx = getSimulatorForTx;
|
|
49
|
-
this.#
|
|
50
|
+
this.#executeUtility = executeUtility;
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
/**
|
|
@@ -72,7 +73,7 @@ export class PXEDebugUtils {
|
|
|
72
73
|
filter.contractAddress,
|
|
73
74
|
null,
|
|
74
75
|
async (privateSyncCall, execScopes) =>
|
|
75
|
-
await this.#
|
|
76
|
+
await this.#executeUtility(contractFunctionSimulator, privateSyncCall, [], execScopes, jobId),
|
|
76
77
|
anchorBlockHeader,
|
|
77
78
|
jobId,
|
|
78
79
|
filter.scopes,
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
export * from '../../../access_scopes.js';
|
|
2
|
+
export * from '../../../notes_filter.js';
|
|
1
3
|
export * from '../../../pxe.js';
|
|
2
4
|
export * from '../../../config/index.js';
|
|
3
5
|
export * from '../../../error_enriching.js';
|
|
6
|
+
export * from '../../../contract_logging.js';
|
|
4
7
|
export * from '../../../storage/index.js';
|
|
5
8
|
export * from './utils.js';
|
|
6
9
|
export type { PXECreationOptions } from '../../pxe_creation_options.js';
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
export * from '../../../access_scopes.js';
|
|
2
|
+
export * from '../../../notes_filter.js';
|
|
1
3
|
export * from '../../../pxe.js';
|
|
2
4
|
export * from '../../../config/index.js';
|
|
3
5
|
export * from '../../../storage/index.js';
|
|
4
6
|
export * from '../../../error_enriching.js';
|
|
7
|
+
export * from '../../../contract_logging.js';
|
|
5
8
|
export * from './utils.js';
|
|
6
9
|
export { type PXECreationOptions } from '../../pxe_creation_options.js';
|
package/src/logs/log_service.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type { AztecNode } from '@aztec/stdlib/interfaces/server';
|
|
|
6
6
|
import { DirectionalAppTaggingSecret, PendingTaggedLog, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs';
|
|
7
7
|
import type { BlockHeader } from '@aztec/stdlib/tx';
|
|
8
8
|
|
|
9
|
+
import type { AccessScopes } from '../access_scopes.js';
|
|
9
10
|
import type { LogRetrievalRequest } from '../contract_function_simulator/noir-structs/log_retrieval_request.js';
|
|
10
11
|
import { LogRetrievalResponse } from '../contract_function_simulator/noir-structs/log_retrieval_response.js';
|
|
11
12
|
import { AddressStore } from '../storage/address_store/address_store.js';
|
|
@@ -107,11 +108,7 @@ export class LogService {
|
|
|
107
108
|
);
|
|
108
109
|
}
|
|
109
110
|
|
|
110
|
-
public async fetchTaggedLogs(
|
|
111
|
-
contractAddress: AztecAddress,
|
|
112
|
-
pendingTaggedLogArrayBaseSlot: Fr,
|
|
113
|
-
scopes?: AztecAddress[],
|
|
114
|
-
) {
|
|
111
|
+
public async fetchTaggedLogs(contractAddress: AztecAddress, pendingTaggedLogArrayBaseSlot: Fr, scopes: AccessScopes) {
|
|
115
112
|
this.log.verbose(`Fetching tagged logs for ${contractAddress.toString()}`);
|
|
116
113
|
|
|
117
114
|
// We only load logs from block up to and including the anchor block number
|
|
@@ -119,7 +116,7 @@ export class LogService {
|
|
|
119
116
|
const anchorBlockHash = await this.anchorBlockHeader.hash();
|
|
120
117
|
|
|
121
118
|
// Determine recipients: use scopes if provided, otherwise get all accounts
|
|
122
|
-
const recipients = scopes && scopes.length > 0 ? scopes : await this.keyStore.getAccounts();
|
|
119
|
+
const recipients = scopes !== 'ALL_SCOPES' && scopes.length > 0 ? scopes : await this.keyStore.getAccounts();
|
|
123
120
|
|
|
124
121
|
// For each recipient, fetch secrets, load logs, and store them.
|
|
125
122
|
// We run these per-recipient tasks in parallel so that logs are loaded for all recipients concurrently.
|
|
@@ -7,6 +7,7 @@ import { Note, NoteDao, NoteStatus } from '@aztec/stdlib/note';
|
|
|
7
7
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
8
8
|
import type { BlockHeader, TxHash } from '@aztec/stdlib/tx';
|
|
9
9
|
|
|
10
|
+
import type { AccessScopes } from '../access_scopes.js';
|
|
10
11
|
import type { NoteStore } from '../storage/note_store/note_store.js';
|
|
11
12
|
|
|
12
13
|
export class NoteService {
|
|
@@ -31,7 +32,7 @@ export class NoteService {
|
|
|
31
32
|
owner: AztecAddress | undefined,
|
|
32
33
|
storageSlot: Fr,
|
|
33
34
|
status: NoteStatus,
|
|
34
|
-
scopes
|
|
35
|
+
scopes: AccessScopes,
|
|
35
36
|
) {
|
|
36
37
|
const noteDaos = await this.noteStore.getNotes(
|
|
37
38
|
{
|
|
@@ -70,10 +71,10 @@ export class NoteService {
|
|
|
70
71
|
*
|
|
71
72
|
* @param contractAddress - The contract whose notes should be checked and nullified.
|
|
72
73
|
*/
|
|
73
|
-
public async syncNoteNullifiers(contractAddress: AztecAddress): Promise<void> {
|
|
74
|
+
public async syncNoteNullifiers(contractAddress: AztecAddress, scopes: AccessScopes): Promise<void> {
|
|
74
75
|
const anchorBlockHash = await this.anchorBlockHeader.hash();
|
|
75
76
|
|
|
76
|
-
const contractNotes = await this.noteStore.getNotes({ contractAddress }, this.jobId);
|
|
77
|
+
const contractNotes = await this.noteStore.getNotes({ contractAddress, scopes }, this.jobId);
|
|
77
78
|
|
|
78
79
|
if (contractNotes.length === 0) {
|
|
79
80
|
return;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
3
|
+
import type { NoteStatus } from '@aztec/stdlib/note';
|
|
4
|
+
|
|
5
|
+
import type { AccessScopes } from './access_scopes.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A filter used to fetch notes.
|
|
9
|
+
* @remarks This filter is applied as an intersection of all its params.
|
|
10
|
+
*/
|
|
11
|
+
export type NotesFilter = {
|
|
12
|
+
/**
|
|
13
|
+
* The contract address the note belongs to.
|
|
14
|
+
* @remarks Providing a contract address is required as we need that information to trigger private state sync.
|
|
15
|
+
*/
|
|
16
|
+
contractAddress: AztecAddress;
|
|
17
|
+
/** The owner of the note. */
|
|
18
|
+
owner?: AztecAddress;
|
|
19
|
+
/** The specific storage location of the note on the contract. */
|
|
20
|
+
storageSlot?: Fr;
|
|
21
|
+
/** The status of the note. Defaults to 'ACTIVE'. */
|
|
22
|
+
status?: NoteStatus;
|
|
23
|
+
/** The siloed nullifier for the note. */
|
|
24
|
+
siloedNullifier?: Fr;
|
|
25
|
+
scopes: AccessScopes;
|
|
26
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MAX_TX_LIFETIME } from '@aztec/constants';
|
|
2
2
|
import type { PrivateKernelCircuitPublicInputs } from '@aztec/stdlib/kernel';
|
|
3
3
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
4
4
|
|
|
@@ -8,12 +8,12 @@ const ROUNDED_DURATIONS = [
|
|
|
8
8
|
1, // 1 second
|
|
9
9
|
];
|
|
10
10
|
|
|
11
|
-
function roundTimestamp(blockTimestamp: bigint,
|
|
11
|
+
function roundTimestamp(blockTimestamp: bigint, expirationTimestamp: bigint): UInt64 {
|
|
12
12
|
return ROUNDED_DURATIONS.reduce((timestamp, duration) => {
|
|
13
13
|
if (timestamp <= blockTimestamp) {
|
|
14
14
|
// The timestamp must be greater than the block timestamp.
|
|
15
15
|
// If it is too small, round it down again using a smaller duration.
|
|
16
|
-
const totalDuration =
|
|
16
|
+
const totalDuration = expirationTimestamp - blockTimestamp;
|
|
17
17
|
const roundedDuration = totalDuration - (totalDuration % BigInt(duration));
|
|
18
18
|
return blockTimestamp + roundedDuration;
|
|
19
19
|
}
|
|
@@ -21,36 +21,36 @@ function roundTimestamp(blockTimestamp: bigint, includeByTimestamp: bigint): UIn
|
|
|
21
21
|
}, 0n);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export function
|
|
24
|
+
export function computeTxExpirationTimestamp(
|
|
25
25
|
previousKernel: PrivateKernelCircuitPublicInputs,
|
|
26
|
-
|
|
26
|
+
txLifetime = MAX_TX_LIFETIME,
|
|
27
27
|
): UInt64 {
|
|
28
|
-
if (
|
|
28
|
+
if (txLifetime > MAX_TX_LIFETIME) {
|
|
29
29
|
throw new Error(
|
|
30
|
-
`Custom
|
|
30
|
+
`Custom tx lifetime cannot be greater than the max allowed. Max allowed: ${MAX_TX_LIFETIME}. Custom value: ${txLifetime}.`,
|
|
31
31
|
);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
const anchorBlockTimestamp = previousKernel.constants.anchorBlockHeader.globalVariables.timestamp;
|
|
35
|
-
const maxTimestamp = anchorBlockTimestamp + BigInt(
|
|
36
|
-
const
|
|
35
|
+
const maxTimestamp = anchorBlockTimestamp + BigInt(txLifetime);
|
|
36
|
+
const expirationTimestamp = previousKernel.expirationTimestamp;
|
|
37
37
|
|
|
38
|
-
// If the
|
|
38
|
+
// If the expirationTimestamp set during the tx execution is greater than or equal to the max allowed duration,
|
|
39
39
|
// use the maximum allowed timestamp.
|
|
40
40
|
// Note: It shouldn't be larger than the max allowed duration, but we check for it anyway.
|
|
41
|
-
if (
|
|
41
|
+
if (expirationTimestamp >= maxTimestamp) {
|
|
42
42
|
return maxTimestamp;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
// Round it down to the nearest hour/min/second to reduce precision and avoid revealing the exact value.
|
|
46
46
|
// This makes it harder for others to infer what function calls may have been used to produce a specific timestamp.
|
|
47
|
-
const roundedTimestamp = roundTimestamp(anchorBlockTimestamp,
|
|
47
|
+
const roundedTimestamp = roundTimestamp(anchorBlockTimestamp, expirationTimestamp);
|
|
48
48
|
|
|
49
49
|
// The tx can't be published if the timestamp is the same or less than the anchor block's timestamp.
|
|
50
50
|
// Future blocks will have a greater timestamp, so the tx would never be included.
|
|
51
51
|
if (roundedTimestamp <= anchorBlockTimestamp) {
|
|
52
52
|
throw new Error(
|
|
53
|
-
`Include-by timestamp must be greater than the anchor block timestamp. Anchor block timestamp: ${anchorBlockTimestamp}. Include-by timestamp: ${
|
|
53
|
+
`Include-by timestamp must be greater than the anchor block timestamp. Anchor block timestamp: ${anchorBlockTimestamp}. Include-by timestamp: ${expirationTimestamp}.`,
|
|
54
54
|
);
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from './private_kernel_reset_private_inputs_builder.js';
|
|
2
|
-
export * from './
|
|
2
|
+
export * from './compute_tx_expiration_timestamp.js';
|