|
| 1 | +# Build Trace |
| 2 | + |
| 3 | +> **Warning** |
| 4 | +> |
| 5 | +> This entire concept is currently |
| 6 | +> [**experimental**](@docroot@/development/experimental-features.md#xp-feature-ca-derivations) |
| 7 | +> and subject to change. |
| 8 | +
|
| 9 | +The *build trace* is a [memoization table](https://en.wikipedia.org/wiki/Memoization) for builds. |
| 10 | +It maps the inputs of builds to the outputs of builds. |
| 11 | +Concretely, that means it maps [derivations][derivation] to maps of [output] names to [store objects][store object]. |
| 12 | + |
| 13 | +In general the derivations used as a key should be [*resolved*](./resolution.md). |
| 14 | +A build trace with all-resolved-derivation keys is also called a *base build trace* for extra clarity. |
| 15 | +If all the resolved inputs of a derivation are content-addressed, that means the inputs will be fully determined, leaving no ambiguity for what build was performed. |
| 16 | +(Input-addressed inputs however are still ambiguous. They too should be locked down, but this is left as future work.) |
| 17 | + |
| 18 | +Accordingly, to look up an unresolved derivation, one must first resolve it to get a resolved derivation. |
| 19 | +Resolving itself involves looking up entries in the build trace, so this is a mutually recursive process that will end up inspecting possibly many entries. |
| 20 | + |
| 21 | +Except for the issue with input-addressed paths called out above, base build traces are trivially *coherent* -- incoherence is not possible. |
| 22 | +That means that the claims that each key-value base build try entry makes are independent, and no mapping invalidates another mapping. |
| 23 | + |
| 24 | +Whether the mappings are *true*, i.e. the faithful recording of actual builds performed, is another matter. |
| 25 | +Coherence is about the multiple claims of the build trace being mutually consistent, not about whether the claims are individually true or false. |
| 26 | + |
| 27 | +In general, there is no way to audit a build trace entry except for by performing the build again from scratch. |
| 28 | +And even in that case, a different result doesn't mean the original entry was a "lie", because the derivation being built may be non-deterministic. |
| 29 | +As such, the decision of whether to trust a counterparty's build trace is a fundamentally subject policy choice. |
| 30 | +Build trace entries are typically *signed* in order to enable arbitrary public-key-based trust polices. |
| 31 | + |
| 32 | +## Derived build traces |
| 33 | + |
| 34 | +Implementations that wish to memoize the above may also keep additional *derived* build trace entries that do map unresolved derivations. |
| 35 | +But if they do so, they *must* also keep the underlying base entries with resolved derivation keys around. |
| 36 | +Firstly, this ensures that the derived entries are merely cache, which could be recomputed from scratch. |
| 37 | +Secondly, this ensures the coherence of the derived build trace. |
| 38 | + |
| 39 | +Unlike with base build traces, incoherence with derived build traces is possible. |
| 40 | +The key ingredient is that derivation resolution is only deterministic with respect to a fixed base build trace. |
| 41 | +Without fixing the base build trace, it inherits the subjectivity of base build traces themselves. |
| 42 | + |
| 43 | +Concretely, suppose there are three derivations \\(a\\), \\(b\\), and \((c\\). |
| 44 | +Let \\(a\\) be a resolved derivation, but let \\(b\\) and \((c\\) be unresolved and both take as an input an output of \\(a\\). |
| 45 | +Now suppose that derived entries are made for \\(b\\) and \((c\\) based on two different entries of \\(a\\). |
| 46 | +(This could happen if \\(a\\) is non-deterministic, \\(a\\) and \\(b\\) are built in one store, \\(a\\) and \\(c\\) are built in another store, and then a third store substitutes from both of the first two stores.) |
| 47 | + |
| 48 | +If trusting the derived build trace entries for \\(b\\) and \((c\\) requires that each's underlying entry for \\(a\\) be also trusted, the two different mappings for \\(a\\) will be caught. |
| 49 | +However, if \\(b\\) and \((c\\)'s entries can be combined in isolation, there will be nothing to catch the contradiction in their hidden assumptions about \\(a\\)'s output. |
| 50 | + |
| 51 | +[derivation]: ./derivation/index.md |
| 52 | +[output]: ./derivation/outputs/index.md |
| 53 | +[store object]: @docroot@/store/store-object.md |
0 commit comments