Creating a successful business case based on Bitcoin is not easy. Oftentimes the structures a blockchain could replace are so ingrained they are hard to make out. Once a potential problem area has been defined, a cost effective solution is needed. I believe this is where the field shows its age, or lack thereof. There is much software out there which has been written by enthusiasts in a frenzy. Crucial parts are missing or the quality isn’t there yet. I believe it is in this stage that you can make a meaningful impact; creating quality software for the blockchain revolution.
We’ve created several quality libraries to further the field:
- pylibbitcoin: Python library for libbitcoin.
- bitcoin_bip32: Dart library for Hierarchical Deterministic (HD) keys.
- bitcoin_bip44: Dart library for HD wallets.
- btcpay_client: Dart library for BTCPay.
- bech32: Dart library for BIP173 SegWit addresses.
Making these libraries impressed some important lessons upon us.
It starts and ends with documentation. When creating these libraries it becomes crystal clear that documentation greatly facilitates the speed of development. A good example is set by the various BIPs. Not only do they describe in detail the proposed software, they also provide a rationale why the proposal has merit. This allows the implementer to place his work in context, furthering understanding of what he’s creating.
A special mention should go to the Test Vectors. BIP32 is a great example. Working with hashes is jarring for the average person. Seemingly random sequences of characters are not easy to interpret. This makes it hard for the implementer to verify if his code works as intended. The test vectors in the specification provide a concrete target to test against. For the users of a library, having these in the test suite should instill confidence the software adheres to the specification.
Having great documentation works both ways. Users of the library are facilitated by a good README. Preferably with examples. Dart goes the extra mile here. When publishing a Dart package to the central repository, the library is scored. Having a runnable example gets you bonus points. Tests also serve as documentation, documentation which never grows stale!
Other implementations may be an inspiration. There was already an unmaintained Python library interfacing with libbitcoin. This library used a different paradigm than the new library, but it was invaluable to read the source of the library. Naming of certain concepts can be inspirational, or pitfalls can be identified. BIP32 has a Go implementation which struggles with the same issues we came across when implementing the standard. Eventually the source of yet an other implementation helped to settle on a final implementation. In more than one way we stand on the shoulders of giants.
The devil is in the details
Seemingly easy tasks might end up costing serious effort. The BIP44 almost casually mentions ‘account scanning’. In short, the library returns the first unused address when requested. This, however, means scanning the blockchain for previous addresses, which is easier said than done. A fully synced Bitcoin Core node knows this, but lacks the API to expose it. Several online block explorers could tell you this, but either lack a public API or have strict rate limits. A good open source block explorer didn’t exist at the time of writing. Luckily Esplora was released since!
Implementing the SegWit P2WSH format also proved trickier than expected. With some help, the fix proved easy but a small part of the spec cost a lot of effort.
Don’t skimp on the parts where your library is not complete either! The account scanning of BIP44 is not implemented in any of the libraries we’ve read leading us to believe BIP44 would be straightforward. A simple TODO list sets the expectations right.
At the end of the day, good software makes it possible to effectively reap the many benefits of blockchain technology.
We are guns for hire! Contact us at firstname.lastname@example.org if you want any blockchain related custom development or support.