WEBVTT 00:00.000 --> 00:10.000 Can everyone hear me? 00:10.000 --> 00:15.000 Hello everyone, I'm Jessica Talon. 00:15.000 --> 00:22.000 As you heard, I've been working on activity football for quite a while and then more recently 00:22.000 --> 00:30.000 at the Spritely Institute and I am involved in both the implementation and standardization 00:30.000 --> 00:40.000 of O'Capon. Spritely is a research institute and we are trying to research and develop 00:40.000 --> 00:47.000 the sort of next generation of decentralized web. We have a few projects, 00:48.000 --> 00:58.000 which is an active model aimed to build decentralized and peer-to-peer applications, 00:58.000 --> 01:02.000 and it's also an implementation of O'Capon. 01:02.000 --> 01:08.000 Huit, which is our scheme to where the assembly compilers, so we can bring us to the web, 01:08.000 --> 01:15.000 and O'Capon, which is something we are involved in the standardization of, 01:15.000 --> 01:27.000 where a US-5.0.1, C3 registered nonprofit, and we can't do our work without donations. 01:27.000 --> 01:34.000 If you think what we're doing is interesting, check us out and if you can donate. 01:34.000 --> 01:41.000 So, what is O'Capon? It stands for object capability network and I know a few of the talks 01:41.000 --> 01:49.000 at least have mentioned capabilities. It's built to allow peer-to-peer communication 01:49.000 --> 01:56.000 and it's utilising capability as it's security model. It has actors at the core 01:56.000 --> 02:02.000 and supports messaging between those actors. It includes something called 02:02.000 --> 02:06.000 promised-fightlining and promises. It's network transport, 02:06.000 --> 02:11.000 agnostic. It has a cyclical distributive GC and third-party hand-offs. 02:11.000 --> 02:16.000 Some of those you don't understand, hopefully you will at the end of this talk. 02:16.000 --> 02:21.000 But why O'Capon? Why are we building this thing? 02:21.000 --> 02:26.000 And my background is in activity purpose, I said, 02:26.000 --> 02:31.000 and when we're building that, we built it with client server and service 02:31.000 --> 02:34.000 federating between one another. 02:34.000 --> 02:39.000 We're building this for the web and people are building these things with Django and Rails 02:39.000 --> 02:43.000 and things like that. That works great. 02:43.000 --> 02:48.000 People are deploying, you know, massive on-service or something. 02:48.000 --> 02:52.000 They've got lots of users, but you're sort of seeding some control 02:52.000 --> 02:55.000 and sometimes privacy to these servers. 02:55.000 --> 02:59.000 And it would be much better if we could build actually peer-to-peer applications 02:59.000 --> 03:03.000 where users can just run their own and they make point-to-point connections 03:03.000 --> 03:07.000 and we can build applications on top of those. 03:07.000 --> 03:12.000 But it can be really hard to do this. There's a lot of things to think about 03:12.000 --> 03:17.000 and so this is where O'Capon is coming in. 03:17.000 --> 03:23.000 And it's designed to make building these peer-to-peer applications 03:23.000 --> 03:27.000 ergonomic and secure and easy. 03:27.000 --> 03:31.000 And O'Capon is a protocol, so it's something you implement 03:31.000 --> 03:34.000 or hopefully use an implementation of. 03:34.000 --> 03:39.000 And then, you know, you can then focus on your application logic 03:39.000 --> 03:44.000 and leave the peer-to-peer stuff to O'Capon. 03:44.000 --> 03:48.000 Well, O'Capon doesn't actually have an opinion on where the 03:48.000 --> 03:50.000 system is fault-tolerant or not. 03:50.000 --> 03:54.000 This is something that typically goes hand in hand with the actor model 03:54.000 --> 03:55.000 as we'll see. 03:55.000 --> 04:00.000 And so this is important in that you often want distributed 04:00.000 --> 04:03.000 applications to be quite fault-tolerant. 04:03.000 --> 04:09.000 And because it's network transport, agnostic applications 04:09.000 --> 04:16.000 don't have to worry about the network and the transport 04:16.000 --> 04:19.000 can be swapped out to their needs. 04:19.000 --> 04:22.000 So capability security, I know the previous talk 04:22.000 --> 04:24.000 and several other talks have mentioned this. 04:24.000 --> 04:26.000 So hopefully you're off a million, 04:26.000 --> 04:29.000 but if you're not, I'll quickly go over it. 04:29.000 --> 04:32.000 We like to say it's brightly. 04:32.000 --> 04:35.000 If you don't have it, you can't use it. 04:35.000 --> 04:39.000 And that means basically if you have a reference to something, 04:39.000 --> 04:42.000 or something like that, you can just use it. 04:42.000 --> 04:47.000 There isn't anything to stop you doing that. 04:47.000 --> 04:53.000 And you can think of this as like procedure arguments 04:53.000 --> 04:56.000 or something, you get past something into a procedure 04:56.000 --> 04:58.000 and then it can use that thing to pass it into it. 04:58.000 --> 05:00.000 Or file handles. 05:00.000 --> 05:03.000 You give it a file handle instead of the entire access 05:03.000 --> 05:06.000 to the file system. 05:06.000 --> 05:09.000 And capability security often goes hand in hand 05:09.000 --> 05:11.000 with the principle of least authority, 05:11.000 --> 05:16.000 which is you give programs just the privileges they need 05:16.000 --> 05:19.000 to do their job. 05:19.000 --> 05:22.000 The alternative to capability security is usually 05:22.000 --> 05:27.000 access control lists, which are susceptible to 05:27.000 --> 05:31.000 confused deputy attacks, which is a security vulnerability. 05:31.000 --> 05:35.000 And also ACLs tend to lead, lend themselves 05:35.000 --> 05:38.000 to centralized systems. 05:38.000 --> 05:43.000 There is usually a program that has a lot of power, 05:43.000 --> 05:48.000 and then gives that out to two other programs. 05:48.000 --> 05:52.000 And this is somewhat inherently centralized. 05:52.000 --> 05:59.000 So capability security can help with building distributed applications. 05:59.000 --> 06:01.000 I'm sorry that these are a little small. 06:01.000 --> 06:03.000 I should have made them bigger. 06:03.000 --> 06:08.000 But this is a very basic diagram showing a blog 06:08.000 --> 06:11.000 and in the middle, you've got these posts, 06:11.000 --> 06:14.000 and these arrows of the capabilities. 06:14.000 --> 06:16.000 And this is showing attenuation, 06:16.000 --> 06:20.000 making a giving just a part of the capability out. 06:20.000 --> 06:24.000 And so you can see here the admin has the capability 06:24.000 --> 06:28.000 to write, that's what the W if you can make that out, 06:29.000 --> 06:32.000 is meaning and the blog itself has the capability to read, 06:32.000 --> 06:34.000 but not write. 06:34.000 --> 06:38.000 So you can take a read write capability and split out. 06:38.000 --> 06:42.000 Just part of the capability and hand bad out. 06:42.000 --> 06:46.000 And so that's a really interesting and useful property 06:46.000 --> 06:48.000 of capabilities. 06:48.000 --> 06:51.000 This is a somewhat scary looking diagram, 06:51.000 --> 06:53.000 but it's not too bad. 06:53.000 --> 06:57.000 This is Lauren and she's got a blog with an admin. 06:57.000 --> 07:01.000 And she wants to give this out to Robert. 07:01.000 --> 07:06.000 And she doesn't just give her entire capability. 07:06.000 --> 07:09.000 She gives a proxy to that capability. 07:09.000 --> 07:14.000 And this proxy is revocable and will log what Robert is doing. 07:14.000 --> 07:19.000 So Lauren can look at the log and then if she chooses, 07:19.000 --> 07:23.000 revoke this arrow, you can see pointing 07:23.000 --> 07:26.000 between the proxy half moon and the admin in the middle. 07:26.000 --> 07:30.000 It's pointing at some kind of like switch in a circuit 07:30.000 --> 07:32.000 or fuse. 07:32.000 --> 07:38.000 And so this would be really difficult to model in a classic ACL system. 07:38.000 --> 07:42.000 But this is actually something pretty easy to model in 07:42.000 --> 07:45.000 capability security system. 07:45.000 --> 07:52.000 The act of model is at the heart of a captain. 07:52.000 --> 07:56.000 And so I'll go over it a little bit. 07:56.000 --> 08:01.000 Actors communicate with other actors by message passing, 08:01.000 --> 08:05.000 sending messages to other actors. 08:05.000 --> 08:08.000 And actors work great in concurrent systems. 08:08.000 --> 08:13.000 So you can have multiple actors working at the same time. 08:13.000 --> 08:20.000 And actors are also great for distributed applications. 08:20.000 --> 08:25.000 You can usually put a network boundary, 08:25.000 --> 08:31.000 sort of have an actor system and then put a network boundary in the middle. 08:31.000 --> 08:33.000 And that's usually fairly trivial. 08:33.000 --> 08:36.000 And again, they often lend themselves to fault-polar 08:36.000 --> 08:38.000 systems, things like Erlang and Lixer, 08:38.000 --> 08:43.000 often tap this and they're relying on the act model. 08:43.000 --> 08:48.000 So to get into a captain, I'm going to sort of go through the protocol 08:48.000 --> 08:52.000 and show you what these messages look like on the wire. 08:52.000 --> 08:56.000 And I've mentioned that we're sending messages to actors. 08:56.000 --> 08:59.000 And so how are actors represented on the wire? 08:59.000 --> 09:02.000 There is this notion of imports and exports. 09:02.000 --> 09:07.000 And these are a pairwise within a session, 09:07.000 --> 09:10.000 ways of representing an actor, 09:10.000 --> 09:15.000 and you represent them with a positive integer. 09:16.000 --> 09:19.000 And these are sessions specific. 09:19.000 --> 09:24.000 So the integer 5 is specific to say an A and B, 09:24.000 --> 09:29.000 P A and B session, but that could reference a completely different actor 09:29.000 --> 09:32.000 within another session. 09:32.000 --> 09:39.000 And this is sort of like the most important operator within O'CAPAN. 09:39.000 --> 09:43.000 And this is how actors message one another. 09:44.000 --> 09:46.000 And this is OP Deliver. 09:46.000 --> 09:49.000 And it takes four arguments. 09:49.000 --> 09:54.000 And you'll see how these two final arguments are used in later slides, 09:54.000 --> 09:56.000 when I go over other features. 09:56.000 --> 10:02.000 But the first one is where which actor are we sending this message to. 10:02.000 --> 10:05.000 And this will be using those imports and exports, 10:05.000 --> 10:07.000 but I was talking about. 10:07.000 --> 10:12.000 And then there is a list of arguments that you're sending to the actor. 10:12.000 --> 10:15.000 The answer position is used for promised pipelining, 10:15.000 --> 10:16.000 but I'll get into. 10:16.000 --> 10:19.000 And this to resolve me descriptor is used for promises. 10:19.000 --> 10:23.000 I'll also get into that in a second. 10:23.000 --> 10:26.000 And so I've got two things here. 10:26.000 --> 10:31.000 The first is a line of goblins code. 10:31.000 --> 10:34.000 Goblins is written in scheme. 10:34.000 --> 10:37.000 And so you're seeing parentheses. 10:37.000 --> 10:40.000 And the first argument is a procedure call. 10:41.000 --> 10:46.000 And so it's this arrow NP, which stands for no promise. 10:46.000 --> 10:49.000 And this is how you message in goblins. 10:49.000 --> 10:54.000 So it's saying message Bob with the argument hello. 10:54.000 --> 10:56.000 And this is a symbol. 10:56.000 --> 11:03.000 And on the wire this is this OP Deliver operator. 11:03.000 --> 11:07.000 And I just made up a number here, 11:07.000 --> 11:11.000 but it could be any number in this case just number one. 11:11.000 --> 11:16.000 And we're messaging Bob who is exported 11:16.000 --> 11:19.000 at position one on the other node. 11:19.000 --> 11:25.000 And we're delivering it with hello. 11:25.000 --> 11:31.000 But that's great sending a message to an actor. 11:31.000 --> 11:36.000 But what if Bob wanted to reply with a greeting or something? 11:36.000 --> 11:39.000 And so this is where promises come in. 11:39.000 --> 11:45.000 This is sort of how you get an answer back when you send a message. 11:45.000 --> 11:49.000 And so promises may resolve to lots of different things. 11:49.000 --> 11:53.000 They may be resolved to a reference to an actor 11:53.000 --> 11:57.000 that either won the actor's spawned itself or a reference 11:57.000 --> 12:00.000 that had to be given it. 12:00.000 --> 12:06.000 But they can also resolve to concrete values 12:06.000 --> 12:08.000 or indeed other promises. 12:08.000 --> 12:12.000 And you can chain promises together. 12:12.000 --> 12:16.000 And you can break promises with an error. 12:16.000 --> 12:19.000 Something goes wrong or indeed promises can be broken 12:19.000 --> 12:21.000 if something went wrong in the network, 12:21.000 --> 12:24.000 such as the network's reference. 12:24.000 --> 12:26.000 And promises can be listened to. 12:26.000 --> 12:30.000 And in the training example where you have, say, promise one. 12:30.000 --> 12:33.000 That's filled with promise two and so forth. 12:33.000 --> 12:39.000 If you listen to it, you'll finally get the answer at the end of the chain, 12:39.000 --> 12:42.000 including errors. 12:42.000 --> 12:47.000 And so this is an example of how promises look in code. 12:47.000 --> 12:51.000 If you're not familiar with scheme, I'll try to explain it. 12:51.000 --> 12:54.000 Define is we're defining a variable. 12:54.000 --> 12:58.000 And in goblins by convention, they're suffixed with vow 12:58.000 --> 13:00.000 if it's a promise. 13:00.000 --> 13:04.000 And so we've got Greeking vow. 13:04.000 --> 13:08.000 And we're using the arrow procedure. 13:08.000 --> 13:12.000 This time not arrow NP, because we're wanting a promise. 13:12.000 --> 13:16.000 And we're sending Alice, hello, and Bob. 13:16.000 --> 13:18.000 So two arguments, hello and Bob. 13:18.000 --> 13:20.000 Alice is our reference here to another actor. 13:20.000 --> 13:23.000 Probably another machine. 13:24.000 --> 13:28.000 And we're then calling this om procedure, 13:28.000 --> 13:32.000 which is how you listen to a promise in goblins. 13:32.000 --> 13:36.000 And we've got this lambda, which is our callback. 13:36.000 --> 13:40.000 And so when that promise finally resolves to some value, 13:40.000 --> 13:48.000 we'll do this, this is how you print something to the terminal in 13:48.000 --> 13:49.000 Gile. 13:49.000 --> 13:55.000 So you'll see you promised said, and then whatever Alice replied with. 13:55.000 --> 14:00.000 And so how's this working on the wire? 14:00.000 --> 14:05.000 So I've got again, we're sending a message with OP deliver. 14:05.000 --> 14:08.000 And this OP deliver will come up a lot. 14:08.000 --> 14:11.000 It's used a lot of no-cuffin. 14:11.000 --> 14:14.000 And this time where we've got both of our arguments, 14:14.000 --> 14:16.000 we've got a good example. 14:16.000 --> 14:21.000 I'm still not using this answer position, so that's set to false. 14:21.000 --> 14:23.000 And now I've got this resolved me descriptor. 14:23.000 --> 14:28.000 And this is this is telling the implementation on the other side. 14:28.000 --> 14:34.000 When you finally get an answer to this, or if you need to break it due to an error, 14:34.000 --> 14:35.000 let me know here. 14:35.000 --> 14:40.000 And this is another object, another actor in the actor model. 14:40.000 --> 14:43.000 And we're just exporting this to the other side. 14:43.000 --> 14:46.000 And so we say it's an import object and two. 14:46.000 --> 14:51.000 So we just made up an available number to export this. 14:51.000 --> 14:55.000 You export by just referencing an object. 14:55.000 --> 14:57.000 And so we've referenced this object. 14:57.000 --> 15:06.000 And then finally later on when our actor, when we get a resolution to it, 15:06.000 --> 15:10.000 they will send another OP deliver. 15:10.000 --> 15:15.000 And this time they're referencing that resolved me descriptor actor. 15:15.000 --> 15:20.000 And they will use the fulfill method on this. 15:20.000 --> 15:25.000 In this case, Alice is saying hello Bob, my name is Alice. 15:25.000 --> 15:33.000 They don't care any about any resolution or promise to get back, 15:33.000 --> 15:39.000 so they've just got the false for the unsubosition and resolved me descriptor. 15:39.000 --> 15:46.000 This is the basic building blocks of OCAPAN and how you would message actors 15:46.000 --> 15:51.000 that might be across the network. 15:51.000 --> 15:54.000 But that's pretty basic stuff. 15:54.000 --> 15:58.000 But that's not the only thing you can do with OCAPAN. 15:58.000 --> 16:01.000 There is this feature called promise pipelineing. 16:01.000 --> 16:06.000 And this allows you to do some pretty neat stuff. 16:06.000 --> 16:11.000 So in this example, I'm going to walk through the example and then explain as they go 16:11.000 --> 16:14.000 why this is so interesting. 16:14.000 --> 16:17.000 So we're starting with this car factory valve. 16:17.000 --> 16:23.000 And we're messaging this actor somewhere on the network and we're saying, 16:23.000 --> 16:27.000 hey, make me a factory, a car factory. 16:27.000 --> 16:31.000 And then we're immediately on the next line, 16:31.000 --> 16:33.000 sending message to this promise. 16:33.000 --> 16:35.000 And how's that happening? 16:35.000 --> 16:38.000 The message may not have left my machine. 16:38.000 --> 16:42.000 Certainly it takes some time to build a car factory right. 16:42.000 --> 16:46.000 And so how am I managing to send a message to this? 16:46.000 --> 16:51.000 But I am sending a message to this and saying, hey, make a car. 16:51.000 --> 16:55.000 And then on the next line, I'm even messaging that promise. 16:55.000 --> 16:58.000 This promise to the car I've just asked for. 16:58.000 --> 17:00.000 And I'm saying, hey, drive a car. 17:00.000 --> 17:04.000 And then I listen to this drive promise. 17:04.000 --> 17:06.000 And I've got another handler. 17:06.000 --> 17:11.000 And you can see here, I've included some error handling to in case something. 17:11.000 --> 17:17.000 Bro, but in most systems, you might send a message to the factory builder. 17:17.000 --> 17:21.000 And then say, wait for the response. 17:21.000 --> 17:24.000 And the other side will say, oh, here's your car factory. 17:24.000 --> 17:26.000 I've just spent a bunch of time building it. 17:26.000 --> 17:29.000 And then you'll say, okay, then now I want that car. 17:29.000 --> 17:31.000 And then I'll go ahead and make the car. 17:31.000 --> 17:33.000 And you'll wait for the answer. 17:33.000 --> 17:35.000 And you'll say, hey, go ahead and drive. 17:35.000 --> 17:40.000 But this I can just have this nice flat ergonomic structure in the code. 17:40.000 --> 17:43.000 And I don't need to do that. 17:43.000 --> 17:47.000 I can just dispatch all my messages to the other side. 17:47.000 --> 17:49.000 And then get my answer back at the end. 17:49.000 --> 17:53.000 And so this both allows for this ergonomic code. 17:53.000 --> 17:58.000 But it also prevents this sort of back and forth conversation, 17:58.000 --> 18:01.000 where I'm going A to B and then B to A. 18:01.000 --> 18:04.000 And then A to B and B to A. 18:04.000 --> 18:08.000 When I'm sending these messages and getting a reply. 18:08.000 --> 18:13.000 And so this saves on network traffic, it saves on time. 18:13.000 --> 18:16.000 And how are we achieving this? 18:16.000 --> 18:20.000 Well, you can see this OP deliver at the top. 18:20.000 --> 18:27.000 In this case, I've just said the car factory builder is number five. 18:27.000 --> 18:30.000 And we're saying, make a factory. 18:30.000 --> 18:33.000 And this is our position two. 18:33.000 --> 18:36.000 And when now using this answer position. 18:36.000 --> 18:43.000 And that side just makes up an integer to represent the promise. 18:43.000 --> 18:46.000 And then you start messaging that answer. 18:46.000 --> 18:50.000 So saying, hey, at that thing, I just hold you to make. 18:50.000 --> 18:53.000 I want you to deliver this message. 18:53.000 --> 18:56.000 And then again, we specified three. 18:56.000 --> 19:01.000 And we're saying, hey, at that car, just hold you to make. 19:01.000 --> 19:02.000 Deliver this message. 19:02.000 --> 19:05.000 And this time, we don't want to pipeline anymore. 19:05.000 --> 19:08.000 So we've just given it a resolve me descriptor. 19:08.000 --> 19:15.000 And B can then fulfill this for the answer or break it with an error 19:15.000 --> 19:18.000 if something would happen. 19:18.000 --> 19:21.000 I don't want to spend too much time on this slide. 19:21.000 --> 19:25.000 But GC turns out to be very important in distributed systems. 19:25.000 --> 19:27.000 You often want to clean up objects. 19:27.000 --> 19:30.000 And if you're handing out references and stuff, 19:30.000 --> 19:34.000 you need to know when the other side's done with that reference. 19:34.000 --> 19:40.000 And so I just want to say that we do have a cyclic garbage collection. 19:40.000 --> 19:43.000 Distributed garbage collection, you know, Captain. 19:43.000 --> 19:46.000 And it works by reference counting on the wire. 19:46.000 --> 19:49.000 And then we have it for both of those answers 19:49.000 --> 19:55.000 from performance supply planning and for regular objects. 19:55.000 --> 19:59.000 Now, this is my favorite feature of our cabin. 19:59.000 --> 20:01.000 It's very neat. 20:01.000 --> 20:07.000 So this is being sent by Alicia on PRA, one machine. 20:07.000 --> 20:13.000 And it's being sent to Ben, who's on another machine, PAB. 20:13.000 --> 20:18.000 And then saying, I'm going to call this method meet. 20:18.000 --> 20:23.000 And interestingly, Ben's passing Carroll on PSE. 20:23.000 --> 20:31.000 So this is Alicia has two sections here. 20:31.000 --> 20:37.000 And how Alicia do this when you've just got integers. 20:37.000 --> 20:41.000 It turns out we've got this third-party handoff thing. 20:41.000 --> 20:44.000 And I'm running out of time to explain this. 20:44.000 --> 20:46.000 I'm going to go very quickly. 20:46.000 --> 20:48.000 Don't worry if you don't understand. 20:48.000 --> 20:52.000 But basically, no-day gives Carroll a gift. 20:52.000 --> 20:55.000 And says, look after this for me. 20:55.000 --> 21:02.000 And then node A then sends a message to Ben, 21:02.000 --> 21:04.000 that OP deliver. 21:04.000 --> 21:06.000 And it includes this certificate. 21:06.000 --> 21:09.000 And you can see it's secure, it's signed. 21:09.000 --> 21:13.000 You can see, because it's got this little rubber stamp on it. 21:13.000 --> 21:15.000 It's a signed certificate. 21:15.000 --> 21:18.000 And that includes information from the A to C session. 21:18.000 --> 21:21.000 And the A to B session. 21:21.000 --> 21:26.000 And then Ben can then establish a new connection to C. 21:26.000 --> 21:31.000 And include some information on its own. 21:31.000 --> 21:34.000 And the certificate it got. 21:34.000 --> 21:40.000 And then finally, node B can kind of have a session with node C. 21:40.000 --> 21:43.000 And there's no proxy in going on here. 21:43.000 --> 21:45.000 Node A could then go down. 21:45.000 --> 21:49.000 And they could continue talking and sending messages. 21:49.000 --> 21:55.000 And Ben has that reference to Carroll. 21:55.000 --> 21:58.000 And so, like I said, don't worry if you don't understand this. 21:58.000 --> 22:01.000 The takeaways that you can have this ergonomic, 22:01.000 --> 22:05.000 intuitive way of programming in with OCAPAN. 22:05.000 --> 22:09.000 And it will handle this secure handoff of references. 22:10.000 --> 22:13.000 And create in connections to other nodes. 22:13.000 --> 22:18.000 And it handles all the security issues with replay attacks and things like that. 22:18.000 --> 22:21.000 It's split into three layers. 22:21.000 --> 22:24.000 Everything I've talked about so far is in CAPTP. 22:24.000 --> 22:25.000 But there is net layers. 22:25.000 --> 22:27.000 Support for TORANY net layers. 22:27.000 --> 22:29.000 Repeat P to P web sockets. 22:29.000 --> 22:32.000 In the X domain sockets and things like that. 22:32.000 --> 22:35.000 You can sort of just pick one and run with it. 22:35.000 --> 22:37.000 And new ones can be defined. 22:37.000 --> 22:40.000 And then there are locators for specifying capabilities 22:40.000 --> 22:44.000 to connect to a machine and get objects and things like that. 22:44.000 --> 22:47.000 The next work I'll be working on is a relay. 22:47.000 --> 22:49.000 Pit peer. 22:49.000 --> 22:53.000 Things can be very difficult in a lot of situations. 22:53.000 --> 22:55.000 Web browsers is one. 22:55.000 --> 22:58.000 It can be really hard to get true peer to peer stuff there. 22:58.000 --> 23:00.000 But also network configurations. 23:00.000 --> 23:03.000 You could be behind firewalls and things. 23:04.000 --> 23:07.000 And so relays do have a use. 23:07.000 --> 23:11.000 But it's important not to have too much centralized relays. 23:11.000 --> 23:13.000 So the relays will be federated. 23:13.000 --> 23:16.000 You don't have to share the relay to form a connection. 23:16.000 --> 23:24.000 And they will leverage their transport agnostic stuff in the net layers. 23:25.000 --> 23:27.000 What happened isn't done. 23:27.000 --> 23:30.000 We have draft specs. 23:30.000 --> 23:35.000 And we meet every month and try and standardize this. 23:35.000 --> 23:38.000 We have an implementation guide on the test suite in Python. 23:38.000 --> 23:41.000 If this sounds really interesting to you. 23:41.000 --> 23:46.000 Check out the website and consider joining. 23:46.000 --> 23:49.000 And if we have time for questions. 23:50.000 --> 23:51.000 Our head. 23:51.000 --> 23:53.000 Let's give it a round of applause. 23:53.000 --> 23:59.000 Unfortunately, we don't have time for a full Q&A right now. 23:59.000 --> 24:01.000 But if you have questions, yeah. 24:01.000 --> 24:03.000 Please talk to Jessica afterwards.