Skip to content

Commit 3a1994e

Browse files
author
Yura Zarudniy
authored
Tickets (#61)
* implement feature Signed-off-by: Yura Zarudniy <[email protected]> * remove redundant comments Signed-off-by: Yura Zarudniy <[email protected]> * complete cbor-operators Signed-off-by: Yura Zarudniy <[email protected]> * add comments, fix ticket decode Signed-off-by: Yura Zarudniy <[email protected]> * fix encode/decode EPostProof Signed-off-by: Yura Zarudniy <[email protected]> * Correct epostticket serialization order Move address tests to address folder add folder and files for ticket tests Signed-off-by: Yura Zarudniy <[email protected]> * add testutils and tests for ticket Signed-off-by: Yura Zarudniy <[email protected]> * fix clang-tidy issue Signed-off-by: Yura Zarudniy <[email protected]> * rename test file Signed-off-by: Yura Zarudniy <[email protected]> * add tests for ticket codec Signed-off-by: Yura Zarudniy <[email protected]> * implement all tests Signed-off-by: Yura Zarudniy <[email protected]> * fix review issues Signed-off-by: Yura Zarudniy <[email protected]>
1 parent e8b69b6 commit 3a1994e

31 files changed

+1142
-26
lines changed

core/primitives/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
#
55

66
add_subdirectory(address)
7+
add_subdirectory(ticket)

core/primitives/ticket/CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright Soramitsu Co., Ltd. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
add_library(tickets
5+
ticket.cpp
6+
epost_ticket.cpp
7+
ticket_codec.cpp
8+
epost_ticket_codec.cpp
9+
)
10+
target_link_libraries(tickets
11+
blob
12+
buffer
13+
cbor
14+
p2p::p2p_sha
15+
)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#include "primitives/ticket/epost_ticket.hpp"
7+
8+
namespace fc::primitives::ticket {
9+
bool operator==(const EPostTicket &lhs, const EPostTicket &rhs) {
10+
return lhs.partial == rhs.partial && lhs.sector_id == rhs.sector_id
11+
&& lhs.challenge_index == rhs.challenge_index;
12+
}
13+
14+
bool operator==(const EPostProof &lhs, const EPostProof &rhs) {
15+
return lhs.proof == rhs.proof && lhs.post_rand == rhs.post_rand
16+
&& lhs.candidates == rhs.candidates;
17+
}
18+
} // namespace fc::primitives::ticket
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#ifndef CPP_FILECOIN_CORE_PRIMITIVES_TICKET_EPOST_TICKET_HPP
7+
#define CPP_FILECOIN_CORE_PRIMITIVES_TICKET_EPOST_TICKET_HPP
8+
9+
#include "common/blob.hpp"
10+
#include "common/buffer.hpp"
11+
#include "crypto/vrf/vrf_types.hpp"
12+
13+
namespace fc::primitives::ticket {
14+
/**
15+
* @struct EPostTicket proof of space/time ticket
16+
* https://github.com/filecoin-project/lotus/blob/2e95a536790113df7bcc95bc9215301fda23b65d/chain/types/blockheader.go#L23
17+
*/
18+
struct EPostTicket {
19+
common::Blob<32> partial;
20+
uint64_t sector_id{};
21+
uint64_t challenge_index{};
22+
};
23+
24+
using PostRandomness = crypto::vrf::VRFResult;
25+
26+
/**
27+
* @struct EPostProof proof of space/time
28+
*/
29+
struct EPostProof {
30+
common::Buffer proof; ///< number of bytes is not known beforehand
31+
PostRandomness post_rand; ///< randomness
32+
std::vector<EPostTicket> candidates; ///< candidates
33+
};
34+
35+
/**
36+
* @brief compares 2 tickets
37+
* @param lhs first ticket
38+
* @param rhs second ticket
39+
* @return true if equal false otherwise
40+
*/
41+
bool operator==(const EPostTicket &lhs, const EPostTicket &rhs);
42+
43+
/**
44+
* @brief compares 2 proofs
45+
* @param lhs first proof
46+
* @param rhs second proof
47+
* @return true if equal false otherwise
48+
*/
49+
bool operator==(const EPostProof &lhs, const EPostProof &rhs);
50+
51+
} // namespace fc::primitives::ticket
52+
53+
#endif // CPP_FILECOIN_CORE_PRIMITIVES_TICKET_EPOST_TICKET_HPP
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#include "primitives/ticket/epost_ticket_codec.hpp"
7+
8+
9+
OUTCOME_CPP_DEFINE_CATEGORY(fc::primitives::ticket, EPoSTTicketCodecError, e) {
10+
using fc::primitives::ticket::EPoSTTicketCodecError;
11+
switch (e) {
12+
case (EPoSTTicketCodecError::INVALID_PARTIAL_LENGTH):
13+
return "Invalid data size of field `partial`";
14+
case (EPoSTTicketCodecError::INVALID_POST_RAND_LENGTH):
15+
return "Invalid data size of field `post_rand`";
16+
}
17+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#ifndef CPP_FILECOIN_CORE_PRIMITIVES_TICKET_EPOST_TICKET_CODEC_HPP
7+
#define CPP_FILECOIN_CORE_PRIMITIVES_TICKET_EPOST_TICKET_CODEC_HPP
8+
9+
#include <vector>
10+
11+
#include "codec/cbor/cbor.hpp"
12+
#include "common/outcome.hpp"
13+
#include "common/outcome_throw.hpp"
14+
#include "primitives/ticket/epost_ticket.hpp"
15+
16+
namespace fc::primitives::ticket {
17+
enum class EPoSTTicketCodecError : int {
18+
INVALID_PARTIAL_LENGTH = 1, // invalid length of field partial
19+
INVALID_POST_RAND_LENGTH, // invalid length of field post_rand
20+
};
21+
22+
/**
23+
* @brief cbor-encode EPostTicket instance
24+
* @tparam Stream cbor-encoder stream type
25+
* @param s stream reference
26+
* @param ticket Ticket const reference to encode
27+
* @return stream reference
28+
*/
29+
template <class Stream,
30+
typename = std::enable_if_t<
31+
std::remove_reference<Stream>::type::is_cbor_encoder_stream>>
32+
Stream &operator<<(Stream &&s, const EPostTicket &ticket) noexcept {
33+
return s << (s.list() << ticket.partial << ticket.sector_id
34+
<< ticket.challenge_index);
35+
}
36+
37+
/**
38+
* @brief cbor-decode EPostTicket instance
39+
* @tparam Stream cbor-decoder stream type
40+
* @param s stream reference
41+
* @param ticket Ticket reference to decode into
42+
* @return stream reference
43+
*/
44+
template <class Stream,
45+
typename = std::enable_if_t<
46+
std::remove_reference<Stream>::type::is_cbor_decoder_stream>>
47+
Stream &operator>>(Stream &&s, EPostTicket &ticket) {
48+
auto &&l = s.list();
49+
std::vector<uint8_t> data{};
50+
51+
l >> data;
52+
if (data.size() != ticket.partial.size()) {
53+
outcome::raise(EPoSTTicketCodecError::INVALID_PARTIAL_LENGTH);
54+
}
55+
std::copy(data.begin(), data.end(), ticket.partial.begin());
56+
l >> ticket.sector_id >> ticket.challenge_index;
57+
return s;
58+
}
59+
60+
/**
61+
* @brief cbor-encodes EPostProof instance
62+
* @tparam Stream cbor-encoder stream type
63+
* @param s stream reference
64+
* @param epp EPostProof const reference to encode
65+
* @return stream reference
66+
*/
67+
template <class Stream,
68+
typename = std::enable_if_t<
69+
std::remove_reference<Stream>::type::is_cbor_encoder_stream>>
70+
Stream &operator<<(Stream &&s, const EPostProof &epp) noexcept {
71+
auto && list = s.list();
72+
list << epp.proof << epp.post_rand;
73+
auto &&l = list.list();
74+
for (auto &item : epp.candidates) {
75+
l << item;
76+
}
77+
78+
return s << (list << l);
79+
}
80+
81+
/**
82+
* @brief cbor-decodes EPostProof instance
83+
* @tparam Stream cbor-decoder stream type
84+
* @param s stream reference
85+
* @param epp EPostProof refefence to decode into
86+
* @return stream reference
87+
*/
88+
template <class Stream,
89+
typename = std::enable_if_t<
90+
std::remove_reference<Stream>::type::is_cbor_decoder_stream>>
91+
Stream &operator>>(Stream &&s, EPostProof &epp) {
92+
std::vector<uint8_t> proof{};
93+
auto &&list = s.list();
94+
list >> proof;
95+
epp.proof = common::Buffer(std::move(proof));
96+
std::vector<uint8_t> rand{};
97+
list >> rand;
98+
if (rand.size() != epp.post_rand.size()) {
99+
outcome::raise(EPoSTTicketCodecError::INVALID_POST_RAND_LENGTH);
100+
}
101+
std::copy(rand.begin(), rand.end(), epp.post_rand.begin());
102+
103+
auto n = list.listLength();
104+
std::vector<EPostTicket> candidates{};
105+
candidates.reserve(n);
106+
107+
auto &&l = list.list();
108+
for (size_t i = 0; i < n; ++i) {
109+
EPostTicket ticket{};
110+
l >> ticket;
111+
candidates.push_back(ticket);
112+
}
113+
114+
epp.candidates = std::move(candidates);
115+
116+
return s;
117+
}
118+
} // namespace fc::primitives::ticket
119+
120+
/**
121+
* @brief tickets encode/decode Outcome errors declaration
122+
*/
123+
OUTCOME_HPP_DECLARE_ERROR(fc::primitives::ticket, EPoSTTicketCodecError)
124+
125+
#endif // CPP_FILECOIN_CORE_PRIMITIVES_TICKET_EPOST_TICKET_CODEC_HPP

core/primitives/ticket/ticket.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#include "primitives/ticket/ticket.hpp"
7+
8+
#include "common/le_encoder.hpp"
9+
10+
namespace fc::primitives::ticket {
11+
using crypto::randomness::Randomness;
12+
13+
libp2p::outcome::result<Randomness> drawRandomness(const Ticket &ticket,
14+
int64_t round) {
15+
common::Buffer buffer{};
16+
buffer.put(ticket.bytes);
17+
common::encodeInteger(round, buffer);
18+
auto &&hash = libp2p::crypto::sha256(buffer);
19+
20+
return Randomness::fromSpan(hash);
21+
}
22+
23+
bool operator==(const Ticket &lhs, const Ticket &rhs) {
24+
return lhs.bytes == rhs.bytes;
25+
}
26+
27+
bool operator<(const Ticket &lhs, const Ticket &rhs) {
28+
return lhs.bytes < rhs.bytes;
29+
}
30+
31+
} // namespace fc::primitives::ticket

core/primitives/ticket/ticket.hpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#ifndef CPP_FILECOIN_CORE_PRIMITIVES_TICKET_TICKET_HPP
7+
#define CPP_FILECOIN_CORE_PRIMITIVES_TICKET_TICKET_HPP
8+
9+
#include <libp2p/crypto/sha/sha256.hpp>
10+
#include "common/blob.hpp"
11+
#include "common/buffer.hpp"
12+
#include "common/outcome.hpp"
13+
#include "crypto/randomness/randomness_types.hpp"
14+
#include "crypto/vrf/vrf_types.hpp"
15+
16+
namespace fc::primitives::ticket {
17+
18+
/**
19+
* @struct Ticket
20+
* https://github.com/filecoin-project/lotus/blob/2e95a536790113df7bcc95bc9215301fda23b65d/chain/types/blockheader.go#L19
21+
*/
22+
struct Ticket {
23+
crypto::vrf::VRFProof bytes;
24+
};
25+
26+
/**
27+
* @brief compares 2 tickets
28+
* @param lhs first ticket
29+
* @param rhs second ticket
30+
* @return true if tickets are equal, false otherwise
31+
*/
32+
bool operator==(const Ticket &lhs, const Ticket &rhs);
33+
34+
/**
35+
* @brief compares two tickets alphabetically
36+
* @param lhs first ticket
37+
* @param rhs second ticket
38+
* @return true if lhs less thatn rhs, false othewise
39+
*/
40+
bool operator<(const Ticket &lhs, const Ticket &rhs);
41+
42+
/**
43+
* @brief draws randomness from ticket
44+
* @param ticket ticket
45+
* @param round round number
46+
* @return randomness value or error
47+
*/
48+
outcome::result<crypto::randomness::Randomness> drawRandomness(
49+
const Ticket &ticket, int64_t round);
50+
51+
} // namespace fc::primitives::ticket
52+
53+
#endif // CPP_FILECOIN_CORE_PRIMITIVES_TICKET_TICKET_HPP
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#include "primitives/ticket/ticket_codec.hpp"
7+
8+
OUTCOME_CPP_DEFINE_CATEGORY(fc::primitives::ticket, TicketCodecError, e) {
9+
using fc::primitives::ticket::TicketCodecError;
10+
switch (e) {
11+
case (TicketCodecError::INVALID_TICKET_LENGTH):
12+
return "Failed to decode ticket: invalid data length";
13+
}
14+
}
15+
16+
namespace fc::primitives::ticket {}
17+

0 commit comments

Comments
 (0)