taler-docs

Documentation for GNU Taler components, APIs and protocols
Log | Files | Refs | README | LICENSE

005-wallet-backup-sync.rst (12531B)


      1 XX 05: Wallet Backup and Sync
      2 #############################
      3 
      4 :Design status: Superseded
      5 :Implementation status: Prototype
      6 :DD shepherd: TBD
      7 :Historical contributors: Florian Dold, Torsten Grote, Christian Grothoff
      8 :First published: 2020-04-27
      9 :Last substantive change: 2023-09-15
     10 :Superseded by: :doc:`092-incremental-backup-sync`
     11 
     12 .. warning::
     13 
     14   This document is deprecated and superseded by DD92, which specifies an
     15   incremental backup and multi-device synchronization protocol.
     16   The multi-device sync described in this document would lead
     17   to a bad/unexpected user experience that does not justify the
     18   conceptual / implementation complexity.
     19 
     20   The body below is retained for historical context and is non-normative.
     21 
     22 Summary
     23 =======
     24 
     25 This document discusses considerations for backup and synchronization of wallets.
     26 
     27 
     28 Requirements
     29 ============
     30 
     31 * Backup and sync must not require any synchronous communication between the
     32   wallets
     33 * Wallets operating (payments/withdrawals/...) for longer periods of time without
     34   synchronizing should be handled well
     35 * Conflicts should be resolved automatically in pretty much all cases
     36 * One wallet can be enrolled with multiple sync servers, and a wallet can
     37   join
     38 * Other wallets connected to the sync server are trusted.
     39 
     40 Proposed Solution
     41 =================
     42 
     43 The blob stored on the backup/sync server is a compressed and encrypted JSON file.
     44 
     45 The various entity types managed by the wallet are modeled as LWW-Sets (Last Write
     46 Wins Set CRDT).  Timestamps for inserts/deletes are Lamport timestamps.  Concurrent, conflicting insert/delete
     47 operations are resolved in favor of "delete".
     48 
     49 The managed entities are:
     50 
     51 * set of exchanges with the data from /keys, /wire
     52 * set of directly trusted exchange public keys
     53 * set of trusted auditors for currencies
     54 * set of reserves together with reserve history
     55 * set of accepted bank withdrawal operations
     56 * set of coins together with coin history and blinding secret (both for normal withdrawal and refresh)
     57   and coin source info (refresh operation, reward, reserve)
     58 * set of purchases (contract terms, applied refunds, ...)
     59 * assignment of coins to their "primary wallet"
     60 
     61 (Some of these might be further split up to allow more efficient updates.)
     62 
     63 Entities that are **not** synchronized are:
     64 
     65 * purchases before the corresponding order has been claimed
     66 * withdrawal operations before they have been accepted by the user
     67 
     68 Entities that **could** be synchronized (to be decided):
     69 
     70 * private keys of other sync accounts
     71 * coin planchets
     72 * rewards before the corresponding coins have been withdrawn
     73 * refresh sessions (not only the "meta data" about the operation,
     74   but everything)
     75 
     76 
     77 Garbage collection
     78 ------------------
     79 
     80 There are two types of garbage collection involved:
     81 
     82 1. CRDT tombstones / other administrative data in the sync blob.  These can be deleted
     83    after we're sure all wallets enrolled in the sync server have a Lamport timestamp
     84    larger than the timestamp of the tombstone.  Wallets include their own Lamport timestamp
     85    in the sync blob:
     86 
     87    .. code:: javascript
     88 
     89      {
     90        clocks: {
     91          my_desktop_wallet: 5,
     92          my_phone_wallet: 3
     93        },
     94        ...
     95      }
     96 
     97    All tombstones / overwritten set elements with a timestamp smaller than the
     98    smallest clock value can be deleted.
     99 
    100 2. Normal wallet GC.  The deletion operations resulting from the wallet garbage
    101    collection (i.g. deleting legally expired denomination keys, coins, exchange
    102    signing keys, ...) are propagated to the respective CRDT set in the sync
    103    blob.
    104 
    105 
    106 Ghost Entities
    107 --------------
    108 
    109 Sometimes a wallet can learn about an operation that happened in another synced
    110 wallet **before** a sync over the sync server happens.  An example of this is a
    111 deposit operation.  When two synced wallets spend the same coin on something,
    112 one of them will receive an error from the exchange that proves the coin has
    113 been spent on something else.  The wallet will add a "ghost entry" for such an
    114 event, in order to be able to show a consistent history (i.e. all numbers
    115 adding up) to the user.
    116 
    117 When the two wallets sync later, the ghost entry is replaced by the actual
    118 purchase entity from the wallet that initiated the spending.
    119 
    120 Ghost entities are not added to the sync state.
    121 
    122 
    123 Multiple sync servers
    124 ---------------------
    125 
    126 When a wallet is connected to multiple sync servers, it automatically
    127 propagates changes it received from one sync server to the others.  Local
    128 changes made by the wallet are propagated to all sync servers.  The goal of
    129 this is to make the state of the sync servers converge.
    130 
    131 The different sync servers one wallet is enrolled with do not necessarily
    132 have the same set of other wallets enrolled.  Each sync server has a separate Lamport clock
    133 and contains a separate CRDT.
    134 
    135 Backup user flow
    136 ================
    137 
    138 .. graphviz::
    139 
    140    digraph G {
    141        nodesep=0.5;
    142        withdrawal [
    143            label = "First\nWithdrawal";
    144            shape = oval;
    145        ];
    146        has_backup [
    147            label = "Has backup\nconfigured?";
    148            shape = diamond;
    149        ];
    150        app_settings [
    151            label = "App\nSettings";
    152            shape = rect;
    153        ];
    154        backup_onboarding [
    155            label = "Backup\nOnboarding";
    156            shape = rect;
    157        ];
    158        backup_settings [
    159            label = "Backup Settings\n\n* time of last backup\n* current service";
    160            shape = rect;
    161        ];
    162        choose_backup_service [
    163            label = "Choose\nBackup Service";
    164            shape = rect;
    165        ];
    166        tos_accepted [
    167            label = "Current ToS\naccepted?";
    168            shape = diamond;
    169        ];
    170        tos [
    171            label = "ToS";
    172            shape = rect;
    173        ];
    174        payment_required [
    175            label = "Payment\nrequired?";
    176            shape = diamond;
    177        ];
    178        payment_confirmation [
    179            label = "Payment\nConfirmation";
    180            shape = rect;
    181        ];
    182        backup_secret [
    183            label = "Backup Secret\n\nStore or write down!";
    184            shape = rect;
    185        ];
    186 
    187        withdrawal -> has_backup;
    188        has_backup -> backup_onboarding [label="No"];
    189        backup_onboarding -> backup_settings;
    190        app_settings -> backup_settings;
    191        backup_settings -> backup_settings [label="Disable Backup"];
    192        backup_settings:w -> backup_settings:w [label="Sync now"];
    193        backup_settings -> choose_backup_service;
    194        choose_backup_service -> tos_accepted [label="Select Service"];
    195        tos_accepted -> tos [label="No"];
    196        tos_accepted -> payment_required [label="Yes"];
    197        choose_backup_service:w -> choose_backup_service [label="Remove current service"];
    198        choose_backup_service:n -> choose_backup_service:n [headlabel="Add new service", labeldistance=3.5];
    199        tos -> payment_required [label="Accept"];
    200        payment_required -> payment_confirmation [label="Yes"];
    201        payment_confirmation -> backup_secret [label="Paid"];
    202        backup_secret -> backup_settings [dir=both, label="Stored"];
    203        payment_required:s -> backup_secret:w [label="No"];
    204 
    205        { rank=same; has_backup; backup_onboarding; }
    206        { rank=same; withdrawal; app_settings; }
    207        { rank=same; tos_accepted; tos; }
    208        { rank=same; payment_required; payment_confirmation; }
    209    }
    210 
    211 Backup Settings Screen
    212 ----------------------
    213 
    214 * **Backup my wallet** [on/off]
    215 * **Backup services**
    216   No service active
    217   (shows time of last backup per service)
    218 * **Show backup secret**
    219   You need this secret to restore from backup
    220 * option to sync/backup now (hidden in action bar overflow menu)
    221 
    222 Choose Backup Service Screen
    223 ----------------------------
    224 This screen can be reached by pressing the **Backup services** setting
    225 in the Backup Settings Screen.
    226 It lists the currently active service and other services that can be used.
    227 The user has the option to add new services to the list.
    228 
    229 A backup service has
    230 
    231 * a name
    232 * a base URL
    233 * a fee per year in an explicit currency
    234 
    235 Clicking an active service shows the above service information as well as:
    236 
    237 * the service secret that is required to restore from backup
    238 * last payment date and next scheduled payment date
    239 * option to deactivate the backup service
    240 
    241 Clicking an inactive service allows the user to use the backup service
    242 (after accepting ToS and making the payment).
    243 
    244 Terms of Service Screen
    245 -----------------------
    246 This screen always appears when a backup provider is selected
    247 and the user did not yet accept the current version of its terms of service.
    248 
    249 It shows the terms of service text and an accept checkbox,
    250 as well as the usual back button.
    251 
    252 Payment Confirmation Screen
    253 ---------------------------
    254 This is the same screen that the user sees when doing other purchases.
    255 The only difference is that after successful payment,
    256 the user will be shown the service secret instead of the transaction list.
    257 
    258 Backup Secret Screen
    259 --------------------
    260 After setting up a backup service,
    261 the user needs to securely store the secret needed to restore from backup.
    262 The secret will be shown as a Taler URI in plain text.
    263 This has the form: ``taler://sync/$SYNC-DOMAIN/$SYNC-PATH#$PRIVATE-KEY``
    264 Additionally, the URI will be encoded as a QRcode.
    265 Depending on the platform, there should be an option to print or export (PDF) the secret.
    266 
    267 Backup Onboarding
    268 -----------------
    269 If no backup service was selected when the user makes the first withdrawal,
    270 an onboarding screen will be shown that takes the user to the backup configuration screen.
    271 
    272     Don't lose your money, use a backup service!
    273 
    274     Your wallet comes with a list of backup services
    275     that can store an encrypted copy of your wallet.
    276     Use one to keep your money safe!
    277 
    278     [Set backup up now]
    279 
    280 References
    281 ==========
    282 
    283 * Shapiro, M., PreguiƧa, N., Baquero, C., & Zawirski, M. (2011). A
    284   comprehensive study of convergent and commutative replicated data types. [`PDF <https://hal.inria.fr/inria-00555588/document>`__]
    285 
    286 Discussion / Q&A
    287 ================
    288 
    289 * Why is backup/sync not split into two services / use-cases?
    290 
    291   * For privacy reasons, we can't use some interactive sync service.  Thus we
    292     use the backup blob as a CRDT that also synchronization for us.
    293 
    294 * Do we need to handle backup/sync state becoming very large e.g. by many transactions
    295   and embedded product images potentially exceeding service quota?
    296 
    297 * Do we synchronize the list of other backup enrollments?  How
    298   do we handle distributing the different private keys for them?
    299 
    300   * If we automatically sync the sync enrollments and the old sync account
    301     is compromised, the new sync account would automatically be compromised as well!
    302 
    303   * If every wallet had its own sync key pair, we could select which existing wallets
    304     to roll over as well.
    305 
    306 * How do we handle a synced wallet that becomes malicious deleting all coins or purchased products?
    307 
    308   * This needs to balance the genuine need to permanently delete data.
    309 
    310   * Should the sync server allow to fetch previous versions of the sync blob?
    311     (If not, how to provide backup functionality?)
    312 
    313   * Should the individual wallets keep tombstones (i.e. entities just marked as deleted)
    314     around for some time, or should they delete and "sanitize" (delete data not needed for the CRDT)
    315     tombstones as soon as possible?
    316 
    317 * How do we make it easy to remove compromised devices from the sync group
    318   and prevent them from getting access to future funds and transactions?
    319 
    320   * We need to remove all sync connections on all connected devices
    321     and then individually (and manually) add all devices to the new backup account.
    322 
    323   * If we encrypted the key with each wallet's private sync key,
    324     we could choose which wallets we want to migrate to the new sync account.
    325 
    326   * Can we then roll-over wallets to the new account automatically
    327     or does it have to be manually on each device to prevent an attacker to roll us over?
    328 
    329 * How are wallets identified for backup/sync?
    330 
    331   * UUID / EdDSA pub and nick name?  When nickname clashes,
    332     some number is added based on lexical sort of the random id ("phone#1", "phone#2").
    333 
    334 * How do we explain to users that it can take days for wallet state to synchronize to all devices?
    335 
    336 * How are people supposed to securely store their backup account key(s)?
    337 
    338   * There can be an option to print/export the QR code
    339   * They can manually write down the taler:// Uri containing the key.
    340   * Maybe encode the key in a different format such as
    341     `BIP39 <https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki>`__?
    342 
    343 * Do we have a passphrase for our backup account key(s)?
    344 
    345   * ???