Skip to content

Commit

Permalink
allow p2p to use dns names
Browse files Browse the repository at this point in the history
expose endpoint for node ENR
  • Loading branch information
just-mitch committed Aug 19, 2024
1 parent 22c45d1 commit 6c0231f
Show file tree
Hide file tree
Showing 13 changed files with 106 additions and 24 deletions.
4 changes: 4 additions & 0 deletions yarn-project/aztec-node/src/aztec-node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@ export class AztecNodeService implements AztecNode {
return Promise.resolve(this.config.l1Contracts);
}

public getEncodedEnr(): Promise<string | undefined> {
return Promise.resolve(this.p2pClient.getEnr()?.encodeTxt());
}

/**
* Method to determine if the node is ready to accept transactions.
* @returns - Flag indicating the readiness for tx submission.
Expand Down
5 changes: 5 additions & 0 deletions yarn-project/circuit-types/src/interfaces/aztec-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,4 +341,9 @@ export interface AztecNode {
* @param address - Address of the deployed contract.
*/
getContract(address: AztecAddress): Promise<ContractInstanceWithAddress | undefined>;

/**
* Returns the ENR of this node for peer discovery, if available.
*/
getEncodedEnr(): Promise<string | undefined>;
}
21 changes: 15 additions & 6 deletions yarn-project/cli/src/cmds/pxe/get_node_info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,20 @@ export async function getNodeInfo(rpcUrl: string, debugLogger: DebugLogger, log:
log(`Node Version: ${info.nodeVersion}`);
log(`Chain Id: ${info.l1ChainId}`);
log(`Protocol Version: ${info.protocolVersion}`);
log(`Rollup Address: ${info.l1ContractAddresses.rollupAddress.toString()}`);
log(`Protocol Contract Addresses:`);
log(` Class Registerer: ${info.protocolContractAddresses.classRegisterer.toString()}`);
log(` Fee Juice: ${info.protocolContractAddresses.feeJuice.toString()}`);
log(`Node ENR: ${info.enr}`);
log(`L1 Contract Addresses:`);
log(` Rollup Address: ${info.l1ContractAddresses.rollupAddress.toString()}`);
log(` Registry Address: ${info.l1ContractAddresses.registryAddress.toString()}`);
log(` L1 -> L2 Inbox Address: ${info.l1ContractAddresses.inboxAddress.toString()}`);
log(` L2 -> L1 Outbox Address: ${info.l1ContractAddresses.outboxAddress.toString()}`);
log(` Availability Oracle Address: ${info.l1ContractAddresses.availabilityOracleAddress.toString()}`);
log(` Fee Juice Address: ${info.l1ContractAddresses.feeJuiceAddress.toString()}`);
log(` Gas Portal Address: ${info.l1ContractAddresses.feeJuicePortalAddress.toString()}`);

log(`L2 Contract Addresses:`);
log(` Class Registerer: ${info.protocolContractAddresses.classRegisterer.toString()}`);
log(` Fee Juice: ${info.protocolContractAddresses.feeJuice.toString()}`);
log(` Instance Deployer: ${info.protocolContractAddresses.instanceDeployer.toString()}`);
log(` Key Registry: ${info.protocolContractAddresses.keyRegistry.toString()}`);
log(` MultiCall: ${info.protocolContractAddresses.multiCallEntrypoint.toString()}`);
log(` Key Registry: ${info.protocolContractAddresses.keyRegistry.toString()}`);
log(` MultiCall: ${info.protocolContractAddresses.multiCallEntrypoint.toString()}`);
}
9 changes: 8 additions & 1 deletion yarn-project/p2p/src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { DiscV5Service } from '../service/discV5_service.js';
import { DummyP2PService } from '../service/dummy_service.js';
import { LibP2PService, createLibP2PPeerId } from '../service/index.js';
import { type TxPool } from '../tx_pool/index.js';
import { getPublicIp, splitAddressPort } from '../util.js';
import { getPublicIp, resolveAddressIfNecessary, splitAddressPort } from '../util.js';

export * from './p2p_client.js';

Expand All @@ -29,6 +29,13 @@ export const createP2PClient = async (
queryForIp,
} = config;

config.tcpAnnounceAddress = configTcpAnnounceAddress
? await resolveAddressIfNecessary(configTcpAnnounceAddress)
: undefined;
config.udpAnnounceAddress = configUdpAnnounceAddress
? await resolveAddressIfNecessary(configUdpAnnounceAddress)
: undefined;

// create variable for re-use if needed
let publicIp;

Expand Down
1 change: 1 addition & 0 deletions yarn-project/p2p/src/client/p2p_client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ describe('In-Memory P2P Client', () => {
stop: jest.fn(),
propagate: jest.fn(),
registerBlockReceivedCallback: jest.fn(),
getEnr: jest.fn(),
};

attestationPool = {
Expand Down
11 changes: 11 additions & 0 deletions yarn-project/p2p/src/client/p2p_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js/constants';
import { createDebugLogger } from '@aztec/foundation/log';
import { type AztecKVStore, type AztecSingleton } from '@aztec/kv-store';

import { ENR } from '@chainsafe/enr';

import { type AttestationPool } from '../attestation_pool/attestation_pool.js';
import { getP2PConfigEnvVars } from '../config.js';
import type { P2PService } from '../service/service.js';
Expand Down Expand Up @@ -124,6 +126,11 @@ export interface P2P {
* Returns the current status of the p2p client.
*/
getStatus(): Promise<P2PSyncState>;

/**
* Returns the ENR for this node, if any.
*/
getEnr(): ENR | undefined;
}

/**
Expand Down Expand Up @@ -324,6 +331,10 @@ export class P2PClient implements P2P {
return this.txPool.getTxStatus(txHash);
}

public getEnr(): ENR | undefined {
return this.p2pService.getEnr();
}

/**
* Deletes the 'txs' from the pool.
* NOT used if we use sendTx as reconcileTxPool will handle this.
Expand Down
1 change: 1 addition & 0 deletions yarn-project/p2p/src/service/discV5_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService
const multiAddrTcp = await enr.getFullMultiaddr('tcp');
const multiAddrUdp = await enr.getFullMultiaddr('udp');
this.logger.debug(`ENR multiaddr: ${multiAddrTcp?.toString()}, ${multiAddrUdp?.toString()}`);
this.onDiscovered(enr);
});
}

Expand Down
8 changes: 8 additions & 0 deletions yarn-project/p2p/src/service/dummy_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ export class DummyP2PService implements P2PService {
* Register a callback into the validator client for when a block proposal is received
*/
public registerBlockReceivedCallback(_: (block: BlockProposal) => Promise<BlockAttestation>) {}

public getEnr(): undefined {
return undefined;
}
}

/**
Expand Down Expand Up @@ -83,4 +87,8 @@ export class DummyPeerDiscoveryService extends EventEmitter implements PeerDisco
public getStatus(): PeerDiscoveryState {
return this.currentState;
}

public getEnr(): undefined {
return undefined;
}
}
5 changes: 5 additions & 0 deletions yarn-project/p2p/src/service/libp2p_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { SerialQueue } from '@aztec/foundation/queue';
import { RunningPromise } from '@aztec/foundation/running-promise';
import type { AztecKVStore } from '@aztec/kv-store';

import { ENR } from '@chainsafe/enr';
import { type GossipsubEvents, gossipsub } from '@chainsafe/libp2p-gossipsub';
import { noise } from '@chainsafe/libp2p-noise';
import { yamux } from '@chainsafe/libp2p-yamux';
Expand Down Expand Up @@ -208,6 +209,10 @@ export class LibP2PService implements P2PService {
return new LibP2PService(config, node, peerDiscoveryService, txPool, attestationPool);
}

public getEnr(): ENR | undefined {
return this.peerDiscoveryService.getEnr();
}

public registerBlockReceivedCallback(callback: (block: BlockProposal) => Promise<BlockAttestation | undefined>) {
this.blockReceivedCallback = callback;
this.logger.verbose('Block received callback registered');
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/p2p/src/service/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ export interface P2PService {

// Leaky abstraction: fix https://github.com/AztecProtocol/aztec-packages/issues/7963
registerBlockReceivedCallback(callback: (block: BlockProposal) => Promise<BlockAttestation>): void;

getEnr(): ENR | undefined;
}

/**
Expand Down Expand Up @@ -74,4 +76,6 @@ export interface PeerDiscoveryService extends EventEmitter {
emit(event: 'peer:discovered', enr: ENR): boolean;

getStatus(): PeerDiscoveryState;

getEnr(): ENR | undefined;
}
40 changes: 30 additions & 10 deletions yarn-project/p2p/src/util.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
import { resolve } from 'dns/promises';

/**
* Converts an address string to a multiaddr string.
* Example usage:
* const tcpAddr = '123.456.7.8:80' -> /ip4/123.456.7.8/tcp/80
* const udpAddr = '[2001:db8::1]:8080' -> /ip6/2001:db8::1/udp/8080
* const dnsAddr = 'example.com:443' -> /dns4/example.com/tcp/443
* @param address - The address string to convert. Has to be in the format <addr>:<port>.
* @param protocol - The protocol to use in the multiaddr string.
* @returns A multiaddr compliant string.
*/
export function convertToMultiaddr(address: string, protocol: 'tcp' | 'udp'): string {
const [addr, port] = splitAddressPort(address, false);

let multiaddrPrefix: string;

if (addr.includes(':')) {
// IPv6 address
multiaddrPrefix = 'ip6';
} else if (addr.match(/^[\d.]+$/)) {
// IPv4 address
multiaddrPrefix = 'ip4';
} else {
const multiaddrPrefix = addressToMultiAddressType(addr);
if (multiaddrPrefix === 'dns') {
throw new Error('Invalid address format. Expected an IPv4 or IPv6 address.');
}

Expand Down Expand Up @@ -60,3 +54,29 @@ export async function getPublicIp(): Promise<string> {
const text = await resp.text();
return text.trim();
}

export async function resolveAddressIfNecessary(address: string): Promise<string> {
const [addr, port] = splitAddressPort(address, false);
const multiaddrPrefix = addressToMultiAddressType(addr);
if (multiaddrPrefix === 'dns') {
const resolvedAddresses = await resolve(addr);
if (resolvedAddresses.length === 0) {
throw new Error(`Could not resolve address: ${addr}`);
}
return `${resolvedAddresses[0]}:${port}`;
} else {
return address;
}
}

// Not public because it is not used outside of this file.
// Plus, it relies on `splitAddressPort` being called on the address first.
function addressToMultiAddressType(address: string): 'ip4' | 'ip6' | 'dns' {
if (address.includes(':')) {
return 'ip6';
} else if (address.match(/^[\d.]+$/)) {
return 'ip4';
} else {
return 'dns';
}
}
17 changes: 10 additions & 7 deletions yarn-project/pxe/src/pxe_service/pxe_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -617,18 +617,21 @@ export class PXEService implements PXE {
}

public async getNodeInfo(): Promise<NodeInfo> {
const [nodeVersion, protocolVersion, chainId, contractAddresses, protocolContractAddresses] = await Promise.all([
this.node.getNodeVersion(),
this.node.getVersion(),
this.node.getChainId(),
this.node.getL1ContractAddresses(),
this.node.getProtocolContractAddresses(),
]);
const [nodeVersion, protocolVersion, chainId, enr, contractAddresses, protocolContractAddresses] =
await Promise.all([
this.node.getNodeVersion(),
this.node.getVersion(),
this.node.getChainId(),
this.node.getEncodedEnr(),
this.node.getL1ContractAddresses(),
this.node.getProtocolContractAddresses(),
]);

const nodeInfo: NodeInfo = {
nodeVersion,
l1ChainId: chainId,
protocolVersion,
enr,
l1ContractAddresses: contractAddresses,
protocolContractAddresses: protocolContractAddresses,
};
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/types/src/interfaces/node-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export interface NodeInfo {
* Protocol version.
*/
protocolVersion: number;
/**
* The node's ENR.
*/
enr: string | undefined;
/**
* The deployed l1 contract addresses
*/
Expand Down

0 comments on commit 6c0231f

Please sign in to comment.