 So first of all a little bit of background. What is the preload node? What is a preload node, right? So the preload node is a node, a GoFPS node that we set up to help out JS IPFS. So JS IPFS, if you're running in a browser, you cannot establish a direct TCP connection. If you reload the page, you lose all of your application state, you have a very limited amount of local storage. I mean, so what we did, what we have is we have some some nodes that on the one hand, they will actually be work as a DHT proxy. So you are in JS IPFS, you want to load something from the IPFS network. Well, you cannot connect to the DHT because you cannot do TCP connections. So it acts as a proxy for JS IPFS and it also serves as a place to persist the the storage of the JS IPFS node so that if you reload the page, your content is still there. So what is a problem with the preload nodes? Well, it turns out that the preload nodes also need to act as bootstrap nodes. We'll get into why in a moment. And the bootstrap node addresses are hard-coded in JS IPFS in the library itself. You can overwrite it if you're running a node app or if you're writing an application on top of it but people usually don't do that. And since the peer IDs are hard-coded, you cannot just, you know, add more bootstrap or preload nodes because they will not connect to them and you cannot change them because you cannot change to a different node because, of course, the peer ID is hard-coded, right? And we to start with PL had two preload nodes, node 0 and node 1. Node 2 and node 3 were added later, but the problem is that older versions of the library only know of node 0 and node 1 and people are not upgrading because upgrading is a pain. Basically, not enough care has been taken to ensure compatibility between versions, API compatibility between versions. I think things are getting better, but older versions, so upgrading from an older version to a newer version can be a hassle. So people don't do it, which means that node 0 and node 1 are basically getting hammered. And I discovered this during my first, the first thing I did when I joined protocol labs, which I had to scale up the preload node, node 0 and node 1. And even after the scaling, because they were crashing, I don't know, every half hour to one hour, basically, the Go IPFS was running out of memory. So we scaled them up and now they're crashing only twice a day, more or less. So it's better, but it's, of course, not ideal. So how do we solve this? Well, we basically do a man in the middle attack. So we create something kind of a reverse proxy. I mean, that's the way you scale things in, that's the way you scale things in web 2. Well, let's grab a page from the play to one of the web 2 playbook and let's create some sort of reverse proxy and load balancer, which would impersonate the node. It would basically take over its PRID, its private key, its private and public keys, and it basically uses a bunch of Go IPFS nodes in the background to downstream to actually get the data, right? I called it Katsune, which in Chinese mythology is the magical, many-tailed fox. So it's one head, which is where the upstream nodes, the JS IPFS nodes connect to, and many tails where are the other Go IPFS nodes. So I had to figure out what does the, how JS IPFS talks to the preload node, right? So basically, yeah, I mean, it connects via WebSocket, to BitSwap via the WebSocket transport, right? So it uses BitSwap, but it also uses the API port and it calls this endpoint called API v0 refs. What that does is it forces the, what the API does is it forces the Go IPFS node to go under DHT, get the, get the block, get that SID, and you can actually tell it to get it recursively. So it will actually get all of the nodes that this node references through IPLD, okay? So it has, basically it has two connections. It has the HTTP port and it has the WebService port. So I dove into how this works, right? So on the one hand, for proxy in the DHT, the application will call IPFS get, for example, and JS IPFS will make a post and request the reps recursively. It does a recursive get. Then the preload node will fetch the content, and then JS IPFS will send a want over the BitSwap channel, and then the Go IPFS node, well, the preload node will send the blocks back, right? So I had to dive into how BitSwap works. For persistence, it does the other way around. So the application calls IPFS add, which adds it to the node's local storage. Then it sends another IPFS reps with that CID. And what that does is the preload node will query its peers for that CID. And of course, the only peer that has it is the JS IPFS node. So the JS IPFS node will respond to that want with the blocks. So we have, on the one hand, we have a want coming from upstream and going to the downstream peers. And then we have, we can also have the want coming from the upstream peer going to the downstream peer. Yeah, anyway, we have wants and blocks going both ways, right? So we have a couple of challenges here. First of all, I did not know Go. So I took this as a chance to learn Go. And then, of course, diving into how to use the P2P and how BitSwap works. There was a couple of challenge. So one problem is that BitSwap actually, when you send a want, it will not send the blocks over the same stream that it got the want on. It will open a new stream. So I get this stream from this, from that upstream node, okay, who requested this, excuse me, because I do not have the association. So I had to make it to keep track of who wanted what, so I could send them what they wanted. The other part is that when you do a request to API these zero refs, you do not have the peer ID. So you do not know who requested that ref. So you do not know who to set the blocks to again. Sorry, who to set the wants to. So the downstream node sends a want and says, okay, who requested this. So right now, what I just, what I did was, okay, just send it to all of them, kind of like Go IPFS does, but there's an optimization that can be done later by the, using the Pierce IP address. There was one unforeseen consequence or effect of this. So on the one hand, Kitsune does not participate in the DHT. Basically, it's only doing BitSwap and of course the identify and pink protocols, the basic to the P2P protocols and it's a bit swap. Which is interesting is that I'm getting the, when I get a don't have message from the downstream peer, meaning, yes, I do not have that. I do not have, I do just represent me a want and I don't have it. So Kitsune will call API v zero refs and actually have the, have that, that the go IPFS node query to hold the HTU, which is basically what also needed for JS IPFS. But the effect of this is that this can be used as a generic one to one to one way P2P to P2P to P2P beer bridge. I might have done a one to extra to P P2P to P2P bridge. Meaning that, for example, you're in a private network, right? You have, you have a private swarm, a private network, but you want to get some content from the public network that happens. For example, when you upgrade a go IPFS and go IPFS needs to upgrade the repository and it does it does a query to get the repository upgraded by of the binary. And I had that, we had that problem in our previous job. So now you can actually peer in with your Kitsune instance. And that will actually get the information from the public swarm without exposing the information from your private swarm. You can also even if you have your private swarm, then you can also do a post to API v zero refs on Kitsune. It will get it from the, from the upstream nodes from your internal nodes and expose it to the world. And it's also, I mean, yes, we're all peer to peer. Yes, we're also supposed to be connected to connect to each other, but network administrators beg to differ. They, some network administrators really want to control what traffic is coming in and out of their networks. So Kitsune will allow them to have computers that will host that participate in IPFS, but without having to allow everyone to connect to everyone to everyone on the internet. That's just some of the ideas I got from possible consequences from from what we're doing here. So next slide, please. So what's our current status? Well, we do have a GitHub repo. And I have actually, it has actually been able to transfer content both between to go IPFS and between to JS IPFS node. We actually have a test test that will check that the preload node works. And that's what I've been using to test this. And a few next steps. Well, the one optimization I mentioned earlier about just sending the one depending on the IP address that the rest call came from. For production use, we use, we will need to add metrics. I would really like to add configuration because right now it's just configured via command line flags. And again, for production use, it's more convenient to have a file or environment variables. Yes, tests, we need to add some tests also loads testing. I have no idea how this will behave under load. Some cleanup of the code. And right now the private swarm thing is not yet a thing because we do not have, have a swarm support. A big thanks to Lydl, to Max, to Adene, to Horopo. They were all extremely helpful in developing this. And thanks for, to everyone in the cohort because it was a blast. It was an awesome time working with you guys. First of all, for web sockets, you actually need to have an SSL certificate. So I was thinking of getting my own SSL certificate. And then I discovered Ngrok. So what it does is it creates a proxy, an SSL proxy. And my proxy is right now, this host here, FB92, blah, blah, blah, is being proxied to 428080. Now here is where Kitsune is running. And I'm telling him, telling, telling it there is one downstream node, which is my, my Go IPFS node on my local machine. I am telling it to listen on, to listen for bit swap on 24001. And I'm telling it to listen on web socket on 28080. And minus P is because I put the preload functionality behind a switch. So if people want to actually use it as proxy, they don't have to enable the proxy functionality. So Kitsune is starting. And now I will just run the, the preload tester. Just need to change so that the bootstrap address is F9B2, which is basically the same address that we have down here. And so I'm connecting, as you see here, I'm connecting through WSS to this node. And this ID is the same ID that I have in Kitsune. So nothing in my sleeve. And basically this, what this does is it starts using puppeteer. It starts a browser, a node inside the browser, and it starts another node in Node.js. And then it adds some content in the browser. And then it tries to get it from Node.js. And hopefully it will work because, of course, you know, the demo gods are the demo gods. It is a bit slow just because of timing. And yeah, the preloader is working as expected. It basically published this content, test content created blah, blah, blah, blah, blah. And it says, yeah, it's working. I mean, if anyone wants to see a little bit more about how it works, then just ping me at any time.