DlcDevKit - Progress Report #1
What I have been building for the first three months of my OpenSats grant for dlcdevkit.
Project Updates
I spent a lot of time contributing and maintaining supporting libraries on top of improving the DlcDevKit
code base. As well, I was fortunate to speak and showcase ddk
at TabConf and Adopting Bitcoin. At TabConf I was on a panel talking about DLCs. I did a short presentation on ddk
and then we fielded questions from the audience about DLCs. Most of the questions directed to me were about DLCs with covenants and as well a question about novation. In El Salvador at Adopting Bitcoin I created a sample application for participants to follow along. I was able to create a desktop application that ran ddk
with memory transport, memory storage, and a local oracle with kormir
.
My TabConf presentation can be found here. I used presenterm which creates powerpoint slides from a markdown document. The repo for my Adopting Bitcoin presentation can be found here. If you have an apple silicon Mac you should be able to download the installer on the release page.
I wrote a blog that goes over the dlcdevkit
API.
Usage and Interest
Attending conferences and hackathons has been huge for exposure to developers and companies. The TabConf hackathon saw two projects use dlcdevkit
to quickly prototype with DLCs. Users were excited to use DLCs after they found my project after trying to implement the rust-dlc components and not focusing on their hackathon project.
I was approached by a company that wants to implement a sports betting application using DLCs and nostr transport. Part of their requirements is to build a mobile application. Although it can be created with tauri today, building the wasm or language bindings is required for their use case which is in the scope of my grant.
While in Adopting Bitcoin I met the teams at Braid Pool and Rad Pool. Both mining pools have an interest in creating hashrate markets and are exploring DLCs. Braid Pool's document defining their hashrate derivatives is defined here in their documentation. Rad Pool's documentation for DLCs can be found here. I will be working with them to spec out the DLC payment mechanism for their respective pool and including ddk
to their repositories.
dlcdevkit
Development Docs - I added a lot of documentation on how to spin up a development environment for contributors
Nostr Oracle Marketplace - Added as a feature to ddk
, developers can add a listener for oracle announcements. This follows the Nostr DLC spec (NIP-88). When a connected oracle publishes an announcement (or attestation), the marketplace listener consumes the announcement and stores it in the ddk::Storage
implemented. When an offerer goes to create an announcement they will be presented with the known oracle announcements to use. As well, if they are offered they can check if they have seen the announcement with the marketplace listener is on. The marketplace is implemented in ddk-node
.
Nostr transport - On top of the marketplace a transport module for nostr was built for sending and receiving DLC messages. This follows the NIP-88 spec as well. The listener is implemented but there still remains work for the segmenting of messages similar to the BOLT-8 segmentation in rust-dlc. Nostr relays have a capped note size which is smaller than some DLC messages. Nostr transport is essential for mobile clients and preospective applications such as the sports betting application.
Featurizing the things - All of the modules for storage, transport, and oracle clients are behind features. This helps with compilation for wasm/language bindings. This also gives consumers more control of which components they want to use or opt to build themselves.
Actor Model - Working with DLC messages is compute intensive, especially when signing adaptor signatures. The DLC manager utilizes an actor model to avoid locking of the manager. Messages are passed to the manager by mpsc channels. This creates a queue of processing so that the manager can handle multiple messages without locking.
Async Manager - One of the first considerations of ddk
was making the manager async instead of blocking in rust-dlc
. This decision was made because the runtimes that are going to consume ddk
are typically going to be in a tokio runtime (REST server and gRPC servers for example). I made the decision to fork the dlc-manger
to ddk-manager
in the ddk
workspace. This allows me to maintain an async manager while still utilizing, and maintaining, the dlc
, dlc-trie
, and dlc-messages
crates. A huge benefit of maintaining my own fork of the manager is that I am able to test against the ddk
structs for the wallet and storage. I am able to use the 50 tests that are used within the manager crate. I added these test to the ddk
CI and can be found here
Mocked Traits for Testing - Implemented memory structs that implement the ddk
traits for rapid testing. I am able to perform integration tests on the entire DlcDevKit
struct. As well it allows me to test specific contract payouts. Enumeration & Options
Other small changes that are not large enough to note.
ddk-payouts
Options - Inspired from conversations with Matt Black from Atomic Finance, I added the ability to create and offer options contracts. Users can create short and long options contracts. The API, users input a strike price, total collateral, direction, and option type and it generates PayoutFunctionPieces
to be used for creating contract input when offering a contract. Options contracts are in production today so it was a great first contract to make available. Although, I am not focused on specifically options contract because of the capital inefficiency and collateral requirements. I am more interested in building hashrate derivatives that is aligned with Braid Pool and Rad Pool. Nonetheless, it is not my decision what users build with dlcdevkit and it is a nicety off the shelf.
rust-dlc
The fork was a decision based on conversations in the async PRs DLC async macro and alternative on rust-dlc
. I spent a lot of time on these PRs so that they are compatible on both blocking and async. The decision came down to my requirement of async which was blocking releases for ddk
because of a git branch patch that was required. The maintainer of library voiced disinterest in the PR because it was not the direction that he wanted the crate to go. Looking back, I spent too many hours on this PR and wish I had done it sooner. But I did get to write my first proc macro which was a great learning lesson!
Update to Bitcoin 32 - In order to use BDK 1.0, as well to keep up to date, I upgraded to bitcoin 32.
Oracle Attestation Validation - The Oracle Attestation struct was not following spec by including the event id, as well it did not validate the attestation. A bug in kormir would have been found immediately if this was in the code.
Use bitcoin::Amount
- Other bitcoin crates with an upgrade to bitcoin:0.32
include a refactor of using bitcoin::Amount
. This keeps rust-dlc
aligned with other repositories. There is as well a though to refactor fee rates, weights, and lock times.
Other small changes as well that are not large enough to note.
kormir
Until benthecarman came through, there was not a readily available oracle implementation in rust. There is a p2pderivatives oracle but it does not give the ability to manually sign events. Kormir allows users to create their own oracle implementation and includes a server as well in the repo. After TabConf and a few PRs made by myself, Carman gave me the repository ownership for kormir.
Update to bitcoin 32 - Same story as with rust-dlc
Routes for retrieving oracle messages - Added routes to easily retrieve oracle announcements and attestations.
Event Id as primary key - There was an odd design decision that makes the key for retrieving messages by a different primary key than the event id. Since the event id should be unique by default it made it awkward for retrieving information from the oracle. As well, clients would have to store extra information specifically for kormir oracles that locks users in to kormir based oracles.
Other small changes as well that are not large enough to note.
Hosting
I am also hosting services for people to use in development as well as defaults for ddk-node
.
https://kormir.dlcdevkit.com - Hosted kormir-server
https://nostr.dlcdevkit.com - Hosted nostr relay to test the marketplace and DLC messages over nostr
https://payouts.dlcdevkit.com - Graphical interface to visualize different DLC contracts
Plans for Next Quarter
I will be testing the nostr transport including building the segmentation so that nostr dlc messages can be sent.
Building the payout structures and implementing hashrate derivatives that are defined by Braid Pool and Rad Pool. The goal is to have a detailed explanation of dlcdevkit
inclusion in the pool's code base.
There is an excellent paper by James Pierog that creates miner variance reduction through the use of DLCs. I am going to implement those contracts and make them available through dlcdevkit
.
Most of my discussions with engineers turns into a conversation about covenants with DLCs. There is great opportunity for novation with DLCs. I understand the hesitancy for covenants research with DLCs. One thing not to be ignored is that rust-dlc
still uses ECDSA adaptor signatures and SegWit. I want to work on taproot DLCs with schnorr signatures as part of rust-dlc
. It is included in the dlc specification under "TBD". As well, to even include covenant DLCs you must have taproot.
Specification for use of V3 transactions in the DLC spec. I have had preliminary conversations with Matt Black about specifying handling of V3 transactions. V3 Package relay included in bitcoin:28 is huge for protocols like DLCs. Because these contracts can be months or years in advance, guessing a fee at contract creation can be a foot gun in the future. By having V3 transactions standardized in rust-dlc
we can have the execution of CETs in the future be much easier to reason about.
Thanks, OpenSats!