[00:00.000 --> 00:16.060] Really simple and kind of a very lazy but like ultimately effective in the same way as a sledgehammer way and it's equally distributed and what I mean by that is that when nodes get near each other they very aggressively seek each other out and then try and exchange as much information as humanly possible. [00:16.380 --> 00:29.980] The idea being to spread a large coherent knowledge graph over as many nodes as possible each with their own redundant local copy and so originally it was it really was just like I was frustrated by JIRA I think and I wanted an offline copy of it. [00:30.000 --> 00:39.200] And then I went down near the data structure rabbit hole of like what can I do with this thing and then I wanted to sync my copy with other people in the office and everything got way out of hand. [00:39.500 --> 00:42.360] But people are actually using it for things now which is amazing and terrifying. [00:43.040 --> 00:54.300] So one of them is Project Byzantium who are working on like a live disk distro that basically like if you're in a disaster affected area you slam this thing into your computer and your laptop forms a mesh with everyone else. [00:54.300 --> 00:58.100] So centralized infrastructure not being there isn't an issue. [00:58.500 --> 01:06.060] And so they built a distributed bulletin board out of it so you can post messages and just by going near people you actually exchange that information. [01:07.320 --> 01:21.400] And so in spite of the fact that I haven't explained what I'm doing or why I'm actually going to demo it now because what I did at 3 o'clock this morning was just like cripple the bit rate to at least guarantee that data will get to the other end and as a result my demo is going to take the whole talk to finish. [01:23.180 --> 01:29.240] It's alright though because it's not... Anyway, before I do that though I'm going to be using some pretty high frequency sound. [01:29.460 --> 01:34.560] So is anyone here like really sensitive to sound around about the 19K mark? [01:34.980 --> 01:37.120] Because that would be bad. [01:37.960 --> 01:38.420] Sorry? [01:38.660 --> 01:39.160] I have a dog. [01:39.340 --> 01:40.380] You do have a dog? [01:40.500 --> 01:40.980] I am a dog. [01:41.100 --> 01:41.820] Oh, alright. [01:41.940 --> 01:42.500] You're good. [01:44.060 --> 01:46.600] If you can speak... Yeah, we're fine. [01:46.820 --> 01:47.200] Alright, cool. [01:48.840 --> 01:56.040] So now like tell me whether or not you can... Is this gonna... Is that like somewhat readable maybe? [01:56.460 --> 01:56.880] Yeah. [01:57.880 --> 01:58.320] Cool. [01:58.880 --> 02:07.720] And so what this does is it basically starts a listener listening at 19.1K which is literally a magic number that I pulled from someone else's project that seems to work very well. [02:08.020 --> 02:08.820] No idea why. [02:09.800 --> 02:12.000] And so on my other machine I'm starting the client. [02:12.180 --> 02:16.900] And basically all this client is doing is like iterating through all of the elements in its graph database. [02:17.800 --> 02:26.880] Serializing them into a bitstream, transmitting the bitstream, and then this end unpacks them and then displays them. [02:27.560 --> 02:32.680] And already it's like experiencing severe corruption and all the work I did this morning was to waste. [02:33.720 --> 02:38.840] Anyway, it actually does correct itself with like somewhat reasonable guarantees. [02:39.480 --> 02:42.020] So I'm just gonna let this run while I give the rest of the talk. [02:42.020 --> 02:47.740] I deliberately kind of made time to like check in on it later and we'll see whether or not it's actually coming good. [02:49.320 --> 02:50.460] Yeah, fingers crossed. [02:50.920 --> 02:52.160] Live demos are the best. [02:52.580 --> 02:57.080] So yeah, it's finally starting to pull through some header data and it's like gradually unpacking it. [02:58.900 --> 02:59.300] Cool. [02:59.440 --> 03:00.300] So back to the topic at hand. [03:00.840 --> 03:02.540] Oh yeah, this slide was relevant. [03:03.000 --> 03:04.180] So let's talk about DAGs. [03:05.240 --> 03:08.820] A DAG is a directed acyclic graph or a snatch reference. [03:09.600 --> 03:11.560] And so who here has used Git? [03:12.940 --> 03:13.400] Cool. [03:13.500 --> 03:13.940] Nearly everyone. [03:14.080 --> 03:14.920] You've all used DAGs. [03:15.680 --> 03:19.280] The three interesting properties are... I mean like the graph thing is fairly self-explanatory. [03:19.740 --> 03:26.720] The directed element is basically that of the graph composed of nodes and edges, that the edges traverse one node to the other. [03:26.960 --> 03:31.860] And the way that they do that is that one node actually contains all of the names of the nodes that it has edges to. [03:33.260 --> 03:36.380] And acyclic just means that you can never have like a loop in it. [03:36.960 --> 03:40.140] And technically like that is possible in Git. [03:40.300 --> 03:42.000] It's just incredibly difficult to arrange. [03:42.380 --> 03:45.280] And it will hopefully be a very long time before anyone does. [03:46.360 --> 03:50.800] And so this is what a DAG looks like in kind of like Git land where you would have played with it before. [03:51.080 --> 03:55.420] These should be arrows, but drawing graphs in Keynote sucks and I was not going back. [03:55.900 --> 03:58.960] So basically the way this works is that at the top you've got a source of truth. [03:58.960 --> 04:02.860] So you have like a commit hash or the, you know, the name of an object. [04:03.320 --> 04:05.640] And then it traverses through a bunch of nodes. [04:05.820 --> 04:08.560] And then eventually you wind up like at an object that has no parents. [04:08.580 --> 04:10.500] And that is the entirety of this graph segment. [04:11.720 --> 04:20.500] And so the interesting properties, particularly of Git, but of Ground Station as well, because I'm using its ODB, are that because everything is immutable, like this graph can never change. [04:20.640 --> 04:23.220] Like this is, this is like a fixed point in the universe. [04:23.220 --> 04:29.040] And while I can add stuff to the top by adding new nodes to the top that then like name other elements. [04:29.140 --> 04:33.320] So I can make this graph bigger, but this graph will always be a subset of any graph that I add to it. [04:33.500 --> 04:34.820] And this graph will never change. [04:35.060 --> 04:38.120] And that's enforced by a second property called content addressability. [04:38.640 --> 04:44.400] And so all content addressability is, is if you take some datum and then you hash it via some process. [04:44.400 --> 04:46.200] I'm using GitsODB, so it's SHA-1. [04:46.400 --> 04:47.980] And then you just name it that thing. [04:48.460 --> 04:50.420] You can trivially check whether or not some object you... [04:50.420 --> 04:55.820] Like, so then when you try to retrieve that object from the database, you can trivially check whether or not you've got the right one, because you just hash it. [04:55.920 --> 05:00.040] And if it has a different hash than the name you asked for, you know, something bad is happening. [05:00.140 --> 05:00.900] Someone's messing with you. [05:00.940 --> 05:01.820] Your disk is going bad. [05:02.000 --> 05:03.620] You know, something, something, whatever. [05:04.540 --> 05:09.840] But so the cool properties about this are basically that like, you can sync these in really, really silly ways. [05:10.220 --> 05:19.940] Like if you're syncing a traditional database, you need to check that like you have like isolation and atomicity and like consistency and like a bunch of other stuff that sounds really, really hard. [05:20.420 --> 05:28.340] Instead with like content addressable immutable objects, you literally just like give people content and tell them to write it into their database and it'll come out in the wash. [05:28.500 --> 05:32.940] And if they get it wrong, it will just, it will actually sidestep the graph and not wind up in it. [05:33.040 --> 05:37.960] So if you just like keep giving it to them over and over again, eventually they'll get a good copy and the graph will come together. [05:39.540 --> 05:49.440] However, because of the way Ground Station works, when you're aggressively giving people data and you have no notion of locking or like a single point of truth, it's not reasonable. [05:49.800 --> 05:54.360] So like, sorry, the thing I forgot to mention is that like this single point of truth has to be absolute. [05:54.540 --> 06:00.660] Like you can only have one point that represents a graph in like gets a hash chain implementation. [06:01.060 --> 06:06.660] Whereas like I very deliberately didn't want that because all of my applications were meant to be incredibly asynchronous. [06:07.000 --> 06:10.100] I like potentially not happening on the same network or the same country. [06:10.640 --> 06:15.100] And so like needing to coordinate with your peers to add stuff to the graph was really, really impractical. [06:15.380 --> 06:19.820] And so what I did instead was I just arbitrarily decided that I would not use the same format. [06:20.120 --> 06:25.380] And instead I represent a source of truth inside the Ground Station database as being a set of points. [06:25.820 --> 06:37.180] And so if you add a new node to the top of the graph, you can safely purge like the node that used to represent the tip from the source of truth because it's now a part of the graph. [06:37.380 --> 06:44.260] But if you're going off in a different direction, you just add your thing and then when you sync it up, you just loop them all in and treat that as a single source of truth. [06:44.700 --> 06:55.580] Now this like really sucks for anything like source code or like an actual database or all kinds of things that you actually do need like a single consistent point and you don't want to rely on computers to awkwardly try and merge. [06:55.900 --> 07:02.740] But for most of the fairly soft applications I had for this, like a bulletin board is actually really, really easy to express as a set of points. [07:02.740 --> 07:08.740] You just like branch the conversation at the literal point the conversation branched and then show it to a user and let them work it out. [07:10.040 --> 07:11.760] And so that's basically what I did. [07:12.720 --> 07:13.160] Yeah. [07:14.560 --> 07:18.240] I'm like not going to do the... I've got this database set up. [07:18.320 --> 07:22.160] I made these screenshots last night but trying to chrome across the other thing that I can't see is a pain. [07:22.580 --> 07:24.480] So basically this is what the interface looks like. [07:24.560 --> 07:25.580] I'm a terrible designer. [07:26.320 --> 07:30.920] But so basically like the important thing is that you can see the point on that graph data... [07:31.980 --> 07:35.640] That graph diagram on the right, you can see that it's actually diverged. [07:35.740 --> 07:38.860] Two people added nodes to the graph that couldn't see each other at the time. [07:40.700 --> 07:45.620] But looking at this, you have no way of telling like which node was inserted first or even which one is which. [07:46.580 --> 07:50.580] And so in my like shitty designer glory, I decided that I would just like... [07:50.580 --> 07:54.180] If you click on one branch, it will just color that branch in separately. [07:55.000 --> 08:00.780] And this kind of makes more sense with a more complicated graph, but unfortunately like size constraints. [08:01.060 --> 08:03.420] And so conversely, you get the other thing. [08:04.240 --> 08:06.880] So, you know, if you click the other side, it'll just highlight that side. [08:06.920 --> 08:11.780] So you can like explore the conversation in like a fairly organic, albeit really ugly way. [08:12.240 --> 08:18.040] And then finally, if you reply to a node, the assumption is that you actually were replying to like everything visible. [08:18.040 --> 08:22.360] So in this instance, it's merged that diverged graph back into a single point. [08:24.200 --> 08:27.780] And so the way this works under the hood is like three discrete components. [08:28.120 --> 08:32.160] You have a protocol driver, which is responsible for doing stuff that the user can see. [08:32.300 --> 08:35.900] So for example, that application is actually called the airship. [08:36.120 --> 08:37.060] It's a silly metaphor. [08:37.540 --> 08:48.340] So the protocol driver is responsible for like unpacking and rendering the markdown inside of the objects, working out how to present them on the graph, working out how to show them to the user, working out what the relationship between objects actually is, [08:48.500 --> 08:50.220] and then managing the internal data structures. [08:50.660 --> 08:59.560] There's the object graph that I talked about already, which is basically just this like DAG structure of nodes that can have this like superposition of multiple points as a source of truth. [08:59.740 --> 09:07.480] And then the transport driver, which is where I'm slowly getting to in this talk, which is like given that I have these data structures, like how do I get them to other people? [09:09.340 --> 09:12.340] And so I'm going to kind of skip over this because we're running short on time. [09:12.480 --> 09:15.180] Originally, I was concerned that I didn't time my talk, but I think we're good. [09:16.100 --> 09:28.760] So like one of the interesting things though is the fact that like because I'm using Git under the hood, all of the ground station specific stuff is actually just using blobs with like magic contents that ground station knows how to deal with, or rather that protocol drivers know how to deal with. [09:28.960 --> 09:31.660] But it doesn't actually know how to move about the entirety of a Git database. [09:31.660 --> 09:37.360] So there's no reason that you couldn't actually sync source code using audio waves, apart from sanity and reason. [09:38.740 --> 09:45.280] But so like one of the other really interesting ideas that someone posed to me that I haven't really looked into yet was a decentralized marketplace. [09:45.680 --> 10:03.260] So like some kind of a Silk Road-esque thing, not that I would necessarily encourage it, but instead of like relying on onion routing or like Internet infrastructure at large, why not have a database that literally is only accessible to people who are physically proximate to it by virtue of the fact that you need to get near someone in order to grab that section of the graph. [10:04.780 --> 10:08.560] So anyway, I already talked a little bit about how the object graph works. [10:09.180 --> 10:12.120] I'll go into like a tiny bit more detail, but it's not super important. [10:12.260 --> 10:13.760] So basically you have root objects. [10:14.120 --> 10:22.000] And as I mentioned, everything in the database is content addressable, meaning that if two people hash identical objects, they'll wind up with literally the same object with the same name. [10:22.280 --> 10:33.700] Meaning that, so for example, if two people are pulling in data from some third party, and as long as you organize that the root object contains very little state, two people doing the same task will actually wind up with the same graph. [10:33.840 --> 10:35.860] And then when you sync them, it'll effectively de-dupe. [10:36.220 --> 10:39.080] So the purpose of a root object isn't actually to carry any data. [10:39.320 --> 10:43.380] All it does is basically act as a placeholder with a tiny little bit of metadata in it. [10:44.460 --> 10:46.480] Like basically optimizing for collisions. [10:47.480 --> 10:58.320] Update objects are the things that actually carry like data that's presentable in some way, whether that be like git commits, messages on the message board, you know, whatever it may be. [10:58.600 --> 11:00.960] And then greftips, so I'm really creative. [11:01.280 --> 11:03.420] Git has refs, crown station has grefts. [11:03.960 --> 11:11.200] And so greftips represent basically the tips of the graph that are like the part that you should start walking at when you want to present whatever data is in the graph. [11:12.360 --> 11:17.520] So the original transport driver is kind of like where we're getting to the meat of this thing. [11:18.020 --> 11:23.620] And so the first transport driver was really, really silly, but like ultimately it worked pretty well. [11:23.800 --> 11:27.300] The assumption was that you're on a more or less homogenous link layer network. [11:27.820 --> 11:32.160] And so all the nodes do is they shriek UDP... [11:32.160 --> 11:36.180] They shriek UDP traffic onto the network in order to find one another. [11:36.400 --> 11:42.640] And then when they find their peers, they connect to them with TCP and proceed to like exchange objects very, very aggressively. [11:43.480 --> 11:49.680] And there is a little bit of magic in it for basically like once you know about a peer, if you get more stuff, you can reach out to them to give it to them. [11:50.000 --> 11:51.980] But the gist of it is really quite simple. [11:52.100 --> 11:54.600] It's basically like make a ton of noise so that people can find you. [11:54.720 --> 11:57.740] And then when they find you, aggressively give them everything in your database. [11:58.340 --> 12:05.900] Which kind of brings me to the data distribution strategy, which is like always try and give people as much state as humanly possible. [12:06.520 --> 12:09.720] Because ideally you want like as much world state as humanly possible. [12:10.340 --> 12:19.120] And there is like some optimizations that you can do later for like probabilistically forgetting things in such a way that like everything is probably still on the graph. [12:19.840 --> 12:25.140] But like luckily I guess it really just hasn't seen enough adoption that like too much data has been a problem yet. [12:25.420 --> 12:30.300] So for the time being just like shoving all of the data that you can find across to your peers is working just fine. [12:31.080 --> 12:35.360] And so here's like the first let's see whether or not this has failed miserably yet slide. [12:37.520 --> 12:40.540] Okay, so it's... there is a fair bit of corruption. [12:41.260 --> 12:46.920] But basically like it's successfully like locating... it's nearly gotten to the end of a byte. [12:47.200 --> 12:48.760] Sorry, it's nearly gotten to the end of a message. [12:49.020 --> 12:55.080] If you scroll up a little bit, it was expecting something in the order of I think 100... oh, right. [12:55.900 --> 13:00.080] Let's... let's just start again and hope for the best is my... is my current plan. [13:00.220 --> 13:02.680] I deliberately timed this so we'd have like a few stabs at it. [13:03.820 --> 13:06.920] Turns out audio is actually a really bad transport layer. [13:07.080 --> 13:07.320] Who knew? [13:10.980 --> 13:11.380] Cool. [13:11.940 --> 13:13.360] So like practical applications. [13:13.640 --> 13:17.460] I... I touched on Byzantium using it for disaster affected areas. [13:17.780 --> 13:19.900] And for them it's actually a really valuable tool. [13:20.100 --> 13:26.920] Like I think it was the hurricane in the Philippines that it was actually deployed in which blew my mind because I'd only just finished writing this at the time. [13:27.060 --> 13:28.700] And I couldn't believe people were actually using it. [13:29.180 --> 13:32.720] But in that case like if you imagine someone who's in like your... [13:33.580 --> 13:39.940] a city or like a small town with very little centralized infrastructure that's taken out by like a flood or a cyclone or whatever. [13:40.440 --> 13:48.100] And there's a message board with people posting like what they have, what they need, whether or not they're okay, and like who they're looking for in like their family members. [13:48.540 --> 13:55.260] And so someone like takes their machine to like a town hall or whatever, grabs the whole graph and then drives 40 kilometers to like the next town. [13:55.560 --> 14:02.540] If the next town also has ground station nodes, they will basically grab the entirety of the message board state from the other town and then have that context. [14:03.080 --> 14:06.340] And that actually can be a really huge deal in some cases. [14:07.960 --> 14:11.760] In more esoteric forms, because it works really well with Git. [14:12.080 --> 14:16.300] I used to work at 99designs and when I was there, like nearly all of the devs ran ground station nodes. [14:16.500 --> 14:20.780] And basically like as you added data to the Git database, it would sync across everyone in the office. [14:21.320 --> 14:24.500] And it basically made git fetch and no op, because all I had to do was update refs from GitHub. [14:25.660 --> 14:29.520] Which is way at the other end of the scale, but it's satisfying every time I do it. [14:30.940 --> 14:34.320] So I already talked a little bit about like kind of other stuff that you could do with it. [14:35.300 --> 14:39.200] You know, painless sneaker nets is kind of where I'm getting towards with this. [14:39.860 --> 14:42.540] But like all of the transport drivers assume physical proximity. [14:43.740 --> 14:48.580] It actually does have support now for Internet routing, but you need to already know the address of your peer and a bunch of contacts. [14:48.580 --> 14:49.580] It kind of sucks. [14:49.700 --> 14:53.080] It's really only good for a congregation point if you're using it very aggressively. [14:54.120 --> 14:56.560] I mean like wireless is really, really easy. [14:57.040 --> 14:59.220] And like it does a lot of the right things. [14:59.380 --> 15:02.840] Byzantium took a lot of the pain out of it, providing that you're willing to like boot their live disk. [15:03.760 --> 15:07.420] But like needing an 802.11 stack is kind of shit. [15:07.560 --> 15:08.600] Like not all laptops have it. [15:08.680 --> 15:10.240] Not all laptops have good drivers for it. [15:10.660 --> 15:18.660] Sometimes you're attached to a network that, you know, wants to filter UDP broadcast traffic because some idiot might shout really, really loudly from all of his machines at the same time. [15:20.700 --> 15:22.120] So let's talk about air gaps. [15:23.120 --> 15:25.240] You're getting back to the radBIOS thing. [15:25.500 --> 15:26.760] Sorry, I kill myself. [15:28.540 --> 15:30.380] So QuietNet, which I touched on from Katie. [15:30.520 --> 15:45.060] This is basically like a simplex channel that will basically let you transmit data from one machine to another very, very lossily, both in terms of like just dropping packets on the floor and also in terms of like, you know, you get tons and tons of bit errors. [15:45.320 --> 15:47.180] You get random garbage sped out to your terminal. [15:47.360 --> 15:49.240] Every now and again, you get like, you get super lucky. [15:49.400 --> 15:51.460] You get some escape codes that changes the encoding of your terminal. [15:51.580 --> 15:52.960] Everything kind of sucks. [15:53.220 --> 15:56.200] The upshot is that it's actually like really simple to understand. [15:57.300 --> 15:59.900] Before I picked up this project, audio was all voodoo to me. [16:00.100 --> 16:01.600] I mean, it still is, but less. [16:02.300 --> 16:08.700] But like most of the like proper projects like new radio, for example, which is amazing, but like the learning curve is a cliff. [16:09.620 --> 16:11.640] And like you fall off it, not go up. [16:14.340 --> 16:15.100] And so... [16:16.340 --> 16:16.840] Thank you. [16:17.500 --> 16:21.600] But so like QuietNet was basically written by someone who was like trying to work out how to audio. [16:22.000 --> 16:24.640] And I'm like really impatient and love instant gratification. [16:24.800 --> 16:30.240] So I was really excited about the prospect of just like picking up a thing and then just like, you know, smushing it into my use case. [16:30.740 --> 16:43.600] But like it was like really well commented and functions had same names and there wasn't a bunch of like, I mean, there's a ton of math in it, but it's not just like arbitrary math because it should be intuitively obvious to you that this is how you FFT or whatever it may be. [16:44.480 --> 16:48.840] It's, you know, like, and especially in the commit log, it's very obvious like how everything fits together. [16:49.060 --> 16:52.980] And as a result, it was like super easy to hack on and at least like build a prototype with. [16:54.360 --> 16:57.680] So like, let's talk about encoding, which is everyone's favorite thing. [16:57.780 --> 17:01.660] Because normally when people say this, they're thinking about like Unicode and the ASCII debacle. [17:02.120 --> 17:10.880] But in this instance, it's literally just that like given some piece of my knowledge graph, I need to turn it into a series of bits in order to like send it across any network. [17:11.600 --> 17:17.860] I mean, like luckily, you know, the BSD socket API makes that kind of simple when you're talking on top of like a very high level abstraction. [17:18.160 --> 17:25.200] But if you're using something like a serial console or audio waves, you need some coherent mechanism for turning it into a bit stream and back. [17:25.780 --> 17:33.180] And so in QuietNet, Katie used PSK31, which is a standardized frequency shift keying scheme. [17:33.700 --> 17:37.400] And so one of the things that's really interesting about it, it looks a little bit like Morse code. [17:37.860 --> 17:42.540] And actually, I assumed that it was when I first saw it, but on closer inspection, it's not and I'm an idiot. [17:43.080 --> 17:49.440] But so the interesting thing here is all of the codes begin and end with a one, and there are no repeated zeros in them. [17:49.580 --> 17:53.940] And the reason for this is that it has a sigil that delimates messages, which is two zeros in a row. [17:54.580 --> 17:59.120] And assuming that you have like no bit errors on the wire, this is like really quite efficient. [17:59.820 --> 18:11.380] The reason I picked this section of the graph is that you can see that the vowels have much shorter encodings than like the letters that aren't used as often in the alphabet, which means that like the letters you're most likely to use occupy less space on the wire. [18:11.560 --> 18:13.680] And like it packs up pretty effectively. [18:14.460 --> 18:18.920] Unfortunately, like bit errors exist and terrible things happen. [18:19.120 --> 18:21.780] And as a result, like it's bad. [18:21.780 --> 18:24.780] It's not a great encoding scheme unless like loss is okay. [18:25.480 --> 18:37.040] Like for clarity, if you're like encoding text messages and you're not trying to process them digitally and you're just trying to like print them on paper to give to someone, yeah, like missing characters or like the occasional character that like bit flips and an A becomes an N, [18:37.300 --> 18:38.280] like whatever, it's fine. [18:38.800 --> 18:43.600] Not so good if you plan to hash that object and then store it by that hash because nothing will ever line up again. [18:44.820 --> 18:47.580] So there's this great thing called an error correcting code or a hamming code. [18:48.760 --> 18:52.710] And so I picked these four sequences fairly arbitrarily. [18:53.440 --> 19:01.860] They're actually buried in the depths of ground station in kind of an awkward way at the moment that's not fully utilized because it is actually so much data that my demo would have taken most of today. [19:03.040 --> 19:11.360] But so the interesting thing about these codes is that you can flip any two bits in any one of these four sequences and still unambiguously decode it. [19:11.360 --> 19:13.780] And the reason for that is that all of these... [19:13.780 --> 19:17.980] all of these bit strings are three bits apart from each other. [19:18.700 --> 19:30.480] And so what this means is that if you're transmitting over a really, really lossy link, bit errors are really not a problem for you unless it's like so lossy that more than 30% of your bits get flipped, in which case you're probably toast. [19:32.060 --> 19:35.780] And so I mentioned that this came up at ShmooCon this year. [19:36.180 --> 19:40.040] So Dominic Spill and Michael Osman presented their work on unambiguous encapsulation. [19:40.040 --> 19:42.420] And like, I'm not going to go too far into it. [19:43.000 --> 19:44.060] The talk is on YouTube. [19:44.260 --> 19:45.020] It's really amazing. [19:45.160 --> 19:46.040] You should definitely check it out. [19:46.520 --> 19:49.280] It was their mitigation for Travis Goodspeed's packet-in-packet-attack. [19:50.400 --> 19:53.020] But one of the cool things about this was... [19:53.020 --> 19:57.400] The basic idea is that instead of having these four... [19:58.980 --> 20:02.160] Instead of having these four bit strings, you have two groups of two bit strings. [20:02.400 --> 20:09.960] And while each of the ones inside of the inner ovals is two bits apart, the two ovals are actually three bits apart. [20:10.040 --> 20:16.360] So even if you get so many bit errors that your internal data gets munched, it's impossible to mis-parse... [20:16.360 --> 20:24.140] So for example, if you use the top code to encode header data and the bottom code to encode payload data, it's impossible to accidentally mis-parse header as payload and vice versa. [20:24.900 --> 20:36.140] And particularly if you know what you're expecting, it gives you a really good way of trying to work out whether or not terrible things are happening, which is why when we checked in on my demo that's not looking so great. [20:36.400 --> 20:38.700] There were so many error messages saying like I was... [20:38.700 --> 20:40.880] I got header data when I was expecting payload data. [20:40.980 --> 20:43.220] The reason for that is that it was encoded in the wrong way. [20:43.640 --> 20:44.980] And hopefully when... [20:44.980 --> 20:48.320] This just like retries, like I said, it just like yells all the objects. [20:48.340 --> 20:51.760] Hopefully the next time the same bits won't flip and we'll get away with it. [20:53.860 --> 20:55.980] And so here is where this turns into a fail talk. [20:56.920 --> 21:01.800] So originally, like Ground Station had this cool TCP driver that like knew how to sync things up. [21:01.900 --> 21:03.160] And it was like, it was pretty fast. [21:03.260 --> 21:05.100] It wasn't super efficient, but it was really easy to debug. [21:05.260 --> 21:08.320] It was like really easy to pull apart in Wireshark, which was important to me. [21:09.160 --> 21:12.680] And so I basically just thought like how hard can audio streams be? [21:12.820 --> 21:21.880] I'm just gonna open like a full duplex connection and then just like literally just wrap it with a BSD Sockets API and it'll just sync up and it'll be done. [21:22.000 --> 21:23.560] I'm gonna be out of here like by this afternoon. [21:24.640 --> 21:25.880] That's not a thing. [21:28.060 --> 21:28.420] Yeah. [21:29.140 --> 21:30.780] I mean, like it sort of is a thing. [21:30.880 --> 21:33.560] It is possible to make it work in a perfectly silent room. [21:33.940 --> 21:37.640] As I discovered, it also needs to be the exact same shape and size as my bedroom. [21:39.620 --> 21:40.340] I like... [21:40.340 --> 21:43.340] So at the moment I actually haven't got the latest code out. [21:43.460 --> 21:44.960] It really desperately needs a rebase. [21:45.080 --> 21:47.440] Like I don't want to publish the shit show that it currently looks like. [21:47.440 --> 21:52.360] When I publish the demos, like I totally encourage you to run the original full duplex demo. [21:52.760 --> 21:59.380] Particularly run it at like 1400 hertz instead of 19k so that you can hear computers beep booping at each other in all of their glory. [22:00.340 --> 22:01.620] It's kind of spectacular. [22:02.440 --> 22:05.360] But yeah, you want to have some time on your hands because it's pretty lossy. [22:06.520 --> 22:14.500] And so in order to actually get this duplex connection, I invented like the stupidest Byzantine fault tolerance algorithm in the entire world. [22:14.920 --> 22:24.000] And so what I did, instead of using the unambiguous encapsulation process for like header and payload, instead I just treat it as like two separate ways to encode ones and zeros. [22:24.520 --> 22:32.120] And so what you do is you just like... you bark a tone and then when your peer receives the tone, they repeat it in the other code and then you flip back and forth. [22:33.460 --> 22:39.320] I tried to make a slide for this but I just couldn't work out how to represent it in a way that looked okay in this size in Keynote. [22:41.420 --> 22:42.980] I don't know, is that actually making sense? [22:43.100 --> 22:44.040] Because it's going to be kind of pivotal. [22:45.100 --> 22:46.860] Like show of hands, who knows what I'm talking about? [22:48.180 --> 22:49.020] All right, awesome. [22:50.200 --> 22:51.660] Yeah, there are way better schemes. [22:52.020 --> 22:54.300] Kind of from the get-go, like I was really... [22:54.300 --> 23:01.040] Like I was actually really taken by the way Katie had kind of decomposed the problem and then like built it from the ground up in a fairly comprehensible way. [23:01.040 --> 23:04.280] So I was really, really loath to like grab some like... [23:04.280 --> 23:11.980] You know, grab half the new radio source or grab some paper from, you know, someone that I didn't understand and just like blindly reimplement it without really knowing what was going on. [23:12.440 --> 23:15.000] In retrospect, I should have because it would have, you know, worked a lot better. [23:15.980 --> 23:19.800] But, you know, it did at least have the advantage of being like really, really easy to debug. [23:21.380 --> 23:27.380] But the cool thing is like... so normally you need to convert your data into a bitstream because you're transmitting it over something digital. [23:27.380 --> 23:29.420] But like audio isn't digital. [23:30.080 --> 23:35.820] So instead of like having ones and zeros, you have the very real possibility of having ones, zeros and nulls. [23:35.900 --> 23:43.120] For example, if you're using like frequency shift keying, which is basically the process of like you take a carrier wave and then you modulate that wave. [23:43.380 --> 23:50.320] So typically what you do for frequency shift keying is like, you'll have your carrier wave and then you will like slow the frequency when you want to transmit a one. [23:50.840 --> 24:06.560] But instead of doing that, you can like slow the frequency for one and speed it up for zero and then like treat the carrier wave What this meant was, once I had a pretty effective way of timing where frames should start and end, bits that I wasn't sure about, [24:06.660 --> 24:09.580] I could just leave out and let the hamming weight sort it out. [24:10.220 --> 24:14.120] The error-correcting code itself was capable of dealing with bits that I weren't sure what they were. [24:15.660 --> 24:17.540] So I spent quite a while on this. [24:18.160 --> 24:23.580] I got to the point where it sort of worked in really, really optimal conditions. [24:24.080 --> 24:31.700] And it was really cool, but ultimately, my goal when I started this was I actually wanted something that would work walking down the street. [24:32.160 --> 24:39.460] And this, it was not, unless you walk very slowly in a perfectly silent, not vacuum, because sound doesn't work so good there. [24:39.560 --> 24:46.320] But you would basically need to be in a place where you and one other person were the only person floating in no gravity. [24:47.040 --> 24:49.580] So I found this library called All The FSKs on GitHub. [24:50.140 --> 24:56.420] And as you may have gathered, this is about the point that, like, I gave up on this whole, like, understand everything I'm doing mantra. [24:56.640 --> 25:00.020] Instead, I was like, I'm going to take some working Python code and I'm going to bolt it to my thing. [25:00.760 --> 25:02.240] And so this guy published a library. [25:02.540 --> 25:04.600] It talks to PyAudio, which I was already using. [25:04.860 --> 25:12.280] It uses SciPy and NumPy interchangeably in ways that I'm not sure are actually legit, which probably explains some of the dramas that I have with it. [25:13.120 --> 25:14.100] But so I took this. [25:14.660 --> 25:15.940] I learned a real lot from it. [25:15.940 --> 25:25.080] And ultimately, I did get this working, but it was another case of, like, the encoded data is so, so long that you will likely die of old age before you actually sync any data up. [25:26.360 --> 25:29.280] And so I concluded, like, yep, audio is still hard. [25:30.620 --> 25:35.120] But so this is the point at which... so up until now, I was still working on my full duplex solution. [25:35.300 --> 25:37.920] Like, I wanted... like, I was going to have duplex streams, dammit. [25:38.400 --> 25:42.420] But about this point, I realized that I was being unreasonable and that was just, like, not going to work. [25:43.120 --> 25:46.700] So instead, I thought, like, well, everything in the universe is immutable. [25:48.640 --> 25:56.960] When you add data to a graph, all you have to do is, like, walk the new point backwards and any of the points that are already meant to be a tip, you just remove them because they're reachable now. [25:58.080 --> 26:02.760] So why don't I just, like, set up boxes that just, like, shout the entirety of their databases all the time. [26:03.500 --> 26:13.120] Go back to using the unambiguous encapsulation stuff to uniquely encode the headers so that it's very easy to tell, like, when the header of a file starts, even if you're just, like, walking in midway on the bitstream. [26:14.160 --> 26:16.200] And then just... yeah. [26:16.400 --> 26:20.300] Just yell everything all the time forever, which is kind of like my discovery protocol anyway. [26:21.600 --> 26:25.300] And so this is what I was working on at 3 o'clock this morning. [26:25.560 --> 26:26.820] It works sometimes. [26:27.920 --> 26:30.940] The flip side was... so I actually went back to using QuietNet's code. [26:30.940 --> 26:38.440] But instead of using PSK31, which is, like, a very aggressive encoding scheme, I took the same basic principle and I just stretched everything. [26:38.980 --> 26:41.720] So instead of using two zeros as the sigil, I used four. [26:42.180 --> 26:45.020] To encode a one, I used three ones and to encode a zero... [26:45.020 --> 26:45.240] Oh, sorry. [26:45.340 --> 26:46.620] To encode a zero, I used three ones. [26:46.800 --> 26:49.400] To encode a one, I used, like, agility ones. [26:49.560 --> 26:50.400] I just leaned on the button. [26:51.060 --> 26:55.800] And then when I go to unpack the data, I basically, like... [26:55.800 --> 26:57.200] There's a little bit of magic in it. [26:57.200 --> 27:03.140] All I have to do is, like, heuristically determine whether or not this thing is likely to be a one or a zero based on its length. [27:03.540 --> 27:06.940] And by sampling the first few bytes that I see, I can basically... [27:06.940 --> 27:14.320] So, like, for reasons I'm not totally sure of, the length of the, like, bit streams that it unpacks tend to vary pretty wildly. [27:14.600 --> 27:24.360] But luckily, like, once you listen in on a stream for a few seconds, like, because there's such a wide difference in, like, the length of a one and a zero, it's pretty easy to work out, like, where you should draw that line in the sand. [27:24.700 --> 27:26.040] And they vary pretty wildly. [27:26.040 --> 27:27.380] Like, so... [27:27.980 --> 27:29.520] I don't have a good demo for it. [27:29.600 --> 27:34.040] But, like, typically, despite the fact that I'm intentionally broadcasting about three ones and... [27:34.040 --> 27:34.520] Sorry. [27:35.660 --> 27:44.100] Three ones for a zero and, like, something in the order of 10 or 12 for a one, I tend to get about four for a zero and, like, 27 for a one. [27:45.300 --> 27:48.820] Which actually makes it pretty easy to, like, distinguish unambiguously. [27:48.820 --> 27:50.980] It's not rocket surgery at that point. [27:52.440 --> 27:52.840] Cool. [27:53.040 --> 27:56.760] So, let's, like, see whether or not anything better happened this time. [27:57.900 --> 28:02.580] So, I mean, there's, like, a lot of bit flipped bytes, like, a real lot of data. [28:03.460 --> 28:10.880] The upshot with this protocol is basically that, like, because it's so aggressive, it's still just, like, shoving these objects into the database pointlessly anyway. [28:11.440 --> 28:16.880] So, like, all things going to plan, if I just, like, leave this running for the rest of the talk, it's gonna come up. [28:17.720 --> 28:19.340] There is, like, a little... [28:20.920 --> 28:28.520] There's a log line that it spits out, like, when it successfully gets something plausible to write into the database that, like, looks like it might be a valid tip. [28:28.840 --> 28:29.860] Which isn't in here. [28:30.540 --> 28:31.980] But, like, I've got 18 more minutes. [28:32.000 --> 28:32.900] This is totally gonna work. [28:32.900 --> 28:36.800] Like, I actually screwed up the ordering of my slides as well. [28:36.920 --> 28:39.160] This was my big plan for if my demo didn't go well. [28:39.440 --> 28:40.760] I figured I'd just... [28:40.760 --> 28:41.680] I really like ducks. [28:44.220 --> 28:45.680] But, so, like, what... [28:48.080 --> 28:52.860] You know, while I was working on this, I, like, I picked up a bunch of really, like, really interesting tech. [28:53.080 --> 28:54.200] If nothing else, like... [28:54.200 --> 28:58.640] So, I'd always known what, like, a 4A series was at a very high level. [28:58.740 --> 29:00.140] But, like, I never actually had to do one. [29:00.240 --> 29:01.480] Definitely never had to implement one. [29:01.480 --> 29:05.420] So, like, I learned a bunch of really interesting stuff about, like, how to do FFT efficiently. [29:05.720 --> 29:08.340] Especially in Python, where arithmetic is kind of terrible. [29:09.360 --> 29:12.500] For the first time, I really, like, stopped to think about how to write a key inks game. [29:13.480 --> 29:16.940] You know, I work on things that are a pretty big scale at work. [29:17.460 --> 29:21.080] But, like, ultimately, I was born in the, like, bandwidth is cheap era. [29:21.660 --> 29:25.640] And as a result, like, doubling the size of something is nearly always not a real problem for me. [29:26.260 --> 29:33.180] In this instance, like, I think the size of the database that I'm trying to move from this laptop to that one is something in the order of about 400 bytes. [29:33.540 --> 29:35.020] And we're 43 minutes in. [29:35.700 --> 29:36.880] And it hasn't gone anywhere. [29:37.540 --> 29:40.060] So, it gave me, like, a bunch of context for, like, holy shit. [29:40.220 --> 29:44.360] Like, trying to work out how to efficiently encode data is, like, a real problem. [29:45.400 --> 29:48.640] As well as just, like, some general context for, like, how to audio in Python. [29:49.080 --> 29:52.860] Like, if you're ever picking up audio, like, the PyAudio library turns out to be amazing. [29:53.860 --> 29:57.420] It basically knows how to do, like, pretty much everything you would want to do out of the box. [29:57.560 --> 30:02.700] The problem is digging into its insane and confusing API to work out why it's named something so totally irrational. [30:05.220 --> 30:09.560] But, so, like, I'm assuming the question you're all asking yourself is, like, holy shit, can I put my production data in this thing? [30:11.380 --> 30:13.120] I mean, Ground Station is, like, a thing. [30:13.240 --> 30:14.280] It's, like, two years old now. [30:15.140 --> 30:16.560] It's, like, I'm still working on it. [30:16.920 --> 30:23.720] If you have a problem that you, like, want to solve, like, you know, if you have a hammer that you want to bash in with this nail, like, by all means, get in touch with me. [30:23.860 --> 30:26.120] I would be super excited to, like, work with you on it. [30:26.360 --> 30:28.900] And if nothing else, like, I just like seeing my problems get adopted. [30:30.020 --> 30:32.960] RadBIOS, as I'm going to release it, like, I really wouldn't. [30:33.740 --> 30:37.320] I mean, play with it, but holy shit, like, moving data around with audio sucks. [30:38.500 --> 30:41.920] And for anyone who falls into the last category, you're my hero and I'll buy you a beer. [30:43.860 --> 30:48.480] But, so, like, instead, if you actually want to do things like this and have it work, there are a few other projects. [30:48.780 --> 30:51.080] So, Kamal Mustafa wrote this thing called Minimodem. [30:51.620 --> 30:53.700] And ostensibly, it does exactly what I want. [30:54.000 --> 31:00.360] It supports a bunch of, like, arbitrary keying schemes that include, like, various things that are, like, you have to use them on ham radio. [31:00.600 --> 31:03.100] It actually refuses to transmit anything without a call sign. [31:04.460 --> 31:07.800] It's also actually not as great as it's made out to be. [31:07.940 --> 31:08.440] Like, don't get me wrong. [31:08.500 --> 31:10.960] I'm not ragging on the developer by any way, shape, or form. [31:11.600 --> 31:19.940] But, like, the guarantees that the readme makes about, like, what data you'll get out the other end and the actual data that you get out the other end are not strictly in line. [31:21.320 --> 31:23.560] So, Linux has an AX.25 driver in the tree. [31:23.860 --> 31:26.020] An AX.25 is basically a packet radio format. [31:26.340 --> 31:28.080] It works really well over ham radio. [31:28.080 --> 31:37.060] I realize I keep going back to these guys, but the Byzantium guys actually had, like, I think a 200-baud link over ham radio for a while that they were using to do something kind of similar. [31:38.800 --> 31:41.160] It, like, it does work really well. [31:41.560 --> 31:45.740] I mean, for the purposes of building something like this, it felt a lot like cheating. [31:46.340 --> 31:52.940] And also, like, it doesn't work very well at, like, audible frequencies, which really robbed me of my joy of wanting to hear a bunch of computers go beep-boop. [31:54.220 --> 31:59.880] But in the Linux tree, there's also a module called Sound Modem, which does exactly what it sounds like. [32:00.020 --> 32:03.540] And so it's a layer-to-encapsulation format that uses audio hardware. [32:04.340 --> 32:08.840] I actually haven't got... the only Linux machine with audio hardware that I have is Chromebook. [32:09.000 --> 32:17.060] And I don't know if you've ever tried to build your own kernel for Chromebook with some kooky module that wants to use non-proprietary sound hardware, but, like, you're gonna have a pretty bad time. [32:17.240 --> 32:19.360] So I never actually got around to trying it. [32:19.580 --> 32:22.120] It sounds really interesting, albeit really chaotic, [32:25.380 --> 32:33.180] because they certainly imply that it will work with, like, more than two machines in the room, which I really just want to see or hear, I guess. [32:34.160 --> 32:38.440] And so, like, there are definitely some people I have to thank, a bunch of whom that I'm forgetting. [32:38.800 --> 32:44.220] So Dominic and Mike for both releasing their unambiguous encapsulation paper and talking me into this ridiculous stunt. [32:44.840 --> 32:48.860] Katie for supplying all the code, which I then gutted and then reintegrated again. [32:49.400 --> 32:56.480] And Mark Jessup, who's the guy who wrote all the FSKs, and also, like, responded incredibly patiently to some of my emails, basically being, like, I'm drooling on myself. [32:56.520 --> 32:57.200] How do I audio? [33:00.680 --> 33:01.040] Cool. [33:01.200 --> 33:03.680] So, like, if you do want to get more info, I'm on the Twitter. [33:03.900 --> 33:05.440] You can definitely reach out to me any time. [33:06.100 --> 33:10.020] I'd be more than happy to talk about computer things or this computer thing or whatever. [33:10.720 --> 33:11.800] Ground Station is up there. [33:11.920 --> 33:16.880] It has, like, a really stupid audio discovery mechanism in the tree that's currently up. [33:16.880 --> 33:21.240] I'll have this code, like, rebased and fixed up hopefully tonight, definitely by tomorrow. [33:21.800 --> 33:25.540] And all the FSKs is, like, a really interesting library as is QuietNet. [33:25.680 --> 33:27.420] Like, you should definitely have a play with both of them. [33:27.540 --> 33:29.680] Especially, like, you're planning a stunt like this. [33:30.140 --> 33:34.800] Picking them up so that you at least get a feeling for the failure modes is really interesting. [33:34.980 --> 33:40.780] If nothing else, there's also a point at which, like, you do start to hear bad data and you realize that you might be in the matrix. [33:43.500 --> 33:46.060] And, like, Byzantium is just a really cool thing. [33:46.320 --> 33:48.260] And, like, I have a lot of heart for those guys. [33:48.400 --> 33:51.680] They also threw a lot of code at Ground Station while I was working on it, while they were integrating it. [33:51.740 --> 33:53.640] And all the bugs that I wrote were inconveniencing them. [33:54.240 --> 33:55.320] So I'm pretty glad of that. [33:57.260 --> 33:57.580] Cool. [33:57.800 --> 33:59.700] I think I timed this almost perfectly. [33:59.940 --> 34:01.360] Are there, like, questions, comments? [34:02.560 --> 34:02.880] Sure. [34:08.190 --> 34:09.970] So, the problem that I... [34:09.970 --> 34:13.690] The problem I had was never, like, how do I encode the data? [34:15.370 --> 34:22.850] Like, at the end of the day, like, once I had reliable transmission, you know, like, encoding data is a very high-level problem. [34:23.830 --> 34:32.210] The problem was very much, like, how do I take, like, this bitstream that I do have and, like, successfully get it to the other end more or less unmolested? [34:32.930 --> 34:34.570] I didn't toy with Morse very much. [34:34.730 --> 34:35.590] A, because, like... [34:35.590 --> 34:37.770] So, at the end of the day, most of my payloads are binary. [34:38.330 --> 34:40.890] And so, like, anything that doesn't have... [34:40.890 --> 34:41.890] I mean, like... [34:41.890 --> 34:51.410] So, right now, I'm actually using Base64 and binary, because the FSK I had basically has a full ASCII set and I can pack it into six bits. [34:52.230 --> 34:56.150] Which, yeah, it was kind of a convenient boundary for a number of reasons. [34:56.730 --> 34:57.990] I did toy with Morse. [34:58.090 --> 35:01.210] If nothing else, like, I originally thought that PSK31 was Morse. [35:01.990 --> 35:05.790] But at the end of the day, like, I'm still pretty confident that, like, how... [35:05.790 --> 35:10.750] Like, how am I gonna represent my data as binary was actually the least significant problem that I ran into. [35:12.870 --> 35:13.270] Sure. [35:13.270 --> 35:14.310] How it [35:17.610 --> 35:23.210] happens and the journey, you're interested in something, and you follow along about it. [35:23.370 --> 35:24.870] You learn a tremendous amount about it. [35:24.870 --> 35:29.700] I didn't have this problem from other areas or other. [35:29.740 --> 35:29.960] There may [35:39.600 --> 35:44.220] not have work done to transmit digital data in very, very noisy environments. [35:44.560 --> 35:47.720] And you talk about a silent room versus a quiet room. [35:47.720 --> 35:52.300] And the ham radio world's operating, continually changing signal to noise. [35:53.040 --> 36:07.640] I don't know if you've looked at any of the other encoding mechanisms or anything they use, but there's hundreds of different software out there that you can run on a laptop and use as an audio connection to a ham transceiver and transmits data. [36:07.800 --> 36:12.320] Very narrow bandwidth, very high reliability, in very, very noisy environments. [36:12.560 --> 36:15.080] And it's probably one of the fastest growing areas of ham radio. [36:15.440 --> 36:20.040] The guys running out here on the station are using some of those modes. [36:20.740 --> 36:24.040] And I just think that's an area you might want to go and look at. [36:24.140 --> 36:24.620] For sure. [36:24.780 --> 36:26.100] I mean, like, it's a really valid criticism. [36:26.740 --> 36:27.880] And so, like... [36:27.880 --> 36:29.480] I mean, like... [36:29.980 --> 36:31.720] It's a very valid comment then. [36:34.360 --> 36:34.980] That's critical. [36:36.140 --> 36:42.400] So, like, I mean, the point from the start was very much, like, I wanted to build an interesting thing so that I'd know what I was doing by the end. [36:42.760 --> 36:43.920] And, like, you're absolutely right. [36:44.060 --> 36:48.400] Like, this is absolutely a solved problem, which is most of the reason I'm like, for the love of God, don't actually use this. [36:49.560 --> 36:50.480] You know, like... [36:50.480 --> 36:59.400] So, all the FSKs has an MPSK and actually, like, a bunch of really interesting, like, noise floor and signal-to-noise ratio instrumentation kind of buried inside it. [36:59.540 --> 37:04.160] And like I mentioned, like, the new radio does more or less work if you're a wizard and you, like, wrote it. [37:06.420 --> 37:19.220] Yeah, I mean, that's basically the issue that I ran into was, like, most of the existing tooling that, like, does this extremely well either does it at, like, such a high level that it's magical and largely uninteresting for my purposes or is incomprehensible and I just, [37:19.240 --> 37:22.460] like, spent nights trying to bolt it to my thing and couldn't work it out. [37:22.460 --> 37:34.560] You made me curious about going home and taking, you know, two laptops that I have and instead of patching the audio out through USB into my transceiver, being a lot of speaker mentioned in 19.1. [37:43.630 --> 37:50.170] I did a lot of electronic music in my background and, you know, you can always sweep the room because every room has got a sweet spot. [37:50.710 --> 37:53.090] And I wonder if that's a better thought than this. [37:53.090 --> 37:56.750] Yeah, so my, like, amateur opinion having screwed up this... [37:56.750 --> 37:58.470] So, like, I was actually kind of cheating. [37:58.670 --> 38:10.050] I was going to talks yesterday and I was sitting in the room and I was running this thing and traumatizing any dog in the vicinity, trying to work out, like, basically, like, what my best chances were of getting away with a working demo. [38:10.510 --> 38:11.470] Oh, shit, my demo. [38:11.630 --> 38:12.100] Yeah, let's... [38:13.850 --> 38:14.730] I remember that guy. [38:14.930 --> 38:15.790] This is going to be amazing. [38:17.850 --> 38:18.230] Cool. [38:18.390 --> 38:18.610] All right. [38:18.790 --> 38:22.030] So, this is the thing called Airship that I told you about. [38:23.990 --> 38:24.630] This is... [38:24.630 --> 38:25.690] I can't actually see what I'm doing. [38:25.910 --> 38:26.570] So, this is going to be... [38:26.570 --> 38:26.890] Oh, shit. [38:27.870 --> 38:28.550] Everything is based. [38:35.300 --> 38:36.020] Okay, so... [38:37.260 --> 38:38.060] All right, so... [38:38.680 --> 38:40.320] I should have... [38:40.320 --> 38:42.960] Come on. [38:44.160 --> 38:44.520] Yes! [38:51.090 --> 38:52.460] I did not anticipate that. [38:53.540 --> 39:00.820] So, the best part is, like, last night when I was, like, toying with the demo, originally I had, like, a paragraph and, like, some markdown to show that it could do the fancy formatting. [39:01.070 --> 39:06.300] And then I started realizing, like, what the chances were of getting those extra six bytes from this machine to that machine. [39:06.420 --> 39:08.480] And I was, like, yeah, nine characters is heaps. [39:12.370 --> 39:13.390] Were there any more questions? [39:13.550 --> 39:13.830] Comments? [39:14.450 --> 39:14.730] Sure. [39:14.870 --> 39:22.070] I mean, just in reply to what he was saying, you know, the project demand team spent about three months trying to do that with the help of the DC hand community. [39:22.330 --> 39:30.470] If you can get two laptops, like, on a table, side by side, to talk to each other with, like, those hand codes, just with their speakers, we would love to talk to you. [39:30.530 --> 39:31.770] So please email our list. [39:35.480 --> 39:35.840] Cool. [39:35.960 --> 39:36.400] Anyone else? [39:36.600 --> 39:36.880] Sure. [39:44.360 --> 39:44.720] Sure. [39:44.960 --> 39:46.280] So, I mean, you basically... [39:46.280 --> 39:48.820] So, like, bloom filtering is the long and the short of it, right? [39:49.140 --> 39:55.300] You basically, like, take a node and then you take, like, a confidence interval, which basically represents, like... [39:55.300 --> 39:59.240] It's basically, like, an educated guess about how many people actually exist on the graph. [39:59.600 --> 40:05.460] And so that's, like, awkwardly not the data graph but actually the graph of, like, discrete people with databases. [40:06.080 --> 40:08.480] And then, so you pick some probability that represents them. [40:08.620 --> 40:09.680] So, like... [40:11.340 --> 40:13.440] I can't remember how to do the math off the top of my head. [40:13.640 --> 40:19.040] So, for, like, the O of, like, 200 people, like, 0.5% is probably pretty... [40:19.040 --> 40:19.360] Oh, sorry. [40:19.520 --> 40:20.220] 0.05. [40:20.360 --> 40:21.800] So, like, 5% is probably pretty reasonable. [40:22.020 --> 40:25.720] And then you just, like, delete that fraction of your nodes at random. [40:26.860 --> 40:29.340] And then you just, like, carry on doing this. [40:30.720 --> 40:33.860] This is basically, like, I somewhat implemented it. [40:34.120 --> 40:43.080] There's obviously some stuff that you should do, like, rather than just deleting at random, which is haphazard, and also stupid, because you wind up deleting, like, stuff in the middle and basically breaking your chains. [40:43.380 --> 40:51.540] So, you should basically delete entire chains and it makes much more sense to actually, like, look at the usage on the local node for, like, which stuff is accessed and don't delete that. [40:52.480 --> 40:57.500] But, so, I mean, the general principle is basically just, like, the way that, you know, random numbers tend to work. [40:57.700 --> 41:07.180] Just, like, delete some of the data at random and assuming that everyone's PRNG isn't DR, dual GR, ER, yeah, the backdoored one that I can't get the name out of right now. [41:07.260 --> 41:07.660] Julie C. [41:08.860 --> 41:17.600] You know, like, everyone will delete different data and provided that you have some mechanism of, like, subsequently querying your peers when you realize that you need something that you deleted, that's how you tackle it. [41:17.760 --> 41:18.840] Sorry, that was really waffly. [41:18.940 --> 41:20.080] Did I answer your question at all? [41:22.280 --> 41:22.820] Anyone else? [41:23.020 --> 41:23.240] Sure. [41:31.070 --> 41:34.150] Actually, significantly less in my totally subjective experience. [41:35.610 --> 41:39.990] Like, I don't have, like, math, science, or anything apart from intuition to back this up. [41:40.510 --> 41:52.570] But, yeah, the two reasons that I did this at such a high frequency for this were, A, because it would be very difficult to talk over my computer beep-booping, and the other one being that, like, while it was really satisfying, and if nothing else, when I just wasn't sure, [41:52.770 --> 41:58.350] like, when I was trying to intuit which parts of my system were actually working, making audible sound made my life a lot easier. [41:59.170 --> 42:06.230] The mere fact that it, like, is in the audible spectrum just tends to mean that, like, more stuff in your house will probably collide with it, is, like, my intuition for why it was so bad. [42:21.780 --> 42:24.820] So, I mean, like, are you talking, like, a copper cable or something? [42:25.060 --> 42:25.400] Yeah, yeah. [42:25.560 --> 42:28.800] Well, I mean, like, that's how we all got Internet for a fair while, right? [42:28.960 --> 42:31.480] I mean, like, you know, telephony is pretty well established. [42:32.060 --> 42:34.260] And, you know, I kind of toyed with doing the... [42:34.260 --> 42:38.480] So, there was actually a really fascinating infographic the other day of, like, what the V.92 handshake looks like. [42:38.600 --> 42:41.060] You know, the, like, stereotypical 90s thing. [42:41.700 --> 42:43.940] Which is, like, I kind of looked at that. [42:44.060 --> 42:46.920] And I was digging through and I'm like, I'm sure there's a bunch of stuff that I can use in this. [42:47.040 --> 42:50.580] And then I was like, nope, this really assumes that you can move more than a few bits every second. [42:51.920 --> 42:59.560] Yeah, I mean, like, you know, moving bits, especially across wire, even if it is kind of, like, encapsulated as audio, is pretty well backed anecdotally. [43:00.380 --> 43:07.000] That said, like, I mean, over, like, a sizeable run, you know, not many people ever did better than 56k. [43:07.380 --> 43:11.720] So, in fairness, 56k is, like, several orders of magnitude faster than what I did. [43:15.400 --> 43:15.720] Yeah? [43:15.780 --> 43:17.020] Can you make the beep boop for a while? [43:17.160 --> 43:17.440] Yeah. [43:19.040 --> 43:21.900] In case you didn't hear, his question was, can I make the beep boop for a while? [43:23.960 --> 43:24.740] Sorry, one second. [43:24.980 --> 43:30.020] There's, like, all good things, there's, like, a constant buried in the middle of a source file with, like, no configuration at all. [43:32.900 --> 43:33.960] Because I'm a professional. [43:38.740 --> 43:42.260] So, this is basically what it was doing at, like, a much higher frequency. [43:48.030 --> 43:48.430] It... [43:48.430 --> 43:51.870] Yeah, I know what you were expecting when I said beep booping, but this is it. [43:55.390 --> 43:56.990] Yeah, I'm just gonna turn it down a little. [43:58.510 --> 43:59.730] Were there any more questions? [44:04.030 --> 44:04.430] Cool. [44:04.850 --> 44:05.870] Thank you very much for coming out. [44:05.870 --> 44:05.930] Thank you very much for coming out!