 All right, how's it going so far? How are the talks? So yeah, my name is Anna. I'm a developer. I work at a consulting shop called Carbon 5. We work with all kinds of companies, startups, growth companies, enterprise, offices all over the country. Some of my coworkers are here. I also co-founded an organization called Elixir Bridge with Matt. Matt, where are you? With Matt, it's a nonprofit. We hold free workshops, usually during the weekend, for underrepresented folks in tech to learn Elixir and Phoenix. We're actually having a workshop this Saturday at the Turing School, hosted at Turing, and sponsored by Elixir Days and Carbon 5 and Turing. If anybody is interested, please come talk to me afterwards if you're local. Should be really fun. And when I'm not doing those things, I'm trying to get better at climbing rocks. It's a picture from Bishop in the Eastern Sierras. I love it there. OK, so what I want to talk about today. I'm going to talk a little bit about Bitcoin in the blockchain, what it is, with all the hypes about, like, why is it valuable? And then a little bit about how it actually works, trying to demystify it. And then why would we want to try and build something like this in Elixir? So what is Bitcoin? And if we look up the definition, we'll see something like Bitcoin uses blockchain to implement a decentralized ledger for payments. So what does that really mean? Well, in its simplified form, what it really means is we have a bunch of nodes, and each of them essentially has a copy of a list, a singly linked list. And each piece of data in the list has a hash that points to the previous piece of data in the list. That's really all that we're talking about. And people will also say that it's this secure and semi-anonymous, talk about why semi-anonymous, store of value. But what do we mean by value? Why is Bitcoin valuable? So we'll take a step back and think about what is value and look at it in the context of something that's a little bit more familiar to us, which is our own currency, and think about our own money. And if we look at the definition of money, really, it's something of value that we can exchange for other goods and services. We can pay taxes with it. We can attribute debt to it. But why is it valuable? If we look back actually at the history of money, up until fairly recently, especially at the very beginning, most transactions were done with precious metals, gold and silver. And why is that? Well, they're hard to find, so they're scarce. They're hard to replicate, you can't really fake them. They're arbitrarily divisible, and they're really durable. So if we think back through the history of money, even as we go forward towards a more recent history, up until the 1970s, all of our currency was backed by these hard precious metals. It wasn't until 1971 where Nixon was like, nope, not gonna do that anymore. Taking the US dollar off of the gold standard, it's gonna be a fiat currency. Yet it was still valuable. And why is that? Well, people still wanted to exchange it. They were able to exchange it for goods and services. It was still relatively scarce. The central bank was able to control the flow of dollars in the economy. You could pay your taxes. And something that I think is interesting, but a little bit less clear, is that they were making a bet on the future. They assumed that the US economy was going to keep doing well, and so the dollar would keep doing well, and so they could store their value in that. So back to Bitcoin. The really big idea behind cryptocurrencies is that for the first time, we're actually doing a digital transfer of value over the internet that isn't backed by some kind of hard collateral. So this idea was what really initially fascinated me and got me interested. And there's also this piece that, you can do it anonymously, right? And that it's secure. So there are several things that really incentivize people. And remember that Bitcoin, so and if we think about the value, like think about going back to the dollar, Bitcoin, and we'll talk about this, it's still scarce. People still want to exchange it for goods and services, and you really can't pay your taxes with it, but people are betting on the future, and it's kind of where it holds its value. So I want to take a step back and really talk about the security piece for a second, because it is a really big part of Bitcoin. Early cryptography, especially in the US for the longest time, was really just an emission of the government and the military. And actually it was considered an emission of the military until the late 1990s. It seems a bit crazy. But in the 70s, like with the advent of computers and technology, cryptographers, early cryptographers really started to realize the importance of privacy in the sending of information. And there are some forefathers of cryptography that really wanted to use it to kind of break the monopoly of the state. But fast forward, I don't know if anybody has seen this photo before. There's a group of people that came together in the early 1990s, particularly three people, Eric Hughes, Timothy May, John Gilmore, who later went on to create the EFF. And they started an organization called the CypherPunks. They created a mailing list, they had a lot of people on it, there are like several hundred people at one point. And a lot of the discussion in the CypherPunks was about anonymity and privacy, and that people, individuals have a right to privacy, and that we can't trust the government or corporations to protect that privacy, we have to do it ourselves. And famously, a year later, he released the CypherPunk manifesto, and that's exactly what it's saying. We have to have privacy in the electronic age, we have to protect it, and the interesting thing about the CypherPunks was it wasn't just talking, they said we write code. So we're gonna build the tools that allow people to maintain this privacy and anonymity. So many of the people who participated in the CypherPunk movement actually started some of the early digital currencies, many of which did not work out, but this idea of digital currency was not a new idea. It's actually a famous one called HashCash, which will see why it actually Satoshi, who released Bitcoin, uses something in HashCash, called Proof of Work, that is very core to how Bitcoin functions. So fast forward again, 2008, we have the financial crisis. And again, this conversation is kind of long going, but it amps up again, the CypherPunk community continues to talk about we need somewhere else to store our value that is outside of the government, that is outside of a nation state. Coincidentally, Bitcoin is released in 2009. So it's unclear whether Satoshi, the person who created and released Bitcoin, was part of the CypherPunk community or not, but he definitely drew inspiration from it. And if we think about how he defines Bitcoin, it's a proof that essentially lets us send secure transactions anonymously and we do not need a middleman for it. So now we have this network where we can store value outside of the government and it's decentralized. So there is no single point of failure, but there's also no one party that controls how the system works. And this was kind of a core thing that the CypherPunk movement wanted. So how does it work? So I talk about it being a decentralized network of nodes. So really it's a bunch of nodes that are communicating with each other via message passing. So we can start to see the correlation, excuse me, we can start to see the correlation, especially given some of the talks today, that might fit well with Lixar. And I mentioned that each node on the blockchain has its own copy or in the Bitcoin protocol has its own copy of the blockchain, which again is really just a list of pieces of data that are pointing to the previous piece of data. And these nodes communicate via something called the Gossip Protocol. And I think Chris mentioned Gossip earlier. I thought this analogy for how Gossip sends messages was really interesting. They basically defined it as similar to the way social networks have sent information or actually epidemics. But the idea being that a node will send messages to its peers, which send messages to its peers and so on and so forth. And eventually the message will get passed through the entire network. And that might look something like this. So before I talk about the specifics of a block and how they process transactions, et cetera, I wanna take a moment and talk a little bit about asymmetric cryptography because it is a big part of how things are done on the blockchain. Asymmetric cryptography really just means public and private keys. And so if I am sending a transaction to say Ben, and I'm gonna send him a certain amount of money, in this case, in this slide, it shows Bob, I'm gonna sign that transaction with my private key. And then I'm gonna send that transaction along with my public key to whoever that transaction is going to. And when they receive it, because they have my public key, they'll be able to decrypt that transaction, but nobody can tamper with it unless they have my private key. And again, the blockchain is really just a ledger of transactions. There's no concept of accounts in the blockchain. So it's not like I have 10 Bitcoin in an account somewhere and I am going to send Ben five Bitcoin, I have five Bitcoin left in an account. Everything is really just a transaction that is written onto a ledger. So let's say I start with 10 Bitcoin in my account. Today, that's actually kind of a lot of money. I have a transaction that basically states I have 10 Bitcoin written onto the ledger. And then I say I am going to send Ben five Bitcoin. What I'm doing is actually creating a new transaction that says I'm gonna send five Bitcoin to Ben and five back to myself. And that gets written into the ledger. So you can see we have like an in point of one transaction that gets output as a new transaction. And then this transaction is no longer valid. It's already been spent. And we call these unspent transaction outputs. So this is a little deceiving because what actually happens, let's say I have a transaction and I'm sending to three people. This will actually be just one big message that I sign that specifies I'm sending how much to each person. But it's a new output that then gets sent onto the blockchain. So what happens when a block actually receives a transaction? So remember, the transaction will be sent and then it'll have a public key. So the node that picks up the transaction to process it will be able to decrypt it and see that it's, and then check if it's valid. So how does it do that? So for our example that we're talking about later, we're actually gonna use one transaction per block just to keep things simple. But how blocks actually store transactions in the blockchain, it'll take a transaction and then they will roll through all of the transactions in the ledger because again, it's just one ledger that's saying this is how much money there is in the blockchain. So let's say I sent such a transaction that says I'm sending Bob five Bitcoin. Every node is gonna roll through all of the transactions in each block and check that that reflects in the ledger, that somewhere in the ledger is a transaction saying I had 10 Bitcoin, that I haven't spent any money since and now I can spend this transaction and it will get written to the ledger. So if the transaction is valid, then it'll say, okay, I'm gonna add that to my block. And how are transactions actually stored on the block? So we're only gonna store one. But really what happens is they get hashed into a Merkle tree. So what that means is we basically take these transactions, all the transactions that go into a block and a block can fit about one megabyte of data. So it varies a little bit and it starts hashing them by twos up until it gets to the root. And you use shot two. What we know about hashing is that if you change one character in the content that you're hashing, you're gonna get a completely different hash, right? And so this makes it really hard to tamper with transactions because if you can imagine you're saying, no, actually there was a different transaction in here, you're telling a node, that's not valid. The node can easily check because it can go back from the root hash and see all of the branches of the tree or ask another node what its tree looks like. So again, this element of security. And there's one really, another interesting piece is that, and I think Chris mentioned this, in a distributed system, there's no global sense of time. There's no real ordering. So in this mechanism for hashing, it actually allows the blockchain to order these transactions. Okay, so we add our transaction to the block. Now, how do we add our block to the blockchain? So this refers to a concept called proof of work. And this is what I was referring to when I talked about hash cache. The guy who created hash cache, Adam Beck, was really the first one to introduce this concept. So we talked about how part of the value in the blockchain is that there is this element of scarcity. Satoshi didn't want people to just keep mining blocks really quickly and then control the longest block. Because also the other idea is that blockchain, each node is always mining on the longest block. So whoever kind of has the longest block at the moment is the leader for that moment, the blockchain. So you create this idea that each block has to do a little bit of work in order to be able to add a block to the chain. And so what does that look like? So the blockchain as a whole has this concept of a work factor. There is this technical difficulty to a puzzle that each block has to solve. And all that really is, is it needs to solve a puzzle to create a hash that starts with a certain amount of zeros. So let's say the work factor for the network is three. They would need to create some hash that starts with three leading zeros. And how do they do that? Well, we talked about how each block has its hashed transactions as a root hash. And how it has a hash from the previous block. So it takes that data and then it has this concept of a nonce. And a nonce is really just an arbitrary value that it will increment and then it will hash all of that content together until it solves this puzzle. And once it's done that, it can send the message to the rest of the network saying, hey, I mined this block, here's how I did it. And if it's valid, all the other nodes will say, okay, cool, we're gonna add this block and we'll start mining off, we'll start adding blocks to this length of the blockchain. So this solves a really interesting problem because A, it provided this consensus algorithm for nodes kind of agreeing on how blocks get added to the chain. But also it solved this political problem of who gets to influence the consensus, right? Satoshi didn't want one person to really have control of the blockchain and it's changed a little bit as hashing power has become more consolidated. But when he first created the blockchain, the idea was that if you could only mine a block every so often and the work factor changes so that a block is really mined once every 10 minutes and every computer has equal, he's thinking of people's personal computers, equal amounts of hashing power, then everybody has the same probability of mining a block and then theoretically has the same power to influence the network. And this concept that blocks are going to get added to the, that nodes are always building off of the longest chain is called Nakimoto consensus. So when the node hears of a new block or a new chain, they're gonna say, oh, okay, I agree to mine off of the first blockchain of height H that I hear about. So I think some of you might already guess, like how does this relate to Elixir? Well, we talked about how we're implementing a decentralized ledger for payments and that nodes communicate sending messages via the gossip protocol. So we needed a decentralized system that has some element of concurrency and communicates via message passing. So this might sound familiar to some of the stuff that we've already heard about today. So before we go into the example that I created, which is a contrived example, but I think you'll be surprised to see it, how little it took to kind of implement this protocol leveraging Elixir, but also, or like an OTP. So first I'm gonna take a look at how message passing works and start at the basic level. Chris already talked about this a little bit, but processes, right? All the work that gets done in Elixir gets done inside of a process. They're isolated from each other. You can have thousands of them running at the same time. They're really lightweight. So we're gonna just look at how you would even spawn a process, so we'll have a simple module. We'll call it, we're just gonna subtract one value from another. And to spawn a process, right? We just pass that information to spawn. In this case, we're passing, it can take an anonymous or a name function. In this case, we're passing the module name, function name, and initial arguments, and we get back a process ID. Cool. So we know processes communicate via message passing, so how do we actually communicate to a process? Well, we have access to two functions, send and receive. So send, so we're going to, we have a module, we call it greet, we're gonna greet somebody by name. So send, we're gonna spawn a process, and send allows us to send information to this process. So we're gonna pass on arguments, the name of the person that we're greeting. And then receive is a function that we implement in our module that we're calling, in the function that we're calling, and it'll match against the arguments that we pass in, and if they match, we'll get output. So cool, we're spawning a process, we're sending it some info, if it matches, and this is really hard to see. Sorry, guys. Otherwise, we don't get anything. What if that process dies, right? In this protocol that we're building, we need to know if our nodes are communicating, we need to know the state of our blockchain, how's that gonna work? So again, this is really, really easy to do with Elixir. We can call a function called spawn link, which links our current process to the process that we're calling. So as an example here, we're gonna force our process to exit. And if we call that, we spawn a process, and we force it to exit, but we don't link to it, we don't know that it's actually done, and that it died. If we do link to it, in this case, it actually killed our process, then we don't want that. I mean, there are ways to trap the exits. That's just an example that we can easily link to another process. And we're also gonna wanna manage state. In this case, we're managing state and memory, given that it's a simple example of the blockchain, and if a node goes down, it's gonna get a message of the longest chain, and every node has a copy of the blockchain, so we're not as worried about a node going down in our current example. But we're gonna need somewhere to manage state. So we're gonna use agents. So agents are really just an abstraction around a background process that lets us manage state. So the way we start up an agent is we pass a function called start link. We call function called start link, we pass it a function, and the output of that function is going to be the state of that agent. And given that in our blockchain, it's going to be additive. We're only really adding elements to our state. We will be able to retrieve our state and then update it, right? So here we pass a function, here we said we're gonna add some stuff, and then we can retrieve it and see that that stuff's been added. So the basics around state and message passing. So back to the blockchain. Well, now that we're building this network, we're gonna need behaviors that are a little bit more sophisticated. So we saw the basics of processes and message passing, but we're gonna need some monitoring processes that are a little bit more robust and we're going to need maybe some server-client interaction, given that a node is gonna need to be able to call to another node and send a message and then process that. So we're gonna be able to have leverage OTP. So one of the things that made it interesting to build this blockchain in Elixir, as opposed to having tried building it in Ruby and JavaScript, which is actually really hard, is managing these processes. And so we get to leverage early in OTP, which is really just a framework that gives us these modules and behaviors that we can then implement and it makes it really, really easy. So finally, I mean, I've been talking a lot about, oh, there's a typo, oops. I've been talking a lot about the blockchain and how it works and how we might implement it. So let's take a look at how we do. So let's start with transactions. Oh my God, well, that's not gonna work because you all can't see that, can you? It's really blurry. Let me see. Is that gonna help? I didn't realize it was gonna be this blurry. Well, I'll just, I'll talk through it. I mean, the idea here, the code is less important as how easy we're able to leverage these callbacks. So I think I'll just talk through it. But really, we're gonna have a transaction and it's going to have a struct, right, built on top of a map. And all that's gonna have is a two key, which is the public key that we're sending our transaction to, a from key, the amount, and our signature. So we're gonna sign it with our private key again so that when we send the transaction, somebody can validate it by decrypting it with our public key. Our new transaction is really just going to be a struct with this information and we have the ability to sign it and we kind of jump into the early crypto module for that, but it makes it really easy. And then we will be able to validate. So when we receive a transaction, we can again take somebody else's public key and validate that the data that they're sending is what we expect them to be sending. So we have a transaction and we're going to need to somehow build a chain of blocks. So let's start with a single block. Oh my God, this is really bad. So again, our block is really just gonna be a struct and it is going to have, like I talked about, a nonce, which is that random integer value that you need in order to solve the proof of work puzzle. It's going to have a hash that points from the previous block and it's gonna have some transaction that it received in our case, right? And we're just going to, when we create a block, we are essentially taking the previous hash for simplicity's sake and our nonce and are iterating it over and over and over again until we solve that proof of work. And when we do, we'll send back a struct with our nonce, the previous hash, and our transaction. Something that I haven't implemented yet but that I think might be interesting is that right now this is just happening in this process, this hashing. And you can imagine with a work factor of one that it's actually really easy to find a hash start with one zero, but if you say the work factor is seven or eight, it does get pretty computationally intensive. So I would imagine that you could maybe spawn this off in a separate series of processes and have them going concurrently and maybe solving that would be more efficient. Okay, so we have a block. So how are we gonna add that block to a chain? So we're gonna have another module. It is going to, it's called blockchain. It, as you can see, has a work factor set of one and has a block reward. So one thing I forgot to mention is that when miners are mining blocks on the chain, they actually need some incentive. So when they, when they mine a block, currently the reward for mining a block is 12 and a half Bitcoin. And as the chain grows progressively longer at certain points in the chain, that reward halves. So when I think miners first started mining Bitcoin, the reward was like 50 Bitcoin per block and then it was 25 and now it's 12.5. So eventually we'll get to the point where there's no reward. There are no more Bitcoin to be blocked. There are no more Bitcoin to be mined adding to that idea of scarcity. And so when we create our blockchain, if when we start it, it is going to have, we're gonna create some, you can't see this, but we're generating some public and private keys. So our blockchain structure is really just gonna have a list of blocks, our private key and our public key. But we're gonna need to have a way of knowing whether that's up, right? It's kind of important to know the state of our blockchain. Is it how many blocks have been added, its length, et cetera. So we're going to add this concept of a supervisor. Another thing that we're leveraging from OTP, right? So supervisors really just a specialized process that lets us monitor other processes. So how do we set this up? Well, when there's not a lot of code, it's a little bit less fully. In our application file that runs when we start our application, we're gonna import this behavior and say we're gonna use our supervisor. And then we call supervisor.startlink and really all we're passing is our module and initial arguments. And then the supervisor gets a strategy defined. There are many different ones. In this case, we're just saying if our process die is restarted. I'm gonna give it the name of our module so that we can refer to the supervisor later. And if you go back to our blockchain, you'll notice that we've defined a function called child spec. So when the supervisor starts our child process, it's gonna look for this and this is gonna tell it how to start our process. And we'll tell it to use the start link function. We'll tell it to always restart. So by having this kind of monitoring, it makes adding fault tolerance for our system pretty easy. And that's kind of what we want in this distributed like blockchain system. So let's look at our blockchain module one more time. So when we're adding a block, we're going to receive a transaction, check if it's valid, and then add it to our blockchain. So remember, when we started, we were using an agent and it's storing our state. So it makes it really easy for us to call agent update, pass in that new block and really just add it to the beginning of that list. To create a block, we've added blocks to our chain. So how do we actually have nodes communicate between other nodes, right? We need this kind of server client interaction. So we're gonna take advantage of this concept called GenServer, right? It starts stands for generic server. This is another behavior of OTP that we're able to leverage. And what it does is it provides us with a series of callbacks that we can implement to, well, it provides you with callbacks, we can use to implement this client server behavior. And we can choose which of those callbacks we implement. We're only using a couple of them and I will go over them. So we'll start, we'll just create a server module. We're gonna initialize it and all it's gonna have is its own process ID, a list of blocks and a list of UUIDs. And the UUIDs, each message that gets sent on the blockchain will have a unique UUID. And that way, when a block receives a message on the chain, it'll know whether or not it's already had processed it so it doesn't have to go through validating all of the blocks on the chain if it's already done that. And given that the gossip protocol is kind of a fire and forget, so we're sending messages, but we're not necessarily waiting for a reply. So we have this asynchronous message passing and GenServer makes that really easy. We can take advantage of what it's called its cast function. So you call GenServer.cast. We tell it what module we're sending to and we pass in some arguments. And then handle cast is the callback that allows us to really easily handle that request. So handle cast will match against those arguments. In this case, we're saying, mine a block and then send it out to your peers. And so we add a block, update our state, and then we send it out to our peers. So we updated the current state of our blockchain. How do we see our current state? So again, GenServer makes that really easy. We can make a synchronous request using something called GenServer.call, pass in our module and the arguments, and then handle call lets us easily process that request. It's gonna match against the arguments we pass in and then be able to reply with our state. One thing I forgot to mention and I should have mentioned in the beginning is GenServer also allows us to manage this concept of state. So when we started in the beginning, we started with this map that held our ID, our blockchain and our UU IDs. And that gets returned with each of these callbacks is the last argument. Okay, so we add a block, we're gonna send it to our peers, but how are they actually able to receive it? So we just implement another asynchronous callback. We're gonna have a call that says, okay, now I want you to send this new blockchain to my peers. So we'll have another cast call to our module and in this case, we can specify it. In the previous call, we didn't specify a location or an address. We just said this module or current process. In this case, we can specify an address. So if we tell it where to send it, it'll send it to a different GenServer running on a different node. And that GenServer will be able to handle that request with its handle cast callback. It's gonna have a different set of arguments to match against. What we do here is we check. Is this blockchain, have we already processed this request? If we have processed this request, we say we're gonna validate the blocks. So we're gonna go through each block and make sure that it actually points to the previous block all the way through the blockchain. And imagine if we had the last block in the blockchain and the block previous to that, it's pretty easy to verify because each block has that previous hash. And so if we take the second to last block and take its previous hash and its nonce and hash that, we will get the previous hash of the last block. So that's what we do all the way down the chain. And then if that blockchain is indeed longer and it is valid, then we swap out the chain. We say, okay, we're gonna start building off of this. This is valid, this is our current state. So we go back to our agent where we had that list and say, okay, we're just gonna change it. We're just gonna update our state and have it be this new list of blocks. And the blockchain blocks, mines blocks every like 10 minutes. We wanna say that we want this to happen for the purposes of this example every 30 seconds. So another thing that GenServer lets us leverage is if you make a call, but you don't specify the type of call that you're making, that callback will be handled by something called handle info. So for us, we're saying, okay, we're gonna start and we're going to send a message. And then you can't read this, but this really says process send to self with arguments that handle info calls. So we have this loop where we're saying, okay, every 10 or every 30 seconds, send another message or send another transaction and then mine another block. So to keep an eye on this process, because this is another process that is important, we wanna make sure it's communicating between our nodes. We're just gonna add it to our supervisor, right? We're gonna have another supervision process that's watching that. We just add it to our list of arguments. We have no initial arguments and that's that. So really to implement the blockchain, all we needed was a GenServer and a couple of modules and an agent storing state, given that we're able to leverage all of this OTP behavior that comes from early. But we want this to be distributed, right? It's not just working on my little local subnet. We want it to work across nodes. So again, not surprisingly, this has made really easy for us. So if I'm just doing this on my local machine at the same IP, for each of the processes that I start up, I can just pass in a short name and then I can call connect and give it the short name that I'm connecting to in the form of an atom. And those nodes will be connected. And the interesting thing is if I have three nodes and I connect node one to node two and three, nodes two and three will be connected automatically. So you can see how it's easy to create this distributed network of nodes. But what about across machines, right? What if I want to connect to Matt's machine? I need a little bit more information, but really not much. Instead of passing a short name, I can pass a name argument and then I name my process and I pass it my IP. I pass it something, a cookie, which I name. And so these nodes are communicating via this TCP IP protocol and they're using the cookie for this kind of low level authentication. So if a node's trying to connect and they don't start with the same cookie, then they won't be able to connect. And I think there's actually way of configuring it otherwise, it's a little bit more work. So that's it. We implemented a blockchain in Elixir with very, very little work. I was gonna demo this across my machine and Matt's machine, just to show you that it actually really does work and it's really easy. I don't think the network here allows for that. So I'm gonna just demo it on my machine. It's down for one second. Maybe marrying displays is usually easier. There we go, all right. Three processes here. If I go with this, can people actually see or is it still super blurry? Is that better? At the top, okay. Okay, cool. Sorry for all the blurriness, y'all. Clear this guy. So I'm gonna start a process at my IP. And this is on my local subnet, so I don't need a cookie. I'm gonna start another process. It's generating our keys, as you can see. I'm gonna say, let's connect. So the default time is about 30 seconds, so hopefully it doesn't take too long. But really, we should start seeing, oh, there we go. Start seeing messages generated, right? So our blockchain's communicating. This is the state of our block. This is our UUID. But soon we should start receiving messages and, assuming this works, hopefully, all of our nodes start receiving messages and being able to keep track of somebody else's UUIDs. Let me flip to a different process and see if that works. For each of these, we'll be able to see that it eventually starts to change. At some point, this chain will have been swapped out for the chain that the third node has. That's it. That's all I got. It's the only problem. Because I wanted to be able to pull up and show you all, but let's see. I'm excited about that process. There we go. That was weird. Doesn't what? Yeah, I think so. Next time, don't do that. Don't do full screen, Anna. I have it on my machine. I'm trying to pull it over, but it doesn't like that I'm full screen. So I will have to show you afterwards. I don't want to waste any more time. Thank you all. Thank you for the talk. Are you aware of any plans to reduce the energy required to maintain the Bitcoin network, or is that just an inherent part of Bitcoin? That's a really good question. I am not an expert on Bitcoin. From what I understand, there are not. I mean, I think people are trying to make it more efficient, and they're thinking about that. I don't actually know. I haven't heard about that. But we know that that's the problem, right? Is that it's becoming more computationally expensive, especially as the work factor goes up, and so the energy requirements are insane. All right, thank you, Anna.