aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/path-info.hh
blob: 9af1309a0b5eb8183b74871947054463dece5581 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#pragma once
///@file

#include "crypto.hh"
#include "path.hh"
#include "hash.hh"
#include "content-address.hh"

#include <string>
#include <optional>

namespace nix {


class Store;


struct SubstitutablePathInfo
{
    std::optional<StorePath> deriver;
    StorePathSet references;
    /**
     * 0 = unknown or inapplicable
     */
    uint64_t downloadSize;
    /**
     * 0 = unknown
     */
    uint64_t narSize;
};

typedef std::map<StorePath, SubstitutablePathInfo> SubstitutablePathInfos;


struct ValidPathInfo
{
    StorePath path;
    std::optional<StorePath> deriver;
    /**
     * \todo document this
     */
    Hash narHash;
    StorePathSet references;
    time_t registrationTime = 0;
    uint64_t narSize = 0; // 0 = unknown
    uint64_t id; // internal use only

    /**
     * Whether the path is ultimately trusted, that is, it's a
     * derivation output that was built locally.
     */
    bool ultimate = false;

    StringSet sigs; // note: not necessarily verified

    /**
     * If non-empty, an assertion that the path is content-addressed,
     * i.e., that the store path is computed from a cryptographic hash
     * of the contents of the path, plus some other bits of data like
     * the "name" part of the path. Such a path doesn't need
     * signatures, since we don't have to trust anybody's claim that
     * the path is the output of a particular derivation. (In the
     * extensional store model, we have to trust that the *contents*
     * of an output path of a derivation were actually produced by
     * that derivation. In the intensional model, we have to trust
     * that a particular output path was produced by a derivation; the
     * path then implies the contents.)
     *
     * Ideally, the content-addressability assertion would just be a Boolean,
     * and the store path would be computed from the name component, ‘narHash’
     * and ‘references’. However, we support many types of content addresses.
     */
    std::optional<ContentAddress> ca;

    bool operator == (const ValidPathInfo & i) const
    {
        return
            path == i.path
            && narHash == i.narHash
            && references == i.references;
    }

    /**
     * Return a fingerprint of the store path to be used in binary
     * cache signatures. It contains the store path, the base-32
     * SHA-256 hash of the NAR serialisation of the path, the size of
     * the NAR, and the sorted references. The size field is strictly
     * speaking superfluous, but might prevent endless/excessive data
     * attacks.
     */
    std::string fingerprint(const Store & store) const;

    void sign(const Store & store, const SecretKey & secretKey);

    /**
     * @return true iff the path is verifiably content-addressed.
     */
    bool isContentAddressed(const Store & store) const;

    static const size_t maxSigs = std::numeric_limits<size_t>::max();

    /**
     * Return the number of signatures on this .narinfo that were
     * produced by one of the specified keys, or maxSigs if the path
     * is content-addressed.
     */
    size_t checkSignatures(const Store & store, const PublicKeys & publicKeys) const;

    /**
     * Verify a single signature.
     */
    bool checkSignature(const Store & store, const PublicKeys & publicKeys, const std::string & sig) const;

    Strings shortRefs() const;

    ValidPathInfo(const ValidPathInfo & other) = default;

    ValidPathInfo(StorePath && path, Hash narHash) : path(std::move(path)), narHash(narHash) { };
    ValidPathInfo(const StorePath & path, Hash narHash) : path(path), narHash(narHash) { };

    virtual ~ValidPathInfo() { }

    static ValidPathInfo read(Source & source, const Store & store, unsigned int format);
    static ValidPathInfo read(Source & source, const Store & store, unsigned int format, StorePath && path);

    void write(Sink & sink, const Store & store, unsigned int format, bool includePath = true) const;
};

typedef std::map<StorePath, ValidPathInfo> ValidPathInfos;

}