13 ms·
Show HN: Mako – a full Bitcoin implementation in C
- zackham 5y agoThis looks like a herculean effort over just the past few months. Congratulations on hitting this milestone and hopefully you can take a breather and tie up loose ends at a more comfortable pace. As much as HN has changed over the years I still think this is a place where there are a lot of people who can appreciate how you feel right now. Nicely done!
- chjj 5y agoThanks. This was definitely the hardest project I've worked on in my life. I fear I may have shaved a few years off my life with all of the all-nighters I pulled with this, so it's good to hear recognition for the work. :)
- b20000 5y agocongrats on your hard work. why did you choose C89 instead of writing this in C++11 or 17? just curious, no criticism.
- spuz 5y agoVery impressive work. Was there a deadline that you were trying to meet? What was the reason for the all-nighters?
- chjj 5y agoNo deadline. I just have a tendency towards obsession when I'm working on a project I'm very interested in. I tend to get into a kind of manic phase where I can't sleep even if I wanted to. There's no real telling when that phase will end. So I end up coding for an unhealthy amount of time. I don't recommend it to anyone.
- HappySweeney 5y agoI have the same thing, self-diagnosed as monomania. I had to train myself to stop thinking about my obsession when not at it, and the condition eventually subsided enough that it doesn't completely screw up my life anymore. nb: looking it up on wikipedia, it seems that monomania was a 19th century psychiatric diagnosis, and is no longer considered a real condition.
- johnnyApplePRNG 5y agoWhen you really love working on something, sometimes you just can't sleep. It's the most productive you can ever be imho.
- bertr4nd 5y agoTruly an amazing output! Did you really do all this in 2.5 months? Seems I need to dramatically up my coding game!
- debo_ 5y agoAgreed! I'm confused by the number of comments that suggest this was a waste of time because other potentially similar implementations exist. There could be a hundred of these and I'd still be interested in looking at them.
- 0des 5y agoDisregard those comments. There will always be critics wondering why you don't just use floppies taped to a carrier pigeon instead of email. We are nerds.
- anonporridge 5y agoWhen I was young, I was taught that Benjamin Franklin taught himself to write well by reading a work, and then trying to rewrite it from memory. I imagine a similar principle is in play here. There's value in rewriting what already exists and works, even if it will only ever be useful to yourself.
- nynx 5y agoThis is very impressive, but I’ll be honest, I wouldn’t want to expose any new software written in C to the internet.
- __vim__ 5y agoI feel this comment is misguided. Plenty of new code is written in C, particularly in the scientific computing space. If the code in question doesnt do lots memory management and expects the user to provide a memory block to be populated with values, then I see no issues. C code tends to be faster than other implementations even without optimizations. Moreover, lots of interpreted languages have good interoperability with C so a C compiled code can be called in many languages using simple high level interfaces.
- 0xFFFFFFFFF 5y agoCan I ask you why? I mean, I know about memory safety and stuff, but it is that bad?
- roca 5y agoYes it is.
- deleted 5y ago[deleted]
- pizza234 5y agoIndependent researches (Microsoft/Mozilla) showed that around 70% of security vulnerabilities are caused by memory safety bugs. That's one heck of a "memory safety and stuff" :) Here's one reference: https://msrc-blog.microsoft.com/2019/07/18/we-need-a-safer-systems-programming-language/ https://msrc-blog.microsoft.com/2019/07/18/we-need-a-safer-s...
- postalrat 5y ago"memory safety bugs" sounds pretty broad. What sort of vulnerability doesn't involve memory access?
- ejanus 5y agoGreat job. I would take a look.
- tmaly 5y agoThis looks super interesting. One thing that kinda bothers me is that most of the tests are just #include <stdint.h> #include <stdlib.h> #include <string.h> #include "lib/tests.h" int main(void) { return 0; }
- chjj 5y agoYeah, I'm embarrassed about that. It's way behind on tests. The past 2 months of limited sleep were a massive scramble just trying to get everything implemented and trying to get the damn thing to sync properly. Things seem to work in practice, but it's very scary not having high test coverage, especially with a project like this. Now that everything has solidified and my sleep schedule has normalized a bit, it's my intention to take the time to write proper tests.
- brighton36 5y agoDid you learn that 'the implementation is the spec' ? (Does that mean Bitcoin is fiat?)
- beebmam 5y agoSome of this C code looks extremely obfuscated. Not a fan.
- chjj 5y agoDo you mind elaborating? I obsess over clean code, so any criticism is appreciated.
- arcticbull 5y agoIt looks super clean to me, the only exception being for the love of all that's good and holy always brace your one-line if statements and loops. You don't want your own "goto fail" do you? ;) [1] I think you did a great job. [1] https://nakedsecurity.sophos.com/2014/02/24/anatomy-of-a-goto-fail-apples-ssl-bug-explained-plus-an-unofficial-patch/ https://nakedsecurity.sophos.com/2014/02/24/anatomy-of-a-got...
- chjj 5y ago> It looks super clean to me, the only exception being for the love of all that's good and holy always brace your one-line if statements and loops. > You don't want your own "goto fail" do you? ;) [1] Ah, that was my style 7+ years ago. Then I started regularly contributing to an open source project which did not add curly braces on one-liners. I wanted to match the style of the project despite it feeling unnatural to me. Within a few weeks, my style was changed forever (for better or for worse). > I think you did a great job. Thank you.
- kazinator 5y agoWon't necessarily work: if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0) { goto fail; } { goto fail; /* MISTAKE! THIS BLOCK SHOULD NOT BE HERE */ } Copy and paste bugs can play out in any number of ways. Newer GCC will catch the goto fail by noting that the indentation is wrong. $ gcc-11 -Wall gotofail.c gotofail.c: In function ‘main’: gotofail.c:5:3: warning: this ‘if’ clause does not guard... [-Wmisleading-indentation] 5 | if (argc > 42) | ^~ gotofail.c:7:5: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘if’ 7 | goto fail; | ^~~~ $ cat gotofail.c #include <stdlib.h> int main(int argc, char **argv) { if (argc > 42) goto fail; goto fail; return 0; fail: return EXIT_FAILURE; } Of course, it could be that the indentation is not wrong. If somneone runs the code through some automatic formatting, the problem will not then be diagnosable that way. Sadly, if I fix the indentation then: $ gcc-11 -Wall -Wunreachable-code -O3 gotofail.c $ # silence even though the return 0; is not reachable. Still, I think I'm going to stick with "brace the else part if the then part is braced, and vice versa*.
- deleted 5y ago[deleted]
- jazzyjackson 5y agoI’m loving the well commented and standalone inplementations of crypto-primatives, will definitely be studying these. One question, in src/crypto/rand.c:25 you have a standalone RNG but comments say it is not used internally? what is it used for?
- chjj 5y agoMost of the crypto is from my more general crypto library libtorsion: https://github.com/bcoin-org/libtorsion https://github.com/bcoin-org/libtorsion I originally wanted to vendor my libtorsion code and link to it, but it felt clunky since libtorsion pulls in a ton of crypto that bitcoin doesn't need. Also, since I was focusing on just a few algorithms, it gave me the opportunity to optimize a lot of them (in particular, the ECC backend was optimized for secp256k1 whereas in libtorsion it supports all kinds of curves). Because of all of this, there's probably some leftover comments. That comment isn't true anymore. rand.c is definitely used internally for libmako, just not libtorsion. edit: fixed link.
- sizzzzlerz 5y agoCloned and built on my Mac without any issues. Everything compiled and linked without warnings. A huge plus in my opinion. Other than stating that it builds two executables, there doesn't seem to be any documentation on using it. Did I miss it?
- chjj 5y agoStill experimental and documentation is lacking, but right now the CLI behavior is almost identical to `bitcoind` and `bitcoin-cli`. So, for example, `$ makod -datadir=foobar -chain=testnet` will create a data directory in `./foobar` and start syncing testnet. `$ mako getblock 100 2 -chain=testnet` will return block #100 to you serialized as json. In other words, it's something akin to this: https://man.archlinux.org/man/bitcoind.1 https://man.archlinux.org/man/bitcoind.1 https://man.archlinux.org/man/community/bitcoin-cli/bitcoin-cli.1.en https://man.archlinux.org/man/community/bitcoin-cli/bitcoin-... Please let me know how things go on Apple. I have yet to test it on a Mac. It's possible Mac has some issues since the event loop backend is using poll(2). Apple has been known to break poll every now and then.
- inter_netuser 5y agoHow did you write this so fast? did you leverage anything from core or other impls at all, or entirely from scratch?
- jlrubin 5y agonicely done jj!
- cfferry 5y agoThis look cool! great job, congrats. What are you using as data storage? I understand btcd uses leveldb, are you using something similar?
- chjj 5y agoI considered using leveldb initially, but that would require a C++ compiler and it also requires linking to libstdc++. So at that point, you might as well just write the project in C++, which defeats the point of this project. Mako uses LMDB. Aside from Berkeley DB, it's pretty much the only key-value store in town if you want a pure C project. In the end, it worked out well because I really like LMDB. It has a very intuitive API, and it's very small, which sort of matches the spirit of this project. The zero-copy on reads feature is also amazing. When reading a UTXO from the database, we do no copying and no allocation whatsoever. The UTXO is simply parsed from the pointer LMDB returns. This is something LevelDB cannot do at all.
- avar 5y agoThere's always SQLite, which can also be used as a key-value store.
- VHRanger 5y agoAnd is similarly pure c, self contained
- cfferry 5y agoI am really impressed with your work! If you ever need or look for C++ collabs, let me know! Also, consider opening a discord server to talk more about this project!
- potiuper 5y agoNot to belittle the work, but it is always prudent to research what the other implementations are before possibly doing duplicate work and providing that comparison along with the new work for justification of it. For example, https://en.bitcoin.it/wiki/Software#C https://en.bitcoin.it/wiki/Software#C shows picocoin (libccoin), which Github also lists as being C. What makes this or what is desired to for this to be different from the alternative(s)? It certainly seems a non-trivial matter to have completely reimplemented the necessary GNU Multiple Precision Arithmetic Library or similar dependencies such as specific compiler extensions.
- auggierose 5y agoIt's not a paper, and no academic who is not interested in it anyway is going to make stupid comments about related work. No need to justify making what you wanted to make. Well done.
- vmception 5y agoThe point wasn’t for this to be desired by anyone It is just a show and tell And now we also have a new client on the network!
- chjj 5y agoRight. Perhaps I should explain this in the readme. To be clear: Libbtc is a small bitcoin library meant for everyday things: signing transactions, maintaining an SPV wallet, etc. It's good at what it does, but you wouldn't be able to actually sync and validate an entire blockchain with it. I suppose picocoin is the most similar to mako, but I think it falls short of being a "full node" in that it doesn't provide a mempool, miner, or RPC (from what I can tell). I'm also not clear on how it is storing UTXOs. It looks incomplete right now, but maybe jgarzik could give more insight on that. Mako is a _full_ reimplementation of bitcoin. It's an alternative to bitcoin core.
- traceddd 5y agoIn my opinion, given the application is cryptocurrency, reimplementations are pretty valuable. It’s important to avoid systemic failure due to a large percentage of nodes having the same exploit or bug. A fully featured reimplementation like this is really great for Bitcoin!
- yardstick 5y agoAnything interesting on your choice of project name?
- chjj 5y agoIts placeholder name was originally "libsatoshi", but I was worried that would cause confusion between this project and bitcoin core. I spent the past few days thinking of names. Mako came to mind because I had recently been playing through the original FF7 (maybe the first time in ~10 years). It's short, memorable, looks cool. It checked all the boxes. On top of that, pretty much every name involving the words "btc", "coin", etc. is already taken when it comes to bitcoin projects. That said, apparently there is a wayland notifier also named "mako", so I may have to think up a different name here. =/
- janzer 5y agoMako is also a fairly popular python template library. https://www.makotemplates.org/ https://www.makotemplates.org/
- debo_ 5y agoMako was the thing that Shinra almost destroyed the planet trying to extract, so you may end up opening the project up to a lot of Barret+Bitcoin memes. That could be a win!
- chjj 5y agoNot to get in a pedantic FF7 debate, but I don't believe Mako was destroying the planet: Shinra's Mako reactors were destroying the planet. Mako energy was a tool, and it could be used for good or evil, just like cryptocurrency. In the case of bitcoin, I believe it is being used for good.
- debo_ 5y agoI don't mind pedantic FF7 debates! I think Mako was Shinra's branding on the energy they obtained by mining the Lifestream via the Mako reactors; I don't think it was some natural force. Edit: Hmmm. "Mako (Japanese: 魔晄, Makō; literally meaning "magic light") is a liquid substance featured throughout Final Fantasy VII. It is the condensed form of lifestream and the primary source of energy used by human beings throughout the world. It is comparable to nuclear energy. Lifestream can condense into Mako via both natural and artificial processes. The terms "Mako" and "Lifestream" are often used interchangeably because one is a derivative of the other." From here: https://finalfantasywiki.com/wiki/Mako https://finalfantasywiki.com/wiki/Mako
- noxer 5y agoCan't help but shake my head over this incredibly impressive waste of time.
- isitdopamine 5y agoHacker news values intellectual curiosity, so why dismissing something so interesting as a waste of time? Moreover, the code is beautifully written, the project is useful and the rules of HN ask you not to dismiss project just the way you did.
- noxer 5y agoI said its "incredibly impressive" in case you missed that. Other than that my post represent only my opinion and my opinion is that the result of this project is not worth its time. Feel free to have another opinion but dont tell me I dismissed something when I did not. You did with my opinion for no reason. Have your own opinion, express your disagreement, do whatever but dont dismiss mine and come around with some BS rules I didn't break.
- isitdopamine 5y agoYou have the right to your opinion. You do not have the right to express it here, since it goes against the rule of this website. I suggest you read them very carefully!
- noxer 5y agoIf you think so, report it to the HN authority and they remove it. Good luck.
- isitdopamine 5y agoTo be honest I don't care that much, I would find much more useful that you understood the rules of a community you are taking part of.
- amelius 5y agoWhat is the official reference implementation written in? (I hope a purely functional language like Haskell.)
- Kranar 5y agoC++ https://github.com/bitcoin/bitcoin https://github.com/bitcoin/bitcoin
- fabianfabian 5y agoThere is no official implementation but http://github.com/bitcoin/bitcoin http://github.com/bitcoin/bitcoin is most widely used to achieve consensus
- deleted 5y ago[deleted]
- atarian 5y agocan something like this actually participate in the real bitcoin network or does everyone have to run the same client?
- rasengan 5y agoBitcoin is a protocol much in the same way HTTP is - so just like there are multiple implementations of web browsers, there are also multiple bitcoin implementations. This is the first in C.
- SavantIdiot 5y agoCool to study. Disappointed there are zero comments and the most terse variable names as possible. Almost like it was js-minified.
- chjj 5y agoSome of the terse variable names are the result of my adherence to a GMP-like naming convention, which I find easy to read and aesthetically pleasing. The GMP naming convention is something like: - Pointer/Data - single letter followed by a "p" - Size/Length - single letter followed by an "n" So a function declaration might look like: static void process_bytes(uint8_t *zp, const uint8_t *xp, size_t xn); The above function would do some processing on `xn` bytes at `xp` and store the result in `zp` (assuming there are `xn` bytes also allocated here). A function which accepts more inputs might have `yp` and `yn` also, so conceptually: `zp = func(xp, xn, yp, yn);` or to simplify: `z = func(x, y)`.
- optymizer 5y agoWhich code is clearer? void f(int c) { l.c = c; ... } or void setColor(int color) { label.color = color; ... } Names are more important than matching data types and sizes because they convey intent and meaning better than types.
- matvore 5y agoI just did this grep for single-character function names on the Mako codebase: grep -r '\<[a-z](' . And there were no matches. There were some one-character macros but they were macros repeated dozens of times in a localized area. It seems like what's being proposed is descriptive function names with simple variable names. If the function bodies are short enough (e.g. fit on a single screen) then this seems like a good trade-off to me. IOW, the variable names are symbolic but the function names are descriptive. The short variable names should be clear enough if you understand the purpose of the function.
- 5y ago
- andrewqu 5y agoGreat work! Curious what you used as a reference when writing ?
- chjj 5y agoMy first bitcoin reimplementation was written in node.js and called bcoin[1]. So this is my second time reimplementing the bitcoin protocol, albeit in a very different language. Bcoin was frequently used as a reference along with bitcoin core v0.8.0-v0.11.0 when I felt like double checking consensus functions (among other things). As an aside, I personally think bitcoin core v0.8.0 is the best version of core if you want to learn bitcoin from it. It's a lot more straightforward than later versions. I personally don't enjoy reading any version beyond v0.11.0. This is also the reason mako doesn't support taproot yet. That code is very new and isn't present in upstream bcoin. I could try to implement it from the BIPs alone, but I won't know what intricacies are present in the actual bitcoin core code until I actually read it. [1] https://github.com/bcoin-org/bcoin https://github.com/bcoin-org/bcoin
- AlexanderTheGr8 5y agoWhen you say "reading bitcoin core v0.8.0", do you mean reading the source code? I want to learn more about the fundamentals (technical part) of bitcoin, but am not sure if diving into the 600k+ lines of src code is worth it. Do you know any way to understand bitcoin (or cryptocurrencies in general)?
- timobile 5y agoI highly recommend the books "Mastering Bitcoin" by Andreas Antonopoulos (technical, for beginners) and "Programming Bitcoin" by Jimmy Song (very technical, advanced).
- cantrevealname 5y agoCall me old school, but I like looking at the number of lines of code to get a feel for how big of a project something is. Mako[1] is 265,618 lines of code. The most widely accepted Bitcoin implementation[2] is 639,074 lines of code -- that's 2.5x bigger and written in a slew of languages. Mako looks like a super-impressive amount of work (and by a single person no less). [1] https://github.com/chjj/mako https://github.com/chjj/mako [2] https://github.com/bitcoin/bitcoin https://github.com/bitcoin/bitcoin [3] How I calculated: find <source-directory> -type f | sed 's/.*/"&"/' | xargs wc -l EDIT: Also of interest is this "from-scratch tour of Bitcoin in Python" that was discussed here on HN a few months ago: https://news.ycombinator.com/item?id=27593772 https://news.ycombinator.com/item?id=27593772
- oars 5y agoThis is a great discussion of how to count code lines of code. Thanks.
- b20000 5y agolast week i got attacked here on HN for suggesting it is not bad to stick to one language and get BETTER over time rather than screwing around with new languages and fads every year. i think this sort of project illustrates what i meant.
- rweichler 5y agoThx for [3]. I usually just do wc -l *.c */*.c */*/*.c */*/*/*.c */*/*/*/*.c */*/*/*/*/*.c */*/*/*/*/*/*.c
- 37ef_ced3 5y agoI've been writing C for two decades. But in recent years I have used Go as a replacement for C whenever possible. I think of Go as an improved C, with slightly different performance characteristics. In your opinion, what is the advantage of writing a program like Mako in C rather than Go?
- thinkmassive 5y agobtcd is an existing implementation in go https://github.com/btcsuite/btcd https://github.com/btcsuite/btcd
- X6S1x6Okd1st 5y ago> Contrary to what some people might tell you, multiple implementations of a protocol are a good thing. In bitcoin's case, they are necessary to mitigate the harm of developer centralization. Important point that I didn't really get until I read more on this topic coming out of Ethereum community
- vegai_ 5y agoOh jeez. What could go wrong?
- gvv 5y agoyes but when moon sir?