]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - docs/specifications/mutable.rst
Update docs, notably performance.rst, to include MDMF. fixes #1772
[tahoe-lafs/tahoe-lafs.git] / docs / specifications / mutable.rst
1 =============
2 Mutable Files
3 =============
4
5 1.  `Mutable Formats`_
6 2.  `Consistency vs. Availability`_
7 3.  `The Prime Coordination Directive: "Don't Do That"`_
8 4.  `Small Distributed Mutable Files`_
9
10     1. `SDMF slots overview`_
11     2. `Server Storage Protocol`_
12     3. `Code Details`_
13     4. `SMDF Slot Format`_
14     5. `Recovery`_
15
16 5.  `Medium Distributed Mutable Files`_
17 6.  `Large Distributed Mutable Files`_
18 7.  `TODO`_
19
20 Mutable files are places with a stable identifier that can hold data that
21 changes over time. In contrast to immutable slots, for which the
22 identifier/capability is derived from the contents themselves, the mutable
23 file identifier remains fixed for the life of the slot, regardless of what
24 data is placed inside it.
25
26 Each mutable file is referenced by two different caps. The "read-write" cap
27 grants read-write access to its holder, allowing them to put whatever
28 contents they like into the slot. The "read-only" cap is less powerful, only
29 granting read access, and not enabling modification of the data. The
30 read-write cap can be turned into the read-only cap, but not the other way
31 around.
32
33 The data in these files is distributed over a number of servers, using the
34 same erasure coding that immutable files use, with 3-of-10 being a typical
35 choice of encoding parameters. The data is encrypted and signed in such a way
36 that only the holders of the read-write cap will be able to set the contents
37 of the slot, and only the holders of the read-only cap will be able to read
38 those contents. Holders of either cap will be able to validate the contents
39 as being written by someone with the read-write cap. The servers who hold the
40 shares are not automatically given the ability read or modify them: the worst
41 they can do is deny service (by deleting or corrupting the shares), or
42 attempt a rollback attack (which can only succeed with the cooperation of at
43 least k servers).
44
45
46 Mutable Formats
47 ===============
48
49 History
50 -------
51
52 When mutable files first shipped in Tahoe-0.8.0 (15-Feb-2008), the only
53 version available was "SDMF", described below. This was a
54 limited-functionality placeholder, intended to be replaced with
55 improved-efficiency "MDMF" files shortly afterwards. The development process
56 took longer than expected, and MDMF didn't ship until Tahoe-1.9.0
57 (31-Oct-2011), and even then it was opt-in (not used by default).
58
59 SDMF was intended for relatively small mutable files, up to a few megabytes.
60 It uses only one segment, so alacrity (the measure of how quickly the first
61 byte of plaintext is returned to the client) suffers, as the whole file must
62 be downloaded even if you only want to get a single byte. The memory used by
63 both clients and servers also scales with the size of the file, instead of
64 being limited to the half-a-MB-or-so that immutable file operations use, so
65 large files cause significant memory usage. To discourage the use of SDMF
66 outside it's design parameters, the early versions of Tahoe enforced a
67 maximum size on mutable files (maybe 10MB). Since most directories are built
68 out of mutable files, this imposed a limit of about 30k entries per
69 directory. In subsequent releases, this limit was removed, but the
70 performance problems inherent in the SDMF implementation remained.
71
72 In the summer of 2010, Google-Summer-of-Code student Kevan Carstensen took on
73 the project of finally implementing MDMF. Because of my (Brian) design
74 mistake in SDMF (not including a separate encryption seed in each segment),
75 the share format for SDMF could not be used for MDMF, resulting in a larger
76 gap between the two implementations (my original intention had been to make
77 SDMF a clean subset of MDMF, where any single-segment MDMF file could be
78 handled by the old SDMF code). In the fall of 2011, Kevan's code was finally
79 integrated, and first made available in the Tahoe-1.9.0 release.
80
81 SDMF vs. MDMF
82 -------------
83
84 The improvement of MDMF is the use of multiple segments: individual 128-KiB
85 sections of the file can be retrieved or modified independently. The
86 improvement can be seen when fetching just a portion of the file (using a
87 Range: header on the webapi), or when modifying a portion (again with a
88 Range: header). It can also be seen indirectly when fetching the whole file:
89 the first segment of data should be delivered faster from a large MDMF file
90 than from an SDMF file, although the overall download will then proceed at
91 the same rate.
92
93 We've decided to make it opt-in for now: mutable files default to
94 SDMF format unless explicitly configured to use MDMF, either in ``tahoe.cfg``
95 (see `<configuration.rst>`__) or in the WUI or CLI command that created a
96 new mutable file.
97
98 The code can read and modify existing files of either format without user
99 intervention. We expect to make MDMF the default in a subsequent release,
100 perhaps 2.0.
101
102 Which format should you use? SDMF works well for files up to a few MB, and
103 can be handled by older versions (Tahoe-1.8.3 and earlier). If you do not
104 need to support older clients, want to efficiently work with mutable files,
105 and have code which will use Range: headers that make partial reads and
106 writes, then MDMF is for you.
107
108
109 Consistency vs. Availability
110 ============================
111
112 There is an age-old battle between consistency and availability. Epic papers
113 have been written, elaborate proofs have been established, and generations of
114 theorists have learned that you cannot simultaneously achieve guaranteed
115 consistency with guaranteed reliability. In addition, the closer to 0 you get
116 on either axis, the cost and complexity of the design goes up.
117
118 Tahoe's design goals are to largely favor design simplicity, then slightly
119 favor read availability, over the other criteria.
120
121 As we develop more sophisticated mutable slots, the API may expose multiple
122 read versions to the application layer. The tahoe philosophy is to defer most
123 consistency recovery logic to the higher layers. Some applications have
124 effective ways to merge multiple versions, so inconsistency is not
125 necessarily a problem (i.e. directory nodes can usually merge multiple
126 "add child" operations).
127
128
129 The Prime Coordination Directive: "Don't Do That"
130 =================================================
131
132 The current rule for applications which run on top of Tahoe is "do not
133 perform simultaneous uncoordinated writes". That means you need non-tahoe
134 means to make sure that two parties are not trying to modify the same mutable
135 slot at the same time. For example:
136
137 * don't give the read-write URI to anyone else. Dirnodes in a private
138   directory generally satisfy this case, as long as you don't use two
139   clients on the same account at the same time
140 * if you give a read-write URI to someone else, stop using it yourself. An
141   inbox would be a good example of this.
142 * if you give a read-write URI to someone else, call them on the phone
143   before you write into it
144 * build an automated mechanism to have your agents coordinate writes.
145   For example, we expect a future release to include a FURL for a
146   "coordination server" in the dirnodes. The rule can be that you must
147   contact the coordination server and obtain a lock/lease on the file
148   before you're allowed to modify it.
149
150 If you do not follow this rule, Bad Things will happen. The worst-case Bad
151 Thing is that the entire file will be lost. A less-bad Bad Thing is that one
152 or more of the simultaneous writers will lose their changes. An observer of
153 the file may not see monotonically-increasing changes to the file, i.e. they
154 may see version 1, then version 2, then 3, then 2 again.
155
156 Tahoe takes some amount of care to reduce the badness of these Bad Things.
157 One way you can help nudge it from the "lose your file" case into the "lose
158 some changes" case is to reduce the number of competing versions: multiple
159 versions of the file that different parties are trying to establish as the
160 one true current contents. Each simultaneous writer counts as a "competing
161 version", as does the previous version of the file. If the count "S" of these
162 competing versions is larger than N/k, then the file runs the risk of being
163 lost completely. [TODO] If at least one of the writers remains running after
164 the collision is detected, it will attempt to recover, but if S>(N/k) and all
165 writers crash after writing a few shares, the file will be lost.
166
167 Note that Tahoe uses serialization internally to make sure that a single
168 Tahoe node will not perform simultaneous modifications to a mutable file. It
169 accomplishes this by using a weakref cache of the MutableFileNode (so that
170 there will never be two distinct MutableFileNodes for the same file), and by
171 forcing all mutable file operations to obtain a per-node lock before they
172 run. The Prime Coordination Directive therefore applies to inter-node
173 conflicts, not intra-node ones.
174
175
176 Small Distributed Mutable Files
177 ===============================
178
179 SDMF slots are suitable for small (<1MB) files that are editing by rewriting
180 the entire file. The three operations are:
181
182  * allocate (with initial contents)
183  * set (with new contents)
184  * get (old contents)
185
186 The first use of SDMF slots will be to hold directories (dirnodes), which map
187 encrypted child names to rw-URI/ro-URI pairs.
188
189 SDMF slots overview
190 -------------------
191
192 Each SDMF slot is created with a public/private key pair. The public key is
193 known as the "verification key", while the private key is called the
194 "signature key". The private key is hashed and truncated to 16 bytes to form
195 the "write key" (an AES symmetric key). The write key is then hashed and
196 truncated to form the "read key". The read key is hashed and truncated to
197 form the 16-byte "storage index" (a unique string used as an index to locate
198 stored data).
199
200 The public key is hashed by itself to form the "verification key hash".
201
202 The write key is hashed a different way to form the "write enabler master".
203 For each storage server on which a share is kept, the write enabler master is
204 concatenated with the server's nodeid and hashed, and the result is called
205 the "write enabler" for that particular server. Note that multiple shares of
206 the same slot stored on the same server will all get the same write enabler,
207 i.e. the write enabler is associated with the "bucket", rather than the
208 individual shares.
209
210 The private key is encrypted (using AES in counter mode) by the write key,
211 and the resulting crypttext is stored on the servers. so it will be
212 retrievable by anyone who knows the write key. The write key is not used to
213 encrypt anything else, and the private key never changes, so we do not need
214 an IV for this purpose.
215
216 The actual data is encrypted (using AES in counter mode) with a key derived
217 by concatenating the readkey with the IV, the hashing the results and
218 truncating to 16 bytes. The IV is randomly generated each time the slot is
219 updated, and stored next to the encrypted data.
220
221 The read-write URI consists of the write key and the verification key hash.
222 The read-only URI contains the read key and the verification key hash. The
223 verify-only URI contains the storage index and the verification key hash.
224
225 ::
226
227  URI:SSK-RW:b2a(writekey):b2a(verification_key_hash)
228  URI:SSK-RO:b2a(readkey):b2a(verification_key_hash)
229  URI:SSK-Verify:b2a(storage_index):b2a(verification_key_hash)
230
231 Note that this allows the read-only and verify-only URIs to be derived from
232 the read-write URI without actually retrieving the public keys. Also note
233 that it means the read-write agent must validate both the private key and the
234 public key when they are first fetched. All users validate the public key in
235 exactly the same way.
236
237 The SDMF slot is allocated by sending a request to the storage server with a
238 desired size, the storage index, and the write enabler for that server's
239 nodeid. If granted, the write enabler is stashed inside the slot's backing
240 store file. All further write requests must be accompanied by the write
241 enabler or they will not be honored. The storage server does not share the
242 write enabler with anyone else.
243
244 The SDMF slot structure will be described in more detail below. The important
245 pieces are:
246
247 * a sequence number
248 * a root hash "R"
249 * the encoding parameters (including k, N, file size, segment size)
250 * a signed copy of [seqnum,R,encoding_params], using the signature key
251 * the verification key (not encrypted)
252 * the share hash chain (part of a Merkle tree over the share hashes)
253 * the block hash tree (Merkle tree over blocks of share data)
254 * the share data itself (erasure-coding of read-key-encrypted file data)
255 * the signature key, encrypted with the write key
256
257 The access pattern for read is:
258
259 * hash read-key to get storage index
260 * use storage index to locate 'k' shares with identical 'R' values
261
262   * either get one share, read 'k' from it, then read k-1 shares
263   * or read, say, 5 shares, discover k, either get more or be finished
264   * or copy k into the URIs
265
266 * read verification key
267 * hash verification key, compare against verification key hash
268 * read seqnum, R, encoding parameters, signature
269 * verify signature against verification key
270 * read share data, compute block-hash Merkle tree and root "r"
271 * read share hash chain (leading from "r" to "R")
272 * validate share hash chain up to the root "R"
273 * submit share data to erasure decoding
274 * decrypt decoded data with read-key
275 * submit plaintext to application
276
277 The access pattern for write is:
278
279 * hash write-key to get read-key, hash read-key to get storage index
280 * use the storage index to locate at least one share
281 * read verification key and encrypted signature key
282 * decrypt signature key using write-key
283 * hash signature key, compare against write-key
284 * hash verification key, compare against verification key hash
285 * encrypt plaintext from application with read-key
286
287   * application can encrypt some data with the write-key to make it only
288     available to writers (use this for transitive read-onlyness of dirnodes)
289
290 * erasure-code crypttext to form shares
291 * split shares into blocks
292 * compute Merkle tree of blocks, giving root "r" for each share
293 * compute Merkle tree of shares, find root "R" for the file as a whole
294 * create share data structures, one per server:
295
296   * use seqnum which is one higher than the old version
297   * share hash chain has log(N) hashes, different for each server
298   * signed data is the same for each server
299
300 * now we have N shares and need homes for them
301 * walk through peers
302
303   * if share is not already present, allocate-and-set
304   * otherwise, try to modify existing share:
305   * send testv_and_writev operation to each one
306   * testv says to accept share if their(seqnum+R) <= our(seqnum+R)
307   * count how many servers wind up with which versions (histogram over R)
308   * keep going until N servers have the same version, or we run out of servers
309
310     * if any servers wound up with a different version, report error to
311       application
312     * if we ran out of servers, initiate recovery process (described below)
313
314 Server Storage Protocol
315 -----------------------
316
317 The storage servers will provide a mutable slot container which is oblivious
318 to the details of the data being contained inside it. Each storage index
319 refers to a "bucket", and each bucket has one or more shares inside it. (In a
320 well-provisioned network, each bucket will have only one share). The bucket
321 is stored as a directory, using the base32-encoded storage index as the
322 directory name. Each share is stored in a single file, using the share number
323 as the filename.
324
325 The container holds space for a container magic number (for versioning), the
326 write enabler, the nodeid which accepted the write enabler (used for share
327 migration, described below), a small number of lease structures, the embedded
328 data itself, and expansion space for additional lease structures::
329
330  #   offset    size    name
331  1   0         32      magic verstr "Tahoe mutable container v1\n\x75\x09\x44\x03\x8e"
332  2   32        20      write enabler's nodeid
333  3   52        32      write enabler
334  4   84        8       data size (actual share data present) (a)
335  5   92        8       offset of (8) count of extra leases (after data)
336  6   100       368     four leases, 92 bytes each
337                         0    4   ownerid (0 means "no lease here")
338                         4    4   expiration timestamp
339                         8   32   renewal token
340                         40  32   cancel token
341                         72  20   nodeid which accepted the tokens
342  7   468       (a)     data
343  8   ??        4       count of extra leases
344  9   ??        n*92    extra leases
345
346 The "extra leases" field must be copied and rewritten each time the size of
347 the enclosed data changes. The hope is that most buckets will have four or
348 fewer leases and this extra copying will not usually be necessary.
349
350 The (4) "data size" field contains the actual number of bytes of data present
351 in field (7), such that a client request to read beyond 504+(a) will result
352 in an error. This allows the client to (one day) read relative to the end of
353 the file. The container size (that is, (8)-(7)) might be larger, especially
354 if extra size was pre-allocated in anticipation of filling the container with
355 a lot of data.
356
357 The offset in (5) points at the *count* of extra leases, at (8). The actual
358 leases (at (9)) begin 4 bytes later. If the container size changes, both (8)
359 and (9) must be relocated by copying.
360
361 The server will honor any write commands that provide the write token and do
362 not exceed the server-wide storage size limitations. Read and write commands
363 MUST be restricted to the 'data' portion of the container: the implementation
364 of those commands MUST perform correct bounds-checking to make sure other
365 portions of the container are inaccessible to the clients.
366
367 The two methods provided by the storage server on these "MutableSlot" share
368 objects are:
369
370 * readv(ListOf(offset=int, length=int))
371
372   * returns a list of bytestrings, of the various requested lengths
373   * offset < 0 is interpreted relative to the end of the data
374   * spans which hit the end of the data will return truncated data
375
376 * testv_and_writev(write_enabler, test_vector, write_vector)
377
378   * this is a test-and-set operation which performs the given tests and only
379     applies the desired writes if all tests succeed. This is used to detect
380     simultaneous writers, and to reduce the chance that an update will lose
381     data recently written by some other party (written after the last time
382     this slot was read).
383   * test_vector=ListOf(TupleOf(offset, length, opcode, specimen))
384   * the opcode is a string, from the set [gt, ge, eq, le, lt, ne]
385   * each element of the test vector is read from the slot's data and 
386     compared against the specimen using the desired (in)equality. If all
387     tests evaluate True, the write is performed
388   * write_vector=ListOf(TupleOf(offset, newdata))
389
390     * offset < 0 is not yet defined, it probably means relative to the
391       end of the data, which probably means append, but we haven't nailed
392       it down quite yet
393     * write vectors are executed in order, which specifies the results of
394       overlapping writes
395
396   * return value:
397
398     * error: OutOfSpace
399     * error: something else (io error, out of memory, whatever)
400     * (True, old_test_data): the write was accepted (test_vector passed)
401     * (False, old_test_data): the write was rejected (test_vector failed)
402
403       * both 'accepted' and 'rejected' return the old data that was used
404         for the test_vector comparison. This can be used by the client
405         to detect write collisions, including collisions for which the
406         desired behavior was to overwrite the old version.
407
408 In addition, the storage server provides several methods to access these
409 share objects:
410
411 * allocate_mutable_slot(storage_index, sharenums=SetOf(int))
412
413   * returns DictOf(int, MutableSlot)
414
415 * get_mutable_slot(storage_index)
416
417   * returns DictOf(int, MutableSlot)
418   * or raises KeyError
419
420 We intend to add an interface which allows small slots to allocate-and-write
421 in a single call, as well as do update or read in a single call. The goal is
422 to allow a reasonably-sized dirnode to be created (or updated, or read) in
423 just one round trip (to all N shareholders in parallel).
424
425 migrating shares
426 ````````````````
427
428 If a share must be migrated from one server to another, two values become
429 invalid: the write enabler (since it was computed for the old server), and
430 the lease renew/cancel tokens.
431
432 Suppose that a slot was first created on nodeA, and was thus initialized with
433 WE(nodeA) (= H(WEM+nodeA)). Later, for provisioning reasons, the share is
434 moved from nodeA to nodeB.
435
436 Readers may still be able to find the share in its new home, depending upon
437 how many servers are present in the grid, where the new nodeid lands in the
438 permuted index for this particular storage index, and how many servers the
439 reading client is willing to contact.
440
441 When a client attempts to write to this migrated share, it will get a "bad
442 write enabler" error, since the WE it computes for nodeB will not match the
443 WE(nodeA) that was embedded in the share. When this occurs, the "bad write
444 enabler" message must include the old nodeid (e.g. nodeA) that was in the
445 share.
446
447 The client then computes H(nodeB+H(WEM+nodeA)), which is the same as
448 H(nodeB+WE(nodeA)). The client sends this along with the new WE(nodeB), which
449 is H(WEM+nodeB). Note that the client only sends WE(nodeB) to nodeB, never to
450 anyone else. Also note that the client does not send a value to nodeB that
451 would allow the node to impersonate the client to a third node: everything
452 sent to nodeB will include something specific to nodeB in it.
453
454 The server locally computes H(nodeB+WE(nodeA)), using its own node id and the
455 old write enabler from the share. It compares this against the value supplied
456 by the client. If they match, this serves as proof that the client was able
457 to compute the old write enabler. The server then accepts the client's new
458 WE(nodeB) and writes it into the container.
459
460 This WE-fixup process requires an extra round trip, and requires the error
461 message to include the old nodeid, but does not require any public key
462 operations on either client or server.
463
464 Migrating the leases will require a similar protocol. This protocol will be
465 defined concretely at a later date.
466
467 Code Details
468 ------------
469
470 The MutableFileNode class is used to manipulate mutable files (as opposed to
471 ImmutableFileNodes). These are initially generated with
472 client.create_mutable_file(), and later recreated from URIs with
473 client.create_node_from_uri(). Instances of this class will contain a URI and
474 a reference to the client (for peer selection and connection).
475
476 NOTE: this section is out of date. Please see src/allmydata/interfaces.py
477 (the section on IMutableFilesystemNode) for more accurate information.
478
479 The methods of MutableFileNode are:
480
481 * download_to_data() -> [deferred] newdata, NotEnoughSharesError
482
483   * if there are multiple retrieveable versions in the grid, get() returns
484     the first version it can reconstruct, and silently ignores the others.
485     In the future, a more advanced API will signal and provide access to
486     the multiple heads.
487
488 * update(newdata) -> OK, UncoordinatedWriteError, NotEnoughSharesError
489 * overwrite(newdata) -> OK, UncoordinatedWriteError, NotEnoughSharesError
490
491 download_to_data() causes a new retrieval to occur, pulling the current
492 contents from the grid and returning them to the caller. At the same time,
493 this call caches information about the current version of the file. This
494 information will be used in a subsequent call to update(), and if another
495 change has occured between the two, this information will be out of date,
496 triggering the UncoordinatedWriteError.
497
498 update() is therefore intended to be used just after a download_to_data(), in
499 the following pattern::
500
501  d = mfn.download_to_data()
502  d.addCallback(apply_delta)
503  d.addCallback(mfn.update)
504
505 If the update() call raises UCW, then the application can simply return an
506 error to the user ("you violated the Prime Coordination Directive"), and they
507 can try again later. Alternatively, the application can attempt to retry on
508 its own. To accomplish this, the app needs to pause, download the new
509 (post-collision and post-recovery) form of the file, reapply their delta,
510 then submit the update request again. A randomized pause is necessary to
511 reduce the chances of colliding a second time with another client that is
512 doing exactly the same thing::
513
514  d = mfn.download_to_data()
515  d.addCallback(apply_delta)
516  d.addCallback(mfn.update)
517  def _retry(f):
518    f.trap(UncoordinatedWriteError)
519    d1 = pause(random.uniform(5, 20))
520    d1.addCallback(lambda res: mfn.download_to_data())
521    d1.addCallback(apply_delta)
522    d1.addCallback(mfn.update)
523    return d1
524  d.addErrback(_retry)
525
526 Enthusiastic applications can retry multiple times, using a randomized
527 exponential backoff between each. A particularly enthusiastic application can
528 retry forever, but such apps are encouraged to provide a means to the user of
529 giving up after a while.
530
531 UCW does not mean that the update was not applied, so it is also a good idea
532 to skip the retry-update step if the delta was already applied::
533
534  d = mfn.download_to_data()
535  d.addCallback(apply_delta)
536  d.addCallback(mfn.update)
537  def _retry(f):
538    f.trap(UncoordinatedWriteError)
539    d1 = pause(random.uniform(5, 20))
540    d1.addCallback(lambda res: mfn.download_to_data())
541    def _maybe_apply_delta(contents):
542      new_contents = apply_delta(contents)
543      if new_contents != contents:
544        return mfn.update(new_contents)
545    d1.addCallback(_maybe_apply_delta)
546    return d1
547  d.addErrback(_retry)
548
549 update() is the right interface to use for delta-application situations, like
550 directory nodes (in which apply_delta might be adding or removing child
551 entries from a serialized table).
552
553 Note that any uncoordinated write has the potential to lose data. We must do
554 more analysis to be sure, but it appears that two clients who write to the
555 same mutable file at the same time (even if both eventually retry) will, with
556 high probability, result in one client observing UCW and the other silently
557 losing their changes. It is also possible for both clients to observe UCW.
558 The moral of the story is that the Prime Coordination Directive is there for
559 a reason, and that recovery/UCW/retry is not a subsitute for write
560 coordination.
561
562 overwrite() tells the client to ignore this cached version information, and
563 to unconditionally replace the mutable file's contents with the new data.
564 This should not be used in delta application, but rather in situations where
565 you want to replace the file's contents with completely unrelated ones. When
566 raw files are uploaded into a mutable slot through the Tahoe-LAFS web-API
567 (using POST and the ?mutable=true argument), they are put in place with
568 overwrite().
569
570 The peer-selection and data-structure manipulation (and signing/verification)
571 steps will be implemented in a separate class in allmydata/mutable.py .
572
573 SMDF Slot Format
574 ----------------
575
576 This SMDF data lives inside a server-side MutableSlot container. The server
577 is oblivious to this format.
578
579 This data is tightly packed. In particular, the share data is defined to run
580 all the way to the beginning of the encrypted private key (the encprivkey
581 offset is used both to terminate the share data and to begin the encprivkey).
582
583 ::
584
585   #    offset   size    name
586   1    0        1       version byte, \x00 for this format
587   2    1        8       sequence number. 2^64-1 must be handled specially, TBD
588   3    9        32      "R" (root of share hash Merkle tree)
589   4    41       16      IV (share data is AES(H(readkey+IV)) )
590   5    57       18      encoding parameters:
591         57       1        k
592         58       1        N
593         59       8        segment size
594         67       8        data length (of original plaintext)
595   6    75       32      offset table:
596         75       4        (8) signature
597         79       4        (9) share hash chain
598         83       4        (10) block hash tree
599         87       4        (11) share data
600         91       8        (12) encrypted private key
601         99       8        (13) EOF
602   7    107      436ish  verification key (2048 RSA key)
603   8    543ish   256ish  signature=RSAsign(sigkey, H(version+seqnum+r+IV+encparm))
604   9    799ish   (a)     share hash chain, encoded as:
605                          "".join([pack(">H32s", shnum, hash)
606                                   for (shnum,hash) in needed_hashes])
607  10    (927ish) (b)     block hash tree, encoded as:
608                          "".join([pack(">32s",hash) for hash in block_hash_tree])
609  11    (935ish) LEN     share data (no gap between this and encprivkey)
610  12    ??       1216ish encrypted private key= AESenc(write-key, RSA-key)
611  13    ??       --      EOF
612
613  (a) The share hash chain contains ceil(log(N)) hashes, each 32 bytes long.
614     This is the set of hashes necessary to validate this share's leaf in the
615     share Merkle tree. For N=10, this is 4 hashes, i.e. 128 bytes.
616  (b) The block hash tree contains ceil(length/segsize) hashes, each 32 bytes
617     long. This is the set of hashes necessary to validate any given block of
618     share data up to the per-share root "r". Each "r" is a leaf of the share
619     has tree (with root "R"), from which a minimal subset of hashes is put in
620     the share hash chain in (8).
621
622 Recovery
623 --------
624
625 The first line of defense against damage caused by colliding writes is the
626 Prime Coordination Directive: "Don't Do That".
627
628 The second line of defense is to keep "S" (the number of competing versions)
629 lower than N/k. If this holds true, at least one competing version will have
630 k shares and thus be recoverable. Note that server unavailability counts
631 against us here: the old version stored on the unavailable server must be
632 included in the value of S.
633
634 The third line of defense is our use of testv_and_writev() (described below),
635 which increases the convergence of simultaneous writes: one of the writers
636 will be favored (the one with the highest "R"), and that version is more
637 likely to be accepted than the others. This defense is least effective in the
638 pathological situation where S simultaneous writers are active, the one with
639 the lowest "R" writes to N-k+1 of the shares and then dies, then the one with
640 the next-lowest "R" writes to N-2k+1 of the shares and dies, etc, until the
641 one with the highest "R" writes to k-1 shares and dies. Any other sequencing
642 will allow the highest "R" to write to at least k shares and establish a new
643 revision.
644
645 The fourth line of defense is the fact that each client keeps writing until
646 at least one version has N shares. This uses additional servers, if
647 necessary, to make sure that either the client's version or some
648 newer/overriding version is highly available.
649
650 The fifth line of defense is the recovery algorithm, which seeks to make sure
651 that at least *one* version is highly available, even if that version is
652 somebody else's.
653
654 The write-shares-to-peers algorithm is as follows:
655
656 * permute peers according to storage index
657 * walk through peers, trying to assign one share per peer
658 * for each peer:
659
660   * send testv_and_writev, using "old(seqnum+R) <= our(seqnum+R)" as the test
661
662     * this means that we will overwrite any old versions, and we will
663       overwrite simultaenous writers of the same version if our R is higher.
664       We will not overwrite writers using a higher seqnum.
665
666   * record the version that each share winds up with. If the write was
667     accepted, this is our own version. If it was rejected, read the
668     old_test_data to find out what version was retained.
669   * if old_test_data indicates the seqnum was equal or greater than our
670     own, mark the "Simultanous Writes Detected" flag, which will eventually
671     result in an error being reported to the writer (in their close() call).
672   * build a histogram of "R" values
673   * repeat until the histogram indicate that some version (possibly ours)
674     has N shares. Use new servers if necessary.
675   * If we run out of servers:
676
677     * if there are at least shares-of-happiness of any one version, we're
678       happy, so return. (the close() might still get an error)
679     * not happy, need to reinforce something, goto RECOVERY
680
681 Recovery:
682
683 * read all shares, count the versions, identify the recoverable ones,
684   discard the unrecoverable ones.
685 * sort versions: locate max(seqnums), put all versions with that seqnum
686   in the list, sort by number of outstanding shares. Then put our own
687   version. (TODO: put versions with seqnum <max but >us ahead of us?).
688 * for each version:
689
690   * attempt to recover that version
691   * if not possible, remove it from the list, go to next one
692   * if recovered, start at beginning of peer list, push that version,
693     continue until N shares are placed
694   * if pushing our own version, bump up the seqnum to one higher than
695     the max seqnum we saw
696   * if we run out of servers:
697
698     * schedule retry and exponential backoff to repeat RECOVERY
699
700   * admit defeat after some period? presumeably the client will be shut down
701     eventually, maybe keep trying (once per hour?) until then.
702
703
704 Medium Distributed Mutable Files
705 ================================
706
707 These are just like the SDMF case, but:
708
709 * We actually take advantage of the Merkle hash tree over the blocks, by
710   reading a single segment of data at a time (and its necessary hashes), to
711   reduce the read-time alacrity.
712 * We allow arbitrary writes to any range of the file.
713 * We add more code to first read each segment that a write must modify.
714   This looks exactly like the way a normal filesystem uses a block device,
715   or how a CPU must perform a cache-line fill before modifying a single word.
716 * We might implement some sort of copy-based atomic update server call,
717   to allow multiple writev() calls to appear atomic to any readers.
718
719 MDMF slots provide fairly efficient in-place edits of very large files (a few
720 GB). Appending data is also fairly efficient.
721
722
723 Large Distributed Mutable Files
724 ===============================
725
726 LDMF slots (not implemented) would use a fundamentally different way to store
727 the file, inspired by Mercurial's "revlog" format. This would enable very
728 efficient insert/remove/replace editing of arbitrary spans. Multiple versions
729 of the file can be retained, in a revision graph that can have multiple heads.
730 Each revision can be referenced by a cryptographic identifier. There are two
731 forms of the URI, one that means "most recent version", and a longer one that
732 points to a specific revision.
733
734 Metadata can be attached to the revisions, like timestamps, to enable rolling
735 back an entire tree to a specific point in history.
736
737 LDMF1 provides deltas but tries to avoid dealing with multiple heads. LDMF2
738 provides explicit support for revision identifiers and branching.
739
740
741 TODO
742 ====
743
744 improve allocate-and-write or get-writer-buckets API to allow one-call (or
745 maybe two-call) updates. The challenge is in figuring out which shares are on
746 which machines. First cut will have lots of round trips.
747
748 (eventually) define behavior when seqnum wraps. At the very least make sure
749 it can't cause a security problem. "the slot is worn out" is acceptable.
750
751 (eventually) define share-migration lease update protocol. Including the
752 nodeid who accepted the lease is useful, we can use the same protocol as we
753 do for updating the write enabler. However we need to know which lease to
754 update.. maybe send back a list of all old nodeids that we find, then try all
755 of them when we accept the update?
756
757 We now do this in a specially-formatted IndexError exception:
758  "UNABLE to renew non-existent lease. I have leases accepted by " +
759  "nodeids: '12345','abcde','44221' ."
760
761 confirm that a repairer can regenerate shares without the private key. Hmm,
762 without the write-enabler they won't be able to write those shares to the
763 servers.. although they could add immutable new shares to new servers.