Figuring out a simple SwingSet chat application

So I have SwingSet up and running here; great. If I’m going to understand it, I should probably build a test application. Since I’m looking at building something that’s networked and has graphical interfaces, a simple chat room application seems like a good starting point. This is a thread where I’ll try to work through it as I go.

The question is: how to do networking? Luckily this is already answered: I don’t want to use anything other than CapTP! … Now I just need to figure out how to get two live vats to spin up and talk to each other. So I guess that’s my first step, get two vats talking across two machines

From there I guess I could do a not-very-good-chat-system: just use the JS repl to connect to the chat room and input messages and receive chats back. Not a good user experience but then I could be sure that layer worked?

Then I’d want to produce a proper interface. Really there seem like two options: use some kind of browser interface or use native desktop interface tools. The former seems undesirable since ideally this is a peer to peer application. Anyone have recommendations for the latter? Are there special considerations to consider when integrating with a SwingSet application?

Side note: this would probably be good tutorial material.

1 Like

A question: the current Agoric examples seem aimed at interacting with a blockchain. But I’m more interested in the moment in spawning two vats on two different live-actor-vat style machines and having them interact. It’s not very obvious to me how to get started with that?

1 Like

I don’t think we have a tutorial for that yet, but we do have a demo and tests for it. The encouragementBot will tell you from another machine that you’re doing a great job. :smiley:

1 Like

Thank you Kate!

Just trying to understand… in this example, these are two abstract “machines” in the Agoric abstractions of machines as a boundary/interface that contains and runs its vat abstraction, but they still run on the same physical machine? As in, there’s no network connection between machines? I’m trying to figure out what the “loopbox” is, and my guess is it’s a way to kind of test for that as a dummy “external process”.

My question would be: is there currently a way for me to launch a SwingSet process on this computer and then another on my VPS server and have them talking to each other yet? If the answer is “No, but we have plans (IBC) and that’s coming” that’s ok, probably if I wrote code that didn’t yet connect over the network my guess would be that as soon as that feature is added, adding support for it will be trivial.

(If the answer is “Yes, and it should have been obvious by looking at that code”, apologies in advance!)

Extra bonus question: let’s say I wanted to share a link to the chat room with friends in some medium that isn’t on the Agoric network. Is there something akin to a sturdyRef that I can copy over to them? Or what would be the best practice?

Hi Chris!

We also have an alternative way of communicating between different machines that doesn’t involve SwingSet. Please have a look at https://github.com/Agoric/captp

The advantage is that it’s much simpler, and doesn’t require that you fully secure the peer, it just acts as a promise-based RPC protocol across arbitrary point-to-point transports. The disadvantage is that it doesn’t keep persistent state. When the connection is torn down, all the pending promises are rejected.

Feel free to write more here to my attention if you choose to use @agoric/captp. If you stick with SwingSet, Kate’s probably the best resource.

Have fun,
Michael.

1 Like

Oh, and even if you’re using SwingSet, it would be an interesting project to implement an @agoric/captp endpoint that exports a public bootstrap object from lib/ag-solo/web.js via WebSocket (see the existing uses of makeCapTP in that file), then connect to it directly from another @agoric/captp as a cheap kind of publically-accessible SturdyRef.

The trick would be outbound connections from that ag-solo to another ag-solo. That would need some kind of SwingSet device to communicate, just as web.js uses an HTTP device for inbound connections.

Thanks for the responses! I’ve started looking at the captp repo, which at the very least is useful so I can better understand how captp works. :slight_smile:

I might look at it as a temporary thing to explore, however I do think that if I go down the Agoric route, I’ll probably want to go with SwingSet. I guess my question at the moment is: is SwingSet currently set up so that two “live solo vats” can talk to each other across a network (ideally in a ~p2p manner) or is that a “future effort” issue? Relatedly, I know from talking to @markm that IBC is planning to go down that route; is that route approximately a usable direction yet or is that also in “future effort”?

So, before SwingSet was https://github.com/agoric-labs/PlaygroundVat

That was before I joined, but IIUC it had all the p2p protocol for doing solo-to-solo communication. SwingSet was a ground-up rewrite that omitted the p2p stuff to focus on a model of running multiple independent vats on a single “kernel”. In a perfect world, SwingSet would have the p2p things from PlaygroundVat available as devices for “live solo vats” to communicate.

IBC is another possibility, but it is still an open question as to whether IBC will be suitable as-is for solo-to-solo comms, or if a different kind of p2p layer (or multiple options) is better. I would hazard that SwingSet’s model of running multiple vats on one kernel buys us all kinds of nice properties and fits the blockchain environment very well.

Both SwingSet p2p and IBC are future efforts, but very germane to Agoric’s goals.

@agoric/captp was created by simply ripping out most of the SwingSet “liveSlots” layer and reusing @agoric/eventual-send and @agoric/marshal. I’m pretty happy that it turned out to be less than 300 lines of code to capture the essential CapTP protocol while leveraging the reusable libraries that were already being used. If you start with @markm’s CapTP descriptions and have a look at the Cap’n’Proto RPC definitions and squint at them from a SwingSet point of view, that’s how I pieced it together.

There are still some features missing (like proper resource deallocation), but we did end up using it for some of the work we did in the San Francisco Blockchain Week hackathon. Mostly, it was used to write scripts that ran in a separate process but communicated with a solo vat machine to install and configure smart contract dApp code.

That was an interesting proof-of-concept to show that captp is useful as a standalone distributed object protocol, even without requiring OCap discipline in the internals of the individual peers. I’d like to go further in this direction.

All opinions are my own, but I’m also trying not to misrepresent Agoric. Other folks will chime in, for sure, if I did. :wink:

1 Like

Gotcha… thank you that is a very useful summary! So I am rephrasing back at you: it sounds like SwingSet is not yet ready to do the live p2p stuff and in the meanwhile for building such a thing I should probably use the captp repo for now, but there is still vision for a grand unification with the abstraction of machines as encompassing many things including both live solo vats and blockchains on SwingSet, it just isn’t there yet.

Good to know that things are still a bit up in the air re: IBC and P2P things also; I had an impression from a previous conversation from @markm that maybe it was a sure thing that it would be used for that purpose. If IBC isn’t strictly being used for that layer, I have maybe some thoughts on what could be done… but it’s probably true that I should get caught up as in terms of what is happening in IBC. Maybe time for me to print out some docs and do some reading.

(Thanks for the patience btw everyone with answering my many questions!)

Hey, thanks for looking at SwingSet!

So the short answer is no, we don’t yet have a solo-to-solo communication pathway built yet (an equivalent of VatTP). We prioritized the solo-to-chain case for a hackathon-driven sprint back in June/July, and we’re in the process of a chain-to-chain pathway (using IBC) now. That might help with the solo-to-solo case too, but as you can imagine it looks different.

SwingSet is effectively a library for building “SwingSet Machines” (we’re in the market for better terminology, sometimes we call these “SwingSets”). You write a host program that links against the SwingSet library, giving it a way to save its persistent state, and you configure it with a set of initial (“genesis”) vats. The SwingSet Machine contains a kernel and a bunch of vats, and the usual run-queue and c-lists and stuff. Your host program gets back a “controller” object, whose primary API is controller.run(), which delivers messages from the run-queue into Vat-side objects until the queue is empty. We call this cycle a “Crank” (each “Turn” is a single message delivery, including resolved Promises that fire a then callback, so the “Crank” is complete when all pending Turns have finished: imagine turning the crank on a hand-operated machine until it stops).

To do more than a basic one-shot test, you need a way to add more messages to the run-queue after startup (in response to inbound network traffic). And to do anything interesting, the machine needs a way to exfiltrate messages. Both are managed with “Devices”, which are configured at the same time as the set of genesis vats. Devices can be given endowments that sit outside the kernel.

The main one to look at is the “Mailbox Device”. At the end of each Crank, you (in the host program) can ask the Mailbox for the outbound messages that need to be delivered to some named peer Machine. This also has the inbound ACK high-watermark number that needs to be delivered to that same Machine. You, in the host, are responsible for taking that bundle of JSON-serializable data and dropping it into the Mailbox of the appropriate remote Machine (including protecting its confidentiality, and providing integrity and authentication). When we build a new VatTP, it might look like a signed/encrypted datagram pipe to carry these Mailbox messages, bound to some sort of public key.

So basically the host application is responsible for IBC or P2P or whatever mechanism is used to get those messages from one machine to another. Neither the SwingSet kernel nor its devices speak directly to a network (which also helps with determinism/checkpointing, and avoiding what MarkM calls “hangover inconsistency”: we don’t release any messages until both the kernel and the mailbox state has been checkpointed).

hope that helps!
-Brian

1 Like

Thanks, it does help!

I guess it’s “stay tuned” on “solo-to-solo” for now, but you can definitely count me as interested in where that goes.