Browse Source

sign gossip messages (#160)

Signed-off-by: turuslan <turuslan.devbox@gmail.com>
pull/161/head
Ruslan Tushov 3 years ago
committed by GitHub
parent
commit
45dbf9c403
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      example/03-gossip/gossip_chat_example.cpp
  2. 3
      example/03-gossip/utility.cpp
  3. 19
      include/libp2p/protocol/gossip/gossip.hpp
  4. 43
      src/protocol/gossip/impl/gossip_core.cpp
  5. 16
      src/protocol/gossip/impl/gossip_core.hpp
  6. 18
      src/protocol/gossip/impl/message_builder.cpp
  7. 2
      src/protocol/gossip/impl/message_builder.hpp

6
example/03-gossip/gossip_chat_example.cpp

@ -113,13 +113,17 @@ int main(int argc, char *argv[]) {
// create gossip node
auto gossip = libp2p::protocol::gossip::create(
injector.create<std::shared_ptr<libp2p::basic::Scheduler>>(), host,
injector.create<std::shared_ptr<libp2p::peer::IdentityManager>>(),
injector.create<std::shared_ptr<libp2p::crypto::CryptoProvider>>(),
injector
.create<std::shared_ptr<libp2p::crypto::marshaller::KeyMarshaller>>(),
std::move(config));
using Message = libp2p::protocol::gossip::Gossip::Message;
// subscribe to chat topic, print messages to the console
auto subscription = gossip->subscribe(
{options->topic}, [](boost::optional<const Message &> m) {
{options->topic}, [](const boost::optional<const Message &> &m) {
if (!m) {
// message with no value means EOS, this occurs when the node has
// stopped

3
example/03-gossip/utility.cpp

@ -52,7 +52,8 @@ namespace libp2p::protocol::example::utility {
boost::asio::ip::tcp::resolver resolver(io);
boost::asio::ip::tcp::resolver::query query(boost::asio::ip::host_name(),
"");
boost::asio::ip::tcp::resolver::iterator it = resolver.resolve(query);
boost::system::error_code ec;
boost::asio::ip::tcp::resolver::iterator it = resolver.resolve(query, ec);
boost::asio::ip::tcp::resolver::iterator end;
std::string addr("127.0.0.1");
while (it != end) {

19
include/libp2p/protocol/gossip/gossip.hpp

@ -24,6 +24,15 @@ namespace libp2p {
namespace basic {
class Scheduler;
}
namespace crypto {
class CryptoProvider;
namespace marshaller {
class KeyMarshaller;
}
} // namespace crypto
namespace peer {
class IdentityManager;
}
} // namespace libp2p
namespace libp2p::protocol::gossip {
@ -79,6 +88,9 @@ namespace libp2p::protocol::gossip {
/// Protocol version
std::string protocol_version = "/meshsub/1.0.0";
/// Sign published messages
bool sign_messages = false;
};
using common::ByteArray;
@ -142,8 +154,11 @@ namespace libp2p::protocol::gossip {
};
// Creates Gossip object
std::shared_ptr<Gossip> create(std::shared_ptr<basic::Scheduler> scheduler,
std::shared_ptr<Host> host,
std::shared_ptr<Gossip> create(
std::shared_ptr<basic::Scheduler> scheduler, std::shared_ptr<Host> host,
std::shared_ptr<peer::IdentityManager> idmgr,
std::shared_ptr<crypto::CryptoProvider> crypto_provider,
std::shared_ptr<crypto::marshaller::KeyMarshaller> key_marshaller,
Config config = Config{});
} // namespace libp2p::protocol::gossip

43
src/protocol/gossip/impl/gossip_core.cpp

@ -8,6 +8,9 @@
#include <cassert>
#include <libp2p/common/hexutil.hpp>
#include <libp2p/crypto/crypto_provider.hpp>
#include <libp2p/crypto/key_marshaller.hpp>
#include <libp2p/peer/identity_manager.hpp>
#include "connectivity.hpp"
#include "local_subscriptions.hpp"
@ -16,16 +19,25 @@
namespace libp2p::protocol::gossip {
std::shared_ptr<Gossip> create(std::shared_ptr<basic::Scheduler> scheduler,
std::shared_ptr<Host> host, Config config) {
std::shared_ptr<Gossip> create(
std::shared_ptr<basic::Scheduler> scheduler, std::shared_ptr<Host> host,
std::shared_ptr<peer::IdentityManager> idmgr,
std::shared_ptr<crypto::CryptoProvider> crypto_provider,
std::shared_ptr<crypto::marshaller::KeyMarshaller> key_marshaller,
Config config) {
return std::make_shared<GossipCore>(std::move(config), std::move(scheduler),
std::move(host));
std::move(host), std::move(idmgr),
std::move(crypto_provider),
std::move(key_marshaller));
}
// clang-format off
GossipCore::GossipCore(Config config,
std::shared_ptr<basic::Scheduler> scheduler,
std::shared_ptr<Host> host)
std::shared_ptr<Host> host,
std::shared_ptr<peer::IdentityManager> idmgr,
std::shared_ptr<crypto::CryptoProvider> crypto_provider,
std::shared_ptr<crypto::marshaller::KeyMarshaller> key_marshaller)
: config_(std::move(config)),
create_message_id_([](const ByteArray &from, const ByteArray &seq,
const ByteArray &data){
@ -33,6 +45,9 @@ namespace libp2p::protocol::gossip {
}),
scheduler_(std::move(scheduler)),
host_(std::move(host)),
idmgr_(std::move(idmgr)),
crypto_provider_(std::move(crypto_provider)),
key_marshaller_(std::move(key_marshaller)),
local_peer_id_(host_->getPeerInfo().id),
msg_cache_(
config_.message_cache_lifetime_msec,
@ -150,6 +165,13 @@ namespace libp2p::protocol::gossip {
auto msg = std::make_shared<TopicMessage>(
local_peer_id_, ++msg_seq_, std::move(data), std::move(topic));
if (config_.sign_messages) {
auto res = signMessage(*msg);
if (!res) {
log_.warn("signMessage error: {}", res.error().message());
}
}
MessageId msg_id = create_message_id_(msg->from, msg->seq_no, msg->data);
[[maybe_unused]] bool inserted = msg_cache_.insert(msg, msg_id);
@ -164,6 +186,19 @@ namespace libp2p::protocol::gossip {
return true;
}
outcome::result<void> GossipCore::signMessage(TopicMessage &msg) const {
const auto &keypair = idmgr_->getKeyPair();
OUTCOME_TRY(signable, MessageBuilder::signableMessage(msg));
OUTCOME_TRY(signature,
crypto_provider_->sign(signable, keypair.privateKey));
msg.signature = std::move(signature);
if (idmgr_->getId().toMultihash().getType() != multi::HashType::identity) {
OUTCOME_TRY(key, key_marshaller_->marshal(keypair.publicKey));
msg.key = std::move(key.key);
}
return outcome::success();
}
void GossipCore::onSubscription(const PeerContextPtr &peer, bool subscribe,
const TopicId &topic) {
assert(started_);

16
src/protocol/gossip/impl/gossip_core.hpp

@ -34,8 +34,12 @@ namespace libp2p::protocol::gossip {
GossipCore(GossipCore &&) = delete;
GossipCore &operator=(GossipCore &&) = delete;
GossipCore(Config config, std::shared_ptr<basic::Scheduler> scheduler,
std::shared_ptr<Host> host);
GossipCore(
Config config, std::shared_ptr<basic::Scheduler> scheduler,
std::shared_ptr<Host> host,
std::shared_ptr<peer::IdentityManager> idmgr,
std::shared_ptr<crypto::CryptoProvider> crypto_provider,
std::shared_ptr<crypto::marshaller::KeyMarshaller> key_marshaller);
~GossipCore() override = default;
@ -53,6 +57,8 @@ namespace libp2p::protocol::gossip {
SubscriptionCallback callback) override;
bool publish(TopicId topic, ByteArray data) override;
outcome::result<void> signMessage(TopicMessage &msg) const;
// MessageReceiver overrides
void onSubscription(const PeerContextPtr &from, bool subscribe,
const TopicId &topic) override;
@ -91,6 +97,12 @@ namespace libp2p::protocol::gossip {
/// Host (interface to libp2p network)
std::shared_ptr<Host> host_;
std::shared_ptr<peer::IdentityManager> idmgr_;
std::shared_ptr<crypto::CryptoProvider> crypto_provider_;
std::shared_ptr<crypto::marshaller::KeyMarshaller> key_marshaller_;
/// This peer's id
peer::PeerId local_peer_id_;

18
src/protocol/gossip/impl/message_builder.cpp

@ -169,4 +169,22 @@ namespace libp2p::protocol::gossip {
empty_ = false;
}
outcome::result<ByteArray> MessageBuilder::signableMessage(
const TopicMessage &msg) {
pubsub::pb::Message pb_msg;
pb_msg.set_from(msg.from.data(), msg.from.size());
pb_msg.set_data(msg.data.data(), msg.data.size());
pb_msg.set_seqno(msg.seq_no.data(), msg.seq_no.size());
pb_msg.set_topic(msg.topic);
constexpr std::string_view kPrefix{"libp2p-pubsub:"};
auto size = pb_msg.ByteSizeLong();
ByteArray signable;
signable.resize(kPrefix.size() + size);
std::copy(kPrefix.begin(), kPrefix.end(), signable.begin());
if (!pb_msg.SerializeToArray(&signable[kPrefix.size()],
static_cast<int>(size))) {
return outcome::failure(Error::MESSAGE_SERIALIZE_ERROR);
}
return signable;
}
} // namespace libp2p::protocol::gossip

2
src/protocol/gossip/impl/message_builder.hpp

@ -59,6 +59,8 @@ namespace libp2p::protocol::gossip {
/// Adds message to be forwarded
void addMessage(const TopicMessage &msg, const MessageId &msg_id);
static outcome::result<ByteArray> signableMessage(const TopicMessage &msg);
private:
/// Creates protobuf structures if needed
void create_protobuf_structures();

Loading…
Cancel
Save