Skip to content

Commit d9689e7

Browse files
authored
FIL-72 Message component (#58)
Signed-off-by: Eugene Kovalev <[email protected]>
1 parent 1d2851c commit d9689e7

21 files changed

+796
-29
lines changed

core/crypto/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ add_subdirectory(bls)
88
add_subdirectory(murmur)
99
add_subdirectory(randomness)
1010
add_subdirectory(vrf)
11+
add_subdirectory(signature)

core/crypto/signature/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#
2+
# Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
# SPDX-License-Identifier: Apache-2.0
4+
#
5+
6+
add_library(signature
7+
signature.cpp
8+
)
9+
target_link_libraries(signature
10+
outcome
11+
)

core/crypto/signature/signature.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 "crypto/signature/signature.hpp"
7+
8+
OUTCOME_CPP_DEFINE_CATEGORY(fc::crypto::signature, SignatureError, e) {
9+
using fc::crypto::signature::SignatureError;
10+
switch (e) {
11+
case (SignatureError::INVALID_SIGNATURE_LENGTH):
12+
return "SignatureError: invalid signature length";
13+
case (SignatureError::WRONG_SIGNATURE_TYPE):
14+
return "SignatureError: wrong signature type";
15+
case (SignatureError::INVALID_KEY_LENGTH):
16+
return "SignatureError: invalid key length";
17+
default:
18+
return "SignatureError: unknown error";
19+
};
20+
}
21+
22+
namespace fc::crypto::signature {
23+
24+
Type typeCode(const Signature &s) {
25+
return visit_in_place(
26+
s,
27+
[](const BlsSignature &v) { return Type::BLS; },
28+
[](const Secp256k1Signature &v) { return Type::SECP256K1; });
29+
}
30+
31+
} // namespace fc::crypto::signature

core/crypto/signature/signature.hpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#ifndef CPP_FILECOIN_CRYPTO_SIGNATURE_HPP
7+
#define CPP_FILECOIN_CRYPTO_SIGNATURE_HPP
8+
9+
#include <boost/variant.hpp>
10+
11+
#include "codec/cbor/cbor.hpp"
12+
#include "common/outcome_throw.hpp"
13+
#include "common/visitor.hpp"
14+
#include "crypto/bls/bls_types.hpp"
15+
#include "crypto/secp256k1/secp256k1_provider.hpp"
16+
17+
namespace fc::crypto::signature {
18+
using BlsSignature = bls::Signature;
19+
using Secp256k1Signature = secp256k1::Signature;
20+
21+
enum Type : uint8_t { SECP256K1 = 0x1, BLS = 0x2 };
22+
23+
constexpr uint64_t kSignatureMaxLength = 200;
24+
25+
/**
26+
* @brief Signature error codes
27+
*/
28+
enum class SignatureError {
29+
INVALID_SIGNATURE_LENGTH = 1,
30+
WRONG_SIGNATURE_TYPE,
31+
INVALID_KEY_LENGTH
32+
};
33+
34+
struct Signature : public boost::variant<BlsSignature, Secp256k1Signature> {
35+
using variant::variant;
36+
using base_type = boost::variant<BlsSignature, Secp256k1Signature>;
37+
38+
inline bool operator==(const Signature &other) const {
39+
return base_type::operator==(static_cast<const base_type &>(other));
40+
}
41+
};
42+
43+
Type typeCode(const Signature &s);
44+
45+
template <class Stream,
46+
typename = std::enable_if_t<
47+
std::remove_reference<Stream>::type::is_cbor_encoder_stream>>
48+
Stream &operator<<(Stream &&s, const Signature &signature) noexcept {
49+
std::vector<uint8_t> bytes{};
50+
visit_in_place(signature,
51+
[&bytes](const BlsSignature &v) {
52+
bytes.push_back(BLS);
53+
return bytes.insert(bytes.end(), v.begin(), v.end());
54+
},
55+
[&bytes](const Secp256k1Signature &v) {
56+
bytes.push_back(SECP256K1);
57+
return bytes.insert(bytes.end(), v.begin(), v.end());
58+
});
59+
return s << bytes;
60+
}
61+
62+
template <class Stream,
63+
typename = std::enable_if_t<
64+
std::remove_reference<Stream>::type::is_cbor_decoder_stream>>
65+
Stream &operator>>(Stream &&s, Signature &signature) {
66+
std::vector<uint8_t> data{};
67+
s >> data;
68+
if (data.empty() || data.size() > kSignatureMaxLength) {
69+
outcome::raise(SignatureError::INVALID_SIGNATURE_LENGTH);
70+
}
71+
switch (data[0]) {
72+
case (SECP256K1):
73+
signature = Secp256k1Signature(std::next(data.begin()), data.end());
74+
break;
75+
case (BLS): {
76+
BlsSignature blsSig{};
77+
if (data.size() != blsSig.size() + 1) {
78+
outcome::raise(SignatureError::INVALID_SIGNATURE_LENGTH);
79+
}
80+
std::copy_n(std::make_move_iterator(std::next(data.begin())),
81+
blsSig.size(),
82+
blsSig.begin());
83+
signature = blsSig;
84+
break;
85+
}
86+
default:
87+
outcome::raise(SignatureError::WRONG_SIGNATURE_TYPE);
88+
};
89+
return s;
90+
}
91+
92+
} // namespace fc::crypto::signature
93+
94+
/**
95+
* @brief Outcome errors declaration
96+
*/
97+
OUTCOME_HPP_DECLARE_ERROR(fc::crypto::signature, SignatureError);
98+
99+
#endif // CPP_FILECOIN_CRYPTO_SIGNATURE_HPP

core/storage/keystore/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ target_link_libraries(keystore
1212
bls_provider
1313
filestore
1414
outcome
15+
signature
1516
)

core/storage/keystore/keystore.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "common/visitor.hpp"
1111

12+
using fc::crypto::signature::Signature;
1213
using fc::primitives::address::Protocol;
1314
using fc::storage::keystore::KeyStore;
1415
using fc::storage::keystore::KeyStoreError;
@@ -43,8 +44,8 @@ fc::outcome::result<bool> KeyStore::checkAddress(
4344
return KeyStoreError::WRONG_ADDRESS;
4445
}
4546

46-
fc::outcome::result<KeyStore::TSignature> KeyStore::sign(
47-
const Address &address, gsl::span<uint8_t> data) noexcept {
47+
fc::outcome::result<Signature> KeyStore::sign(
48+
const Address &address, gsl::span<const uint8_t> data) noexcept {
4849
OUTCOME_TRY(private_key, get(address));
4950
OUTCOME_TRY(valid, checkAddress(address, private_key));
5051
if (!valid) return KeyStoreError::WRONG_ADDRESS;
@@ -67,7 +68,7 @@ fc::outcome::result<KeyStore::TSignature> KeyStore::sign(
6768

6869
fc::outcome::result<bool> KeyStore::verify(const Address &address,
6970
gsl::span<const uint8_t> data,
70-
const TSignature &signature) const
71+
const Signature &signature) const
7172
noexcept {
7273
OUTCOME_TRY(private_key, get(address));
7374
OUTCOME_TRY(valid, checkAddress(address, private_key));

core/storage/keystore/keystore.hpp

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,31 @@
1313
#include "crypto/bls/bls_provider.hpp"
1414
#include "crypto/bls/bls_types.hpp"
1515
#include "crypto/secp256k1/secp256k1_provider.hpp"
16+
#include "crypto/signature/signature.hpp"
1617
#include "primitives/address/address.hpp"
1718
#include "primitives/address/address_verifier.hpp"
1819
#include "storage/keystore/keystore_error.hpp"
1920

2021
namespace fc::storage::keystore {
2122

2223
using crypto::bls::BlsProvider;
23-
using libp2p::crypto::secp256k1::Secp256k1Provider;
24+
using crypto::secp256k1::Secp256k1Provider;
25+
using BlsKeyPair = crypto::bls::KeyPair;
26+
using BlsPrivateKey = crypto::bls::PrivateKey;
27+
using BlsSignature = crypto::bls::Signature;
28+
using Secp256k1KeyPair = crypto::secp256k1::KeyPair;
29+
using Secp256k1PrivateKey = crypto::secp256k1::PrivateKey;
30+
using Secp256k1Signature = crypto::secp256k1::Signature;
31+
using crypto::signature::Signature;
2432
using primitives::address::Address;
25-
using BlsKeyPair = fc::crypto::bls::KeyPair;
26-
using BlsPrivateKey = fc::crypto::bls::PrivateKey;
27-
using BlsSignature = fc::crypto::bls::Signature;
28-
using Secp256k1KeyPair = libp2p::crypto::secp256k1::KeyPair;
29-
using Secp256k1PrivateKey = libp2p::crypto::secp256k1::PrivateKey;
30-
using Secp256k1Signature = libp2p::crypto::secp256k1::Signature;
31-
using fc::primitives::address::AddressVerifier;
33+
using primitives::address::AddressVerifier;
3234

3335
/**
3436
* An interface to a facility to store and use cryptographic keys
3537
*/
3638
class KeyStore {
3739
public:
3840
using TPrivateKey = boost::variant<BlsPrivateKey, Secp256k1PrivateKey>;
39-
using TSignature = boost::variant<BlsSignature, Secp256k1Signature>;
4041

4142
KeyStore(std::shared_ptr<BlsProvider> blsProvider,
4243
std::shared_ptr<Secp256k1Provider> secp256K1Provider,
@@ -77,8 +78,9 @@ namespace fc::storage::keystore {
7778
* @param data to sign
7879
* @return signature
7980
*/
80-
virtual outcome::result<TSignature> sign(const Address &address,
81-
gsl::span<uint8_t> data) noexcept;
81+
virtual outcome::result<Signature> sign(
82+
const Address &address, gsl::span<const uint8_t> data) noexcept;
83+
8284
/**
8385
* @brief verify signature
8486
* @param address of keypair
@@ -87,7 +89,7 @@ namespace fc::storage::keystore {
8789
*/
8890
virtual outcome::result<bool> verify(const Address &address,
8991
gsl::span<const uint8_t> data,
90-
const TSignature &signature) const
92+
const Signature &signature) const
9193
noexcept;
9294

9395
protected:

core/vm/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
add_subdirectory(actor)
77
add_subdirectory(exit_code)
88
add_subdirectory(state)
9+
add_subdirectory(message)

core/vm/message/CMakeLists.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#
2+
# Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
# SPDX-License-Identifier: Apache-2.0
4+
#
5+
6+
add_library(message
7+
message.cpp
8+
message_util.cpp
9+
impl/message_signer_impl.cpp
10+
)
11+
12+
target_link_libraries(message
13+
Boost::boost
14+
address
15+
logger
16+
keystore
17+
outcome
18+
signature
19+
)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#include "vm/message/impl/message_signer_impl.hpp"
7+
#include "vm/message/message_util.hpp"
8+
9+
namespace fc::vm::message {
10+
11+
MessageSignerImpl::MessageSignerImpl(std::shared_ptr<KeyStore> ks)
12+
: keystore_(std::move(ks)),
13+
logger_(common::createLogger("message_signer")) {}
14+
15+
outcome::result<SignedMessage> MessageSignerImpl::sign(
16+
const Address &address, const UnsignedMessage &msg) noexcept {
17+
auto maybe_cid = cid(msg);
18+
if (maybe_cid.has_error()) {
19+
logger_->error(maybe_cid.error().message());
20+
return outcome::failure(MessageError::SERIALIZATION_FAILURE);
21+
}
22+
auto maybe_cid_bytes =
23+
libp2p::multi::ContentIdentifierCodec::encode(maybe_cid.value());
24+
if (maybe_cid_bytes.has_error()) {
25+
logger_->error(maybe_cid_bytes.error().message());
26+
return outcome::failure(MessageError::SERIALIZATION_FAILURE);
27+
}
28+
OUTCOME_TRY(signature, keystore_->sign(address, maybe_cid_bytes.value()));
29+
return SignedMessage{msg, signature};
30+
}
31+
32+
outcome::result<UnsignedMessage> MessageSignerImpl::verify(
33+
const Address &address, const SignedMessage &msg) const noexcept {
34+
auto maybe_cid = cid(msg.message);
35+
if (maybe_cid.has_error()) {
36+
logger_->error(maybe_cid.error().message());
37+
return outcome::failure(MessageError::SERIALIZATION_FAILURE);
38+
}
39+
auto maybe_cid_bytes =
40+
libp2p::multi::ContentIdentifierCodec::encode(maybe_cid.value());
41+
if (maybe_cid_bytes.has_error()) {
42+
logger_->error(maybe_cid_bytes.error().message());
43+
return outcome::failure(MessageError::SERIALIZATION_FAILURE);
44+
}
45+
OUTCOME_TRY(
46+
res,
47+
keystore_->verify(address, maybe_cid_bytes.value(), msg.signature));
48+
if (!res) {
49+
return outcome::failure(MessageError::VERIFICATION_FAILURE);
50+
}
51+
return msg.message;
52+
}
53+
54+
}; // namespace fc::vm::message

0 commit comments

Comments
 (0)