Open guggero opened 1 year ago
add another index to the universe tree
https://github.com/benbjohnson/litestream is a critical component
Okay, I thought a lot about backups and also discussed things with @jharveyb and @dstadulis. Thanks for the inputs and ideas, I'll try to incorporate those here.
As I see it, we can attack this in two phases.
As described above, this would involve a single file on disk (and maybe a corresponding RPC that returns the same content on request) that contains all data required to represent the current un-spent asset outputs of the daemon.
The main benefits of using a file based backup are:
The following steps need to be taken to implement this phase:
There are multiple reasons why public universes shouldn't be used to rely on crucial financial data retention and availability. That's why we're introducing the concept of a personal backup universe here. A personal backup universe is just a tapd
operated by the same user/entity, running on a different machine (and availability zone) that acts as a passive data receiver.
The main benefits of using a backup universe compared to a backup file are:
tapd
nodes can use the same backup universe serverThe following steps need to be taken to implement this phase:
--backupuniverse=host:port
)lnd
for the TAP key familytapd
node to be configured in a way to act as a backup universe that doesn't need to be connected to an lnd
node to simplify the setup. For example a --backupuniverseonly
flag that would turn off the requirement of connecting to an lnd
node and would therefore also skip block header verification of proofs (and automatically turn on --universe.public-access
and --allow-public-uni-proof-courier
)The main item that is not covered by the mechanism outlined above is the list of TAP addresses generated by a node. Because we need to know all addresses in order to detect future transfers (meaning transfers that happen after a node was recovered from backup), those addresses should be backed up as well when using a personal backup universe. The following options present themselves at the moment:
https://github.com/lightninglabs/taproot-assets/issues/343#issuecomment-1841375105 elucidated an additional element of necessary data to scope for backup and recovery: the full tapscript tree.
E.g. when a user add scripts to encumber their taproot assets, that data will need to be persisted / backed up to ensure asset access recovery / spendability
Background
As a prerequisite for being able to officially support Bitcoin
mainnet
for taproot assets, we need to carefully think about how we approach the question of backup and recovery oftapd
data, since not only assets might be at stake but also the BTC of the anchoring transaction output (you can't spend the BTC that carries assets without being able to reconstruct the full asset tree).This issue serves as a collection/brainstorm issue around everything related to data safety, backups and recovery procedures.
Documentation
Similar to the
lnd
Operational Safety Guidelines document, we'll want a doc that describes the different data sources, what they are used for and how to best prevent loss thereof. The document should (at least) describe the following key items:script_key
s) andlnd
's wallet/seed?tapd
's database,lnd
's wallet database,lnd
's channel database)?tapd
store its files and which files need to be backed up regularly?tapd
database be set up in a production ready manner?How to prevent database loss
As long as the
tapd
database is fully intact and the seed for thelnd
wallet is known, all funds are SAFU. So to have a replicated (or at least regularly backed up) state of the DB should be the highest priority. We should test and then document the following ways of setting up a database cluster or streaming replication:tapd
in a production environment. We'll want to document some setup recommendations and best practices around this though.How to recover from full database loss
Even though keeping the
tapd
database intact should always be the highest priority, the reality is that users often don't realize that uninstalling and re-installing an app on platforms like Umbrel causes all data to be deleted. So because we want to shiptapd
as part of Lightning Terminal, which is available on such platforms, we need to have a strategy for basic recovery of assets and BTC for the case when the fulltapd
database is lost.Possible approaches:
lnd
for static channel information) around that is updated on every mint, send and receive and keeps track of the latest on-chain output and proof chain, as well as the universe information. The file would basically contain all the information to be able to recover the asset and BTC funds, but not the transaction history. Then mobile and other platform apps would only need to make sure to create an off-device backup of that file whenever it changes.lnd
could be enough to query those multiverses for the information required to recover access to asset and BTC funds. This requires thelnd
wallet database to be fully intact though, as some of this information is added to the wallet DB bytapd
and is not recoverable through a simplelnd
wallet restore from seed.lnd
wallet for unspent p2tr outputs that aren't BIP-0086, then look up the multiverse for assets related to those outpoints (this will only work if the asset anchoring transaction has a change output that goes back to thelnd
wallet, because the actual asset anchoring output will not be recognized as "belonging" to thelnd
wallet). This will work for asset mints and asset change outputs.lnd
wallet for any specifically registered tapscript addresses, then look those outpoints up in the multiverse to recover asset proofs. This will work for assets received through taproot asset addresses (non-interactive receives). Though the tapscript addresses aren't directly derived from the seed, so if thelnd
wallet was recovered from seed, this won't be possible.New universe RPCs required for multiverse proof lookup
To allow some of the multiverse lookups described above, we might need additional indexes into the universe/multiverse tree structure:
assetID => outpoint || scriptKey
outpoint => assetID || scriptKey
andscriptKey => assetID || outpoint