Good morning everyone welcome back to another vlog. I'm currently really cold I'm on the roll Canyon driving to Pilates. It is 6 38 a.m. Today. I have class then tonight We have our like Christmas party thing. I need to go get it's an ugly Christmas water theme And I need to go get a sweater I really I like cannot go home between because I live so far away And so it just like doesn't make sense. So I'm gone like all day anyways I'm just in my Lulu's where I have my Ritzy up off her I'm gonna set you guys down right here. I Have Morgan's suitcase in the back because she let us borrow it Okay, so I was listening to okay sis with Searon who's a vlogger I don't know what just got on my lens, but I'm heading out every time I start to vlog here Oh, I need to wear this. I don't know. Okay. Bye. Good morning guys.  I lie, but I might just do it. Anyways, I'm getting ready I wanted to show you guys the new mascara combo that I'm loving so lately. I've been putting on roller lash It's like a light coat followed by my dry bar and cosmetics Mascara and Honestly, I feel like when I oh This is literally the worst feeling in the world definitely got under here too. Great I'm gonna use my capari little. Oh, nope. Oh my gosh. No, this is not. Oh found it. Thank God. Oh, okay. Great Another Apply things like that. Oh my gosh. That's really great. So this is the capari lip glossy I got this when I was in Texas Shopping at North Park Mall and I really really liked it. Oh my gosh. I forgot I have this facial mist This will be great later today. Um, okay This probably needs to go on quick. This is the Last blowout It's the collab with It cosmetics and dry bar And at first I was like, this is not my favorite mascara, but I actually really like them layered together. Oh There's got all over my island, you know, this is not. Oh my god. This is not my morning Oh, I forgot to put my cloud paint on Okay, so I'm about to head off to Morgan's to drop off this suitcase And then hopefully I'll have time to get some breakfast before class And we'll see finals are over. I'm done with class for sure And that's really incredible. Honestly, I probably should have worn something on my face today I didn't want to get fully ready because we have like a Party tonight, so I don't want to do my makeup twice, you know what I'm saying, you know Slash I also really don't do makeup for class So so I'm gonna finish listening to the okay sis podcast also guys They went to Tom's one-hour photo lab and got these photos done Comment down below Maybe I'll go back in January and get some photos done with like Taylor or something the house or the photo That's framed in my house and me in my roommate Bailey Is from there, but I love that they have their podcast are like I should have friggin thought of that But it's literally the best thing ever. It's so great. All right, so I'm gonna head to Morgan's really quick All my way to class she was pretty close and then I'm out All right, just parked. I'm almost done with this podcast. It's been great I have class in like 10 minutes and I have to walk over here. We are all right guys So surprise surprise we're back at Central City Mall. It's just Making your parents because we're out such a city catering for my angelina catering for our angelina So we're going to Old Navy to look for ugly person sweaters. Oh the setting is right We have to go to the It's really kind of like when you only have one to go to that year They're kind of like stuff, you know, you know, we should have gotten just regular sweaters and put pictures of each other's faces on it Oh, yeah, that would be so nice We should have that and then we're gonna eat some lunch But yeah, or like maybe H&M has some I don't know. I just want like the cheapest one possible Yeah, and yeah When I was saying the children's ones Maybe I thought I thought it was all Navy Okay, so we're never going to H&M. There is nothing at all. Maybe Unfortunately, yeah, maybe I just saw sweaters and I just assumed because they're next door I don't know. I haven't been to Old Navy like a long time Here we are guys H&M We have Yeah, no time All right guys, so ignore our drama for today We just ended up like ordering some sweaters on Prime now H&M like they're all like tight-fitted and like they're already ugly So you just don't want a good one with a good oversized vibe like they didn't see our vision They weren't here for us. They weren't here for us. So it's fine. So anyways, we're gonna get food and food court Where do you want to go? Oh my gosh, I forgot to tell you we were walking by Bloomingdale's.  So he was like, why I wonder where you were there. And I was like No, now he like definitely knows so that's embarrassing. Anyways Also, like I haven't tried it on in Dallas though. So I'm pretty sure he knew anyways, you know what I mean? Anyways, anyways, anyways, anyways, I'm gonna say that where do you want to go? All right, there we go Okay, guys Here we are back at the food. I'm gonna try my Five strawberry lavender. This was eight dollars and I didn't realize I would not have bought this But I realized it like after cuz my meal here is so cheap that I just didn't it was like a normal price So that'd be good That's the only thing I want in life Just I will try to get John mayor on my podcast But like I just don't think it's gonna happen. Hi everyone. I just wanted to reach out. Sorry Why is there something on the lens again? Don't knock it just wanted to reach out because my number one goal of 2020 one of my big goals of 2020 is to get Jojo on my podcast. So if anyone has a connect slash knows anyone on her team Slash knows her like personally. Thank you. She just looked at me as I'm coming to grab it Thank you. I was gonna do it, but I appreciate Messable, yeah, it's really good Please guys hook a girl up. I need Jojo to come on the podcast Please not Jojo Siwa to be clear like too little too late. You'd be surprised who gets that mixed up Yeah, and so I actually don't know the last clip that I vlogged when I was at the mall Then I went back to class. I had like an hour and a half my last track of The school year. Oh my gosh if you guys I like really need to get gas really really bad This is really really not good, but I'm so close to the mall. So I'm just not gonna do it right now But I'm meeting Quinton Anyways, I finished class a little bit earlier than I thought I would and he was actually in this area So he's just meeting at the mall because I'm doing an Instagram deal with Nordstrom actually Which is so cool because like actually like okay Funny story where Quinton I've logged like last weekend at Nordstrom in that like gift department thing That's literally what I'm doing the deal with and that's just so funny because like I was literally just there But I'm doing a deal with them. So I need to go take some photos get some gifts and whatever, but guys so They're giving me obviously like credit for gifts to buy for the deal and They have Quinton's all-time favorite clone the Tom Ford vanilla tobacco. It smells so freakin good There and it's like one of the things that I could pick out So I am gonna be getting that for him. He has no idea. I already got like all this Christmas gifts and stuff And this is like like oh my gosh, it's not like cheap clone by any means just smells So amazing actually if it's my number one gift idea for guys I actually think clones are really good gift idea pretty much anything I'm like my dad everyone always asked for clone because that's actually what they want But anyways, it's a really good gift idea. So the Tom Ford vanilla tobacco. I don't think any one of the world dislikes it It's so it smells so red. So we're on our way. He has no idea that he's oh, I think I'm going a little bit longer, right? He has no idea that he's getting it. I told him that I might have another surprise for him this week He's been really reaping some benefits as of lately, but I'm just gonna I Mean like obviously he deserves something because he does a lot for me. So We're heading to the mall right now and it's gonna be so fun and I'm so excited cuz he's gonna be so happy Literally is gonna be so happy. So I'm so excited. But um, yeah, today was really great in class It's one of my last days So it was really cool tomorrow is actually my last day tonight with the Christmas party and yeah All right guys, so we're in Nordstrom doing my Nordstrom content Quinton found out about his prize. I told him Very sad in front of the planet. I already told them before You okay, so can you hold this for a second? I need to make sure but this is the white one Wait, I'm getting a sleep mask. I'm being so extra all of our flights from now on I have a really great sleep mask Nair skin care actually They don't have it my color the slip pillowcase. I will be getting another silk pillowcase. I needed another one Let's see what else actually I'm actually gonna party this but Okay, we got the stuff very exciting I got some slips actually but For myself, we're gonna go look at luggage because I think that's what I want for Christmas And my mom keeps pounding me so I have to figure that out today All right guys now. We're really leaving. I didn't find any luggage, but I can't be posted. That's cool I like this look up here It's very open so we have I honestly wasn't planning on staying over it since your city all day, but Like there's really it's almost four. There's no point. We've a party at seven. So we're gonna go see a movie What movie are we seeing again? It's called Knives Out Daniel Craig's in it. It's like a mystery murder mystery This is so cool I know you would do really well In like movie reviews, you know, oh, it's kind of his vibe. We have food vlogger And a movie blogger. Yeah things that no, but yeah, but I'm still having Still haven't posted the recipe for the garlic. This just needs to be it's dead.  It's your Christmas present. Okay, so yeah, we're walking to AMC right now Comment down below your favorite movie hater. Quinton is die-hard AMC They fit the movie pass 2199. You know, if I get a deal up, I would love a deal with movie pass movie pass Seriously, my boyfriend's obsessed with you Very organic Something we use well movies a month. Come on. There you go. What? Okay, well, there we go. Okay update. We saw was it nice out nice out. It was really good big Canada movie lots of twists and turns So this way anyways, we have the parties in like 20 minutes. So it was kind of perfect timing I'm gonna throw my party love holiday parties. It's an ugly sweater themed He was not in my program. He was just invited but anyway, so Jess is bringing it because we ordered it earlier Oh, yeah, you guys already know this I forgot. I was literally here earlier, but Look how cute and pretty This anthropology appears my favorite anthropology ever if you go to the second floor and then all the way up They have this one area. That's like the best lighting ever and it's so beautiful. It's amazing There's nothing to say. I feel like you're like about to chime in No, I just saw somebody I knew You didn't say anything. No, yeah, I didn't say that. Oh, okay the girls. I didn't know if there's like a Maybe not now. Oh wait Back from the party this is my week Christmas letter we primed out it like and our for the party. Oh My gosh, good morning everyone Welcome back to today's vlog I got I normally wake up at 6 and then I'm at the door like 6 25 But for some reason I was like out the door at 6 10 and I'm already at Pilates and it doesn't start until 7 But today is my last day of class, which I'm so Happy about I just oh my gosh Why that just means that I go to New York this weekend and it's when I break into that means that I stopped making But I stopped spending like half my day in my car And I can't really vlog and whatever these vlogs are all about to be so much better so Yeah, last night the Christmas party was really fun and then I got home I watched like a movie and I went to bed and Now we are here Have my Celsius as always guys. I'm so sorry that a lot of these are so similar. I just like I Don't do crazy different things every single day So I'm just like kind of vlogging my life and showing you guys but tonight actually I am going to be packing for New York because I'm pretty busy the next two days and then I leave Sunday. So like tonight's my only time to do it I'm not the person that packs it in advance ever But I need to like plan outfits and stuff and Keaton Legitimately has a Google doc with her outfits like our itinerary along with her outfits for each thing So it's really put a little bit of pressure on me and I feel like I really have to like, you know Try my best, but I I feel like I'm just gonna wear all black and coats the whole time because I'll be freezing so That is it. I'm really excited for today I think I might actually just like import some footage from a vlog while I'm in my car I might as well at this point and then go into Pilates. Oh my gosh This is my second to last Pilates cost of the entire year because I can't go tomorrow Sadly accepted from a bus by video and then I'm gone basically in the one day after this then I'm back I need to book it actually the 19th today's the 12th. Yeah, basically. I can only take two more of the year Which is absolutely heartbreaking to me But I did find out that Corp our yoga is in Dallas. They have a bit like not a billion. They have a few locations So I'm gonna try that. It's just hot yoga. I know that My teacher said that I would like it. So I'm like, alright, let's see about a party. It's a shower. I got ready I'm on my way to class. I had to take a call in the office at some point. Wait a second How am I just not realizing there's a night market in West Hollywood? Is that the same one and silver like if any of you guys are watching please let me know But it looks very similar. Also, I like scab my face under here That's really bothering me and I really don't need this to be on my face for New York Because we're gonna be taking a lot of photos and I just remember when Keaton I don't remember what she did But really talk about Keaton a lot in this vlog, but she like scabs her face somehow So I just texted her how she fixed it. So anyways, I'm on my way to class I'm really upset because I was gonna wear sweats today and They told us that we need to like not wear sweats essentially because they're filming something. So That sucks, you know Anyways on my way. I'm listening well one I have a new podcast episode out with Roman and Erica my favorite couple Erica's one on the podcast before Honestly the best guys like they were just the best and the episode so good. So definitely go listen and then I'm right now listening to TK's juicy pod with okay, sis, which is fun So love that. Um, yeah, I'm on my way to class. I'm really hungry. I don't know if I'm gonna have time to get food So great made it to Starbucks.  I just I'm making time, you know Got some breakfast really I got some breakfast, which I really hate when I do this in Starbucks I just I'm in such a rush because they literally just worked out and this is like, you know, not healthy But whatever Should my entire close friend story guys, okay uploading vlogmas at class, but I uploaded a new Gift guide. How cute uploaded. I don't know that's the term for Instagram. It's on my highlights. So go check it out All my gift guides guys Good afternoon guys. Um, I'm home as you guys can see it's currently I think 345 I am officially done with class for the semester. I'm seriously So freaking happy and excited like not because I like don't want to be at school or anything I actually like love my program and like I actually don't mind school I kind of like the routine of it and stuff more so just because I'm really excited to go to New York and I have a Lot to get done before then so it's more so just to like be able to get stuff done And also the vlogs are gonna be so much better now because I'm not in class like tomorrow I'm going horseback riding and which is very exciting. So it hang out with all my things. So anyways today I am just going to be prepping for New York. I need to Play out some stuff. I've actually been home for a few hours. I had to Send over some like creative briefs some brands and I'm filming videos with I need to edit yesterday's vlog Pack pick out some outfits prep for that which is a whole ordeal now apparently and yeah, I'm really tired So I got home. I showered. I did a bunch of stuff. I took a 30 minute nap. I'm not a napper I literally never nap comment down below if you guys regularly nap and how long you nap for this might sound so But every single time I nap I wake up more tired So am I like doing it wrong like what time how long do you guys not you know what I mean? I didn't even really sleep. I really just lay down and rested my eyes Remember what everyone's parents would say that cuz they would no anyways So I'm gonna drink some coffee. I'm gonna plan some outfits. I will take you guys with me I don't really know how to film a style with me video, but I guess we'll figure it out, you know Wow, okay That's what we're gonna do all right guys I'd absolutely trashed my backpack because I unpacked my gym bag and just things that I have in everyday bags that I Don't need anymore and then I just have some outfits out I'm like trying outfits on which I never ever do, but I just want to be very prepared So I'm just trying on things to see what I like what I don't like. Yeah, that's what I'm currently doing So at first I was just trying to be organized and it kind of play on my outfits with what we're doing But honestly just like wasn't really working for me because I always switched things up So then I was like I need for casual outfits and for nicer outfits because we have like a nicer thing pretty much every day And a more casual thing and then I just realized that basically what I'm gonna do is just wear black pants sneakers or boots And like a black hoodie black jacket pretty much for every single thing I need like turtlenecks and stuff like that I have ideas and outlines and then I need to do like one nicer outfit and then Yeah, that's pretty much what I'm gonna do. I can't really pack until Saturday I'm gonna kind of pack up a few things, but yeah, that's kind of my plan for now Hopefully this works out. I have so much stuff. Look at how crazy this looks. My dresser is still broken I have all the stuff over there kind of packed up Obviously can't really pack all the way until Saturday. All right guys, so I'm now I haven't wanted denim jacket in forever I feel very weird. I also don't have hoops on so I feel even weirder. I'm about to go pick up some Produce at Trader Joe's just for juice in the morning. I'm really trying to stay very healthy this holiday season I feel like I always like just get off track and stop working out and whatnot But I'm honestly terrified of coming back to my workouts and I'm getting a personal trainer in January So I'm so terrified of coming back and dying. So I'm just making sure I'm staying healthy So I'm gonna go pick up some fruit and vegetables and stuff and then after that We're going to a Tex-Mex barbecue place, which is not healthy, but whatever balance, you know, um with some friends So that'll be fun. And yeah, I'll thank you guys a lot Hey guys, so I'm home now we went to this place in the valley called AJ's Tex-Mex barbecue Weird spin if you guys are actually from Texas But they have like brisket and breakfast tacos and queso things that are like really big in Texas And we went with my friend Amanda who's also from Texas. So it was really fun But anyways, hope you guys enjoyed this vlog This is the end of my repetitive vlogs and we are going into fun Holiday of logs and here we go Coco, but I love you guys so much Hope you guys enjoyed if you guys have not already be sure to subscribe follow me on Instagram And I'll see you guys soon


and I'm stalking this team, no. All right, well thank you everybody so much for being here. I'm really excited to be a part of DEF CON this year. So I want to of course thank Nathan, Ajit and the whole team that's running the blockchain village for having me and I want to give special thanks to my friend, Ron Stoner at Forward Secrecy for encouraging me to participate and submit a talk this year. So we are going to be talking about building a microcontroller Bitcoin address generator. And what that means is building essentially a homemade hardware wallet or at least a homemade hardware wallet with some limited functionality. So first a little bit about myself. I'm a full-time software engineer at Microsoft based out of Pittsburgh. So I am working on backend and system stuff for an Azure storage product. My day job doesn't have anything to do with Bitcoin or blockchain, but I run chaintoots.com and a YouTube channel on the side. So I like to create content about explaining how cryptocurrency and blockchain systems work and what some of the use cases are. So I put up articles, videos, code projects and that sort of thing. And I really focus on kind of teaching the core concepts around blockchain systems and use cases. I don't really do any kind of like investing or money talk, but I do explain why sound money is important. So first, of course, the quick disclaimers. I am not a cryptography or security expert by profession, but I am a working software engineer and care a lot about code security and those sorts of things. Security is a complex and evolving topic, especially in the blockchain space when it comes to securing our funds and our wallets and those sorts of things. So this is really a proof of concept project and I wanted to show that it was possible and kind of enjoy the process of trying to build an open harbor open source cryptocurrency tool that I could use and share with others. So a little bit of context for the project that I actually built here and that is what's the core of crypto ownership? So if you've been around in the space, you know that the core of crypto ownership is private keys. Every Bitcoin wallet or Ethereum wallet or DigiByte wallet starts out with a seed phrase these days and that's used to generate private keys which are 256 bit numbers that are kept totally secret on the client side. So we never reveal our secret keys with anybody else. Those private keys are used to generate public keys and those public keys are then hashed and encoded and turned into our addresses. So these are the actual public facing addresses that we give to somebody else when we want them to send some funds to us. So private keys are used to prove that we own some amount of Bitcoin funds that we wanna spend by using digital signatures. Anyone with the keys can spend the funds and so it's absolutely critical when it comes to cryptocurrency that the keys are both securely generated and securely stored so that nobody else can get at them. Andreas Antonopoulos likes to say, I've heard him say, and I repeat often, not your keys, not your coins. So that's a really critical concept when it comes to any of these cryptocurrencies. One of the innovations that has come along in the space because of this security concern is hardware and other forms of offline wallets. So the commercial solutions like the Keep Key, the Trezor, the Ledger, those are examples of hardware wallets. And what those are is those are specialized devices that generates cryptocurrency private keys. They store them and generate them securely offline so they don't have to be done on a network device and they will sign transactions presented to them using a very limited protocol for communication between the hardware device and the PC that you're using to actually broadcast that transaction to the blockchain. There are also even simpler and earlier solutions like paper, metal, et cetera, wallets. So people would generate key pairs using maybe an air-gapped network or air-gapped offline computer and sent to a non-networked printer to create a paper wallet and store those key pairs so that they could load up a paper wallet with funds that they wanted to later sweep into an online wallet and spend. So in general with offline wallets, whether it's a hardware wallet or a paper style wallet, these keys are generated and stored on a device that's not connected to a network. So this is fundamentally distinct from the kind of hot wallets like full-node wallets, like a Bitcoin Core instance or mobile-like clients like you would use on a cell phone. Now, so the typical solutions for this, building a hardware wallet to keep your keys secure is a commercial device. So these are devices that are developed by a company. For example, I like the keep key which is developed by ShapeShift. There's the Trezor and the Ledger and these are devices that are ready-made that you can go out and buy. Now, almost all of these devices, as far as I'm aware, do have open-source firmware because we often like open-source to help mitigate issues of trust and backdoors in the crypto space. But I kept thinking to myself, why couldn't I build one of these myself on some cheap hardware? And thus my project, MicroBitAdder, was born out of lots of tinkering, experimentation and perhaps getting on my wife's nerves. So I thought it would be really interesting to generate real offline key pairs for cryptocurrencies using my own code that I developed myself. I had some basic experience with microcontrollers from another project that I built and presented at the blockchain training conference last year, actually where I met Ron Stoner. And this was a proof of work simulator on a little circuit playground device. So I'm not an embedded engineer by any means but I had some experience working with these little devices and just found them to be really fascinating. And I wanted to see if I could build something like this, a tool for generating key pairs on readily available, fairly straightforward to code products. There's a couple major challenges with this idea though. First, I needed a platform with enough memory and computing power to store and run code to do these cryptographic computations. The M0 platform, which is that little circuit playground device that I showed in the last slide was way too insufficient for being able to do SHA and ECDSA and store all of that code on the flash memory available on that device. The next major concern was cryptographic primitives. So to do Bitcoin address computation, I needed SHA-256, write MD-160. In order to support Ethereum, I needed Kekak SHA-3 and I needed the appropriate elliptic curve algorithm used for the public key cryptography. And the final very important requirement is it has to have a cryptographically secure random number generator. So I have to have some way to get true randomness, not pseudo randomness to generate keys. So how did I work through these particular challenges in picking a simple hardware platform? For the memory and power needs, I decided on the Adafruit M4 platforms. So they have several different devices, such as the ITSI-BITSI M4 and the Grand Central M4, which are the ones that I use to develop and test this particular project. It runs on an Atmel, a SAMD51 processor. Across the devices, both have at least 256 kilobytes of flash memory and 192 kilobytes or greater of RAM. So they had plenty of juice to load some cryptographic code and be able to do these computations quickly. Now, how do I get cryptographic primitives? I think most of us in this space know kind of the number one rule is don't roll your own crypto. I'm definitely not a cryptographer and don't have quite the math knowledge to implement my own crypto. So I needed to get trusted secure crypto primitives that would run on these little platforms that don't have an operating system. Standalone Python libraries are fairly hard to find and run on the microcontroller platform due to the space concerns. On the other hand, what I stumbled on is that the Trezor commercial hardware wallet firmware is open source and very standalone C code. Most of these individual modules that I needed to run to get this project to work were standalone and didn't tie in other C libraries. And so what I did was I ended up porting some of Trezor's open source code that was licensed compatible with what I wanted to release as and I'll go into a little more detail on how I did that later on. Now, the final very important concern was the need for true cryptographically secure random number generation. And luckily the platform choice fixed this for me. The M4 microcontrollers that I used, the entire family of them from Adafruit come built in with a true random number generator. If this was a limitation, but the platform was suitable otherwise, there are other options for getting some cryptographically suitable randomness. I could have done something like use an accelerometer or other device to get the appropriate amount of environmental noise. But having this built in made life a little bit easier. So putting it all together, how did I build this standalone address generator project? The stack starts on the bottom with a custom circuit Python module written in C. So I am actually mostly a Python developer. I do have C and C++ knowledge, but I do a lot of my work at my day job and a lot of the stuff I do for chain tutorials in Python because of the ease of development and comfort that I have with it. It's a very powerful and robust language, even if it's not necessarily powerful in the sense of getting most speed out of it. So I wanted to build the application layer for this in Circuit Python, which is designed specifically for these small devices. And I found that it was possible to extend Circuit Python to build a custom C module where I would do all of the cryptography work. The device itself is one of these M4 family devices from Adafruit, so the Grand Central or the Itzy Bitsy with an I2C character LCD screen or a receipt printer hooked up to it. And ultimately at the time of doing this presentation, I support Bitcoin, Bitcoin Cash with Cash Adder, Ethereum, Litecoin and Digivite addresses that you can generate with this. This was I think the most interesting and fun part of this project was building a custom Circuit Python module. I followed a tutorial called Extending Circuit Python by Dave Astels that's available on the Adafruit Learn website. And so I went through that tutorial and just learned the basics of creating a custom module for the Circuit Python build. This is where all the cryptography happens thanks to the Trezor code. So I get a true random number generator seed passed in from the Python layer because it's easy to use os.urandom to get your seed from Circuit Python directly. I then hash that seed into a private key, generate the associated public key and return an encoded key pair from this layer. So this is using chain appropriate address encoding. It's base 58 addresses for Bitcoin, Litecoin and Digivites, Cash Adder for Bitcoin Cash and of course, Hexadecimal for Ethereum. And as well, this custom module function returns the width or hex encoded private key depending on the chain as well. So this of course required actually building the custom Circuit Python module. I had to run the make file that's provided by the Circuit Python code, make sure all the files were in the appropriate places and this ultimately gives you a UF2 firmware that you can drag onto your microcontroller device and it will reboot with that new firmware. So since I was actually essentially building the platform that the device runs on from scratch, it required a little bit more work than the basic sort of Circuit Python functionality where you just have to edit a Python file. This required me getting down into the firmware layer a little bit. It definitely presented some challenges but luckily the folks over at Adafruit and the folks that work on Circuit Python are really helpful about getting you up and running if you talk to them on GitHub or somewhere else and have questions. I personally found for whatever it's worth that I was able to get this build running most easily on Linux. It is possible to build Circuit Python on Windows and Mac I do believe but I just worked on Ubuntu when I was working on the core of this project. Now within this custom Circuit Python module, since all of the Trezor crypto primitive code are pretty standalone, it also made it possible to do testing for this on a command line interface. So every time I wanted to go in and work on some of the important cryptography stuff and make sure that I was getting correct addresses and correct encoding, I didn't have to worry about rebooting the firmware, reloading the firmware, making sure my LCD screen was hooked up correctly and all of those little challenges that you run into when you're developing on hardware devices. So for example, on this slide here is an example of just running a test driver to generate a new DigiBite address right on the command line with a private key. Since everyone at Defcon gets to see this key pair, I would say don't take that and send any of your precious DigiBite to it but I think you all know that. Now for the Circuit Python layer, all this layer does is it's kind of the application layer that's built on top of the lower level crypto stuff which is done in C. This generates the entropy. So I'm using pythons os.urandom function which is tied right into the CSRNG built into the platform. I call that custom module code. The function call takes that randomness seed as an argument and I get a tuple back so I get the private key and the address back already encoded in the correct format. And then this code uses the appropriate libraries to display that final address and private key on an LCD screen. I also tested as well with a receipt printer which I thought was kind of fun. It's not the most robust way to store your cryptographic key data long term but I could press a button to generate a new Bitcoin address and have it printed right out for me and I just thought that was pretty cool. But I primarily tested with an LCD screen which simply rotates between displaying the address and the private key about every 30 seconds or so. All you have to do here and one of the reasons I picked CircuitPython even for an embedded and microcontroller project is with CircuitPython when you connect the device to your development PC you'll simply see a drive called CircuitPyMount to that computer and you simply edit the main code.py file and this is where all of that application layer code went and when you restart the device it will automatically run that code.py file. If this iteration of this project the usage is really straightforward and simple then and comes with some pitfalls that I'll talk about next but each reset of the device will just generate you a new completely random key pair that you can copy down. So this is what the final project looks like wired up in a couple different ways. Generating Bitcoin addresses with a little itsy bitsy on the screen with the larger Grand Central and also showing it generating key pairs and printing to a receipt printer. So this was a really interesting project. I had a lot of fun building it and I was really, really pleased with the results and the fact that I was able to get a real working Bitcoin address generator running. That said, there's a lot of potential pitfalls when you're working with cryptography and I wanted to talk about some of those issues as part of this talk because I don't want everybody to think that this is something that you can just take and run with if it's guaranteed to be secure and more so what are some of the things that you can run into if you're choosing to tinker with a project like this on your own. The first and perhaps most obvious pitfalls are cryptography foot guns. Again, I'm not a crypto expert and there's always hidden dangers with implementations. I tried to mitigate those as much as possible by using trusted primitives. So I used libraries for the Trezor hardware device which is a very, very popular crypto hardware wallet. The Trezor team works really hard to take in bug reports. I'm sure has people that are cryptography experts working on the code and I felt fairly confident using these and was able to I think go forward assuming that shot 256 was gonna work correctly if I use their code. I also kept things simple. For this at least first round of this project, all it does is generate a key pair. It generates a random private key and then walks through the steps to get a pub key and finally an encoded usable address. I don't have any extended support for many of the features that we've come to enjoy like HD wallets and those sorts of things and I'll get to that in a bit as well. And then finally tested, tested, tested manually against known working implementations of key generators. So I would use some different places where I would use my device to generate completely throw away private keys. I would plug that into a paper wallet tool for example and make sure that I kept getting the correct public address because the last thing that I would wanna do is send funds to an address and have it turn out that the address was wrong based on the private key and then lose those funds forever. Major pitfall that many of you may have been thinking of while listening to this right now is that single key pairs are simply way out of favor and considered a legacy way of dealing with private key data. You have to make sure that if you're generating a single key pair for fund storage that you copy it correctly and double triple check before you send any funds to it because base 58 like is used in Bitcoin addresses and in the with private key format is not the most human friendly format. It's a little bit more compact than hex but it's also super easy to screw up was that a capital or a lowercase W that I wanted and that was something that I ran into when I was actually testing this stuff with some live funds. The encoding's just not human friendly and it is easily corrupted. Bad handwriting, character distinctions like lowercase uppercase, potential for water damage if you're on paper. These are all huge problems for long-term key storage that are important to consider. And as is, the code that I generated only shows this key pair once. So you had to be really careful to copy down everything and then if you were gonna reset the device you had no way of verifying the key pair you copied down was correct again. So let's talk about the fun stuff which is potential future improvements. How can we make a project like this that's a tinkerers homemade offline wallet better, safer, more secure? I think the first and best thing that I could have done to make this better and would like to consider as I maybe iterate on this project in the future is upgrade to BIP39, BIP44 compatible seed phrases instead of single key pairs. So instead of directly generating a private key from the true random number generator generate a seed phrase and encode it as a mnemonic using the BIP39 standard. This is much, much, much better for reasons that a lot of us in the crypto space are fairly familiar with. You have a backup that's much more human readable. A backup that is much easier to fix if you do get a little bit of water damage or something like that or dealing with bad handwriting. It's much easier to figure out what an English word might be if a character or two is off than in a string of seemingly random information like a with encoded private key. We could then generate new addresses as needed or even if we wanted to keep it simple and just grab the first address from the tree. This is still a much safer and easier backup solution even for a single address usage of this type of device. Now I will say of course again another thing that's fallen out of favor is address reuse in general for privacy concerns. So it would be best if we're using a BIP44 standard in an implementation of this in the future that it would allow you to generate new addresses from the given seed but as well even if it was just used to generate the first key pair if you have a mnemonic backup it's gonna be much safer for the users. Several UI UX improvements that could be made, warnings about some of the things that I talked about like, hey, don't lose this, make sure that your seed or make sure that your key is copied down correctly. Maybe in fact it should actually store the key pairs for a while since it's designed to be a standalone offline never connected to a network device. It could be feasible that you would wanna keep maybe an encrypted copy of the seed phrase on there or a list of the generated key pairs on there in case the user screws up and wants to go back and make sure they copied something correctly. This was built on CircuitPython 4 which has now been superseded by CircuitPython 5. So it would of course be wise to upgrade my custom module custom firmware to the latest builds for supportability. Downside the build process was tricky. It was probably the hardest part of getting this up and running. Question could be a potential improvement. Is this device powerful enough for a pure Python implementation? I originally got the idea of doing the lower level cryptography in C and then having a CircuitPython application layer because I was dealing with the particularly limited devices I was trying to do this on first before I moved to the M4 platform. I haven't really tested out whether or not the M4 is powerful enough to load pure Python implementations of the cryptography and therefore have a pure Python project. I would like to do that for easier development and less complexity for both myself and potential users of a project like this. The downside is of course with anything cryptography making sure that the crypto primitive libraries that I'm using are up to snuff in terms of their security. And as far as I understand it, there can be some more concerns with doing crypto in a Python environment versus a C environment with like side channels and those sorts of things. I would love to consider doing more unit testing. It's always a good idea to catch basic cases and edge cases through a unit test instead of manual testing. So anytime I make some kind of change to the code I could have test cases that would check and make sure that key pairs are being generated correctly. A lot of the Bitcoin BIPs that are involved with these sort of wallet generation actions do have some test vectors that I could put into a unit test and make sure that I'm not missing strange edge cases. And I'm just open to ideas. I build projects like this outside of work just as something that I enjoy. I like to tinker. I like to learn about Bitcoin and crypto tech and then teach other people about it. So I'm always looking for ideas and perhaps something new will pop into my head tomorrow about how I could work on a project like this and make it better. And that's all I had for the main presentation. I would love to take any questions you all have. If I'm not mistaken, I do believe that the Grand Central M4, which is one of the devices that I worked on, it might have some kind of key store capability but I can't say for sure on that. Yeah, that definitely would be nice and that would be something to investigate as well as part of potential future improvements and tinkering with the idea. I think at the very least, if I could get it to generate a seed phrase instead of just a raw width and address key pair, it would certainly make backup safer even if it doesn't store them on the device because that way at the very least, you can make sure that you're writing it down correctly and backing it up. It's obviously not a full hardware wallet implementation. It doesn't sign transactions or offer modern trees of addresses. It was kind of a proof of concept for the initial idea of can I generate a basic, basic crypto wallet with a little microcontroller, like something that's simpler even than a Raspberry Pi and I'm glad I tinkered with it and it worked out.


The use of polypropylene fibers and nanosilica has been shown to improve the performance of ultra-high-strength geopolymer concrete, UHSGPC, making it suitable for use as an alternative material for Portland cement-based concrete. Polypropylene fibers increase the strength of the concrete while nanosilica improves the durability of the concrete under extreme temperatures. This article was authored by Fadi Althoi, Osama Zayed, Salah Al-Salamiy and others.


The remarkable stylus options are very expensive and don't have the best build quality, so let's look at these two popular alternatives. The Lami is €42 and gives you two extra tips. The pen has a triangular shape and is very well balanced if you leave the cap off. The Norris Digital Jumbo is €30 and gives you five extra tips. It has an eraser on the back, the tip is more screwed than the tip of the Lami pen when you write. This makes the Jumbo the best replacement for the remarkable stylus in terms of pricing, build quality, feel and options with having the eraser tip. If you like the remarkable feel better, there is a nice hack. The tips of these pens are interchangeable, so you can use the remarkable tips on both of these pens. You buy nine remarkable tips for €14. This makes the Jumbo the best replacement for the remarkable stylus. The Lami is still my favorite though. I hope this helps.


QuickBooks Desktop 2023, import bank transactions into QuickBooks. Let's do it with Intuitz QuickBooks Desktop 2023. Support Accounting Instruction by clicking the link below giving you a free month membership to all of the content on our website broken out by category further broken out by course. Each course then organized in a logical reasonable fashion making it much more easy to find what you need than can be done on a YouTube page. We also include added resources such as Excel practice problems, PDF files and more like QuickBooks backup files when applicable. So once again click the link below for a free month membership to our website and all the content on it. Here we are in QuickBooks Desktop Bank Feed Practice File. We started up in a prior presentation. We've been thinking about how to get the data from the bank into the system. There generally being two ways to do that connecting directly from QuickBooks to the bank and downloading the information from the bank directly to QuickBooks or going to the bank itself downloading the information in a QuickBooks file or a file that has the capacity to then be uploaded into QuickBooks and then upload that file into QuickBooks. Either method will get us to the same point after we have the data in the system which then leads to the more complex part which is to take that information and then try to set it up in such a way that we can construct our financial statements from it. So if I go to the banking dropdown here we've got the bank feeds. We talked about this is the direct connection method that we could be using. We also have this item here which is the import web connect file and this is one way that we can basically upload the file. Also note that we might then also want to look at the list dropdown, the chart of accounts and we talked about the fact that we could set up our checking account first whether we check the checking account up first, take me there maybe later or not it's going to set up an account of course that will be a general ledger account that's going to have to be a bank type of account because that's the account that's going to tie to the bank feeds. So if you don't have that account set up then if you just go through the setup process whether you're going to upload it or whether you're going to connect to the bank you're going to have to set up kind of an account as you go. You might want to name it like a generic name like I have here or if you have multiple checking accounts you might want to have like a parent account and then the sub accounts and possibly the last four digits of the number so that you know which account that you're dealing with. Although note that the bank feeds when you actually go into the bank feeds they have some identifications by the institution in there that can kind of help you out but when you're looking at your financial statements still it's kind of useful to have different accounts related to each bank and have some identifiable marks on them such as the last four digits of the number. Okay so what we have done is last time we downloaded the information from our bank onto our desktop so we talked about how to do that last time most banks have the capacity to download a QBO type file which basically takes the raw data that you find on your bank statements in essence but then puts it into a format that can easily be uploaded meaning it's just increases decreases to the checking account and the date basically in memos right and we talked about we can also get that in a comma deliminated file which looks kind of like an Excel file. Now this one up here however is the one that's most easily uploaded into the QuickBooks system so that's the one that we're going to be using we could upload it either by going to the banking dropdown and we could go to the bank feeds and import the WebConnect file because we're importing the file as opposed to connecting directly to the bank which is good for a practice if you want to practice doing that and it's also good in the event that maybe you want more data for example those are two main reasons why you might download the data file and then upload it but after we upload it will be in the same place but QuickBooks I believe actually recommends that we actually close QuickBooks and double click on the data file which will then open up the program so I'm going to do it that way and so what I'd like to make sure is that I have the file that I want to be importing the data file into this is the correct company file that I want the data to go into I'm then going to close this back out the whole thing closing the program and into it recommends backing up would you like to back up I'm not going to back up right now thanks for reminding me QuickBooks and then I'm going to go back into my desktop and so note this is the actual QuickBooks program icon this is the data file that I downloaded this is the actual this is the data file that's actually my QuickBooks data this is the data file which is the bank data which just has the banking information I'm going to double click on this one which should then open up the program and then start an installation wizard asking if I want to proceed taking the data from this item into our system now note if you're following along with your own data you're going to have to sort your own data because it's going to be your banking data and you can practice with the same kind of types so once we get the data into the system well then I'll then look at it and imagine different scenarios with the data that won't necessarily be applied to this particular data in real life it's just we're going to use the data in order to think about different scenarios once we have it in place which hopefully you can apply to your own data for practice purposes or for your own data file so I'm going to double click on this and it opens QuickBooks backup that looks good looks promising it asks for my password again we then get a pop up screen that says QuickBooks has received new transaction data please indicate whether you want to import this data now or save the file for import later import new transactions that's what I want I don't want to save the file here always give me the option of saving to a file when I download the web connect probably don't need that but I'm going to keep it because I won't change anything right now I'm going to say ok and there we go so then it's going to give me the information so you are downloading transactions for the following account it gives us our account information financial institution the type of account checking account account number and then that's from your institution so we got QuickBooks does not have an online account to handle these transactions please make a selection below so we can then choose to use an existing QuickBooks account or if we don't have one set up create a new QuickBooks account so if I hadn't already set up that checking account then I would use this one and I'd set up a new account since I do have it set up I can pick this one and say I just want it going to the checking account now note when I have the drop down here it doesn't show me the all the chart of accounts it only shows me the account types that I have available which are bank account types also note that I gave it a generic name so that could be fine however if you have multiple accounts you might want to have an account with like put the last four digits of the account number or something to identify one account versus another account if you're dealing with multiple accounts so I'm going to say continue let's do it and it says your web connect data has been successfully read into QuickBooks you can view the downloaded data in bank feed center by selecting your financial institution so I'm going to say ok and then it usually takes you there directly so it gives me this little thing advanced bank feeds a faster and improved way to categorize your bank data create enhanced rules and transactions to look books quickly so I'm going to say don't show me this again and skip it and then I think it's going to take me right into the bank feeds directly now if it didn't take me directly into the bank feeds I can close this back up and I could then say ok I'm going into the bank feeds by going to the banking drop down I can go to the bank feeds and now I've got a bank feed center I didn't have a bank feed center before all I had in here the first one was set up bank feeds for an account because I didn't have any bank feed set up before now I do so now I have a bank feed center so if we go into that we get into this screen for the for the bank feed center so it gives you like kind of your recap item up top and we will have multiple cards later because I believe we'll just check out a credit card as well so you might if you have multiple accounts you'd have multiple kind of cards up top so the look and feel that they they've changed it recently to this look and feel we'll talk more about it in the future but it's it's nicer it's cleaner looking although there's this huge gap up top which is kind of annoying and so now that I'm zoomed in on my screen I'm actually zoomed in using my settings here on my window settings and I'm zoomed in to like 150 so I might bring it back down to like 125 and that wouldn't be so much of a problem if you were working yourself and you didn't need to because I'm trying to zoom in for presentation purposes but still it seems like there's a lot of empty space with these cards it would be kind of nice if they allowed us to collapse the cards or whatever but it is what it is we'll talk more about that later so now we've got our data down below the thing we want to note right now is this data is now in what I call bank feed limbo it's not being used to create financial statements yet in other words if I go to the reports up top company and financial look at my balance sheet for example there's nothing there right nothing has happened thus far because because I need to take this data into the system now when you first set up your bank feeds that will typically be the case because all QuickBooks has then from the bank are increases and decreases to the checking account and if you have electronic transfers it gives you this memo information which is useful to finish the information necessary to add the data into the system but usually you're going to need a couple other things what are you going to need you're going to need to identify an account for it to be hitting the QuickBooks knows it's going to be adjusting cash cash is either going up or down but what's the other account in the double entry accounting system if it's a deposit you would think mainly the other side would be income and so you have to assign it to an income account if that's the case QuickBooks can't make that assumption because it might not be income it could be from you or a loan or something like that so we've got to set that up and if it's a decrease you would think the other side of the account would be an expense so we've got to tell QuickBooks what the expenses are now we can then start to memorize those things as we go the other information that the system needs is if we want to know who the money came from we've got to give a customer which gives us more detail and if we want to know who we are paying and track by who we paid in the system we've got to give the system a vendor usually that information can be found in the demo which is nice so we'll get into that in more detail we'll talk about this whole kind of layout in more detail in future presentations


Hi everyone, my name is Ben Walker and I'll be presenting along with Chung Hong Liu on high performance NVMe virtualization with SBDK and the new VFIO user protocol. So we'll be covering today four sections. The first is standardization of the protocol itself, which is new. This is being standardized through QEMU and in a library called live VFIO user. Then we'll talk about how SBDK is using this new standard protocol to emulate NVMe devices into guests. And then we'll close with my colleague Chung Hong talking about how we have implemented an NVMe client library and then some benchmarks. So I'll start a little bit with standardization, but first I want to talk about some upcoming talks that will occur later at this conference. Importantly, there is a talk on the live VFIO user library that is open source and available that implements a client and a server. Using the new VFIO user protocol, this one will be at the very end of the conference. I know this talk that I'm giving now is at the very beginning, so you'll have to wait. But this will cover all of the details about how the protocol works, the current status of the enabling library, which is called live VFIO user and a lot of the lower level details that we'll have to skip over here. There's also a talk on live migration support, which we'll touch on VFIO user also tomorrow on Thursday. This will cover a lot of the details about how to migrate VMs when you're using VFIO user to present disks. So we are going to talk about using VFIO user here to present NVMe devices into the guest. So with that, since I'm going before the other talks, some brief background on what VFIO user is, there is a need to emulate storage devices or many kinds of devices, but storage in our case, outside of the VMM. And the reason we want to do this is for performance, for security, but also for stability and resilience. If the target process crashes, we need it to be able to fast restart and not take down the VM. We may want to run the emulation or the target even itself in a separate VM. So this concept of VFIO user was initially conceived as a way to emulate devices in a separate process or outside of the guest for disks. This was originally, the goal was we want to present virtualized NVMe devices into guests. But of course, VFIO user has gotten much broader than that use case. Now it can emulate any device type. So the actual VFIO user protocol, and again, there's much more detail coming up on this in later talks, is modeled after the VFIO I octals, because basically we want to do the same thing, except we're not sending I octals, we want to send commands over a Unix domain socket. And so the other way to think about this is it's like V host user, but it's not tied to verb IO. So the protocol looks more like VFIO and you can do arbitrary operations to emulate a broader range of devices instead of just verb IO devices. And so the protocol itself is agnostic to the VMM. This is not necessarily tied to QEMU. Anything can implement this. And we'll show a demonstration of full NN implementation that doesn't use QEMU at all in this talk. OK, so emulating NVMe devices. The initial problem statement was we want to present emulated NVMe devices into guests, because the guests all have NVMe drivers built into them, you know, Windows does, the BIOS has an NVMe driver, you know, any, of course, Linux does and FreeBSD and things like that. Any operating system you would probably be running and a guest has an NVMe driver in it, whereas they don't all have VirdIO drivers, VirdIO block in particular. So the original idea was we want to present NVMe devices fully virtualized, but NVMe devices into the guest and we need a way to do that. And so the guys at Nutanix and other places went off and found a way to emulate any PCIe device. They came up with several strategies and it's it's sort of morphed over time to become VFIO user and then they said, OK, now we've built a little prototype, you know, we're maybe emulating a GPIO device or something simple. Now we need code that knows how to act like NVMe. And so they they came to me in the broader SBDK team and said, hey, you guys know a lot about NVMe stuff. What can we use in terms of code to pretend it's an NVMe device? And my first thought was, well, NVMe over fabrics, which is remote connected NVMe over transfers like TCP or RDMA already requires the software to essentially emulate an NVMe device. There's a couple of important differences, which is what we'll cover mostly in this talk. And it already at least the target in SBDK and also in the Linux kernel, they're already designed to have this concept of a pluggable transport layer. So NVMe over fabrics allows you to export discs over the network using either TCP or RDMA or Fiber channel. And so the software is already designed to have a common layer and a plug-in system for different fabrics transports. So the idea is maybe we can reuse all of this. So that's exactly what we did. We set out to make a new NVMe over fabrics transport where the transport is shared memory with VFIO user. So the transport here is really shared memory between the guest in a backing process and a Unix domain socket for control messages. And that's what we'll cover the rest of the time in this talk. Is the problems with that and also the success we've had with that. So NVMe over fabrics, unfortunately, is slightly different than local NVMe in particular, some of the initialization flow is reversed and I'm going to get into that. So the first question we had to answer is can we generalize the NVMe over transport plug-in system that was already in SBDK to handle these differences. And fortunately, the answer is yes. So here's what it looks like today. This is all checked into SBDK and is available for anybody to test out. You have a QEMU with a guest running and it is running its regular stock NVMe driver, you know, whatever that guest operating system is, whether it's Windows or Linux or whatever thinks it has a local NVMe device and it loads its NVMe driver. The device itself is emulated by the SBDK NVMe over fabrics target running on the same host system just in a separate process. And it is communicating with QEMU to do initial setup, discovery of the device and all that using libvfiouser, which again will be covered in that talk later in this conference, as both the client and the server side. So SBDK is using it on the server side here. And the actual data transfers between the guest and the target and the descriptors that describe, you know, I want to do a read or a write to the disk are also placed in shared memory rings. And so once the setup is done, it's all just a shared memory system. There's no system calls or anything like that. It's very fast. So this is all checked in. It's available for people to go check out in SBDK today and it works. Okay, so let's go into a little bit of the details about what we struggled with to get this working because that's the interesting part. In NVMe over fabrics, traditionally, there is a concept of a listener because it's a fabric space thing. So something listens on an endpoint, you know, an IP address for TCP. And that IP address periodically attempts to accept new connections after it's listened on that IP address. And those connections become like the NVMe over fabrics Q-Pairs. For a local NVMe device, none of this exists. And so this was all baked into like the generic layer in SBDK NVMe over fabrics. Originally, you know, it assumed there was some listener socket that, you know, occasionally had to be polled with an accept to find connections. It didn't necessarily assume it was a socket. But this model was baked into the generic layer. And of course that doesn't happen with a VFI user device. There's only one Unix domain socket and it's not a listener, right? You just connect to it and you assume the other side is there and it's going to send you messages. And you don't have to pull for accept. There's only one, it's point to point. There's only one guest connected to your Unix domain socket per device. And so you're not doing multiplexing. You're not doing multipath. Any of these things, these are all disabled. So local NVMe device effectively. So the first thing I do is sit down and generalize the concept of a listener to become an endpoint. And really we push down the idea of having a listener and having to pull it to accept new connections down into the individual transports because now they behave differently. And so each transport is doing whatever it thinks is right. TCP and RUM are fairly similar here. They're both IP based. Fiber channel does its thing and VFI user is very simple. It just opens the domain socket and assumes somebody's on the other side. Okay. And so some of the other challenges are with a local NVMe device. There are register reads and writes that the driver is going to make. NVMe by spec defines a set of registers in a PCIe bar. And these are read and written with MMIO during initialization time. And so the main differences are with a fabrics device. There's obviously no MMIO. There's no PCIe bar in NVMe over fabrics. These are replaced by something called fabrics property get or set command. And so the NVMF target NVMe over fabrics target in SBDK understands how to process property get and set commands, but it doesn't know what an MMIO is. So fortunately, Livvia FIO user, the way it does MMIO is we can create a thread blocked on the file descriptor on the target side. And that file descriptor will become ready and wake our thread up anytime the client does an MMIO to the memory mapped region. And so it'll wake us up and say, hey, they did a right, or they're trying to read from this memory range. And we then take that and we generate a fake fabrics property get and set command as needed based on if it's an MMIO read or write. And then we send it to the SBDK NVMe over fabrics target. So we basically translate it from an MMIO style operation into a command. So these commands are inherently asynchronous, whereas MMIO, at least the read side is synchronous. So we have to for MMIO read have this thread block. So it sends the command to SBDK, which processes it asynchronously and completes it sometime later. But the thread that does MMIO has to sit blocked just that thread, not the whole target has to sit blocked until it gets a completion back. For the read path. And then it can return control back to live via our user, which completes the read request. So this is not particularly fast, but fortunately NVMe only does MMIO reads in the configuration path, like the initial setup. For writes, it's a little bit simpler because MMIO writes are posted. And so you don't have to wait for the response. We basically say, oh, you wrote four bytes to this offset in the bar. Okay, we'll generate a property set command and we'll send it and forget it. The other challenge we had is that the set of registers that you're allowed to do an MMIO read or write on is a little different than the set of things that you're allowed to do a property get and set on, just because local devices are different than remote devices. And so we had to add additional emulation. I think it was just two or three things to get this fully supported. All right. And then another major difference with actual fabric connected devices versus a local NVMe devices, the order in which they create what's called the admin Q pair. And so for NVMe devices, every controller has a single admin Q pair where you do administrative stuff. And then it has a set of NIO Q pairs, usually one per cores, how people allocate those. And those do reads and writes from the disk. And for a fabrics device, you have to create the admin Q pair first because it's a TCP connection and you can't talk to the remote side until you have at least one connection. So you create that first and then you read or write the properties, quote unquote, which are like registers using that connection. But for a local NVMe device, it's the other way around. You actually read or write registers in the bar first in order to create the admin Q pair. And then you can do other admin stuff with commands after that. So this presented a little bit of a challenge where of course handling MMIO by sending commands on the admin Q pair, these property get and set commands. And they're doing MMIO before they've created the admin Q. So we have to, what we do in SBDK on the backend is as soon as the endpoint is created and we say we're going to create a UNIX domain socket and you should open it up, we just create the admin Q pair internally in SBDK. And it's not mapped to any shared memory in the guest yet. So you can't send admin commands on it from the guest right away. But we can still send our internally generated property get and set commands at the beginning. And so we just create one of those right away. We know we're going to get a bunch of MMIO to do configuration and we can send those on that admin Q internally. And then later on in the initialization process when the guest tries to create an actual admin Q, it will say, here's my memory in the guest. I've got my descriptor ring of shared memory that I'd like you to look at when I try to send you admin commands. Then we take our internal admin Q and we point it at this newly mapped memory and say, here's really where the commands are instead of this temporary internal thing. And so this sort of works out the, this order of operations difference between fabrics, NVMe over fabrics devices and local NVMe devices, so that we can still use the NVMe over fabrics target in SBDK to emulate these local devices. So that was probably the trickiest part of this whole thing, but it actually worked out in a relatively small amount of code. So with those things, it just started working. We got everything together and we pushed the patches to SBDK to generalize the transport interfaces ahead of time before the FIO user was actually ready. And when it came down to it, the final patch that went into SBDK to support VFIO user only added a new plugin. It didn't change anything else in SBDK. It was just add a file and touch some of the build stuff so it gets compiled. So this was great. This was exactly what we wanted is, we just wrote a new transport plugin and nothing else had to change. And so this generalization also we think will be useful to us in the future as SBDK begins to be used in more places, in particular as firmware on various accelerator devices. They're going to have other pieces of hardware that will behave in various ways that are NVMe related. We may do a quick transport at some point, which will behave more like TCP and RDMA, but make it easier for us to do that. But may have aspects needed from what we've done here. And ultimately, SBDK becomes a great NVMe emulator. And we have since used this to quickly prototype possible NVMe features that we're thinking about adding to real SSD products. Just hack it up in SBDK real quick and pretend you have the feature and see what it does, see how it behaves, see if we can use it. So it's pretty neat. Okay, from here, I'm going to hand it off to my colleague, Chanpeng, who's going to actually talk about how we used VFIO user on the client side so that we have an alternate client to QEMU that can connect to our target, primarily for our testing purposes. And then he'll close with some talks about performance benchmarks, which is the exciting part. Thanks, Ben. So let's continue the rest of this presentation. The first is the NVMe client library. As you already know that QEMU client is a user usage scenario with VFIO user NVMe target. But we can also support SBDK NVMe client with VFIO user NVMe target. We have a client, VFIO user, PCI library to provide abstract API to access the emulated PCI devices. And on top of this library, we added VFIO user transport in NVMe client library so that users can use the existing NVMe APIs to connect with the remote VFIO user NVMe target. Okay, let's see the performance numbers of VFIO user NVMe target and VFIO user block target. Actually, VFIO user and VFIO user target have different thread modeling. For VHOS target, the IO is processed in unit of VHOS controller. That means for multiple IO queues in each controller, all the IO queues are processed in the same core context. While for the VFIO user NVMe target, each submission queue can be processed in different calls. Here, we have an example to emulated the efficiency of VFIO user. We use a knob, BDAV, and 16 VCPUs and 16 IO queues. The performance number of VFIO user NVMe can increase based on the number of calls used in host. While VHOS user block is almost the same even you use four calls in the host. Here is another two test cases. The chart one tested four VMs using one, two, four calls respectively. You can see the performance number increase linearly when used in one, two, four calls in the whole side. Another test case showed in chart two. We would like to compare the performance with VHOS user block. For this comparison, we don't expect VFIO user NVMe will improve the performance a lot due to the actually similar mechanism. The result shows that VFIO user NVMe is a little still a little slower than VHOS user block. So that means for the outpass, we still have some work to do to optimize the outprocessing for VFIO user NVMe. And here is another several test cases using the physical NVMe SSD as a backend. First of all, we tested interoperative SSD using SPDG NVMe Proof 2. The performance number hit the hardware's limitation. We will use this performance number as the base number to compare with other test cases. Then we run SPDG NVMe Proof 2 inside the VM to test the emulated NVMe SSD inside the VM. And we can see that due to the pulling in mechanism in both the VM and the whole side, we can see that the performance number in the VM is almost the same with physical NVMe SSD. And finally, we run a file test cases inside the VM using the native NVMe driver and the VTHO block driver, respectively. We can see that for VFIO user NVMe, we can get 725K OPS while the VHOS user block can get 786K OPS. VFIO user NVMe can reach about 84% of the physical NVMe base performance number while VHOS user block can reach about 91% of the base performance number. So it's really very hard and efficient for the true virtualization solution. That's all for today's presentation. For any questions and issues, feel free to contact with us in the SPDG Select channel. You may find the information in SPDG.io website. Thanks for watching.


Ṉ Ṭ Ṭ Ṭ Ṭ ṬṬ Ṭ Ṭ Ṭ Ṭ Ṭ Ṭ Ṭ Ṭ Ṭ Ṭ Ṭ Ṭ Ṭ Ṭ Milk needs to be placed in the system, Nature is humans release animals from everything. Ma'am dit Ṫa ṭa Ṭ�聯 Ṱa ṭe Ṭ輹市 Nothing dripping with water from the suggestion. ಎತಾನಿಿ ಒಗತ ಎಿ ಸ್was compassionate ಬೈಕೆWhite Finance débutರಿಸ್..ಮನಿದಿ ನಗ್,ನೂ ಪರಿವಗ� micron ಮರಳಕಡಲಭೆಲಿ ನೂಘರೆಲಿ,ಕೈತಶುಣತ್ಲಿ ಮಿವರಿಱಿ ಯ಩ virtual ನೂದಾಳವ.. ನಮವ ಥಿವಲ್... ತಶಿವಕಿೆ ಚುಸಿಘಿವರ.ρωಲಲ、 ಸೊರಡೇ ಬ್ತ vigilantilim.ವಾಡಿಬಣಾಲು. ವಾಡಿ ಸಾಾರೆisión. ಹೀರಡರಳಿಸಿಲ್ಷಿನಿನಿನಾದು. ಹಾರ್ತ್ಂದು. ಮನ್ತಿಮ ಻ನೀಫತ ಬರಾ.owanಲಸಿದ!! Suppose someone has spotted her with her uniform on, hence their guy has come to see her now. నిల్ రిల్లినిలొ పిసిసి ఆభ్లి రిసి నికూప you always say this but i think and i amolorhead and even i don't know You keep saying when i predicted you did not know next time our video was made please dear trial and error


If you're interested in this talk, if it doesn't suck enough for you to follow up on it later, I'm going to be tweeting out the slide deck and all that information, so follow me on Twitter. And so let's get started. Like many stories, this story starts out in the year 2000. I was a recent college grad, I had a degree in chemistry, and so I decided the best thing for me to do with my career was to pursue old-timey sign painting. Somebody actually made this by hand, it's pretty cool. I wanted to be able to do that. So I did what any brash 21-year-old guy would do. I went out and bought some badger tail brushes, bought a couple cans of one shot, and started doing cold calls on local businesses, just sort of walking in and costing whatever random person happened to be walking there. And yeah, I didn't make any sales, which turned out to be a blessing in disguise because I'm a horrible salesman, but I'm a worst artist. But little did I know, little did I know that I had taken one step on the road towards becoming a virtuous programmer.   But it kind of makes sense here because we all kind of do this. And we all kind of go in and promise things that we're not quite sure how to deliver. And then we go and figure out how to deliver them, and I think that's pretty awesome. I think that's a great thing about our community, being a software developer.  You say things like, sure it'll scale your, I don't know, Brony social network. But what you really mean is, yeah, sure it'll scale long enough for like for your three months runway to like run out and you go out of business. No, I'm not that cold. But occasionally something does scale. Occasionally you need to deal with what I call big ish data. And big ish data is not big data. It's not architecture. It's not networking together, you know, like 40 EC2 instances and making some fancy architecture. What I'm talking about is how do you keep a normal pretty vanilla Rails app running as your production data set grows? And even if you don't have a fire hose of data, you can easily find yourself in this situation. So whenever I talk to people about this, they always want to know, like Star, like you're being wishy-washy, like define big ish data. Like what does that mean in terms of numbers? So I made up some numbers. I'm talking about like a terabyte of data in your database, a couple gigabytes a day, you serve it with a normal Rails app. And the good news is that Postgres can handle this really well. This is the sort of thing that Postgres just tears up. But chances are your application cannot. The reason is that a lot of the conventions that we use when developing web applications, especially using something like ActiveRecord, is these conventions work well for small and mid-sized web apps. Web apps that don't have, you know, gigabytes or terabytes of data. But as soon as you start using these conventions with larger data sets, you find that, well, it just doesn't really work that well. This is actually a live query that's been running since this morning. I wanted to show you guys how many errors we had in our database. But yeah, similarly, if you want to page your data, you install some paging gem and it doesn't really work.  I just want to get rid of this, right? This isn't worth the hassle, so I'm just going to delete this all. And that doesn't even work. Like if we ran this, this would take probably three days for us to delete that much data. And understand why this is the case, to understand how you can work around it and how you can configure your database so that it performs well under these conditions. We need to go all the way back to the summer of 1978. Summer of disco, free love in the VT100 terminal. Now the VT100 was the first computer-like thing that you could buy and put on your desk and prove to the rest of the office that you were in fact the alpha nerd. 1978 was the year that Oracle 1.0 was written in PDP11 assembly language. And just a little aside, this was the most interesting image I could find that had anything to do with Oracle. I looked for an hour. And if you haven't ever seen a PDP11, this is what it looks like. So nowadays, people, marketers use buzzwords like platform as a service. And we're doing everything in the cloud. And back then, they had marketers too. Only they were talking about real-time computing. Only for them, real-time meant that report that you asked for runs in five minutes instead of a day. And that's all great, I'm sure it was great at the time. But it doesn't seem like a very good platform to build the web on. But if you think about it, that's kind of what we've done. I mean, all the technologies that we use today for web development are either direct descendants or kind of bastard nephews of this stack. So how did that happen? Well, this real-time computing thing, it took queries from a day down to five minutes, down to five seconds, down to 50 milliseconds. And all of a sudden, you can use this as a foundation for a real-time web app. And all this happens because of Moore's law. And I'll just remind you, in case you don't know the formal definition of Moore's law. So as time goes forward, computers get more awesome. They can crunch more data. They can do queries faster. And so I want to postulate Starr's corollary to Moore's law, which is this. As your database grows, you actually travel back in time. And this is a situation that I found myself in about two years ago on my company. I'm with Honey Badger. We do exception monitoring for Ruby apps. And there's a lot of freaking exceptions out there. I mean, you guys need to do your jobs better. But the thing is, we didn't expect this to succeed. It was just a side project. We built it like a normal Rails app. And then people started using it and people started sending us thousands of requests a day and then thousands of requests a minute and a second. And we essentially found that we had to go back and start worrying about things that web developers were worried about five, ten, 15 years ago. I guess there weren't too many web developers 15 years ago. Or were there, I'm old. So the first thing we did, and the first thing I suggest you do, if you have any sort of database performance issues at all, just use a real damn computer, please. If you're on anything called Rackspace or EC2 or Linode and your database is slow, put it on a real computer. And it's just awesome, right? You'll probably get an order of magnitude performance. And if possible, put it on a computer with a ton of hard drives, right? Put your operating system on a separate hard drive, put your logs on a separate hard drive, and put your actual database data on a SCSI array. And that will give you awesome performance. And the reason that you want to do this is because, well, most VPSs have horrible disk IO. And disk IO is what databases eat, it's what they need to be fast. So that's the first thing, that's your first and easiest big one, is just throw some money at the problem by a computer. The second thing that we need to do is we need to understand our queries better, and I can put this on a slide because I'm from Arkansas, so it's not offensive. I haven't broken out my good old boy on y'all yet. So everybody knows what explain is, right?  It gives you back a query plan that looks about the same as the other one. But we're only going to be worried about one aspect of this gobbledygook. We're just going to look at rows. The number of rows in this case is how many rows does Postgres expect to have to chew through to give you the answer that you're wanting? And about rows, there's only one rule, right? More rows, more problems. Now let's go back to that original count query that we did that took forever. Why did that take forever? Well, it turns out when you explain it, it's actually, well, when you ask Postgres to count the number of rows in a table, it actually counts them one by one by one. Which it seems like there'd be a better way to do that, but I don't know. You wind up with that. When you do a pagination query, you wind up with a similar problem. If you happen to have a really high offset, an offset of, say, 500,000, Postgres counts up to 500,000, and then it counts up 100 more. Now, the best solution to this sort of problem is to make it so that your users cannot page through 100 or 500,000 records of data, like that would be the best solution. But if that doesn't work, there's sort of a little hack you can use, which is to use a range query, which can use the index, and which is actually pretty fast. So here's a similar, it's not the same query, but here's a similar thing you might do. And you can see it's only touching 100 rows instead of 500,000, 100. Sorting, I'm just gonna wave my hands around sorting, cuz it's a little bit complicated. If you would have asked me a couple of years ago, man, I was so naive about sorting. I just thought that I just had to put an index in my migration file, and everything would be good. Everything would be good as long as I put that migration in there, it'd be fast. But yeah, no, it doesn't work that way. Sometimes, if you happen to hit on exactly, if the star is a line, Postgres might be able to use the index for sorting. But most of the time, it's gonna actually be faster to load all that data into memory and do like a quick sort on it, which is kind of crazy when you think about it. But yeah, so be careful about sorting.  Really get in there and really understand what your queries are doing. And at this point, I think you guys deserve a cookie. So those are the big wins, right? And nothing could ever go wrong with this, as I'm sure, yeah, nothing could ever go wrong. So I know that does have anything to do with the talk, I just liked it so much, I had to put it up there. Okay, so I'm gonna run through some of the common problems that you find when you have these sort of big data sets, right? First, slow cache misses. Well, as you may know, your database has its own internal cache. And if you keep accessing the same data all the time, well, it's gonna load that into its internal cache, and it's going to be really fast to access that data, which is great until a user logs into your site who hasn't logged in in a couple months. And it takes them five seconds to load the page where it takes your frequent user a second or whatever. And so the solution to this, well, the main solution is to get a lot of RAM. But then you also have to configure Postgres to be able to use that RAM. Out of the box, the Postgres configuration is meant for the really the lowest common in the denominator. It's meant for those 64 megabytes of RAM Linux boxes that used to be able to buy like 10 years ago. So a simple solution to this is to use a tool like PGTune, which inspects your server and spits out a decent configuration file that you can use as a jumping off point. Also, whenever you have a cache miss, what happens is a database has to go to the disk and it has to pull that information off the disk. So disk.io is really important here. The easiest way to get high disk.io is to get one of those high performance like rate arrays and like spend 100 grand on a server. But if you want a much, much smaller performance boost, that's free. There's this interesting little configuration parameter on most Linux, I think all Linux systems, it's called the readahead cache.  I'm gonna go ahead and load those into memory so that I can serve them from RAM instead of serving them from the disk, which is a great idea. But normally, Linux ships with this number set super low, like 32K or something, like a ridiculous number. However, you can increase that to two megs, four megs, whatever your system can handle. And a lot of people say that they get a big performance boost on this, especially on reads. Next problem is slow vacuums. If you have a database server that's under a ton of load, you may log in, you may run the process command, and you may see that there's all these Postgres processes that save vacuum next to them. And you think to yourself, well, those aren't my user's queries, that's not actually doing anything for me. So a common mistake that people make is to sort of decrease the amount of vacuuming that Postgres does because you think, okay, well, this is like a maintenance thing, I can maybe turn off auto vacuum and do it once a night at midnight, or maybe I can only do it once an hour. But the problem with that is that vacuuming is essentially garbage collection for Postgres. So if you turn it off, you wind up with Postgres consuming all of these resources and never sort of freeing them back into its own pool so it can use them again. And so your performance will just go down. So actually, if you find yourself with a vacuuming problem, you need to vacuum more. And that's true for both your house and for Postgres. Also, when you're looking at your processes, you may notice that you have a ton of database connections happening, or you have a ton of Postgres processes. And the reason that you have a ton of Postgres processes is because, well, for each database connection you make, Postgres does a new process. That's not something you typically have to think about that much for a normal web application, like a small to medium sized web application, because, for example, like ActiveRecord has connection pooling that sort of takes care of this in the background. Make sure that you don't have to manage these connections manually. However, if you wind up running a lot of jobs, for example, in job queues, if you have a very distributed architecture where you have, say, 20 different servers running unicorns for whatever reason, or if you have 20 different servers running different jobs, and they all connect to the database, you can wind up racking up a thousand database connections, it's not that difficult. And that's bad, because each of these database connections is a process, and that takes overhead, and that slows down your database in general. So, as mentioned, you can either use these, you can use an application layer connection pool, or you can use a tool like PG Bouncer, which is actually a proxy that sits between Postgres and your app. And so, PG Bouncer maintains, say, 50 connections to the database, and then your app and all of its components may have like a thousand connections to PG Bouncer. So that's one thing. Well, and if you have so many incoming connections, if you have so many jobs happening, you probably have a lot of inserts and updates and all that stuff happening to your database. Well, this gives you locking problems, or it can give you locking problems. One common example that I've actually run into is it's really normal for us to have, say, an active record, you have a parent class, a parent model, and a child model, where the parent has many children. And every time you add a child or delete a child, it updates a countercash on the parent model, right? And that all works pretty well until you have somebody updating or adding like 10,000 children to the same parent within the course of a second or two. And so what happens there is that first update that gets through, it goes in and locks that row in the database so that nothing else can modify it. It updates the cache, it releases a lock, and it's good to go. The next query comes through. And that probably works for maybe a couple hundred queries. But by the time it hits a couple hundred queries, that 10,000th query has already timed out. Either your application server is timed out, or your workers have timed out, or your connection have timed out. Yeah, I meant to hide this slide. But so imagine you have, it's really common to have the situation where you have all this data in your database and you want to be able to run these complicated reports on it. The problem with that is that that can sometimes adversely affect your application performance. Like these reports are super intensive database queries, but you don't want them to affect your real-time application. And in that case, it can be really useful to have just a read-only replicant that you only use to run those reports on. And then you cache the values of those reports. Now finally, and not finally, there's one more slide. But unless you wind up with some sort of heavily sharded architecture or some sort of distributed system, you eventually need to start taking data out of your database, right? You need to either delete it or move it into some sort of archival system. But as we've shown already, those delete queries are murder. They take forever. And for this, Postgres has a really nice set of features around auto-partitioning. If you haven't seen it, auto-partitioning is, it essentially lets you define a parent table and multiple child tables. And they all have the same schema. And what happens is your Rails application only talks to the parent table. It only knows about the parent table. But when you insert a record, Postgres then looks at that record and based on rules that you've specified, it stores that record in a child table. Then when you go to query the parent table, it can pull it from the child table. And so this is used really commonly, for example, when you want to expire something by date. So I can say that all errors that come in for today go into a table that is specific to today. And the same thing for yesterday and the day before. And so when I want to delete errors that are 180 days old, I just go back and drop those child tables that are 180 days old. And you can use this for a number of really interesting things. You can partition by account ID, all sorts of cool stuff. And finally, really finally, backups. When you're dealing with a big data set like this, you really need to investigate a streaming backup system. Because that whole dump the entire database at midnight and upload it to S3 just doesn't work anymore, right? Unfortunately, Postgres has this nice feature called, well, it uses these things called wall files. It uses them as part of it to sort of prevent disasters and also to aid in its replication. But this allows you to do a nice sort of streaming backup where you actually have a backup of your database every, say, 20 minutes that's sent to Postgres, or sent to S3. Okay, so I've just been talking at a million miles a minute. And that's a lot of stuff to take in. But I just want to point out that you guys can totally do this. That me and my team, we are normal Rails developers. We built this thing, it had to scale. And we sort of figured out how to make it work. And you guys can do that too. So yeah, this is my favorite guy. This is a Mexican soccer coach from the World Cup. This is the best thing about the World Cup this year. Anyway, if you want to see this slide deck and also some of the links that were in there, I'll be tweeting that out. If you want to know about your errors, use Honey Badger. And I'm done, so.