Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move port allocation in network vat to PortAllocator #9228

Merged
merged 18 commits into from
Apr 30, 2024

Conversation

iomekam
Copy link
Contributor

@iomekam iomekam commented Apr 12, 2024

closes: #9165

Description

bindPort gives a caller too much power to specify exactly what port they want allocated. With this change, we create a central object, PortAllocator that handles handing out ports to the caller. As of today, we are allocating ports for:

  1. /ibc-port
  2. /ibc-port/icacontroller
  3. /ibc-port/pegasus

Security Considerations

This will prevent squatting, where callers can come and claim certain ports that they have no association with

Documentation Considerations

We've removed the bindPort method from the network vat. All the contracts inside of agoric-sdk have been changed to use portAllocator

Testing Considerations

I've included some unit test testing the new allocate APIs

@@ -168,6 +168,7 @@ export const getManifestForNetwork = (_powers, { networkRef, ibcRef }) => ({
zoe: 'zoe',
provisioning: 'provisioning',
vatUpgradeInfo: true,
portAllocator: 'portAllocator',
Copy link
Member

Choose a reason for hiding this comment

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

This isn't write up yet, I guess?

@@ -168,6 +168,7 @@ export const getManifestForNetwork = (_powers, { networkRef, ibcRef }) => ({
zoe: 'zoe',
provisioning: 'provisioning',
vatUpgradeInfo: true,
portAllocator: 'portAllocator',
Copy link
Member

Choose a reason for hiding this comment

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

Should this go in produce instead of consume? Then in vat-orchestration, we can consume portAllocator instead of networkVat?

Copy link

cloudflare-workers-and-pages bot commented Apr 22, 2024

Deploying agoric-sdk with  Cloudflare Pages  Cloudflare Pages

Latest commit: aa5e919
Status: ✅  Deploy successful!
Preview URL: https://4437662c.agoric-sdk.pages.dev
Branch Preview URL: https://iomekam-port-allocation.agoric-sdk.pages.dev

View logs

@iomekam iomekam changed the title Deprecate bindPort for PortAllocator in network vat Remove bindPort for PortAllocator in network vat Apr 23, 2024
@iomekam iomekam changed the title Remove bindPort for PortAllocator in network vat Move port allocation in network vat to PortAllocator Apr 23, 2024
@iomekam iomekam marked this pull request as ready for review April 23, 2024 20:50
@iomekam iomekam requested a review from michaelfig April 23, 2024 20:51
Copy link
Member

@michaelfig michaelfig left a comment

Choose a reason for hiding this comment

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

The single-character portId (the 1 in /ibc-port/1) needs to be fixed.

Maybe my hopes for a solution to vanity port names vs. squatting can't be satisfied. Please spend a little time thinking about that, but if there are no clear solutions, let's rip out the Pegasus special case and have it listen on just a generated allocateIBCPort instead.

packages/network/src/network.js Outdated Show resolved Hide resolved
const portAllocator = makePortAllocator({ protocol });

const ibcPort = await when(portAllocator.allocateIBCPort());
t.is(ibcPort.getLocalAddress(), '/ibc-port/1');
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't look like the correct result (the IBC standard states that port identifiers need to be at least 2 characters in length). The local address should be /ibc-port/port-1. Maybe a port- prefix got dropped somewhere in the PRs?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We actually mock the generatePortID method, and in that implementation, we drop the port prefix. I've updated it to be inline with what we do in production

const port = await E(networkVat).bindPort('/ibc-port/pegasus');
const port = await E(portAllocator).allocateIBCPegasusPort();
Copy link
Member

Choose a reason for hiding this comment

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

This makes me somewhat uncomfortable. It seems to illustrate that allocateIBCPegasusPort() is too specific and doesn't really solve the need for custom port names. Is there a solution that exists between the power of bindPort() and the rigidity of allocateIBCPegasusPort()?

Comment on lines 75 to 71
* - loopback ports: `E(networkVat).bindPort('/local/')`
* - an echo port: `E(vats.network).bindPort('/ibc-port/echo')`
* - loopback ports: `E(portAllocator).allocateLocalPort()`
* - an echo port: `E(portAllocator).allocateIBCPort()`
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't produce /ibc-port/echo, so it loses the port identity that the outside world could rely on (like how ICS-20 is usually found at /ibc-port/transfer).

export type AttenuatedPortAllocator = Pick<
PortAllocator,
'allocateICAControllerPort'
>;
Copy link
Member

Choose a reason for hiding this comment

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

I think we can get rid of this typedef (and Far('PortAllocator', ...) in orchestration-proposal.js) and just use PortAllocator directly. Feel free to leave as is and we can make this change in the course of #9198 where we'll need to add allocateICQControllerPort.

@@ -152,7 +151,7 @@ export const setupNetworkProtocols = async (
await registerNetworkProtocols(vats, dibcBridgeManager);

// Add an echo listener on our ibc-port network (whether real or virtual).
const echoPort = await when(E(vats.network).bindPort('/ibc-port/echo'));
const echoPort = await when(E(allocator).allocateIBCPort());
Copy link
Member

Choose a reason for hiding this comment

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

This looks like it may be a change in behavior - /ibc-port/echo -> /ibc-port/1 - is this intentional/expected?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Intentional in that it fits with the design, but not intentional in that it breaks the ability to bind to a known /ibc-port/echo port. Trying to iterate on a solution where we can still provision this port without having access to bindPort

packages/network/src/types.js Outdated Show resolved Hide resolved
@iomekam iomekam requested a review from michaelfig April 27, 2024 00:40
Copy link
Member

@michaelfig michaelfig left a comment

Choose a reason for hiding this comment

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

Looking good! I'd just like to see some different names, so that the "custom" address is clearly apparent:

  • allocateCustomLocalPort
  • allocateCustomIBCPort

packages/network/src/network.js Outdated Show resolved Hide resolved
packages/network/src/network.js Outdated Show resolved Hide resolved
@iomekam iomekam added the automerge:squash Automatically squash merge label Apr 30, 2024
@mergify mergify bot merged commit d15cb41 into master Apr 30, 2024
67 checks passed
@mergify mergify bot deleted the iomekam-port-allocation branch April 30, 2024 18:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
automerge:squash Automatically squash merge
Projects
None yet
4 participants