|
7 | 7 |
|
8 | 8 | #include <libp2p/multi/content_identifier_codec.hpp>
|
9 | 9 |
|
| 10 | +#include "codec/uvarint.hpp" |
10 | 11 | #include "crypto/blake2/blake2b160.hpp"
|
11 | 12 |
|
| 13 | +using Multicodec = libp2p::multi::MulticodecType::Code; |
| 14 | +using libp2p::multi::HashType; |
| 15 | +using libp2p::multi::Multihash; |
| 16 | + |
12 | 17 | namespace fc {
|
13 |
| - CID::CID() |
14 |
| - : ContentIdentifier( |
15 |
| - {}, {}, libp2p::multi::Multihash::create({}, {}).value()) {} |
| 18 | + CID::CID() : ContentIdentifier({}, {}, Multihash::create({}, {}).value()) {} |
16 | 19 |
|
17 | 20 | CID::CID(const ContentIdentifier &cid) : ContentIdentifier(cid) {}
|
18 | 21 |
|
19 | 22 | CID::CID(ContentIdentifier &&cid) noexcept
|
20 | 23 | : ContentIdentifier(
|
21 | 24 | cid.version, cid.content_type, std::move(cid.content_address)) {}
|
22 | 25 |
|
23 |
| - CID::CID(Version version, |
24 |
| - libp2p::multi::MulticodecType::Code content_type, |
25 |
| - libp2p::multi::Multihash content_address) |
| 26 | + CID::CID(Version version, Multicodec content_type, Multihash content_address) |
26 | 27 | : ContentIdentifier(version, content_type, std::move(content_address)) {}
|
27 | 28 |
|
28 | 29 | CID &CID::operator=(CID &&cid) noexcept {
|
@@ -67,14 +68,60 @@ namespace fc {
|
67 | 68 | OUTCOME_TRY(cid, libp2p::multi::ContentIdentifierCodec::decode(input));
|
68 | 69 | return CID{std::move(cid)};
|
69 | 70 | }
|
| 71 | + |
| 72 | + outcome::result<CID> CID::read(gsl::span<const uint8_t> &input, bool prefix) { |
| 73 | + using Error = libp2p::multi::ContentIdentifierCodec::DecodeError; |
| 74 | + CID cid; |
| 75 | + if (input.size() >= 2 && HashType{input[0]} == HashType::sha256 |
| 76 | + && input[1] == 32) { |
| 77 | + cid.version = Version::V0; |
| 78 | + cid.content_type = Multicodec::DAG_PB; |
| 79 | + if (!prefix && input.size() < 34) { |
| 80 | + return Multihash::Error::INCONSISTENT_LENGTH; |
| 81 | + } |
| 82 | + } else { |
| 83 | + OUTCOME_TRY(version, |
| 84 | + codec::uvarint::read<Error::EMPTY_VERSION, Version>(input)); |
| 85 | + if (version <= Version::V0) { |
| 86 | + return Error::MALFORMED_VERSION; |
| 87 | + } |
| 88 | + if (version != Version::V1) { |
| 89 | + return Error::RESERVED_VERSION; |
| 90 | + } |
| 91 | + cid.version = version; |
| 92 | + OUTCOME_TRY( |
| 93 | + codec, |
| 94 | + codec::uvarint::read<Error::EMPTY_MULTICODEC, Multicodec>(input)); |
| 95 | + cid.content_type = codec; |
| 96 | + } |
| 97 | + |
| 98 | + OUTCOME_TRY( |
| 99 | + hash_type, |
| 100 | + codec::uvarint::read<Multihash::Error::ZERO_INPUT_LENGTH, HashType>( |
| 101 | + input)); |
| 102 | + OUTCOME_TRY(hash_size, |
| 103 | + codec::uvarint::read<Multihash::Error::INPUT_TOO_SHORT>(input)); |
| 104 | + gsl::span<const uint8_t> hash_span; |
| 105 | + if (prefix) { |
| 106 | + static const uint8_t empty[Multihash::kMaxHashLength]{}; |
| 107 | + hash_span = gsl::make_span(empty, hash_size); |
| 108 | + } else { |
| 109 | + if (input.size() < static_cast<ptrdiff_t>(hash_size)) { |
| 110 | + return Multihash::Error::INCONSISTENT_LENGTH; |
| 111 | + } |
| 112 | + hash_span = input.subspan(0, hash_size); |
| 113 | + input = input.subspan(hash_size); |
| 114 | + } |
| 115 | + OUTCOME_TRY(hash, Multihash::create(hash_type, hash_span)); |
| 116 | + cid.content_address = std::move(hash); |
| 117 | + return cid; |
| 118 | + } |
70 | 119 | } // namespace fc
|
71 | 120 |
|
72 | 121 | namespace fc::common {
|
73 | 122 | outcome::result<CID> getCidOf(gsl::span<const uint8_t> bytes) {
|
74 | 123 | auto hash_raw = crypto::blake2b::blake2b_256(bytes);
|
75 |
| - OUTCOME_TRY(hash, |
76 |
| - libp2p::multi::Multihash::create( |
77 |
| - libp2p::multi::HashType::blake2b_256, hash_raw)); |
78 |
| - return CID(CID::Version::V1, libp2p::multi::MulticodecType::DAG_CBOR, hash); |
| 124 | + OUTCOME_TRY(hash, Multihash::create(HashType::blake2b_256, hash_raw)); |
| 125 | + return CID(CID::Version::V1, Multicodec::DAG_CBOR, hash); |
79 | 126 | }
|
80 | 127 | } // namespace fc::common
|
0 commit comments