Kagome
Polkadot Runtime Engine in C++17
vrf_provider_impl.cpp
Go to the documentation of this file.
1 
7 
8 #include <gsl/span>
9 
10 #include "common/mp_utils.hpp"
11 
12 namespace kagome::crypto {
13  namespace vrf_constants = constants::sr25519::vrf;
14 
15  VRFProviderImpl::VRFProviderImpl(std::shared_ptr<CSPRNG> generator)
16  : generator_{std::move(generator)} {}
17 
19  auto seed = generator_->randomBytes(constants::sr25519::SEED_SIZE);
20 
21  std::array<uint8_t, constants::sr25519::KEYPAIR_SIZE> kp{};
22  sr25519_keypair_from_seed(kp.data(), seed.data());
23 
24  Sr25519Keypair keypair;
25  std::copy(kp.begin(),
27  keypair.secret_key.begin());
28  std::copy(kp.begin() + constants::sr25519::SECRET_SIZE,
31  keypair.public_key.begin());
32  return keypair;
33  }
34 
35  std::optional<VRFOutput> VRFProviderImpl::signTranscript(
36  const primitives::Transcript &msg,
37  const Sr25519Keypair &keypair,
38  const VRFThreshold &threshold) const {
39  return signTranscriptImpl(msg, keypair, threshold);
40  }
41 
42  std::optional<VRFOutput> VRFProviderImpl::signTranscript(
43  const primitives::Transcript &msg, const Sr25519Keypair &keypair) const {
44  return signTranscriptImpl(msg, keypair, std::nullopt);
45  }
46 
47  std::optional<VRFOutput> VRFProviderImpl::signTranscriptImpl(
48  const primitives::Transcript &msg,
49  const Sr25519Keypair &keypair,
50  const std::optional<std::reference_wrapper<const VRFThreshold>> threshold)
51  const {
52  common::Buffer keypair_buf{};
53  keypair_buf.put(keypair.secret_key).put(keypair.public_key);
54 
55  std::array<uint8_t, vrf_constants::OUTPUT_SIZE + vrf_constants::PROOF_SIZE>
56  out_proof{};
57  auto threshold_value = threshold.value_or(std::cref(kMaxThreshold));
58  auto threshold_bytes = common::uint128_to_le_bytes(threshold_value);
59  auto sign_res = sr25519_vrf_sign_transcript(
60  out_proof.data(),
61  keypair_buf.data(),
62  reinterpret_cast<const Strobe128 *>(msg.data().data()), // NOLINT
63  threshold_bytes.data());
64 
65  if (SR25519_SIGNATURE_RESULT_OK != sign_res.result) {
66  return std::nullopt;
67  }
68  if (threshold.has_value() and not sign_res.is_less) {
69  return std::nullopt;
70  }
71 
72  VRFOutput res;
73  std::copy_n(
74  out_proof.begin(), vrf_constants::OUTPUT_SIZE, res.output.begin());
75  std::copy_n(out_proof.begin() + vrf_constants::OUTPUT_SIZE,
77  res.proof.begin());
78 
79  return res;
80  }
81 
83  const primitives::Transcript &msg,
84  const VRFOutput &output,
85  const Sr25519PublicKey &public_key,
86  const VRFThreshold &threshold) const {
87  auto res = sr25519_vrf_verify_transcript(
88  public_key.data(),
89  reinterpret_cast<const Strobe128 *>(msg.data().data()), // NOLINT
90  output.output.data(),
91  output.proof.data(),
92  common::uint128_to_le_bytes(threshold).data());
93  return VRFVerifyOutput{
94  .is_valid = res.result == SR25519_SIGNATURE_RESULT_OK,
95  .is_less = res.is_less};
96  }
97 
98  std::optional<VRFOutput> VRFProviderImpl::sign(
99  const common::Buffer &msg,
100  const Sr25519Keypair &keypair,
101  const VRFThreshold &threshold) const {
102  common::Buffer keypair_buf{};
103  keypair_buf.put(keypair.secret_key).put(keypair.public_key);
104 
105  std::array<uint8_t, vrf_constants::OUTPUT_SIZE + vrf_constants::PROOF_SIZE>
106  out_proof{};
107  auto threshold_bytes = common::uint128_to_le_bytes(threshold);
108  auto sign_res = sr25519_vrf_sign_if_less(out_proof.data(),
109  keypair_buf.data(),
110  msg.data(),
111  msg.size(),
112  threshold_bytes.data());
113  if (not sign_res.is_less
114  or (SR25519_SIGNATURE_RESULT_OK != sign_res.result)) {
115  return std::nullopt;
116  }
117 
118  VRFOutput res;
119  std::copy_n(
120  out_proof.begin(), vrf_constants::OUTPUT_SIZE, res.output.begin());
121  std::copy_n(out_proof.begin() + vrf_constants::OUTPUT_SIZE,
123  res.proof.begin());
124 
125  return res;
126  }
127 
129  const VRFOutput &output,
130  const Sr25519PublicKey &public_key,
131  const VRFThreshold &threshold) const {
132  auto res =
133  sr25519_vrf_verify(public_key.data(),
134  msg.data(),
135  msg.size(),
136  output.output.data(),
137  output.proof.data(),
138  common::uint128_to_le_bytes(threshold).data());
139  return VRFVerifyOutput{
140  .is_valid = res.result == SR25519_SIGNATURE_RESULT_OK,
141  .is_less = res.is_less};
142  }
143 
144 } // namespace kagome::crypto
Class represents arbitrary (including empty) byte buffer.
Definition: buffer.hpp:29
std::optional< VRFOutput > signTranscript(const primitives::Transcript &msg, const Sr25519Keypair &keypair, const VRFThreshold &threshold) const override
std::optional< VRFOutput > signTranscriptImpl(const primitives::Transcript &msg, const Sr25519Keypair &keypair, const std::optional< std::reference_wrapper< const VRFThreshold >> threshold) const
VRFVerifyOutput verifyTranscript(const primitives::Transcript &msg, const VRFOutput &output, const Sr25519PublicKey &public_key, const VRFThreshold &threshold) const override
boost::multiprecision::uint128_t VRFThreshold
Sr25519Keypair generateKeypair() const override
std::shared_ptr< CSPRNG > generator_
SLBuffer & put(std::string_view view)
Put a string into byte buffer.
Definition: buffer.hpp:117
std::array< uint8_t, 16 > uint128_to_le_bytes(const boost::multiprecision::uint128_t &i)
Definition: mp_utils.cpp:76
VRFVerifyOutput verify(const common::Buffer &msg, const VRFOutput &output, const Sr25519PublicKey &public_key, const VRFThreshold &threshold) const override
std::optional< VRFOutput > sign(const common::Buffer &msg, const Sr25519Keypair &keypair, const VRFThreshold &threshold) const override
VRFProviderImpl(std::shared_ptr< CSPRNG > generator)
static constexpr VRFThreshold kMaxThreshold