Skip to content

Commit

Permalink
Merge pull request #56 from obsidiansystems/more-types
Browse files Browse the repository at this point in the history
Add types for IPFSHash in references
  • Loading branch information
Ericson2314 authored Jul 9, 2020
2 parents 73404ce + 2b44cb9 commit 2928587
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 71 deletions.
21 changes: 9 additions & 12 deletions src/libstore/content-address.cc
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,8 @@ std::string renderContentAddress(ContentAddress ca)
throw Error("ipfs info not handled");
return s;
},
[](IPFSCid ic) {
return renderLegacyContentAddress(std::variant<TextHash, FixedOutputHash, IPFSHash> {
IPFSHash {
.hash = Hash::parseAny(std::string(ic.cid, 9), htSHA256)
}
});
[](IPFSHash ic) {
return renderLegacyContentAddress(std::variant<TextHash, FixedOutputHash, IPFSHash> { ic });
}
}, ca.info);

Expand Down Expand Up @@ -205,9 +201,7 @@ ContentAddress parseContentAddress(std::string_view rawCa)
auto hash = std::get<IPFSHash>(ca);
return ContentAddress {
.name = name,
.info = IPFSCid {
.cid = "f01711220" + hash.hash.to_string(Base16, false)
}
.info = hash
};
} else throw Error("unknown content address type for '%s'", rawCa);
}
Expand Down Expand Up @@ -303,8 +297,8 @@ void to_json(nlohmann::json& j, const PathReferences<IPFSRef> & references)
auto refs = nlohmann::json::array();
for (auto & i : references.references) {
refs.push_back(nlohmann::json {
{ "name", i.second },
{ "cid", nlohmann::json {{ "/", i.first }} }
{ "name", i.name },
{ "cid", nlohmann::json {{ "/", "f01711220" + i.hash.hash.to_string(Base16, false) }} }
});
}

Expand All @@ -324,7 +318,10 @@ void from_json(const nlohmann::json& j, PathReferences<IPFSRef> & references)
for (auto & ref : j.at("references")) {
auto name = ref.at("name").get<std::string>();
auto cid = ref.at("cid").at("/").get<std::string>();
refs.insert(IPFSRef(cid, name));
refs.insert(IPFSRef {
.name = name,
.hash = Hash::parseAny(std::string(cid, 9), htSHA256)
});
}
references = PathReferences<IPFSRef> {
.references = refs,
Expand Down
21 changes: 13 additions & 8 deletions src/libstore/content-address.hh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct FixedOutputHash {
std::string printMethodAlgo() const;
};

// hash of some IPFSInfo
struct IPFSHash {
Hash hash;
};
Expand Down Expand Up @@ -139,27 +140,31 @@ struct FixedOutputInfo : FixedOutputHash {
PathReferences<StorePath> references;
};

// pair of cid and name for ipfs references
typedef std::pair<std::string, std::string> IPFSRef;
// pair of name and a hash of a content address
struct IPFSRef {
std::string name;
IPFSHash hash;

bool operator < (const IPFSRef & other) const
{
return name < other.name;
// FIXME second field
}
};

struct IPFSInfo {
Hash hash;
// References for the paths
PathReferences<IPFSRef> references;
};

// just the cid, which is a hash of ipfsinfo
struct IPFSCid {
std::string cid;
};

struct ContentAddress {
std::string name;
std::variant<
TextInfo,
FixedOutputInfo,
IPFSInfo,
IPFSCid
IPFSHash
> info;

bool operator < (const ContentAddress & other) const
Expand Down
15 changes: 7 additions & 8 deletions src/libstore/ipfs-binary-cache-store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -511,10 +511,8 @@ std::optional<std::string> IPFSBinaryCacheStore::getCidFromCA(ContentAddress ca)
assert(ca_.hash.type == htSHA1);
return "f01781114" + ca_.hash.to_string(Base16, false);
}
} else if (std::holds_alternative<IPFSInfo>(ca.info))
return computeIPFSCid(ca);
else if (std::holds_alternative<IPFSCid>(ca.info))
return std::get<IPFSCid>(ca.info).cid;
} else if (std::holds_alternative<IPFSHash>(ca.info))
return "f01711220" + std::get<IPFSHash>(ca.info).hash.to_string(Base16, false);

return std::nullopt;
}
Expand Down Expand Up @@ -667,10 +665,11 @@ void IPFSBinaryCacheStore::addToStore(const ValidPathInfo & info, Source & narSo

IPFSInfo caWithRefs { .hash = Hash::parseAny(std::string(key, 9), htSHA1) };
caWithRefs.references.hasSelfReference = info.hasSelfReference;
for (auto & ref : info.references) {
auto cid = std::get<IPFSHash>(*queryPathInfo(ref)->ca);
caWithRefs.references.references.insert(IPFSRef("f01711220" + cid.hash.to_string(Base16, false), ref.name()));
}
for (auto & ref : info.references)
caWithRefs.references.references.insert(IPFSRef {
.name = std::string(ref.name()),
.hash = std::get<IPFSHash>(*queryPathInfo(ref)->ca)
});

auto fullCa = *info.fullContentAddressOpt();
auto cid = getCidFromCA(fullCa);
Expand Down
51 changes: 20 additions & 31 deletions src/libstore/store-api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,10 @@ static std::vector<uint8_t> packMultihash(std::string cid)
return result;
}

Hash computeIPFSHash(const ContentAddress & info, HashType ht)
static IPFSHash computeIPFSHash(const ContentAddress & info)
{
assert(std::holds_alternative<IPFSInfo>(info.info));

nlohmann::json j = info;

// replace {"/": ...} with packed multihash
Expand All @@ -257,32 +259,19 @@ Hash computeIPFSHash(const ContentAddress & info, HashType ht)
ref.at("cid") = nlohmann::json::binary(packMultihash(ref.at("cid").at("/").get<std::string>()), 42);

std::vector<std::uint8_t> cbor = nlohmann::json::to_cbor(j);
return hashString(ht, std::string(cbor.begin(), cbor.end()));
}

std::string computeIPFSCid(const ContentAddress & info)
{
return "f01711220" + computeIPFSHash(info, htSHA256).to_string(Base16, false);
return IPFSHash { hashString(htSHA256, std::string(cbor.begin(), cbor.end())) };
}

StorePath Store::makeIPFSPath(IPFSRef ref) const
StorePath Store::makeIPFSPath(std::string name, IPFSHash hash) const
{
string type = "ipfs";
assert(hash.hash.type == htSHA256);
string cid = "f01711220" + hash.hash.to_string(Base16, false);

// copy pase from makeStorePath
string s = type + ":" + ref.first + ":" + storeDir + ":" + std::string(ref.second);
// copy paste from makeStorePath
string s = type + ":" + cid + ":" + storeDir + ":" + name;
auto h = compressHash(hashString(htSHA256, s), 20);
return StorePath(h, ref.second);
}

StorePath Store::makeIPFSPath(std::string cid, std::string name) const
{
return makeIPFSPath(IPFSRef(cid, name));
}

StorePath Store::makeIPFSPath(const ContentAddress & info) const
{
return makeIPFSPath(computeIPFSCid(info), info.name);
return StorePath(h, name);
}

StorePath Store::makeFixedOutputPathFromCA(const ContentAddress & info) const
Expand All @@ -296,10 +285,10 @@ StorePath Store::makeFixedOutputPathFromCA(const ContentAddress & info) const
return makeFixedOutputPath(info.name, foi);
},
[&](IPFSInfo io) {
return makeIPFSPath(info);
return makeIPFSPath(info.name, computeIPFSHash(info));
},
[&](IPFSCid ic) {
return makeIPFSPath(ic.cid, info.name);
[&](IPFSHash ic) {
return makeIPFSPath(info.name, ic);
}
}, info.info);
}
Expand Down Expand Up @@ -974,15 +963,15 @@ std::optional<ContentAddress> ValidPathInfo::fullContentAddressOpt() const
TextInfo info { th };
assert(!hasSelfReference);
info.references = references;
return std::variant<TextInfo, FixedOutputInfo, IPFSInfo, IPFSCid> { info };
return std::variant<TextInfo, FixedOutputInfo, IPFSInfo, IPFSHash> { info };
},
[&](FixedOutputHash foh) {
FixedOutputInfo info { foh };
info.references = static_cast<PathReferences<StorePath>>(*this);
return std::variant<TextInfo, FixedOutputInfo, IPFSInfo, IPFSCid> { info };
return std::variant<TextInfo, FixedOutputInfo, IPFSInfo, IPFSHash> { info };
},
[&](IPFSHash io) {
return std::variant<TextInfo, FixedOutputInfo, IPFSInfo, IPFSCid> { IPFSCid { "f01711220" + io.hash.to_string(Base16, false) } };
return std::variant<TextInfo, FixedOutputInfo, IPFSInfo, IPFSHash> { io };
},
}, *ca),
};
Expand Down Expand Up @@ -1050,11 +1039,11 @@ ValidPathInfo::ValidPathInfo(
[this, &store, info](IPFSInfo foi) {
this->hasSelfReference = foi.references.hasSelfReference;
for (auto & ref : foi.references.references)
this->references.insert(store.makeIPFSPath(ref));
this->ca = IPFSHash { computeIPFSHash(info, htSHA256) };
this->references.insert(store.makeIPFSPath(ref.name, ref.hash));
this->ca = IPFSHash { computeIPFSHash(info) };
},
[](IPFSCid foi) {
throw Error("cannot make a valid path from a cid");
[](IPFSHash foi) {
throw Error("cannot make a valid path from an ipfs hash without talking to the ipfs daemon");
},
}, std::move(info.info));
}
Expand Down
9 changes: 1 addition & 8 deletions src/libstore/store-api.hh
Original file line number Diff line number Diff line change
Expand Up @@ -264,11 +264,7 @@ public:

StorePath bakeCaIfNeeded(StorePathOrCA path) const;

StorePath makeIPFSPath(const ContentAddress & info) const;

StorePath makeIPFSPath(IPFSRef ref) const;

StorePath makeIPFSPath(std::string cid, std::string name) const;
StorePath makeIPFSPath(std::string name, IPFSHash hash) const;

/* This is the preparatory part of addToStore(); it computes the
store path to which srcPath is to be copied. Returns the store
Expand Down Expand Up @@ -771,8 +767,5 @@ std::pair<std::string, Store::Params> splitUriAndParams(const std::string & uri)

std::optional<ContentAddress> getDerivationCA(const BasicDerivation & drv);

Hash computeIPFSHash(const ContentAddress & info);
std::string computeIPFSCid(const ContentAddress & info);


}
9 changes: 5 additions & 4 deletions src/nix/make-content-addressable.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,11 @@ struct CmdMakeContentAddressable : StorePathsCommand, MixJSON
Hash gitHash = dumpGitHashWithCustomHash([&]{ return std::make_unique<HashModuloSink>(htSHA1, oldHashPart); }, (Path) tmpDir + "/tmp");

std::set<IPFSRef> ipfsRefs;
for (auto & ref : refs.references) {
auto cid = std::get<IPFSHash>(*store->queryPathInfo(ref)->ca);
ipfsRefs.insert(IPFSRef("f01711220" + cid.hash.to_string(Base16, false), ref.name()));
}
for (auto & ref : refs.references)
ipfsRefs.insert(IPFSRef {
.name = std::string(ref.name()),
.hash = std::get<IPFSHash>(*store->queryPathInfo(ref)->ca)
});
ca.info = IPFSInfo {
.hash = gitHash,
PathReferences<IPFSRef> {
Expand Down

0 comments on commit 2928587

Please sign in to comment.