Skip to content
Closed
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
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@
"SSTORE",
"staticcall",
"stdlib",
"stringly",
"struct",
"structs",
"subarrays",
Expand Down
41 changes: 22 additions & 19 deletions yarn-project/aztec/src/cli/cmds/start_node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { mnemonicToAccount, privateKeyToAccount } from 'viem/accounts';
import { MNEMONIC, createAztecNode, createAztecPXE, deployContractsToL1 } from '../../sandbox.js';
import { mergeEnvVarsAndCliOptions, parseModuleOptions } from '../util.js';

const { DEPLOY_AZTEC_CONTRACTS } = process.env;
const { DEPLOY_AZTEC_CONTRACTS = '' } = process.env;

export const startNode = async (
options: any,
Expand All @@ -23,7 +23,26 @@ export const startNode = async (
// get config from options
const nodeCliOptions = parseModuleOptions(options.node);
// merge env vars and cli options
let nodeConfig = mergeEnvVarsAndCliOptions<AztecNodeConfig>(aztecNodeConfigEnvVars, nodeCliOptions);
let nodeConfig = mergeEnvVarsAndCliOptions<AztecNodeConfig>(aztecNodeConfigEnvVars, {
...nodeCliOptions,
...parseModuleOptions(options.archiver),
...parseModuleOptions(options.sequencer),
...parseModuleOptions(options.prover),
});

let hdAccount;
if (nodeConfig.publisherPrivateKey === NULL_KEY) {
hdAccount = mnemonicToAccount(MNEMONIC);
const privKey = hdAccount.getHdKey().privateKey;
nodeConfig.publisherPrivateKey = `0x${Buffer.from(privKey!).toString('hex')}`;
} else {
hdAccount = privateKeyToAccount(nodeConfig.publisherPrivateKey);
}

// Deploy contracts if needed
if (nodeCliOptions.deployAztecContracts || ['1', 'true'].includes(DEPLOY_AZTEC_CONTRACTS)) {
await deployContractsToL1(nodeConfig, hdAccount);
}

// if no publisher private key, then use MNEMONIC
if (!options.archiver) {
Expand All @@ -36,27 +55,11 @@ export const startNode = async (
nodeConfig.archiverUrl = archiverUrl;
} else {
const archiverCliOptions = parseModuleOptions(options.archiver);
nodeConfig = mergeEnvVarsAndCliOptions<AztecNodeConfig>(aztecNodeConfigEnvVars, archiverCliOptions, true);
}

// Deploy contracts if needed
if (nodeCliOptions.deployAztecContracts || DEPLOY_AZTEC_CONTRACTS === 'true') {
let account;
if (nodeConfig.publisherPrivateKey === NULL_KEY) {
account = mnemonicToAccount(MNEMONIC);
} else {
account = privateKeyToAccount(nodeConfig.publisherPrivateKey);
}
await deployContractsToL1(nodeConfig, account);
nodeConfig = mergeEnvVarsAndCliOptions<AztecNodeConfig>(nodeConfig, archiverCliOptions, true);
}

if (!options.sequencer) {
nodeConfig.disableSequencer = true;
} else if (nodeConfig.publisherPrivateKey === NULL_KEY) {
// If we have a sequencer, ensure there's a publisher private key set.
const hdAccount = mnemonicToAccount(MNEMONIC);
const privKey = hdAccount.getHdKey().privateKey;
nodeConfig.publisherPrivateKey = `0x${Buffer.from(privKey!).toString('hex')}`;
}

if (!options.prover) {
Expand Down
53 changes: 37 additions & 16 deletions yarn-project/circuit-types/src/interfaces/configs.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,48 @@
import { AztecAddress, EthAddress, Fr } from '@aztec/circuits.js';
import { aztecAddress, ethAddress, fr, stringlyNumber, z } from '@aztec/foundation/zod';

/**
* The sequencer configuration.
*/
export interface SequencerConfig {
export const sequencerConfig = z.object({
/** The number of ms to wait between polling for pending txs. */
transactionPollingIntervalMS?: number;
transactionPollingIntervalMS: stringlyNumber.optional().default(1_000),
/** The maximum number of txs to include in a block. */
maxTxsPerBlock?: number;
maxTxsPerBlock: stringlyNumber.optional().default(32),
/** The minimum number of txs to include in a block. */
minTxsPerBlock?: number;
minTxsPerBlock: stringlyNumber.optional().default(1),
/** Recipient of block reward. */
coinbase?: EthAddress;
coinbase: ethAddress.optional(),
/** Address to receive fees. */
feeRecipient?: AztecAddress;
feeRecipient: aztecAddress.optional(),
/** The working directory to use for simulation/proving */
acvmWorkingDirectory?: string;
acvmWorkingDirectory: z.string().optional(),
/** The path to the ACVM binary */
acvmBinaryPath?: string;
acvmBinaryPath: z.string().optional(),

/** The list of permitted fee payment contract classes */
allowedFeePaymentContractClasses?: Fr[];

allowedFeePaymentContractClasses: z
.preprocess(val => {
if (typeof val === 'string') {
return val.split(',');
} else {
return z.NEVER;
}
}, z.array(fr))
.or(z.array(fr))
.optional()
.default([]),
/** The list of permitted fee payment contract instances. Takes precedence over contract classes */
allowedFeePaymentContractInstances?: AztecAddress[];
}
allowedFeePaymentContractInstances: z
.preprocess(val => {
if (typeof val === 'string') {
return val.split(',');
} else {
return z.NEVER;
}
}, z.array(aztecAddress))
.or(z.array(aztecAddress))
.optional()
.default([]),
});

/**
* The sequencer configuration.
*/
export type SequencerConfig = z.infer<typeof sequencerConfig>;
13 changes: 13 additions & 0 deletions yarn-project/ethereum/src/l1_contract_addresses.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { EthAddress } from '@aztec/foundation/eth-address';
import { optionalEthAddress, z } from '@aztec/foundation/zod';

export const l1ContractsNames = [
'availabilityOracleAddress',
Expand All @@ -16,3 +17,15 @@ export const l1ContractsNames = [
export type L1ContractAddresses = {
[K in (typeof l1ContractsNames)[number]]: EthAddress;
};

export const l1ContractAddresses = z
.object<Record<(typeof l1ContractsNames)[number], typeof optionalEthAddress>>({
availabilityOracleAddress: optionalEthAddress,
rollupAddress: optionalEthAddress,
registryAddress: optionalEthAddress,
inboxAddress: optionalEthAddress,
outboxAddress: optionalEthAddress,
gasTokenAddress: optionalEthAddress,
gasPortalAddress: optionalEthAddress,
})
.default({});
3 changes: 2 additions & 1 deletion yarn-project/foundation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
"./noir": "./dest/noir/index.js",
"./testing": "./dest/testing/index.js",
"./array": "./dest/array/index.js",
"./validation": "./dest/validation/index.js"
"./validation": "./dest/validation/index.js",
"./zod": "./dest/zod/index.js"
},
"scripts": {
"build": "yarn clean && tsc -b",
Expand Down
24 changes: 24 additions & 0 deletions yarn-project/foundation/src/aztec-address/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,28 @@ export class AztecAddress extends Fr {
static random() {
return new AztecAddress(super.random().toBuffer());
}

static isAddress(address: string): boolean {
if (/^(0x)?[0-9a-f]{64}$/i.test(address)) {
return true;
}

return false;
}

static isAztecAddress(value: any): value is AztecAddress {
if (!value || typeof value !== 'object') {
return false;
}

if (value instanceof AztecAddress) {
return true;
}

if ('buffer' in value && Buffer.isBuffer(value.buffer) && value.buffer.length === AztecAddress.SIZE_IN_BYTES) {
return true;
}

return false;
}
}
21 changes: 21 additions & 0 deletions yarn-project/foundation/src/eth-address/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,27 @@ export class EthAddress {
}
}

/**
* Checks if the given value is an EthAddress instance even if the prototype chain is incorrect
* @param value - A value to check if it is an EthAddress instance.
* @returns Whether the value is an EthAddress instance.
*/
public static isEthAddress(value: any): value is EthAddress {
if (!value || typeof value !== 'object') {
return false;
}

if (value instanceof EthAddress) {
return true;
}

if ('buffer' in value && Buffer.isBuffer(value.buffer) && value.buffer.length === EthAddress.SIZE_IN_BYTES) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: might be safer here to try/catch fromBuffer. this is making assumptions about the validity checks in the constructor.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I understand correctly, would it look something like:

try {
  if ('toBuffer' in value && EthAddress.fromBuffer(value.toBuffer()) {
    return true;
  }
} catch {
  return false;
}

I think that will work and be safe but we'd be creating objects and discarding them immediately.

Copy link
Collaborator

Choose a reason for hiding this comment

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

That is what I had meant, but perhaps the best approach is to extract the validation code to a function that both this typeguard and the constructor use?

return true;
}

return false;
}

/**
* Checks if the EthAddress instance represents a zero address.
* A zero address consists of 20 bytes filled with zeros and is considered an invalid address.
Expand Down
30 changes: 30 additions & 0 deletions yarn-project/foundation/src/zod/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { z } from 'zod';

import { AztecAddress } from '../aztec-address/index.js';
import { EthAddress } from '../eth-address/index.js';
import { Fr } from '../fields/fields.js';

export const ethAddress = z
.custom<`0x${string}` | EthAddress>(
val => (typeof val === 'string' && EthAddress.isAddress(val)) || EthAddress.isEthAddress(val),
)
.transform(val => (typeof val === 'string' ? EthAddress.fromString(val) : val));

export const optionalEthAddress = ethAddress.optional().default(EthAddress.ZERO);

export const aztecAddress = z
.custom<`0x${string}` | AztecAddress>(
val => (typeof val === 'string' && AztecAddress.isAddress(val)) || AztecAddress.isAztecAddress(val),
)
.transform(val => (typeof val === 'string' ? AztecAddress.fromString(val) : val));

export const stringlyNumber = z.number().or(z.string()).pipe(z.coerce.number());

export const fr = z
.number()
.or(z.string())
.or(z.bigint())
.or(z.instanceof(Fr))
.transform(val => (typeof val === 'string' ? Fr.fromString(val) : new Fr(val)));

export { z };
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export class SequencerClient {
* Updates sequencer config.
* @param config - New parameters.
*/
public updateSequencerConfig(config: SequencerConfig) {
public updateSequencerConfig(config: Partial<SequencerConfig>) {
this.sequencer.updateConfig(config);
}

Expand Down
Loading