Browse Source

Go Echo Client Compatibility (#8)

Signed-off-by: Akvinikym <anarant12@gmail.com>
pull/12/head
Akvinikym 5 years ago
committed by GitHub
parent
commit
84a81e1470
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .clang-tidy
  2. 1
      CMakeLists.txt
  3. 19
      example/01-echo/CMakeLists.txt
  4. 10
      example/01-echo/README.md
  5. 183
      example/01-echo/libp2p_client.go
  6. 64
      example/01-echo/libp2p_echo_server.cpp
  7. 6
      example/CMakeLists.txt
  8. 1
      include/libp2p/basic/reader.hpp
  9. 52
      include/libp2p/common/byteutil.hpp
  10. 41
      include/libp2p/common/literals.hpp
  11. 1
      include/libp2p/crypto/error.hpp
  12. 11
      include/libp2p/crypto/key.hpp
  13. 1
      include/libp2p/crypto/key_generator.hpp
  14. 14
      include/libp2p/crypto/key_marshaller.hpp
  15. 10
      include/libp2p/crypto/key_marshaller/key_marshaller_impl.hpp
  16. 29
      include/libp2p/crypto/protobuf/protobuf_key.hpp
  17. 4
      include/libp2p/crypto/sha/sha256.hpp
  18. 2
      include/libp2p/event/subscription.hpp
  19. 2
      include/libp2p/injector/host_injector.hpp
  20. 2
      include/libp2p/injector/network_injector.hpp
  21. 1
      include/libp2p/multi/hash_type.hpp
  22. 2
      include/libp2p/multi/multihash.hpp
  23. 21
      include/libp2p/muxer/yamux/yamux_frame.hpp
  24. 36
      include/libp2p/muxer/yamux/yamuxed_connection.hpp
  25. 2
      include/libp2p/network/impl/listener_manager_impl.hpp
  26. 8
      include/libp2p/outcome/outcome-register.hpp
  27. 5
      include/libp2p/peer/impl/identity_manager_impl.hpp
  28. 7
      include/libp2p/peer/peer_id.hpp
  29. 2
      include/libp2p/protocol/echo/echo.hpp
  30. 5
      include/libp2p/protocol/echo/echo_config.hpp
  31. 6
      include/libp2p/protocol/echo/server_echo_session.hpp
  32. 2
      include/libp2p/protocol/identify/identify_msg_processor.hpp
  33. 11
      include/libp2p/security/plaintext/exchange_message_marshaller.hpp
  34. 12
      include/libp2p/security/plaintext/exchange_message_marshaller_impl.hpp
  35. 24
      include/libp2p/security/plaintext/plaintext.hpp
  36. 23
      include/libp2p/security/plaintext/plaintext_connection.hpp
  37. 14
      src/common/CMakeLists.txt
  38. 32
      src/common/byteutil.cpp
  39. 46
      src/common/literals.cpp
  40. 2
      src/common/logger.cpp
  41. 2
      src/crypto/error.cpp
  42. 84
      src/crypto/key_generator/key_generator_impl.cpp
  43. 100
      src/crypto/key_marshaller/key_marshaller_impl.cpp
  44. 43
      src/crypto/key_validator/key_validator_impl.cpp
  45. 24
      src/crypto/protobuf/keys.proto
  46. 8
      src/host/basic_host/basic_host.cpp
  47. 2
      src/multi/multihash.cpp
  48. 1
      src/muxer/yamux/CMakeLists.txt
  49. 120
      src/muxer/yamux/yamux_frame.cpp
  50. 2
      src/muxer/yamux/yamux_stream.cpp
  51. 264
      src/muxer/yamux/yamuxed_connection.cpp
  52. 11
      src/peer/impl/identity_manager_impl.cpp
  53. 25
      src/peer/peer_id.cpp
  54. 28
      src/protocol/echo/server_echo_session.cpp
  55. 1
      src/protocol/identify/CMakeLists.txt
  56. 18
      src/protocol/identify/identify_msg_processor.cpp
  57. 3
      src/protocol/identify/observed_addresses.cpp
  58. 3
      src/protocol_muxer/multiselect/message_manager.cpp
  59. 40
      src/protocol_muxer/multiselect/multiselect.cpp
  60. 1
      src/security/plaintext/CMakeLists.txt
  61. 44
      src/security/plaintext/exchange_message_marshaller_impl.cpp
  62. 118
      src/security/plaintext/plaintext.cpp
  63. 37
      src/security/plaintext/plaintext_connection.cpp
  64. 11
      src/security/plaintext/plaintext_session.cpp
  65. 1
      test/acceptance/p2p/CMakeLists.txt
  66. 2
      test/acceptance/p2p/host/CMakeLists.txt
  67. 3
      test/acceptance/p2p/host/basic_host_test.cpp
  68. 37
      test/acceptance/p2p/host/peer/test_peer.cpp
  69. 39
      test/acceptance/p2p/host/peer/test_peer.hpp
  70. 33
      test/acceptance/p2p/muxer.cpp
  71. 1
      test/libp2p/common/CMakeLists.txt
  72. 2
      test/libp2p/common/hexutil_test.cpp
  73. 1
      test/libp2p/connection/security_conn/CMakeLists.txt
  74. 26
      test/libp2p/connection/security_conn/plaintext_connection_test.cpp
  75. 2
      test/libp2p/crypto/CMakeLists.txt
  76. 18
      test/libp2p/crypto/aes_test.cpp
  77. 4
      test/libp2p/crypto/hmac_test.cpp
  78. 24
      test/libp2p/crypto/key_generator_test.cpp
  79. 20
      test/libp2p/crypto/key_validator_test.cpp
  80. 30
      test/libp2p/crypto/marshaller_test.cpp
  81. 4
      test/libp2p/injector/network_injector_test.cpp
  82. 4
      test/libp2p/multi/CMakeLists.txt
  83. 4
      test/libp2p/multi/multiaddress_test.cpp
  84. 2
      test/libp2p/multi/multibase_codec_test.cpp
  85. 5
      test/libp2p/multi/multihash_test.cpp
  86. 8
      test/libp2p/multi/utils/string_from_to_bytes_test.cpp
  87. 3
      test/libp2p/muxer/yamux/CMakeLists.txt
  88. 4
      test/libp2p/muxer/yamux/yamux_acceptance_test.cpp
  89. 8
      test/libp2p/muxer/yamux/yamux_frame_test.cpp
  90. 2
      test/libp2p/muxer/yamux/yamux_integration_test.cpp
  91. 4
      test/libp2p/network/CMakeLists.txt
  92. 11
      test/libp2p/network/connection_manager_test.cpp
  93. 3
      test/libp2p/network/dialer_test.cpp
  94. 4
      test/libp2p/network/listener_manager_test.cpp
  95. 3
      test/libp2p/network/transport_manager_test.cpp
  96. 4
      test/libp2p/peer/CMakeLists.txt
  97. 1
      test/libp2p/peer/address_repository/CMakeLists.txt
  98. 4
      test/libp2p/peer/address_repository/inmem_address_repository_test.cpp
  99. 14
      test/libp2p/peer/key_book/inmem_key_repository_test.cpp
  100. 8
      test/libp2p/peer/peer_id_test.cpp

2
.clang-tidy

@ -1,5 +1,5 @@
---
Checks: '-*,clang-analyzer-*,clang-diagnostic-*,readability-*,modernize-*,boost-*,bugprone-*,cppcoreguidelines-*,google-*,hicpp-*,performance-*,readability-*,-google-readability-namespace-comments,-readability-inconsistent-declaration-parameter-name,-readability-braces-around-statements,-hicpp-signed-bitwise,-google-runtime-references,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-hicpp-explicit-conversions,-hicpp-uppercase-literal-suffix,-readability-uppercase-literal-suffix,-hicpp-special-member-functions,-bugprone-narrowing-conversions,-modernize-use-nodiscard'
Checks: '-*,clang-analyzer-*,clang-diagnostic-*,readability-*,modernize-*,boost-*,bugprone-*,cppcoreguidelines-*,google-*,hicpp-*,performance-*,readability-*,-google-readability-namespace-comments,-readability-inconsistent-declaration-parameter-name,-readability-braces-around-statements,-hicpp-signed-bitwise,-google-runtime-references,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-type-vararg,-readability-magic-numbers,-hicpp-explicit-conversions,-hicpp-uppercase-literal-suffix,-hicpp-member-init,-readability-uppercase-literal-suffix,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-type-member-init,-hicpp-vararg,-hicpp-no-array-decay,-hicpp-static-assert,-hicpp-special-member-functions,-bugprone-narrowing-conversions,-modernize-use-nodiscard'
WarningsAsErrors: 'modernize-*,cppcoreguidelines-*,boost-*,performance-*,google-build-using-namespace,readability-else-after-return,google-readability-todo'
HeaderFilterRegex: 'libp2p/.*\.hpp'
AnalyzeTemporaryDtors: false

1
CMakeLists.txt

@ -99,6 +99,7 @@ include_directories(
)
add_subdirectory(src)
add_subdirectory(example)
if(TESTING)

19
example/01-echo/CMakeLists.txt

@ -0,0 +1,19 @@
#
# Copyright Soramitsu Co., Ltd. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
#
add_executable(libp2p_echo_server
libp2p_echo_server.cpp
)
target_link_libraries(libp2p_echo_server
p2p_basic_host
p2p_default_network
p2p_peer_repository
p2p_inmem_address_repository
p2p_inmem_key_repository
p2p_inmem_protocol_repository
p2p_protocol_echo
p2p_literals
)

10
example/01-echo/README.md

@ -0,0 +1,10 @@
# Example Libp2p Echo Server
## To be moved into a separate repo and turned into a test
In order to build the C++ Libp2p Echo Server and test its compatibility with the Go Libp2p Echo Client, do the following:
1. Build a C++ target
2. Build a Go example via `go build libp2p_client.go`
3. Start a C++ server. It will run for some number of seconds
4. Execute `./libp2p_client -insecure -l 40011 -d /ip4/127.0.0.1/tcp/40010/ipfs/12D3KooWLs7RC93EGXZzn9YdKyZYYx3f9UjTLYNX1reThpCkFb83`
5. Watch how "Hello, world!" is exchanged between server and client

183
example/01-echo/libp2p_client.go

@ -0,0 +1,183 @@
package main
import (
"bufio"
"context"
"crypto/rand"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
mrand "math/rand"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/peerstore"
golog "github.com/ipfs/go-log"
ma "github.com/multiformats/go-multiaddr"
)
// makeBasicHost creates a LibP2P host with a random peer ID listening on the
// given multiaddress. It won't encrypt the connection if insecure is true.
func makeBasicHost(listenPort int, insecure bool, randseed int64) (host.Host, error) {
// If the seed is zero, use real cryptographic randomness. Otherwise, use a
// deterministic randomness source to make generated keys stay the same
// across multiple runs
var r io.Reader
if randseed == 0 {
r = rand.Reader
} else {
r = mrand.New(mrand.NewSource(randseed))
}
// Generate a key pair for this host. We will use it at least
// to obtain a valid host ID.
priv, p, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, r)
log.Println("============ %s", p)
if err != nil {
return nil, err
}
opts := []libp2p.Option{
libp2p.ListenAddrStrings(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", listenPort)),
libp2p.Identity(priv),
libp2p.DisableRelay(),
}
if insecure {
opts = append(opts, libp2p.NoSecurity)
}
basicHost, err := libp2p.New(context.Background(), opts...)
if err != nil {
return nil, err
}
// Build host multiaddress
hostAddr, _ := ma.NewMultiaddr(fmt.Sprintf("/ipfs/%s", basicHost.ID().Pretty()))
// Now we can build a full multiaddress to reach this host
// by encapsulating both addresses:
addr := basicHost.Addrs()[0]
fullAddr := addr.Encapsulate(hostAddr)
log.Printf("I am %s\n", fullAddr)
if insecure {
log.Printf("Now run \"./echo -l %d -d %s -insecure\" on a different terminal\n", listenPort+1, fullAddr)
} else {
log.Printf("Now run \"./echo -l %d -d %s\" on a different terminal\n", listenPort+1, fullAddr)
}
return basicHost, nil
}
func main() {
// LibP2P code uses golog to log messages. They log with different
// string IDs (i.e. "swarm"). We can control the verbosity level for
// all loggers with:
// golog.SetAllLoggers(golog.LevelInfo) // Change to DEBUG for extra info
golog.SetDebugLogging()
// Parse options from the command line
listenF := flag.Int("l", 0, "wait for incoming connections")
target := flag.String("d", "", "target peer to dial")
insecure := flag.Bool("insecure", false, "use an unencrypted connection")
seed := flag.Int64("seed", 0, "set random seed for id generation")
flag.Parse()
if *listenF == 0 {
log.Fatal("Please provide a port to bind on with -l")
}
// Make a host that listens on the given multiaddress
ha, err := makeBasicHost(*listenF, *insecure, *seed)
if err != nil {
log.Fatal(err)
}
// Set a stream handler on host A. /echo/1.0.0 is
// a user-defined protocol name.
ha.SetStreamHandler("/echo/1.0.0", func(s network.Stream) {
log.Println("Got a new stream!")
if err := doEcho(s); err != nil {
log.Println(err)
s.Reset()
} else {
s.Close()
}
})
if *target == "" {
log.Println("listening for connections")
select {} // hang forever
}
/**** This is where the listener code ends ****/
// The following code extracts target's the peer ID from the
// given multiaddress
ipfsaddr, err := ma.NewMultiaddr(*target)
if err != nil {
log.Fatalln(err)
}
pid, err := ipfsaddr.ValueForProtocol(ma.P_IPFS)
if err != nil {
log.Fatalln(err)
}
peerid, err := peer.IDB58Decode(pid)
if err != nil {
log.Fatalln(err)
}
// Decapsulate the /ipfs/<peerID> part from the target
// /ip4/<a.b.c.d>/ipfs/<peer> becomes /ip4/<a.b.c.d>
targetPeerAddr, _ := ma.NewMultiaddr(
fmt.Sprintf("/ipfs/%s", peer.IDB58Encode(peerid)))
targetAddr := ipfsaddr.Decapsulate(targetPeerAddr)
// We have a peer ID and a targetAddr so we add it to the peerstore
// so LibP2P knows how to contact it
ha.Peerstore().AddAddr(peerid, targetAddr, peerstore.PermanentAddrTTL)
log.Println("opening stream")
// make a new stream from host B to host A
// it should be handled on host A by the handler we set above because
// we use the same /echo/1.0.0 protocol
s, err := ha.NewStream(context.Background(), peerid, "/echo/1.0.0")
if err != nil {
log.Fatalln(err)
}
log.Println("opened stream")
_, err = s.Write([]byte("Hello, world!\n"))
if err != nil {
log.Fatalln(err)
}
log.Println("written hello world")
out, err := ioutil.ReadAll(s)
if err != nil {
log.Fatalln(err)
}
log.Printf("read reply: %q\n", out)
}
// doEcho reads a line of data a stream and writes it back
func doEcho(s network.Stream) error {
buf := bufio.NewReader(s)
str, err := buf.ReadString('\n')
if err != nil {
return err
}
log.Printf("read: %s\n", str)
_, err = s.Write([]byte(str))
return err
}

64
example/01-echo/libp2p_echo_server.cpp

@ -0,0 +1,64 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#include <chrono>
#include <iostream>
#include <memory>
#include <libp2p/common/literals.hpp>
#include <libp2p/host/basic_host.hpp>
#include <libp2p/injector/host_injector.hpp>
#include <libp2p/protocol/echo.hpp>
int main() {
using libp2p::crypto::Key;
using libp2p::crypto::KeyPair;
using libp2p::crypto::PrivateKey;
using libp2p::crypto::PublicKey;
using libp2p::common::operator""_unhex;
// this keypair generates a PeerId
// "12D3KooWLs7RC93EGXZzn9YdKyZYYx3f9UjTLYNX1reThpCkFb83"
KeyPair keypair{PublicKey{{Key::Type::Ed25519,
"a4249ea6d62bdd8bccf62257ac4899ff284796"
"3228b388fda288db5d64e517e0"_unhex}},
PrivateKey{{Key::Type::Ed25519,
"4a9361c525840f7086b893d584ebbe475b4ec"
"7069951d2e897e8bceb0a3f35ce"_unhex}}};
// create a default Host via an injector, overriding a random-generated
// keypair with ours
auto injector =
libp2p::injector::makeHostInjector(libp2p::injector::useKeyPair(keypair));
auto host = injector.create<std::shared_ptr<libp2p::Host>>();
// set a handler for Echo protocol
libp2p::protocol::Echo echo{libp2p::protocol::EchoConfig{1}};
host->setProtocolHandler(
echo.getProtocolId(),
[&echo](std::shared_ptr<libp2p::connection::Stream> received_stream) {
echo.handle(std::move(received_stream));
});
// launch a Listener part of the Host
auto context = injector.create<std::shared_ptr<boost::asio::io_context>>();
context->post([host{std::move(host)}] {
auto ma =
libp2p::multi::Multiaddress::create("/ip4/127.0.0.1/tcp/40010").value();
auto listen_res = host->listen(ma);
if (!listen_res) {
std::cerr << "host cannot listen the given multiaddress: "
<< listen_res.error().message() << "\n";
std::exit(EXIT_FAILURE);
}
host->start();
std::cout << "Server started\nListening on: " << ma.getStringAddress()
<< "\nPeer id: " << host->getPeerInfo().id.toBase58() << "\n";
});
// run the IO context
context->run_for(std::chrono::seconds(5));
}

6
example/CMakeLists.txt

@ -0,0 +1,6 @@
#
# Copyright Soramitsu Co., Ltd. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
#
add_subdirectory(01-echo)

1
include/libp2p/basic/reader.hpp

@ -9,7 +9,6 @@
#include <functional>
#include <vector>
#include <boost/system/error_code.hpp>
#include <gsl/span>
#include <libp2p/outcome/outcome.hpp>

52
include/libp2p/common/byteutil.hpp

@ -0,0 +1,52 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef LIBP2P_BYTEUTIL_HPP
#define LIBP2P_BYTEUTIL_HPP
#include <cstdint>
#include <vector>
namespace libp2p::common {
using ByteArray = std::vector<uint8_t>;
/**
* Put an 8-bit number into the byte array
*/
ByteArray &putUint8(ByteArray &bytes, uint8_t n);
/**
* Put a 16-bit number into the byte array in Big Endian encoding
*/
ByteArray &putUint16BE(ByteArray &bytes, uint16_t n);
/**
* Put an 32-bit number into the byte array in Big Endian encoding
*/
ByteArray &putUint32BE(ByteArray &bytes, uint32_t n);
/**
* Put an 64-bit number into the byte array in Big Endian encoding
*/
ByteArray &putUint64BE(ByteArray &bytes, uint64_t n);
/**
* Convert value, to which the pointer (\param v) references, to the value of
* (\tparam T)
*
* @example
* std::vector<uint8_t> bytes_of_uint16{0x2A, 0x08};
* uint16_t converted_value = convert<uint16_t>(bytes_of_uint16.data());
* printf(converted_value); // 10760 (2A08 in hex)
*/
template <typename T>
T convert(const void *v) {
T t;
memcpy(&t, v, sizeof(T));
return t;
}
} // namespace libp2p::common
#endif // LIBP2P_BYTEUTIL_HPP

41
include/libp2p/common/literals.hpp

@ -0,0 +1,41 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef LIBP2P_LITERALS_HPP
#define LIBP2P_LITERALS_HPP
#include <cstdint>
#include <vector>
#include <libp2p/common/types.hpp>
namespace libp2p {
namespace multi {
class Multiaddress;
class Multihash;
} // namespace multi
namespace peer {
class PeerId;
}
namespace common {
Hash256 operator""_hash256(const char *c, size_t s);
std::vector<uint8_t> operator""_v(const char *c, size_t s);
std::vector<uint8_t> operator""_unhex(const char *c, size_t s);
multi::Multiaddress operator""_multiaddr(const char *c, size_t s);
multi::Multihash operator""_multihash(const char *c, size_t s);
peer::PeerId operator""_peerid(const char *c, size_t s);
} // namespace common
} // namespace libp2p
#endif // LIBP2P_LITERALS_HPP

1
include/libp2p/crypto/error.hpp

@ -54,6 +54,7 @@ namespace libp2p::crypto {
WRONG_KEY_TYPE, ///< incorrect key type
CANNOT_LOAD_UNSPECIFIED, ///< cannot load unspecified key
GET_KEY_BYTES_FAILED, ///< failed to get key bytes from PKEY
INTERNAL_ERROR ///< internal error happened
};
enum class KeyValidatorError {

11
include/libp2p/crypto/key.hpp

@ -19,12 +19,11 @@ namespace libp2p::crypto {
* Supported types of all keys
*/
enum class Type {
UNSPECIFIED,
RSA1024,
RSA2048,
RSA4096,
ED25519,
SECP256K1
UNSPECIFIED = 100,
RSA = 0,
Ed25519 = 1,
Secp256k1 = 2,
ECDSA = 3
};
Type type = Type::UNSPECIFIED; ///< key type

1
include/libp2p/crypto/key_generator.hpp

@ -21,6 +21,7 @@ namespace libp2p::crypto {
using Buffer = std::vector<uint8_t>;
virtual ~KeyGenerator() = default;
/**
* @brief generates new key pair of specified type
* @param key_type key type

14
include/libp2p/crypto/key_marshaller.hpp

@ -8,6 +8,7 @@
#include <libp2p/crypto/error.hpp>
#include <libp2p/crypto/key.hpp>
#include <libp2p/crypto/protobuf/protobuf_key.hpp>
namespace libp2p::crypto::marshaller {
/**
@ -16,15 +17,16 @@ namespace libp2p::crypto::marshaller {
*/
class KeyMarshaller {
public:
using ByteArray = std::vector<uint8_t>;
virtual ~KeyMarshaller() = default;
/**
* Convert the public key into Protobuf representation
* @param key - public key to be mashalled
* @return bytes of Protobuf object if marshalling was successful, error
* otherwise
*/
virtual outcome::result<ByteArray> marshal(const PublicKey &key) const = 0;
virtual outcome::result<ProtobufKey> marshal(
const PublicKey &key) const = 0;
/**
* Convert the private key into Protobuf representation
@ -32,15 +34,15 @@ namespace libp2p::crypto::marshaller {
* @return bytes of Protobuf object if marshalling was successful, error
* otherwise
*/
virtual outcome::result<ByteArray> marshal(const PrivateKey &key) const = 0;
virtual outcome::result<ProtobufKey> marshal(
const PrivateKey &key) const = 0;
/**
* Convert Protobuf representation of public key into the object
* @param key_bytes - bytes of the public key
* @return public key in case of success, error otherwise
*/
virtual outcome::result<PublicKey> unmarshalPublicKey(
const ByteArray &key_bytes) const = 0;
const ProtobufKey &key) const = 0;
/**
* Convert Protobuf representation of private key into the object
@ -48,7 +50,7 @@ namespace libp2p::crypto::marshaller {
* @return private key in case of success, error otherwise
*/
virtual outcome::result<PrivateKey> unmarshalPrivateKey(
const ByteArray &key_bytes) const = 0;
const ProtobufKey &key) const = 0;
};
} // namespace libp2p::crypto::marshaller

10
include/libp2p/crypto/key_marshaller/key_marshaller_impl.hpp

@ -21,17 +21,15 @@ namespace libp2p::crypto::marshaller {
~KeyMarshallerImpl() override = default;
outcome::result<KeyMarshaller::ByteArray> marshal(
const PublicKey &key) const override;
outcome::result<ProtobufKey> marshal(const PublicKey &key) const override;
outcome::result<KeyMarshaller::ByteArray> marshal(
const PrivateKey &key) const override;
outcome::result<ProtobufKey> marshal(const PrivateKey &key) const override;
outcome::result<PublicKey> unmarshalPublicKey(
const KeyMarshaller::ByteArray &key_bytes) const override;
const ProtobufKey &key) const override;
outcome::result<PrivateKey> unmarshalPrivateKey(
const KeyMarshaller::ByteArray &key_bytes) const override;
const ProtobufKey &key) const override;
private:
std::shared_ptr<validator::KeyValidator> key_validator_;

29
include/libp2p/crypto/protobuf/protobuf_key.hpp

@ -0,0 +1,29 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef KAGOME_PROTOBUF_KEY_HPP
#define KAGOME_PROTOBUF_KEY_HPP
#include <cstdint>
#include <vector>
#include <boost/operators.hpp>
namespace libp2p::crypto {
/**
* Strict type for key, which is encoded into Protobuf format
*/
struct ProtobufKey : public boost::equality_comparable<ProtobufKey> {
explicit ProtobufKey(std::vector<uint8_t> key) : key{std::move(key)} {}
std::vector<uint8_t> key;
bool operator==(const ProtobufKey &other) const {
return key == other.key;
}
};
} // namespace libp2p::crypto
#endif // KAGOME_PROTOBUF_KEY_HPP

4
include/libp2p/crypto/sha/sha256.hpp

@ -17,14 +17,14 @@ namespace libp2p::crypto {
* @param input to be hashed
* @return hashed bytes
*/
common::Hash256 sha256(std::string_view input);
libp2p::common::Hash256 sha256(std::string_view input);
/**
* Take a SHA-256 hash from bytes
* @param input to be hashed
* @return hashed bytes
*/
common::Hash256 sha256(gsl::span<const uint8_t> input);
libp2p::common::Hash256 sha256(gsl::span<const uint8_t> input);
} // namespace libp2p::crypto
#endif // LIBP2P_SHA256_HPP

2
include/libp2p/event/subscription.hpp

@ -15,7 +15,7 @@ namespace libp2p::event {
*/
class Subscription {
public:
explicit Subscription(boost::signals2::connection conn)
explicit Subscription(boost::signals2::connection conn) // NOLINT (moved)
: connection_{std::move(conn)} {}
/**

2
include/libp2p/injector/host_injector.hpp

@ -28,6 +28,8 @@ namespace libp2p::injector {
di::bind<Host>.template to<host::BasicHost>(),
di::bind<muxer::MuxedConnectionConfig>.to(muxer::MuxedConnectionConfig()),
// repositories
di::bind<peer::PeerRepository>.template to<peer::PeerRepositoryImpl>(),
di::bind<peer::AddressRepository>.template to<peer::InmemAddressRepository>(),

2
include/libp2p/injector/network_injector.hpp

@ -227,7 +227,7 @@ namespace libp2p::injector {
auto validator = std::make_shared<crypto::validator::KeyValidatorImpl>(gen);
// assume no error here. otherwise... just blow up executable
auto keypair = gen->generateKeys(crypto::Key::Type::ED25519).value();
auto keypair = gen->generateKeys(crypto::Key::Type::Ed25519).value();
// clang-format off
return di::make_injector(

1
include/libp2p/multi/hash_type.hpp

@ -9,6 +9,7 @@
namespace libp2p::multi {
/// https://github.com/multiformats/js-multihash/blob/master/src/constants.js
enum HashType : uint64_t {
identity = 0x0,
sha1 = 0x11,
sha256 = 0x12,
sha512 = 0x13,

2
include/libp2p/multi/multihash.hpp

@ -74,7 +74,7 @@ namespace libp2p::multi {
/**
* @return the hash stored in this multihash
*/
const gsl::span<const uint8_t> getHash() const;
gsl::span<const uint8_t> getHash() const;
/**
* @return a string with hexadecimal representation of the multihash

21
include/libp2p/muxer/yamux/yamux_frame.hpp

@ -26,10 +26,11 @@ namespace libp2p::connection {
GO_AWAY = 3 // close the session
};
enum class Flag : uint16_t {
SYN = 1, // start of a new stream
ACK = 2, // acknowledge start of a new stream
FIN = 4, // half-close of the stream
RST = 8 // reset a stream
NONE = 0, // no flag is set
SYN = 1, // start of a new stream
ACK = 2, // acknowledge start of a new stream
FIN = 4, // half-close of the stream
RST = 8 // reset a stream
};
enum class GoAwayError : uint32_t {
NORMAL = 0,
@ -41,7 +42,7 @@ namespace libp2p::connection {
uint8_t version;
FrameType type;
Flag flag;
uint16_t flags;
StreamId stream_id;
uint32_t length;
ByteArray data;
@ -49,11 +50,21 @@ namespace libp2p::connection {
/**
* Get bytes representation of the Yamux frame with given parameters
* @return bytes of the frame
*
* @note even though Flag should be a number, in our implementation we do
* not send messages with more than one flag set, so enum can be accepted as
* well
*/
static ByteArray frameBytes(
uint8_t version, FrameType type, Flag flag, uint32_t stream_id,
uint32_t length,
gsl::span<const uint8_t> data = gsl::span<const uint8_t>());
/**
* Check if the (\param flag) is set in this frame
* @return true, if the flag is set, false otherwise
*/
bool flagIsSet(Flag flag) const;
};
/**

36
include/libp2p/muxer/yamux/yamuxed_connection.hpp

@ -95,9 +95,9 @@ namespace libp2p::connection {
private:
struct WriteData {
Buffer data;
std::function<void(outcome::result<size_t>)> cb;
bool some = false;
Buffer data{};
std::function<void(outcome::result<size_t>)> cb{};
bool some = false; // true, if writeSome is to be called over the data
};
std::queue<WriteData> write_queue_;
bool is_writing_ = false;
@ -147,16 +147,10 @@ namespace libp2p::connection {
void doReadData(size_t data_size, basic::Reader::ReadCallbackFunc cb);
/**
* Process frame of data type
* Process frame of data or window update type
* @param frame to be processed
*/
void processDataFrame(const YamuxFrame &frame);
/**
* Process frame of window size update type
* @param frame to be processed
*/
void processWindowUpdateFrame(const YamuxFrame &frame);
void processDataOrWindowUpdateFrame(const YamuxFrame &frame);
/**
* Process frame of ping type
@ -185,9 +179,9 @@ namespace libp2p::connection {
/**
* Register a new stream in this instance, making it active
* @param stream_id to be registered
* @param cb - callback with registered stream or error
* @return pointer to a newly registered stream
*/
void registerNewStream(StreamId stream_id, StreamHandlerFunc cb);
std::shared_ptr<YamuxStream> registerNewStream(StreamId stream_id);
/**
* If there is data in this length, buffer it to the according stream
@ -195,19 +189,11 @@ namespace libp2p::connection {
* @param frame, which can have some data inside
* @return true if there is some data in the frame, and the function is
* going to read it, false otherwise
* @param discard_data - set to true, if the data is to be discarded after
* read
*/
bool processData(std::shared_ptr<YamuxStream> stream,
const YamuxFrame &frame);
/**
* Process ack message for such stream_id
* @param stream_id of the stream to be processed
* @param cb to be called with stream, if there is one on our side, or
* with error after failed write of reset
*/
void processAck(
StreamId stream_id,
std::function<void(outcome::result<std::shared_ptr<Stream>>)> cb);
void processData(std::shared_ptr<YamuxStream> stream,
const YamuxFrame &frame, bool discard_data);
/**
* Process a window update by notifying a related stream about a change

2
include/libp2p/network/impl/listener_manager_impl.hpp

@ -63,7 +63,7 @@ namespace libp2p::network {
std::shared_ptr<ConnectionManager> cmgr_;
void onConnection(
outcome::result<std::shared_ptr<connection::CapableConnection>>);
outcome::result<std::shared_ptr<connection::CapableConnection>> rconn);
};
} // namespace libp2p::network

8
include/libp2p/outcome/outcome-register.hpp

@ -45,10 +45,14 @@ namespace __libp2p {
return c;
}
private:
Category() = default;
~Category() override = default;
Category(const Category &) = delete;
Category &operator=(const Category &) = delete;
Category(Category &&) = delete;
Category &operator=(Category &&) = delete;
private:
Category() = default;
}; /* end of class */
} // namespace __libp2p

5
include/libp2p/peer/impl/identity_manager_impl.hpp

@ -9,13 +9,16 @@
#include <libp2p/crypto/key_generator.hpp>
#include <libp2p/peer/identity_manager.hpp>
#include <libp2p/peer/key_repository.hpp>
#include <libp2p/crypto/key_marshaller.hpp>
namespace libp2p::peer {
class IdentityManagerImpl : public IdentityManager {
public:
~IdentityManagerImpl() override = default;
explicit IdentityManagerImpl(crypto::KeyPair keyPair);
IdentityManagerImpl(
crypto::KeyPair keyPair,
const std::shared_ptr<crypto::marshaller::KeyMarshaller> &marshaller);
const peer::PeerId &getId() const override;

7
include/libp2p/peer/peer_id.hpp

@ -7,6 +7,7 @@
#define LIBP2P_PEER_ID_HPP
#include <libp2p/crypto/key.hpp>
#include <libp2p/crypto/protobuf/protobuf_key.hpp>
#include <libp2p/multi/multihash.hpp>
#include <libp2p/outcome/outcome.hpp>
@ -33,7 +34,7 @@ namespace libp2p::peer {
* @param key, from which PeerId is to be created
* @return instance of PeerId
*/
static PeerId fromPublicKey(const crypto::PublicKey &key);
static FactoryResult fromPublicKey(const crypto::ProtobufKey &key);
/**
* Create a PeerId from the byte array (serialized multihash).
@ -83,6 +84,10 @@ namespace libp2p::peer {
bool operator!=(const PeerId &other) const;
private:
/// if key, from which a PeerId is created, does not exceed this size, it's
/// put as a PeerId as-is, without SHA-256 hashing
static constexpr size_t kMaxInlineKeyLength = 42;
/**
* Create an instance of PeerId
* @param hash, with which PeerId is to be created

2
include/libp2p/protocol/echo/echo.hpp

@ -36,7 +36,7 @@ namespace libp2p::protocol {
private:
EchoConfig config_;
libp2p::common::Logger log_ = libp2p::common::createLogger("echo");
common::Logger log_ = common::createLogger("echo");
};
} // namespace libp2p::protocol

5
include/libp2p/protocol/echo/echo_config.hpp

@ -11,6 +11,11 @@
namespace libp2p::protocol {
struct EchoConfig {
static constexpr size_t kInfiniteNumberOfRepeats = 0;
// number of times echo server will repeat the cycle <listen-respond>
size_t max_server_repeats = kInfiniteNumberOfRepeats;
// maximum size of message we can receive
size_t max_recv_size = 4096;
};

6
include/libp2p/protocol/echo/server_echo_session.hpp

@ -8,7 +8,7 @@
#include <vector>
#include <boost/assert.hpp>
#include <libp2p/common/logger.hpp>
#include <libp2p/connection/stream.hpp>
#include <libp2p/protocol/echo/echo_config.hpp>
@ -32,6 +32,10 @@ namespace libp2p::protocol {
private:
std::shared_ptr<connection::Stream> stream_;
std::vector<uint8_t> buf_;
EchoConfig config_;
common::Logger log_ = common::createLogger("Echo");
bool repeat_infinitely_;
void doRead();

2
include/libp2p/protocol/identify/identify_msg_processor.hpp

@ -132,7 +132,7 @@ namespace libp2p::protocol {
std::shared_ptr<crypto::marshaller::KeyMarshaller> key_marshaller_;
ObservedAddresses observed_addresses_;
libp2p::common::Logger log_ = libp2p::common::createLogger("Identify");
common::Logger log_ = common::createLogger("IdentifyMsgProcessor");
};
} // namespace libp2p::protocol

11
include/libp2p/security/plaintext/exchange_message_marshaller.hpp

@ -6,8 +6,12 @@
#ifndef LIBP2P_EXCHANGE_MESSAGE_MARSHALLER_HPP
#define LIBP2P_EXCHANGE_MESSAGE_MARSHALLER_HPP
#include <utility>
#include <vector>
#include <gsl/span>
#include <libp2p/crypto/protobuf/protobuf_key.hpp>
#include <libp2p/outcome/outcome.hpp>
#include <libp2p/security/plaintext/exchange_message.hpp>
namespace libp2p::security::plaintext {
@ -31,10 +35,11 @@ namespace libp2p::security::plaintext {
/**
* @param msg_bytes a byte array containing a Protobuf representation of an
* exchange message
* @returns a deserialized exchange message
* @returns a deserialized exchange message and a Protobuf representation of
* the public key
*/
virtual outcome::result<ExchangeMessage> unmarshal(
gsl::span<const uint8_t> msg_bytes) const = 0;
virtual outcome::result<std::pair<ExchangeMessage, crypto::ProtobufKey>>
unmarshal(gsl::span<const uint8_t> msg_bytes) const = 0;
};
} // namespace libp2p::security::plaintext

12
include/libp2p/security/plaintext/exchange_message_marshaller_impl.hpp

@ -12,6 +12,10 @@
#include <libp2p/security/plaintext/exchange_message.hpp>
#include <libp2p/security/plaintext/exchange_message_marshaller.hpp>
namespace libp2p::crypto::protobuf {
class PublicKey;
}
namespace libp2p::security::plaintext {
class ExchangeMessageMarshallerImpl : public ExchangeMessageMarshaller {
@ -21,7 +25,8 @@ namespace libp2p::security::plaintext {
*/
enum class Error {
PUBLIC_KEY_SERIALIZING_ERROR = 1,
MESSAGE_SERIALIZING_ERROR
MESSAGE_SERIALIZING_ERROR,
PUBLIC_KEY_DESERIALIZING_ERROR
};
explicit ExchangeMessageMarshallerImpl(
@ -30,10 +35,13 @@ namespace libp2p::security::plaintext {
outcome::result<std::vector<uint8_t>> marshal(
const ExchangeMessage &msg) const override;
outcome::result<ExchangeMessage> unmarshal(
outcome::result<std::pair<ExchangeMessage, crypto::ProtobufKey>> unmarshal(
gsl::span<const uint8_t> msg_bytes) const override;
private:
outcome::result<std::unique_ptr<crypto::protobuf::PublicKey>>
allocatePubKey(const crypto::PublicKey &pubkey) const;
std::shared_ptr<crypto::marshaller::KeyMarshaller> marshaller_;
};

24
include/libp2p/security/plaintext/plaintext.hpp

@ -6,6 +6,8 @@
#ifndef LIBP2P_PLAINTEXT_ADAPTOR_HPP
#define LIBP2P_PLAINTEXT_ADAPTOR_HPP
#include <libp2p/common/logger.hpp>
#include <libp2p/crypto/key_marshaller.hpp>
#include <libp2p/peer/identity_manager.hpp>
#include <libp2p/security/plaintext/exchange_message_marshaller.hpp>
#include <libp2p/security/security_adaptor.hpp>
@ -27,15 +29,16 @@ namespace libp2p::security {
enum class Error {
EXCHANGE_SEND_ERROR = 1,
EXCHANGE_RECEIVE_ERROR,
INVALID_PEER_ID, // peer id in an exchange message doesn't much actual
// peer id
EMPTY_PEER_ID // remote multiaddr doesn't contain a peer id
INVALID_PEER_ID,
EMPTY_PEER_ID
};
~Plaintext() override = default;
Plaintext(std::shared_ptr<plaintext::ExchangeMessageMarshaller> marshaller,
std::shared_ptr<peer::IdentityManager> idmgr);
Plaintext(
std::shared_ptr<plaintext::ExchangeMessageMarshaller> marshaller,
std::shared_ptr<peer::IdentityManager> idmgr,
std::shared_ptr<crypto::marshaller::KeyMarshaller> key_marshaller);
peer::Protocol getProtocolId() const override;
@ -56,13 +59,22 @@ namespace libp2p::security {
const MaybePeerId &p, SecConnCallbackFunc cb) const;
// the callback passed to an async read call in receiveExchangeMsg
void readCallback(std::shared_ptr<connection::RawConnection> conn,
void readCallback(const std::shared_ptr<connection::RawConnection> &conn,
const MaybePeerId &p, const SecConnCallbackFunc &cb,
const std::shared_ptr<std::vector<uint8_t>> &read_bytes,
outcome::result<size_t> read_call_res) const;
/**
* Close (\param conn) and report error in case of failure
*/
void closeConnection(
const std::shared_ptr<libp2p::connection::RawConnection> &conn,
const std::error_code &err) const;
std::shared_ptr<plaintext::ExchangeMessageMarshaller> marshaller_;
std::shared_ptr<peer::IdentityManager> idmgr_;
std::shared_ptr<crypto::marshaller::KeyMarshaller> key_marshaller_;
common::Logger log_ = common::createLogger("Plaintext");
};
} // namespace libp2p::security

23
include/libp2p/security/plaintext/plaintext_connection.hpp

@ -10,13 +10,16 @@
#include <optional>
#include <libp2p/connection/secure_connection.hpp>
#include <libp2p/crypto/key_marshaller.hpp>
namespace libp2p::connection {
class PlaintextConnection : public SecureConnection {
public:
PlaintextConnection(std::shared_ptr<RawConnection> raw_connection,
crypto::PublicKey localPubkey,
crypto::PublicKey remotePubkey);
PlaintextConnection(
std::shared_ptr<RawConnection> raw_connection,
crypto::PublicKey localPubkey,
crypto::PublicKey remotePubkey,
std::shared_ptr<crypto::marshaller::KeyMarshaller> key_marshaller);
~PlaintextConnection() override = default;
@ -32,16 +35,20 @@ namespace libp2p::connection {
outcome::result<multi::Multiaddress> remoteMultiaddr() override;
void read(gsl::span<uint8_t> out, size_t bytes,
void read(gsl::span<uint8_t> out,
size_t bytes,
ReadCallbackFunc cb) override;
void readSome(gsl::span<uint8_t> out, size_t bytes,
void readSome(gsl::span<uint8_t> out,
size_t bytes,
ReadCallbackFunc cb) override;
void write(gsl::span<const uint8_t> in, size_t bytes,
void write(gsl::span<const uint8_t> in,
size_t bytes,
WriteCallbackFunc cb) override;
void writeSome(gsl::span<const uint8_t> in, size_t bytes,
void writeSome(gsl::span<const uint8_t> in,
size_t bytes,
WriteCallbackFunc cb) override;
bool isClosed() const override;
@ -53,6 +60,8 @@ namespace libp2p::connection {
crypto::PublicKey local_;
crypto::PublicKey remote_;
std::shared_ptr<crypto::marshaller::KeyMarshaller> key_marshaller_;
};
} // namespace libp2p::connection

14
src/common/CMakeLists.txt

@ -13,3 +13,17 @@ target_link_libraries(p2p_hexutil
libp2p_add_library(p2p_logger
logger.cpp
)
libp2p_add_library(p2p_byteutil
byteutil.cpp
)
libp2p_add_library(p2p_literals
literals.cpp
)
target_link_libraries(p2p_literals
p2p_peer_id
p2p_multihash
p2p_multiaddress
p2p_hexutil
)

32
src/common/byteutil.cpp

@ -0,0 +1,32 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#include <libp2p/common/byteutil.hpp>
namespace libp2p::common {
ByteArray &putUint8(ByteArray &bytes, uint8_t n) {
bytes.push_back(n);
return bytes;
}
ByteArray &putUint16BE(ByteArray &bytes, uint16_t n) {
bytes.push_back(static_cast<unsigned char &&>((n >> 8u) & 0xFF));
return putUint8(bytes, n);
}
ByteArray &putUint32BE(ByteArray &bytes, uint32_t n) {
bytes.push_back(static_cast<unsigned char &&>((n >> 24u) & 0xFF));
bytes.push_back(static_cast<unsigned char &&>((n >> 16u) & 0xFF));
return putUint16BE(bytes, n);
}
ByteArray &putUint64BE(ByteArray &bytes, uint64_t n) {
bytes.push_back(static_cast<unsigned char &&>((n >> 56u) & 0xFF));
bytes.push_back(static_cast<unsigned char &&>((n >> 48u) & 0xFF));
bytes.push_back(static_cast<unsigned char &&>((n >> 40u) & 0xFF));
bytes.push_back(static_cast<unsigned char &&>((n >> 32u) & 0xFF));
return putUint32BE(bytes, n);
}
} // namespace libp2p::common

46
src/common/literals.cpp

@ -0,0 +1,46 @@
/**
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
#include <libp2p/common/literals.hpp>
#include <libp2p/common/hexutil.hpp>
#include <libp2p/crypto/protobuf/protobuf_key.hpp>
#include <libp2p/multi/multiaddress.hpp>
#include <libp2p/multi/multihash.hpp>
#include <libp2p/peer/peer_id.hpp>
namespace libp2p::common {
libp2p::common::Hash256 operator""_hash256(const char *c, size_t s) {
libp2p::common::Hash256 hash{};
std::copy_n(c, std::min(s, 32ul), hash.rbegin());
return hash;
}
std::vector<uint8_t> operator""_v(const char *c, size_t s) {
std::vector<uint8_t> chars(c, c + s); // NOLINT
return chars;
}
std::vector<uint8_t> operator""_unhex(const char *c, size_t s) {
return libp2p::common::unhex(std::string_view(c, s)).value();
}
libp2p::multi::Multiaddress operator""_multiaddr(const char *c, size_t s) {
return libp2p::multi::Multiaddress::create(std::string_view(c, s)).value();
}
libp2p::multi::Multihash operator""_multihash(const char *c, size_t s) {
return libp2p::multi::Multihash::createFromHex(std::string_view(c, s))
.value();
}
libp2p::peer::PeerId operator""_peerid(const char *c, size_t s) {
libp2p::crypto::PublicKey p;
p.data = std::vector<uint8_t>(c, c + s); // NOLINT
return libp2p::peer::PeerId::fromPublicKey(
libp2p::crypto::ProtobufKey{p.data})
.value();
}
} // namespace libp2p::common

2
src/common/logger.cpp

@ -33,7 +33,7 @@ namespace libp2p::common {
static std::mutex mutex;
std::lock_guard<std::mutex> lock(mutex);
auto logger = spdlog::get(tag);
if (logger == nullptr) {
if (logger == nullptr) { // NOLINT
logger = ::createLogger(tag);
}
return logger;

2
src/crypto/error.cpp

@ -100,6 +100,8 @@ OUTCOME_CPP_DEFINE_CATEGORY(libp2p::crypto, KeyGeneratorError, e) {
return "cannot load unspecified key";
case KeyGeneratorError::GET_KEY_BYTES_FAILED:
return "failed to get key bytes from PKEY";
case KeyGeneratorError::INTERNAL_ERROR:
return "internal error happened";
}
return "unknown KeyGenerator error";
}

84
src/crypto/key_generator/key_generator_impl.cpp

@ -218,16 +218,15 @@ namespace libp2p::crypto {
outcome::result<KeyPair> KeyGeneratorImpl::generateKeys(
Key::Type key_type) const {
switch (key_type) {
case Key::Type::RSA1024:
return generateRsa(common::RSAKeyType::RSA1024);
case Key::Type::RSA2048:
return generateRsa(common::RSAKeyType::RSA2048);
case Key::Type::RSA4096:
return generateRsa(common::RSAKeyType::RSA4096);
case Key::Type::ED25519:
case Key::Type::RSA:
// TODO(akvinikym) 01.10.19 PRE-314: implement
BOOST_ASSERT_MSG(false, "not implemented");
case Key::Type::Ed25519:
return generateEd25519();
case Key::Type::SECP256K1:
case Key::Type::Secp256k1:
return generateSecp256k1();
case Key::Type::ECDSA:
BOOST_ASSERT_MSG(false, "not implemented");
default:
return KeyGeneratorError::UNSUPPORTED_KEY_TYPE;
}
@ -235,32 +234,31 @@ namespace libp2p::crypto {
outcome::result<KeyPair> KeyGeneratorImpl::generateRsa(
common::RSAKeyType bits_option) const {
int bits = 0;
Key::Type key_type;
switch (bits_option) {
case common::RSAKeyType::RSA1024:
bits = 1024;
key_type = Key::Type::RSA1024;
break;
case common::RSAKeyType::RSA2048:
bits = 2048;
key_type = Key::Type::RSA2048;
break;
case common::RSAKeyType::RSA4096:
bits = 4096;
key_type = Key::Type::RSA4096;
break;
}
// normally unreachable
if (0 == bits) {
return KeyGeneratorError::INCORRECT_BITS_COUNT;
}
OUTCOME_TRY(keys, detail::generateRsaKeys(bits));
return KeyPair{{{key_type, std::move(keys.first)}},
{{key_type, std::move(keys.second)}}};
BOOST_ASSERT_MSG(false, "not implemented");
/// previous implementation is commented - it can be used as a hint when
/// implementing a new version of the method
// int bits = 0;
// Key::Type key_type;
// switch (bits_option) {
// case common::RSAKeyType::RSA1024:
// bits = 1024;
// key_type = Key::Type::RSA1024;
// break;
// case common::RSAKeyType::RSA2048:
// bits = 2048;
// key_type = Key::Type::RSA2048;
// break;
// case common::RSAKeyType::RSA4096:
// bits = 4096;
// key_type = Key::Type::RSA4096;
// break;
// }
//
// OUTCOME_TRY(keys, detail::generateRsaKeys(bits));
//
// return KeyPair{{{key_type, std::move(keys.first)}},
// {{key_type, std::move(keys.second)}}};
}
outcome::result<KeyPair> KeyGeneratorImpl::generateEd25519() const {
@ -291,8 +289,8 @@ namespace libp2p::crypto {
OUTCOME_TRY(public_key_bytes,
detail::getEvpPkeyRawBytes(pkey, EVP_PKEY_get_raw_public_key));
return KeyPair{{{Key::Type::ED25519, std::move(public_key_bytes)}},
{{Key::Type::ED25519, std::move(private_key_bytes)}}};
return KeyPair{{{Key::Type::Ed25519, std::move(public_key_bytes)}},
{{Key::Type::Ed25519, std::move(private_key_bytes)}}};
}
outcome::result<KeyPair> KeyGeneratorImpl::generateSecp256k1() const {
@ -350,21 +348,21 @@ namespace libp2p::crypto {
return KeyGeneratorError::KEY_GENERATION_FAILED;
}
return KeyPair{{{Key::Type::SECP256K1, std::move(public_bytes)}},
{{Key::Type::SECP256K1, std::move(private_bytes)}}};
return KeyPair{{{Key::Type::Secp256k1, std::move(public_bytes)}},
{{Key::Type::Secp256k1, std::move(private_bytes)}}};
}
outcome::result<PublicKey> KeyGeneratorImpl::derivePublicKey(
const PrivateKey &private_key) const {
switch (private_key.type) {
case Key::Type::RSA1024:
case Key::Type::RSA2048:
case Key::Type::RSA4096:
case Key::Type::RSA:
return detail::deriveRsa(private_key);
case Key::Type::ED25519:
case Key::Type::Ed25519:
return detail::deriveEd25519(private_key);
case Key::Type::SECP256K1:
case Key::Type::Secp256k1:
return detail::deriveSecp256k1(private_key);
case Key::Type::ECDSA:
BOOST_ASSERT_MSG(false, "not implemented");
case Key::Type::UNSPECIFIED:
return KeyGeneratorError::WRONG_KEY_TYPE;
}

100
src/crypto/key_marshaller/key_marshaller_impl.cpp

@ -13,23 +13,21 @@ namespace libp2p::crypto::marshaller {
namespace {
/**
* @brief converts Key::Type to protobuf::KeyType
* @param key_type common key type value
* @param type common key type value
* @return protobuf key type value
*/
outcome::result<protobuf::KeyType> marshalKeyType(Key::Type key_type) {
switch (key_type) {
outcome::result<protobuf::KeyType> marshalKeyType(Key::Type type) {
switch (type) {
case Key::Type::RSA:
return protobuf::KeyType::RSA;
case Key::Type::Ed25519:
return protobuf::KeyType::Ed25519;
case Key::Type::Secp256k1:
return protobuf::KeyType::Secp256k1;
case Key::Type::ECDSA:
return protobuf::KeyType::ECDSA;
case Key::Type::UNSPECIFIED:
return protobuf::KeyType::UNSPECIFIED;
case Key::Type::RSA1024:
return protobuf::KeyType::RSA1024;
case Key::Type::RSA2048:
return protobuf::KeyType::RSA2048;
case Key::Type::RSA4096:
return protobuf::KeyType::RSA4096;
case Key::Type::ED25519:
return protobuf::KeyType::ED25519;
case Key::Type::SECP256K1:
return protobuf::KeyType::SECP256K1;
return CryptoProviderError::INVALID_KEY_TYPE;
}
return CryptoProviderError::UNKNOWN_KEY_TYPE;
@ -37,23 +35,19 @@ namespace libp2p::crypto::marshaller {
/**
* @brief converts protobuf::KeyType to Key::Type
* @param key_type protobuf key type value
* @param type protobuf key type value
* @return common key type value
*/
outcome::result<Key::Type> unmarshalKeyType(protobuf::KeyType key_type) {
switch (key_type) {
case protobuf::KeyType::UNSPECIFIED:
return Key::Type::UNSPECIFIED;
case protobuf::KeyType::RSA1024:
return Key::Type::RSA1024;
case protobuf::KeyType::RSA2048:
return Key::Type::RSA2048;
case protobuf::KeyType::RSA4096:
return Key::Type::RSA4096;
case protobuf::KeyType::ED25519:
return Key::Type::ED25519;
case protobuf::KeyType::SECP256K1:
return Key::Type::SECP256K1;
outcome::result<Key::Type> unmarshalKeyType(protobuf::KeyType type) {
switch (type) {
case protobuf::KeyType::RSA:
return Key::Type::RSA;
case protobuf::KeyType::Ed25519:
return Key::Type::Ed25519;
case protobuf::KeyType::Secp256k1:
return Key::Type::Secp256k1;
case protobuf::KeyType::ECDSA:
return Key::Type::ECDSA;
default:
return CryptoProviderError::UNKNOWN_KEY_TYPE;
}
@ -64,57 +58,57 @@ namespace libp2p::crypto::marshaller {
std::shared_ptr<validator::KeyValidator> key_validator)
: key_validator_{std::move(key_validator)} {}
outcome::result<KeyMarshallerImpl::ByteArray> KeyMarshallerImpl::marshal(
outcome::result<ProtobufKey> KeyMarshallerImpl::marshal(
const PublicKey &key) const {
protobuf::PublicKey protobuf_key;
OUTCOME_TRY(key_type, marshalKeyType(key.type));
protobuf_key.set_key_type(key_type);
protobuf_key.set_key_value(key.data.data(), key.data.size());
OUTCOME_TRY(type, marshalKeyType(key.type));
protobuf_key.set_type(type);
protobuf_key.set_data(key.data.data(), key.data.size());
auto string = protobuf_key.SerializeAsString();
KeyMarshallerImpl::ByteArray out(string.begin(), string.end());
return KeyMarshallerImpl::ByteArray(string.begin(), string.end());
return ProtobufKey{{string.begin(), string.end()}};
}
outcome::result<KeyMarshallerImpl::ByteArray> KeyMarshallerImpl::marshal(
outcome::result<ProtobufKey> KeyMarshallerImpl::marshal(
const PrivateKey &key) const {
// TODO(Harrm): Check if it's a typo
protobuf::PrivateKey protobuf_key;
OUTCOME_TRY(key_type, marshalKeyType(key.type));
protobuf_key.set_key_type(key_type);
protobuf_key.set_key_value(key.data.data(), key.data.size());
OUTCOME_TRY(type, marshalKeyType(key.type));
protobuf_key.set_type(type);
protobuf_key.set_data(key.data.data(), key.data.size());
auto string = protobuf_key.SerializeAsString();
return KeyMarshallerImpl::ByteArray(string.begin(), string.end());
return ProtobufKey{{string.begin(), string.end()}};
}
outcome::result<PublicKey> KeyMarshallerImpl::unmarshalPublicKey(
const KeyMarshallerImpl::ByteArray &key_bytes) const {
const ProtobufKey &proto_key) const {
protobuf::PublicKey protobuf_key;
if (!protobuf_key.ParseFromArray(key_bytes.data(), key_bytes.size())) {
if (!protobuf_key.ParseFromArray(proto_key.key.data(),
proto_key.key.size())) {
return CryptoProviderError::FAILED_UNMARSHAL_DATA;
}
OUTCOME_TRY(key_type, unmarshalKeyType(protobuf_key.key_type()));
KeyMarshallerImpl::ByteArray key_value(protobuf_key.key_value().begin(),
protobuf_key.key_value().end());
auto key = PublicKey{{key_type, key_value}};
OUTCOME_TRY(type, unmarshalKeyType(protobuf_key.type()));
auto key = PublicKey{
{type, {protobuf_key.data().begin(), protobuf_key.data().end()}}};
OUTCOME_TRY(key_validator_->validate(key));
return key;
}
outcome::result<PrivateKey> KeyMarshallerImpl::unmarshalPrivateKey(
const KeyMarshallerImpl::ByteArray &key_bytes) const {
const ProtobufKey &proto_key) const {
protobuf::PublicKey protobuf_key;
if (!protobuf_key.ParseFromArray(key_bytes.data(), key_bytes.size())) {
if (!protobuf_key.ParseFromArray(proto_key.key.data(),
proto_key.key.size())) {
return CryptoProviderError::FAILED_UNMARSHAL_DATA;
}
OUTCOME_TRY(key_type, unmarshalKeyType(protobuf_key.key_type()));
KeyMarshallerImpl::ByteArray key_value(protobuf_key.key_value().begin(),
protobuf_key.key_value().end());
auto key = PrivateKey{{key_type, key_value}};
OUTCOME_TRY(type, unmarshalKeyType(protobuf_key.type()));
auto key = PrivateKey{
{type, {protobuf_key.data().begin(), protobuf_key.data().end()}}};
OUTCOME_TRY(key_validator_->validate(key));
return key;

43
src/crypto/key_validator/key_validator_impl.cpp

@ -5,25 +5,15 @@
#include <libp2p/crypto/key_validator/key_validator_impl.hpp>
#include <openssl/rsa.h>
#include <openssl/x509.h>
#include <gsl/gsl_util>
#include <libp2p/common/hexutil.hpp>
#include <libp2p/crypto/error.hpp>
namespace libp2p::crypto::validator {
namespace {
constexpr int getRsaBitsCount(Key::Type key_type) {
switch (key_type) {
case Key::Type::RSA1024:
return 1024;
case Key::Type::RSA2048:
return 2048;
case Key::Type::RSA4096:
return 4096;
default:
return 0;
}
}
constexpr int kMinimumRSABitsCount = 2048;
// ed25519 private key has fixed size
constexpr size_t ED25519_PRIVATE_KEY_SIZE = 32u;
@ -47,14 +37,15 @@ namespace libp2p::crypto::validator {
outcome::result<void> KeyValidatorImpl::validate(
const PrivateKey &key) const {
switch (key.type) {
case Key::Type::RSA1024:
case Key::Type::RSA2048:
case Key::Type::RSA4096:
case Key::Type::RSA:
return validateRsa(key);
case Key::Type::ED25519:
case Key::Type::Ed25519:
return validateEd25519(key);
case Key::Type::SECP256K1:
case Key::Type::Secp256k1:
return validateSecp256k1(key);
case Key::Type::ECDSA:
// TODO(25.09.19) Akvinikym PRE-312: handle ECDSA keys validation
BOOST_ASSERT_MSG(false, "not implemented"); // NOLINT
case Key::Type::UNSPECIFIED: // consider unspecified key valid
break;
}
@ -64,14 +55,14 @@ namespace libp2p::crypto::validator {
outcome::result<void> KeyValidatorImpl::validate(const PublicKey &key) const {
switch (key.type) {
case Key::Type::RSA1024:
case Key::Type::RSA2048:
case Key::Type::RSA4096:
case Key::Type::RSA:
return validateRsa(key);
case Key::Type::ED25519:
case Key::Type::Ed25519:
return validateEd25519(key);
case Key::Type::SECP256K1:
case Key::Type::Secp256k1:
return validateSecp256k1(key);
case Key::Type::ECDSA:
BOOST_ASSERT_MSG(false, "not implemented"); // NOLINT
case Key::Type::UNSPECIFIED: // consider unspecified key valid
break;
}
@ -108,7 +99,7 @@ namespace libp2p::crypto::validator {
}
auto cleanup_rsa = gsl::finally([rsa]() { RSA_free(rsa); });
int bits = RSA_bits(rsa);
if (bits != getRsaBitsCount(key.type)) {
if (bits < kMinimumRSABitsCount) {
return KeyValidatorError::INVALID_PRIVATE_KEY;
}
@ -118,13 +109,13 @@ namespace libp2p::crypto::validator {
outcome::result<void> KeyValidatorImpl::validateRsa(
const PublicKey &key) const {
const unsigned char *data_pointer = key.data.data();
RSA *rsa = d2i_RSAPublicKey(nullptr, &data_pointer, key.data.size());
RSA *rsa = d2i_RSA_PUBKEY(nullptr, &data_pointer, key.data.size());
if (nullptr == rsa) {
return KeyValidatorError::INVALID_PUBLIC_KEY;
}
auto cleanup_rsa = gsl::finally([rsa]() { RSA_free(rsa); });
int bits = RSA_bits(rsa);
if (bits != getRsaBitsCount(key.type)) {
if (bits < kMinimumRSABitsCount) {
return KeyValidatorError::INVALID_PRIVATE_KEY;
}

24
src/crypto/protobuf/keys.proto

@ -3,24 +3,22 @@
* SPDX-License-Identifier: Apache-2.0
*/
syntax = "proto3";
syntax = "proto2";
package libp2p.crypto.protobuf;
enum KeyType {
UNSPECIFIED = 0;
RSA1024 = 1;
RSA2048 = 2;
RSA4096 = 3;
ED25519 = 4;
SECP256K1 = 5;
RSA = 0;
Ed25519 = 1;
Secp256k1 = 2;
ECDSA = 3;
}
message PrivateKey {
KeyType key_type = 1;
bytes key_value = 2;
message PublicKey {
required KeyType Type = 1;
required bytes Data = 2;
}
message PublicKey {
KeyType key_type = 1;
bytes key_value = 2;
message PrivateKey {
required KeyType Type = 1;
required bytes Data = 2;
}

8
src/host/basic_host/basic_host.cpp

@ -5,6 +5,10 @@
#include <libp2p/host/basic_host/basic_host.hpp>
#include <boost/assert.hpp>
#include <libp2p/common/hexutil.hpp>
#include <libp2p/crypto/key_marshaller/key_marshaller_impl.hpp>
namespace libp2p::host {
BasicHost::BasicHost(std::shared_ptr<peer::IdentityManager> idmgr,
@ -74,8 +78,8 @@ namespace libp2p::host {
const peer::Protocol &proto,
const std::function<connection::Stream::Handler> &handler,
const std::function<bool(const peer::Protocol &)> &predicate) {
network_->getListener().getRouter().setProtocolHandler(
proto, handler, predicate);
network_->getListener().getRouter().setProtocolHandler(proto, handler,
predicate);
}
void BasicHost::newStream(const peer::PeerInfo &p,

2
src/multi/multihash.cpp

@ -92,7 +92,7 @@ namespace libp2p::multi {
return type_;
}
const gsl::span<const uint8_t> Multihash::getHash() const {
gsl::span<const uint8_t> Multihash::getHash() const {
return hash_;
}

1
src/muxer/yamux/CMakeLists.txt

@ -20,5 +20,6 @@ libp2p_add_library(p2p_yamuxed_connection
target_link_libraries(p2p_yamuxed_connection
Boost::boost
p2p_logger
p2p_byteutil
p2p_peer_id
)

120
src/muxer/yamux/yamux_frame.cpp

@ -5,103 +5,89 @@
#include <libp2p/muxer/yamux/yamux_frame.hpp>
namespace {
using ByteArray = libp2p::common::ByteArray;
#include <arpa/inet.h>
#include <libp2p/common/byteutil.hpp>
ByteArray &putUint8(ByteArray &buffer, uint8_t number) {
buffer.push_back(number);
return buffer;
}
ByteArray &putUint16NetworkOrder(ByteArray &buffer, uint16_t number) {
buffer.push_back(static_cast<unsigned char &&>((number)&0xFFu));
buffer.push_back(static_cast<unsigned char &&>((number >> 8u) & 0xFFu));
return buffer;
namespace libp2p::connection {
YamuxFrame::ByteArray YamuxFrame::frameBytes(uint8_t version, FrameType type,
Flag flag, uint32_t stream_id,
uint32_t length,
gsl::span<const uint8_t> data) {
using common::putUint16BE;
using common::putUint32BE;
using common::putUint8;
ByteArray bytes;
bytes.reserve(kHeaderLength); // minimum header size
// TODO(akvinikym) 03.10.19 PRE-319: refine the functions
putUint32BE(putUint32BE(putUint16BE(putUint8(putUint8(bytes, version),
static_cast<uint8_t>(type)),
static_cast<uint16_t>(flag)),
stream_id),
length);
bytes.insert(bytes.end(), data.begin(), data.end());
return bytes;
}
ByteArray &putUint32NetworkOrder(ByteArray &buffer, uint32_t number) {
buffer.push_back(static_cast<unsigned char &&>((number)&0xFFu));
buffer.push_back(static_cast<unsigned char &&>((number >> 8u) & 0xFFu));
buffer.push_back(static_cast<unsigned char &&>((number >> 16u) & 0xFFu));
buffer.push_back(static_cast<unsigned char &&>((number >> 24u) & 0xFFu));
return buffer;
bool YamuxFrame::flagIsSet(Flag flag) const {
return (static_cast<uint16_t>(flag) & flags) != 0;
}
} // namespace
namespace libp2p::connection {
ByteArray YamuxFrame::frameBytes(uint8_t version, FrameType type, Flag flag,
uint32_t stream_id, uint32_t length,
gsl::span<const uint8_t> data) {
// TODO(akvinikym) PRE-118 15.04.19: refactor with NetworkOrderEncoder, when
// implemented
ByteArray buffer{};
putUint32NetworkOrder(
putUint32NetworkOrder(
putUint16NetworkOrder(
putUint8(putUint8(buffer, version), static_cast<uint8_t>(type)),
static_cast<uint16_t>(flag)),
stream_id),
length);
// put data to the end
buffer.insert(buffer.end(), data.begin(), data.end());
return buffer;
}
ByteArray newStreamMsg(YamuxFrame::StreamId stream_id) {
YamuxFrame::ByteArray newStreamMsg(YamuxFrame::StreamId stream_id) {
return YamuxFrame::frameBytes(YamuxFrame::kDefaultVersion,
YamuxFrame::FrameType::DATA,
YamuxFrame::Flag::SYN, stream_id, 0);
}
ByteArray ackStreamMsg(YamuxFrame::StreamId stream_id) {
YamuxFrame::ByteArray ackStreamMsg(YamuxFrame::StreamId stream_id) {
return YamuxFrame::frameBytes(YamuxFrame::kDefaultVersion,
YamuxFrame::FrameType::DATA,
YamuxFrame::Flag::ACK, stream_id, 0);
}
ByteArray closeStreamMsg(YamuxFrame::StreamId stream_id) {
YamuxFrame::ByteArray closeStreamMsg(YamuxFrame::StreamId stream_id) {
return YamuxFrame::frameBytes(YamuxFrame::kDefaultVersion,
YamuxFrame::FrameType::DATA,
YamuxFrame::Flag::FIN, stream_id, 0);
}
ByteArray resetStreamMsg(YamuxFrame::StreamId stream_id) {
YamuxFrame::ByteArray resetStreamMsg(YamuxFrame::StreamId stream_id) {
return YamuxFrame::frameBytes(YamuxFrame::kDefaultVersion,
YamuxFrame::FrameType::DATA,
YamuxFrame::Flag::RST, stream_id, 0);
}
ByteArray pingOutMsg(uint32_t value) {
YamuxFrame::ByteArray pingOutMsg(uint32_t value) {
return YamuxFrame::frameBytes(YamuxFrame::kDefaultVersion,
YamuxFrame::FrameType::PING,
YamuxFrame::Flag::SYN, 0, value);
}
ByteArray pingResponseMsg(uint32_t value) {
YamuxFrame::ByteArray pingResponseMsg(uint32_t value) {
return YamuxFrame::frameBytes(YamuxFrame::kDefaultVersion,
YamuxFrame::FrameType::PING,
YamuxFrame::Flag::ACK, 0, value);
}
ByteArray dataMsg(YamuxFrame::StreamId stream_id,
gsl::span<const uint8_t> data) {
YamuxFrame::ByteArray dataMsg(YamuxFrame::StreamId stream_id,
gsl::span<const uint8_t> data) {
return YamuxFrame::frameBytes(YamuxFrame::kDefaultVersion,
YamuxFrame::FrameType::DATA,
YamuxFrame::Flag::SYN, stream_id,
YamuxFrame::Flag::NONE, stream_id,
static_cast<uint32_t>(data.size()), data);
}
ByteArray goAwayMsg(YamuxFrame::GoAwayError error) {
YamuxFrame::ByteArray goAwayMsg(YamuxFrame::GoAwayError error) {
return YamuxFrame::frameBytes(
YamuxFrame::kDefaultVersion, YamuxFrame::FrameType::GO_AWAY,
YamuxFrame::Flag::SYN, 0, static_cast<uint32_t>(error));
YamuxFrame::Flag::NONE, 0, static_cast<uint32_t>(error));
}
ByteArray windowUpdateMsg(YamuxFrame::StreamId stream_id,
uint32_t window_delta) {
YamuxFrame::ByteArray windowUpdateMsg(YamuxFrame::StreamId stream_id,
uint32_t window_delta) {
return YamuxFrame::frameBytes(
YamuxFrame::kDefaultVersion, YamuxFrame::FrameType::WINDOW_UPDATE,
YamuxFrame::Flag::SYN, stream_id, window_delta);
YamuxFrame::Flag::NONE, stream_id, window_delta);
}
boost::optional<YamuxFrame> parseFrame(gsl::span<const uint8_t> frame_bytes) {
@ -130,40 +116,16 @@ namespace libp2p::connection {
return {};
}
// TODO(akvinikym) PRE-118 15.04.19: refactor with NetworkOrderEncoder, when
// implemented
frame.flags = ntohs(common::convert<uint16_t>(&frame_bytes[2]));
switch ((static_cast<uint16_t>(frame_bytes[3]) << 8u) | frame_bytes[2]) {
case 1:
frame.flag = YamuxFrame::Flag::SYN;
break;
case 2:
frame.flag = YamuxFrame::Flag::ACK;
break;
case 4:
frame.flag = YamuxFrame::Flag::FIN;
break;
case 8:
frame.flag = YamuxFrame::Flag::RST;
break;
default:
return {};
}
frame.stream_id = ntohl(common::convert<uint32_t>(&frame_bytes[4]));
frame.stream_id = (static_cast<uint32_t>(frame_bytes[7]) << 24u)
| (static_cast<uint16_t>(frame_bytes[6]) << 16u)
| (static_cast<uint16_t>(frame_bytes[5]) << 8u)
| (static_cast<uint16_t>(frame_bytes[4]));
frame.length = (static_cast<uint32_t>(frame_bytes[11]) << 24u)
| (static_cast<uint16_t>(frame_bytes[10]) << 16u)
| (static_cast<uint16_t>(frame_bytes[9]) << 8u)
| (static_cast<uint16_t>(frame_bytes[8]));
frame.length = ntohl(common::convert<uint32_t>(&frame_bytes[8]));
const auto &data_begin = frame_bytes.begin() + YamuxFrame::kHeaderLength;
if (data_begin != frame_bytes.end()) {
frame.data = std::vector<uint8_t>(data_begin, frame_bytes.end());
};
}
return frame;
}

2
src/muxer/yamux/yamux_stream.cpp

@ -137,7 +137,7 @@ namespace libp2p::connection {
auto write_lambda = [self{shared_from_this()}, cb = std::move(cb), in,
bytes, some]() mutable {
if (self->send_window_size_ - bytes >= 0) {
if (self->send_window_size_ >= bytes) {
// we can write - window size on the other side allows us
auto conn_wptr = self->yamuxed_connection_;
if (conn_wptr.expired()) {

264
src/muxer/yamux/yamuxed_connection.cpp

@ -216,18 +216,13 @@ namespace libp2p::connection {
}
switch (header_opt->type) {
case FrameType::DATA: {
return processDataFrame(*header_opt);
}
case FrameType::WINDOW_UPDATE: {
return processWindowUpdateFrame(*header_opt);
}
case FrameType::PING: {
case FrameType::DATA:
case FrameType::WINDOW_UPDATE:
return processDataOrWindowUpdateFrame(*header_opt);
case FrameType::PING:
return processPingFrame(*header_opt);
}
case FrameType::GO_AWAY: {
case FrameType::GO_AWAY:
return processGoAwayFrame(*header_opt);
}
default:
log_->critical("garbage in parsed frame's type; closing the session");
return closeSession();
@ -236,6 +231,7 @@ namespace libp2p::connection {
void YamuxedConnection::doReadData(size_t data_size,
basic::Reader::ReadCallbackFunc cb) {
data_buffer_.clear();
return connection_->read(
data_buffer_, data_size,
[self{shared_from_this()}, cb = std::move(cb)](auto &&res) {
@ -243,138 +239,87 @@ namespace libp2p::connection {
});
}
void YamuxedConnection::processDataFrame(const YamuxFrame &frame) {
void YamuxedConnection::processDataOrWindowUpdateFrame(
const YamuxFrame &frame) {
using Flag = YamuxFrame::Flag;
auto stream_id = frame.stream_id;
switch (frame.flag) {
case Flag::SYN:
// can be start of a new stream, just data or both
if (auto stream = findStream(stream_id)) {
// this is just data
if (processData(stream, frame)) {
// there is some data in the frame, and the function will read next
// header by itself
return;
}
break;
}
// this is a new stream request, maybe with data inside
if (streams_.size() < config_.maximum_streams || !new_stream_handler_) {
return registerNewStream(
stream_id, [self{shared_from_this()}, frame](auto &&stream_res) {
if (stream_res) {
if (self->processData(std::static_pointer_cast<YamuxStream>(
stream_res.value()),
frame)) {
return;
}
}
self->doReadHeader();
});
}
// if we cannot accept another stream, reset it on the other side
return write(
{resetStreamMsg(stream_id), [self{shared_from_this()}](auto &&res) {
if (!res) {
self->log_->error("cannot reset stream: {}",
res.error().message());
}
self->doReadHeader();
}});
case Flag::ACK:
// can be ack of a new stream, just data or both
return processAck(
stream_id, [self{shared_from_this()}, frame](auto &&stream_res) {
if (stream_res) {
if (self->processData(std::static_pointer_cast<YamuxStream>(
stream_res.value()),
frame)) {
return;
}
}
self->doReadHeader();
});
case Flag::FIN:
closeStreamForRead(stream_id);
break;
case Flag::RST:
removeStream(stream_id);
break;
default:
log_->critical("garbage in parsed frame's flag");
auto stream = findStream(stream_id);
// after the function execution decision to discard either data or window
// update can be made
auto discard = false;
if (frame.flagIsSet(Flag::SYN)) {
// request to open a new stream
if (stream) {
// duplicate stream request - critical protocol violation
log_->error(
"duplicate stream request was sent; closing the Yamux session");
return closeSession();
}
doReadHeader();
}
void YamuxedConnection::processWindowUpdateFrame(const YamuxFrame &frame) {
using Flag = YamuxFrame::Flag;
}
auto stream_id = frame.stream_id;
auto window_delta = frame.length;
switch (frame.flag) {
case Flag::SYN:
// can be start of a new stream or update of a window size
if (auto stream = findStream(stream_id)) {
processWindowUpdate(stream, window_delta);
break;
}
// no such stream found => it's a creation of a new stream
if (streams_.size() < config_.maximum_streams || !new_stream_handler_) {
return registerNewStream(
stream_id,
[self{shared_from_this()}](auto &&res) { self->doReadHeader(); });
}
if (streams_.size() < config_.maximum_streams && new_stream_handler_) {
stream = registerNewStream(stream_id);
} else {
// if we cannot accept another stream, reset it on the other side
return write(
write(
{resetStreamMsg(stream_id), [self{shared_from_this()}](auto &&res) {
if (!res) {
self->log_->error("cannot reset stream: {}",
res.error().message());
}
self->doReadHeader();
}});
case Flag::ACK:
if (auto stream = findStream(stream_id)) {
processWindowUpdate(stream, window_delta);
break;
}
// if no such stream found, some error happened - reset the stream on
// the other side just in case
return write(
discard = true;
}
}
if (frame.flagIsSet(Flag::ACK)) {
// ack of the stream we initiated
if (!stream) {
// if we don't have such a stream, reset it on the other side
write(
{resetStreamMsg(stream_id), [self{shared_from_this()}](auto &&res) {
if (!res) {
self->log_->error("cannot reset stream: {}",
res.error().message());
}
self->doReadHeader();
}});
case Flag::FIN:
if (auto stream = findStream(stream_id)) {
processWindowUpdate(stream, window_delta);
closeStreamForRead(stream_id);
}
break;
case Flag::RST:
removeStream(stream_id);
break;
default:
log_->critical("garbage in parsed frame's flag");
return closeSession();
discard = true;
}
}
if (frame.flagIsSet(Flag::FIN)) {
closeStreamForRead(stream_id);
}
if (frame.flagIsSet(Flag::RST)) {
removeStream(stream_id);
discard = true;
}
if (frame.type == YamuxFrame::FrameType::DATA) {
// even if the data is to be discarded, it still must be drawn from the
// wire
return processData(std::move(stream), frame, discard);
}
if (stream && !discard) {
return processWindowUpdate(stream, frame.length);
}
doReadHeader();
}
void YamuxedConnection::processPingFrame(const YamuxFrame &frame) {
return write(
write(
{pingResponseMsg(frame.length), [self{shared_from_this()}](auto &&res) {
if (!res) {
self->log_->error("cannot write ping message: {}",
res.error().message());
}
}});
doReadHeader();
}
void YamuxedConnection::resetAllStreams() {
@ -397,85 +342,73 @@ namespace libp2p::connection {
return stream->second;
}
void YamuxedConnection::registerNewStream(StreamId stream_id,
StreamHandlerFunc cb) {
return write(
{ackStreamMsg(stream_id),
[self{shared_from_this()}, stream_id, cb = std::move(cb)](auto &&res) {
if (!res) {
self->log_->error("cannot register new stream: {}",
res.error().message());
return cb(res.error());
}
auto new_stream =
std::make_shared<YamuxStream>(self->weak_from_this(), stream_id,
self->config_.maximum_window_size);
self->streams_.insert({stream_id, new_stream});
self->new_stream_handler_(new_stream);
return cb(std::move(new_stream));
}});
std::shared_ptr<YamuxStream> YamuxedConnection::registerNewStream(
StreamId stream_id) {
// optimistic approach: assuming ACK will be successfully written
auto new_stream = std::make_shared<YamuxStream>(
weak_from_this(), stream_id, config_.maximum_window_size);
streams_.insert({stream_id, new_stream});
new_stream_handler_(new_stream);
write({ackStreamMsg(stream_id),
[self{shared_from_this()}, stream_id](auto &&res) {
if (!res) {
self->log_->error("cannot register new stream: {}",
res.error().message());
self->removeStream(stream_id);
}
}});
return new_stream;
}
bool YamuxedConnection::processData(std::shared_ptr<YamuxStream> stream,
const YamuxFrame &frame) {
void YamuxedConnection::processData(std::shared_ptr<YamuxStream> stream,
const YamuxFrame &frame,
bool discard_data) {
auto data_len = frame.length;
if (data_len == 0) {
return false;
return doReadHeader();
}
if (data_len > config_.maximum_window_size) {
log_->error(
"too much data was received by this connection; closing the session");
closeSession();
return true;
return closeSession();
}
// read the data, commit it to the stream and call handler, if exists
doReadData(
data_len,
[self{shared_from_this()}, stream = std::move(stream), data_len,
frame](auto &&res) {
[self{shared_from_this()}, stream = std::move(stream), data_len, frame,
discard_data](auto &&res) {
if (!res) {
self->log_->error("cannot read data from the connection: {} ",
self->log_->error("cannot read data from the connection: {}",
res.error().message());
return self->closeSession();
}
if (auto commit_res =
stream->commitData(self->data_buffer_, data_len);
!commit_res) {
self->log_->error("cannot commit data to the stream's buffer: {} ",
commit_res.error().message());
return self->closeSession();
if (stream && !discard_data) {
auto commit_res = stream->commitData(self->data_buffer_, data_len);
if (!commit_res) {
self->log_->error("cannot commit data to the stream's buffer: {}",
commit_res.error().message());
return self->closeSession();
}
} else {
// the data is to be discarded
return;
}
if (auto stream_data_sub = self->data_subs_.find(frame.stream_id);
stream_data_sub != self->data_subs_.end()) {
// if someone is waiting for the data from that stream, notify it
if (stream_data_sub->second()) {
self->data_subs_.erase(stream_data_sub);
}
}
self->doReadHeader();
});
return true;
}
void YamuxedConnection::processAck(
StreamId stream_id,
std::function<void(outcome::result<std::shared_ptr<Stream>>)> cb) {
// acknowledge of start of a new stream; if we don't have such a stream,
// a reset should be sent in order to notify the other side about the
// problem
if (auto stream = findStream(stream_id)) {
return cb(std::move(stream));
}
write({resetStreamMsg(stream_id),
[self{shared_from_this()}, cb = std::move(cb)](auto &&res) {
if (!res) {
self->log_->error("cannot reset stream: {}",
res.error().message());
return cb(res.error());
}
cb(nullptr);
}});
}
void YamuxedConnection::processWindowUpdate(
@ -488,6 +421,7 @@ namespace libp2p::connection {
window_updates_subs_.erase(window_update_sub);
}
}
doReadHeader();
}
void YamuxedConnection::closeStreamForRead(StreamId stream_id) {

11
src/peer/impl/identity_manager_impl.cpp

@ -5,6 +5,8 @@
#include <libp2p/peer/impl/identity_manager_impl.hpp>
#include "libp2p/crypto/key_marshaller.hpp"
namespace libp2p::peer {
const peer::PeerId &IdentityManagerImpl::getId() const {
@ -17,13 +19,18 @@ namespace libp2p::peer {
return *keyPair_;
}
IdentityManagerImpl::IdentityManagerImpl(crypto::KeyPair keyPair) {
IdentityManagerImpl::IdentityManagerImpl(
crypto::KeyPair keyPair,
const std::shared_ptr<crypto::marshaller::KeyMarshaller> &marshaller) {
BOOST_ASSERT(!keyPair.publicKey.data.empty());
BOOST_ASSERT(marshaller);
keyPair_ = std::make_unique<crypto::KeyPair>(std::move(keyPair));
// it is ok to use .value()
auto id = peer::PeerId::fromPublicKey(keyPair_->publicKey);
auto id = peer::PeerId::fromPublicKey(
marshaller->marshal(keyPair_->publicKey).value())
.value();
id_ = std::make_unique<peer::PeerId>(std::move(id));
}
} // namespace libp2p::peer

25
src/peer/peer_id.cpp

@ -28,18 +28,28 @@ namespace libp2p::peer {
PeerId::PeerId(multi::Multihash hash) : hash_{std::move(hash)} {}
PeerId PeerId::fromPublicKey(const crypto::PublicKey &key) {
auto hash = crypto::sha256(key.data);
auto rmultihash = Multihash::create(multi::sha256, hash);
BOOST_ASSERT(rmultihash.has_value());
return PeerId{std::move(rmultihash.value())};
PeerId::FactoryResult PeerId::fromPublicKey(const crypto::ProtobufKey &key) {
std::vector<uint8_t> hash;
auto algo = multi::sha256;
if (key.key.size() <= kMaxInlineKeyLength) {
algo = multi::identity;
hash = key.key;
} else {
auto shash = crypto::sha256(key.key);
hash = std::vector<uint8_t>{shash.begin(), shash.end()};
}
OUTCOME_TRY(multihash, Multihash::create(algo, hash));
return PeerId{std::move(multihash)};
}
PeerId::FactoryResult PeerId::fromBase58(std::string_view id) {
OUTCOME_TRY(decoded_id, decodeBase58(id));
OUTCOME_TRY(hash, Multihash::createFromBuffer(decoded_id));
if (hash.getType() != multi::HashType::sha256) {
if (hash.getType() != multi::HashType::sha256
&& hash.toBuffer().size() > kMaxInlineKeyLength) {
return FactoryError::SHA256_EXPECTED;
}
@ -47,7 +57,8 @@ namespace libp2p::peer {
}
PeerId::FactoryResult PeerId::fromHash(const Multihash &hash) {
if (hash.getType() != multi::HashType::sha256) {
if (hash.getType() != multi::HashType::sha256
&& hash.toBuffer().size() > kMaxInlineKeyLength) {
return FactoryError::SHA256_EXPECTED;
}

28
src/protocol/echo/server_echo_session.cpp

@ -5,13 +5,18 @@
#include <libp2p/protocol/echo/server_echo_session.hpp>
#include <boost/assert.hpp>
namespace libp2p::protocol {
ServerEchoSession::ServerEchoSession(
std::shared_ptr<connection::Stream> stream, EchoConfig config)
: stream_(std::move(stream)), buf_(config.max_recv_size, 0) {
: stream_(std::move(stream)),
buf_(config.max_recv_size, 0),
config_{config},
repeat_infinitely_{config.max_server_repeats == 0} {
BOOST_ASSERT(stream_ != nullptr);
BOOST_ASSERT(config.max_recv_size > 0);
BOOST_ASSERT(config_.max_recv_size > 0);
}
void ServerEchoSession::start() {
@ -19,13 +24,16 @@ namespace libp2p::protocol {
}
void ServerEchoSession::stop() {
stream_->close([self{shared_from_this()}](auto && /* ignore */) {
// ignore result
stream_->close([self{shared_from_this()}](auto &&res) {
if (!res) {
self->log_->error("cannot close the stream: {}", res.error().message());
}
});
}
void ServerEchoSession::doRead() {
if (stream_->isClosedForRead()) {
if (stream_->isClosedForRead()
|| (!repeat_infinitely_ && config_.max_server_repeats == 0)) {
return stop();
}
@ -38,9 +46,12 @@ namespace libp2p::protocol {
void ServerEchoSession::onRead(outcome::result<size_t> rread) {
if (!rread) {
log_->error("error happened during read: {}", rread.error().message());
return stop();
}
log_->info("read message: {}",
std::string{buf_.begin(), buf_.begin() + rread.value()});
this->doWrite(rread.value());
}
@ -57,9 +68,16 @@ namespace libp2p::protocol {
void ServerEchoSession::onWrite(outcome::result<size_t> rwrite) {
if (!rwrite) {
log_->error("error happened during write: {}", rwrite.error().message());
return stop();
}
log_->info("written message: {}",
std::string{buf_.begin(), buf_.begin() + rwrite.value()});
if (!repeat_infinitely_) {
--config_.max_server_repeats;
}
doRead();
}
} // namespace libp2p::protocol

1
src/protocol/identify/CMakeLists.txt

@ -17,4 +17,5 @@ target_link_libraries(p2p_identify
p2p
p2p_identify_proto
p2p_protobuf_message_read_writer
p2p_logger
)

18
src/protocol/identify/identify_msg_processor.cpp

@ -56,7 +56,8 @@ namespace libp2p::protocol {
marshalled_pubkey_res.error().message());
} else {
auto &&marshalled_pubkey = marshalled_pubkey_res.value();
msg.set_publickey(marshalled_pubkey.data(), marshalled_pubkey.size());
msg.set_publickey(marshalled_pubkey.key.data(),
marshalled_pubkey.key.size());
}
// set versions of Libp2p and our implementation
@ -197,7 +198,8 @@ namespace libp2p::protocol {
// unmarshal a received public key
std::vector<uint8_t> pubkey_buf;
pubkey_buf.insert(pubkey_buf.end(), pubkey_str.begin(), pubkey_str.end());
auto pubkey_res = key_marshaller_->unmarshalPublicKey(pubkey_buf);
auto pubkey_res =
key_marshaller_->unmarshalPublicKey(crypto::ProtobufKey{pubkey_buf});
if (!pubkey_res) {
log_->info("cannot unmarshal public key for peer {}: {}",
stream_peer_id ? stream_peer_id->toBase58() : "",
@ -206,8 +208,16 @@ namespace libp2p::protocol {
}
pubkey = std::move(pubkey_res.value());
// derive a peer id from the received public key
auto msg_peer_id = peer::PeerId::fromPublicKey(*pubkey);
// derive a peer id from the received public key; PeerId is made from
// Protobuf-marshalled key, so we use it here
auto msg_peer_id_res =
peer::PeerId::fromPublicKey(crypto::ProtobufKey{pubkey_buf});
if (!msg_peer_id_res) {
log_->info("cannot derive PeerId from the received key: {}",
msg_peer_id_res.error().message());
return stream_peer_id;
}
auto msg_peer_id = std::move(msg_peer_id_res.value());
auto &key_repo = host_.getPeerRepository().getKeyRepository();
if (!stream_peer_id) {

3
src/protocol/identify/observed_addresses.cpp

@ -115,7 +115,6 @@ namespace libp2p::protocol {
const multi::Multiaddress &addr) const {
// for now, we only use the root part of the multiaddress; in most cases, it
// is IP4, and this is the behaviour we want
auto [observer_group, rest] = addr.splitFirst();
return observer_group;
return addr.splitFirst().first;
}
} // namespace libp2p::protocol

3
src/protocol_muxer/multiselect/message_manager.cpp

@ -33,8 +33,7 @@ namespace {
libp2p::protocol_muxer::MessageManager::MultiselectMessage;
/// header of Multiselect protocol
constexpr std::string_view kMultiselectHeaderString =
"/multistream-select/1.0.0\n";
constexpr std::string_view kMultiselectHeaderString = "/multistream/1.0.0\n";
/// string of ls message
constexpr std::string_view kLsString = "ls\n";

40
src/protocol_muxer/multiselect/multiselect.cpp

@ -8,13 +8,14 @@
namespace libp2p::protocol_muxer {
using peer::Protocol;
void Multiselect::selectOneOf(
gsl::span<const peer::Protocol> supported_protocols,
std::shared_ptr<basic::ReadWriter> connection, bool is_initiator,
ProtocolMuxer::ProtocolHandlerFunc handler) {
if (supported_protocols.empty()) {
handler(MultiselectError::PROTOCOLS_LIST_EMPTY);
return;
void Multiselect::selectOneOf(
gsl::span<const peer::Protocol> supported_protocols,
std::shared_ptr<basic::ReadWriter> connection,
bool is_initiator,
ProtocolMuxer::ProtocolHandlerFunc handler) {
if (supported_protocols.empty()) {
handler(MultiselectError::PROTOCOLS_LIST_EMPTY);
return;
}
negotiate(connection, supported_protocols, is_initiator, handler);
@ -22,7 +23,8 @@ namespace libp2p::protocol_muxer {
void Multiselect::negotiate(
const std::shared_ptr<basic::ReadWriter> &connection,
gsl::span<const peer::Protocol> supported_protocols, bool is_initiator,
gsl::span<const peer::Protocol> supported_protocols,
bool is_initiator,
const ProtocolHandlerFunc &handler) {
auto [write_buffer, read_buffer, index] = getBuffers();
@ -31,13 +33,21 @@ namespace libp2p::protocol_muxer {
connection,
std::make_shared<std::vector<peer::Protocol>>(
supported_protocols.begin(), supported_protocols.end()),
handler, write_buffer, read_buffer, index, shared_from_this()));
handler,
write_buffer,
read_buffer,
index,
shared_from_this()));
} else {
MessageReader::readNextMessage(std::make_shared<ConnectionState>(
connection,
std::make_shared<std::vector<peer::Protocol>>(
supported_protocols.begin(), supported_protocols.end()),
handler, write_buffer, read_buffer, index, shared_from_this(),
handler,
write_buffer,
read_buffer,
index,
shared_from_this(),
ConnectionState::NegotiationStatus::NOTHING_SENT));
}
}
@ -179,8 +189,8 @@ namespace libp2p::protocol_muxer {
return negotiationRoundFailed(connection_state,
MultiselectError::INTERNAL_ERROR);
}
if (std::find(protocols_to_search->begin(), protocols_to_search->end(),
protocol)
if (std::find(
protocols_to_search->begin(), protocols_to_search->end(), protocol)
!= protocols_to_search->end()) {
return MessageWriter::sendProtocolAck(std::move(connection_state),
protocol);
@ -231,13 +241,15 @@ namespace libp2p::protocol_muxer {
}
std::tuple<std::shared_ptr<common::ByteArray>,
std::shared_ptr<boost::asio::streambuf>, size_t>
std::shared_ptr<boost::asio::streambuf>,
size_t>
Multiselect::getBuffers() {
if (!free_buffers_.empty()) {
auto free_buffers_index = free_buffers_.front();
free_buffers_.pop();
return {write_buffers_[free_buffers_index],
read_buffers_[free_buffers_index], free_buffers_index};
read_buffers_[free_buffers_index],
free_buffers_index};
}
return {
write_buffers_.emplace_back(std::make_shared<common::ByteArray>()),

1
src/security/plaintext/CMakeLists.txt

@ -15,6 +15,7 @@ target_link_libraries(p2p_plaintext
p2p_security_error
p2p_plaintext_exchange_message_marshaller
p2p_crypto_error
p2p_logger
)
libp2p_add_library(p2p_plaintext_exchange_message_marshaller

44
src/security/plaintext/exchange_message_marshaller_impl.cpp

@ -16,6 +16,9 @@ OUTCOME_CPP_DEFINE_CATEGORY(libp2p::security::plaintext,
case E::MESSAGE_SERIALIZING_ERROR:
return "Error while encoding the plaintext exchange message to Protobuf "
"format";
case E::PUBLIC_KEY_DESERIALIZING_ERROR:
return "Error while decoding the plaintext exchange message from "
"Protobuf format";
}
return "Unknown error";
}
@ -29,18 +32,13 @@ namespace libp2p::security::plaintext {
outcome::result<std::vector<uint8_t>> ExchangeMessageMarshallerImpl::marshal(
const ExchangeMessage &msg) const {
plaintext::protobuf::Exchange exchange_msg;
auto id = msg.peer_id.toMultihash().toBuffer();
exchange_msg.set_id(id.data(), id.size());
auto pubkey = msg.pubkey;
OUTCOME_TRY(pub_key, marshaller_->marshal(pubkey));
std::string str_pubkey(pub_key.begin(), pub_key.end());
auto pubkey_msg = std::make_unique<crypto::protobuf::PublicKey>();
if (!pubkey_msg->ParseFromString(str_pubkey)) {
return Error::PUBLIC_KEY_SERIALIZING_ERROR;
}
OUTCOME_TRY(pubkey_msg, allocatePubKey(msg.pubkey));
exchange_msg.set_allocated_pubkey(pubkey_msg.get());
auto id = msg.peer_id.toMultihash().toBuffer();
exchange_msg.set_id(id.data(), id.size());
std::vector<uint8_t> out_msg(exchange_msg.ByteSizeLong());
if (!exchange_msg.SerializeToArray(out_msg.data(), out_msg.size())) {
return Error::MESSAGE_SERIALIZING_ERROR;
@ -49,19 +47,39 @@ namespace libp2p::security::plaintext {
return out_msg;
}
outcome::result<ExchangeMessage> ExchangeMessageMarshallerImpl::unmarshal(
outcome::result<std::pair<ExchangeMessage, crypto::ProtobufKey>>
ExchangeMessageMarshallerImpl::unmarshal(
gsl::span<const uint8_t> msg_bytes) const {
plaintext::protobuf::Exchange exchange_msg;
exchange_msg.ParseFromArray(msg_bytes.data(), msg_bytes.size());
if (!exchange_msg.ParseFromArray(msg_bytes.data(), msg_bytes.size())) {
return Error::PUBLIC_KEY_DESERIALIZING_ERROR;
}
std::vector<uint8_t> pubkey_bytes(exchange_msg.pubkey().ByteSizeLong());
exchange_msg.pubkey().SerializeToArray(pubkey_bytes.data(),
pubkey_bytes.size());
OUTCOME_TRY(pubkey, marshaller_->unmarshalPublicKey(pubkey_bytes));
OUTCOME_TRY(
pubkey,
marshaller_->unmarshalPublicKey(crypto::ProtobufKey{pubkey_bytes}));
std::vector<uint8_t> peer_id_bytes(exchange_msg.id().begin(),
exchange_msg.id().end());
OUTCOME_TRY(peer_id, peer::PeerId::fromBytes(peer_id_bytes));
return ExchangeMessage{pubkey, peer_id};
return {ExchangeMessage{pubkey, peer_id},
crypto::ProtobufKey{std::move(pubkey_bytes)}};
}
outcome::result<std::unique_ptr<crypto::protobuf::PublicKey>>
ExchangeMessageMarshallerImpl::allocatePubKey(
const crypto::PublicKey &pubkey) const {
OUTCOME_TRY(proto_pub_key_bytes, marshaller_->marshal(pubkey));
std::string str_pubkey(proto_pub_key_bytes.key.begin(),
proto_pub_key_bytes.key.end());
auto pubkey_msg = std::make_unique<crypto::protobuf::PublicKey>();
if (!pubkey_msg->ParseFromString(str_pubkey)) {
return Error::PUBLIC_KEY_SERIALIZING_ERROR;
}
return outcome::success(std::move(pubkey_msg));
}
} // namespace libp2p::security::plaintext

118
src/security/plaintext/plaintext.cpp

@ -11,12 +11,11 @@
#include <libp2p/security/error.hpp>
#include <libp2p/security/plaintext/plaintext_connection.hpp>
// TODO(warchant): why is conn->close() result is not handled?
#define PLAINTEXT_OUTCOME_TRY(name, res, conn, cb) \
auto name = (res); \
if (name.has_error()) { \
conn->close(); \
cb(name.error()); \
auto(name) = (res); \
if ((name).has_error()) { \
closeConnection(conn, (name).error()); \
cb((name).error()); \
return; \
}
@ -39,10 +38,14 @@ namespace libp2p::security {
Plaintext::Plaintext(
std::shared_ptr<plaintext::ExchangeMessageMarshaller> marshaller,
std::shared_ptr<peer::IdentityManager> idmgr)
: marshaller_(std::move(marshaller)), idmgr_(std::move(idmgr)) {
std::shared_ptr<peer::IdentityManager> idmgr,
std::shared_ptr<crypto::marshaller::KeyMarshaller> key_marshaller)
: marshaller_(std::move(marshaller)),
idmgr_(std::move(idmgr)),
key_marshaller_{std::move(key_marshaller)} {
BOOST_ASSERT(marshaller_);
BOOST_ASSERT(idmgr_);
BOOST_ASSERT(key_marshaller_);
}
peer::Protocol Plaintext::getProtocolId() const {
@ -53,6 +56,7 @@ namespace libp2p::security {
void Plaintext::secureInbound(
std::shared_ptr<connection::RawConnection> inbound,
SecConnCallbackFunc cb) {
log_->info("securing inbound connection");
sendExchangeMsg(inbound, cb);
receiveExchangeMsg(inbound, boost::none, cb);
}
@ -60,6 +64,7 @@ namespace libp2p::security {
void Plaintext::secureOutbound(
std::shared_ptr<connection::RawConnection> outbound,
const peer::PeerId &p, SecConnCallbackFunc cb) {
log_->info("securing outbound connection");
sendExchangeMsg(outbound, cb);
receiveExchangeMsg(outbound, p, cb);
}
@ -67,55 +72,114 @@ namespace libp2p::security {
void Plaintext::sendExchangeMsg(
const std::shared_ptr<connection::RawConnection> &conn,
SecConnCallbackFunc cb) const {
PLAINTEXT_OUTCOME_TRY(out_msg,
PLAINTEXT_OUTCOME_TRY(out_msg_res,
marshaller_->marshal(plaintext::ExchangeMessage{
.pubkey = idmgr_->getKeyPair().publicKey,
.peer_id = idmgr_->getId()}),
conn, cb);
conn->write(out_msg.value(), out_msg.value().size(),
[cb{std::move(cb)}, conn](auto &&res) {
conn, cb)
auto out_msg = out_msg_res.value();
auto len = out_msg.size();
std::vector<uint8_t> len_bytes = {
static_cast<uint8_t>(len >> 24u), static_cast<uint8_t>(len >> 16u),
static_cast<uint8_t>(len >> 8u), static_cast<uint8_t>(len)};
conn->write(len_bytes, 4,
[self{shared_from_this()}, out_msg, conn,
cb{std::move(cb)}](auto &&res) mutable {
if (res.has_error()) {
conn->close();
cb(Error::EXCHANGE_SEND_ERROR);
self->closeConnection(conn, Error::EXCHANGE_SEND_ERROR);
return cb(Error::EXCHANGE_SEND_ERROR);
}
conn->write(
out_msg, out_msg.size(),
[self{std::move(self)}, cb{cb}, conn](auto &&res) {
if (res.has_error()) {
self->closeConnection(conn,
Error::EXCHANGE_SEND_ERROR);
return cb(Error::EXCHANGE_SEND_ERROR);
}
});
});
}
void Plaintext::receiveExchangeMsg(
const std::shared_ptr<connection::RawConnection> &conn,
const MaybePeerId &p, SecConnCallbackFunc cb) const {
constexpr size_t kMaxMsgSize = 10000;
constexpr size_t kMaxMsgSize = 4; // we read uint32_t first
auto read_bytes = std::make_shared<std::vector<uint8_t>>(kMaxMsgSize);
conn->readSome(
conn->read(
*read_bytes, kMaxMsgSize,
[self{shared_from_this()}, conn, p, cb{std::move(cb)}, read_bytes](
auto &&r) { self->readCallback(conn, p, cb, read_bytes, r); });
[self{shared_from_this()}, conn, p, cb{std::move(cb)},
read_bytes](auto &&r) {
auto bytes_size = (static_cast<uint32_t>(read_bytes->at(0)) << 24u)
+ (static_cast<uint32_t>(read_bytes->at(1)) << 16u)
+ (static_cast<uint32_t>(read_bytes->at(2)) << 8u)
+ read_bytes->at(3);
auto received_bytes =
std::make_shared<std::vector<uint8_t>>(bytes_size);
conn->read(*received_bytes, received_bytes->size(),
[self, conn, p, cb, received_bytes](auto &&r) {
self->readCallback(conn, p, cb, received_bytes, r);
});
});
}
void Plaintext::readCallback(
std::shared_ptr<connection::RawConnection> conn, const MaybePeerId &p,
const SecConnCallbackFunc &cb,
const std::shared_ptr<connection::RawConnection> &conn,
const MaybePeerId &p, const SecConnCallbackFunc &cb,
const std::shared_ptr<std::vector<uint8_t>> &read_bytes,
outcome::result<size_t> read_call_res) const {
PLAINTEXT_OUTCOME_TRY(r, read_call_res, conn, cb);
PLAINTEXT_OUTCOME_TRY(in_exchange_msg, marshaller_->unmarshal(*read_bytes),
conn, cb);
auto received_pid = in_exchange_msg.value().peer_id;
auto pkey = in_exchange_msg.value().pubkey;
auto derived_pid = peer::PeerId::fromPublicKey(pkey);
auto &msg = in_exchange_msg.value().first;
auto received_pid = msg.peer_id;
auto pkey = msg.pubkey;
// PeerId is derived from the Protobuf-serialized public key, not a raw one
auto derived_pid_res =
peer::PeerId::fromPublicKey(in_exchange_msg.value().second);
if (!derived_pid_res) {
log_->error("cannot create a PeerId from the received public key: {}",
derived_pid_res.error().message());
return cb(derived_pid_res.error());
}
auto derived_pid = std::move(derived_pid_res.value());
if (received_pid != derived_pid) {
conn->close();
cb(Error::INVALID_PEER_ID);
log_->error(
"ID, which was received in the message ({}) and the one, which was "
"derived from the public key ({}), differ",
received_pid.toBase58(), derived_pid.toBase58());
closeConnection(conn, Error::INVALID_PEER_ID);
return cb(Error::INVALID_PEER_ID);
}
if (p.has_value()) {
if (received_pid != p.value()) {
conn->close();
cb(Error::INVALID_PEER_ID);
closeConnection(conn, Error::INVALID_PEER_ID);
return cb(Error::INVALID_PEER_ID);
}
}
cb(std::make_shared<connection::PlaintextConnection>(
std::move(conn), idmgr_->getKeyPair().publicKey, std::move(pkey)));
conn, idmgr_->getKeyPair().publicKey, std::move(pkey),
key_marshaller_));
}
void Plaintext::closeConnection(
const std::shared_ptr<libp2p::connection::RawConnection> &conn,
const std::error_code &err) const {
log_->error("error happened while establishing a Plaintext session: {}",
err.message());
if (auto close_res = conn->close(); !close_res) {
log_->error("connection close attempt ended with error: {}",
close_res.error().message());
}
}
} // namespace libp2p::security

37
src/security/plaintext/plaintext_connection.cpp

@ -5,21 +5,38 @@
#include <libp2p/security/plaintext/plaintext_connection.hpp>
#include <boost/assert.hpp>
#include "libp2p/crypto/protobuf/protobuf_key.hpp"
namespace libp2p::connection {
PlaintextConnection::PlaintextConnection(
std::shared_ptr<RawConnection> raw_connection,
crypto::PublicKey localPubkey, crypto::PublicKey remotePubkey)
crypto::PublicKey localPubkey,
crypto::PublicKey remotePubkey,
std::shared_ptr<crypto::marshaller::KeyMarshaller> key_marshaller)
: raw_connection_{std::move(raw_connection)},
local_(std::move(localPubkey)),
remote_(std::move(remotePubkey)) {}
remote_(std::move(remotePubkey)),
key_marshaller_{std::move(key_marshaller)} {
BOOST_ASSERT(raw_connection_);
BOOST_ASSERT(key_marshaller_);
}
outcome::result<peer::PeerId> PlaintextConnection::localPeer() const {
return peer::PeerId::fromPublicKey(local_);
auto proto_local_key_res = key_marshaller_->marshal(local_);
if (!proto_local_key_res) {
return proto_local_key_res.error();
}
return peer::PeerId::fromPublicKey(proto_local_key_res.value());
}
outcome::result<peer::PeerId> PlaintextConnection::remotePeer() const {
return peer::PeerId::fromPublicKey(remote_);
auto proto_remote_key_res = key_marshaller_->marshal(remote_);
if (!proto_remote_key_res) {
return proto_remote_key_res.error();
}
return peer::PeerId::fromPublicKey(proto_remote_key_res.value());
}
outcome::result<crypto::PublicKey> PlaintextConnection::remotePublicKey()
@ -39,22 +56,26 @@ namespace libp2p::connection {
return raw_connection_->remoteMultiaddr();
}
void PlaintextConnection::read(gsl::span<uint8_t> in, size_t bytes,
void PlaintextConnection::read(gsl::span<uint8_t> in,
size_t bytes,
Reader::ReadCallbackFunc f) {
return raw_connection_->read(in, bytes, std::move(f));
};
void PlaintextConnection::readSome(gsl::span<uint8_t> in, size_t bytes,
void PlaintextConnection::readSome(gsl::span<uint8_t> in,
size_t bytes,
Reader::ReadCallbackFunc f) {
return raw_connection_->readSome(in, bytes, std::move(f));
};
void PlaintextConnection::write(gsl::span<const uint8_t> in, size_t bytes,
void PlaintextConnection::write(gsl::span<const uint8_t> in,
size_t bytes,
Writer::WriteCallbackFunc f) {
return raw_connection_->write(in, bytes, std::move(f));
}
void PlaintextConnection::writeSome(gsl::span<const uint8_t> in, size_t bytes,
void PlaintextConnection::writeSome(gsl::span<const uint8_t> in,
size_t bytes,
Writer::WriteCallbackFunc f) {
return raw_connection_->writeSome(in, bytes, std::move(f));
}

11
src/security/plaintext/plaintext_session.cpp

@ -23,7 +23,8 @@ namespace libp2p::security {
void PlaintextSession::recvKey(PlaintextSession::PubkeyFunc f) {
conn_->readSome(
recvbuf_, recvbuf_.size(),
recvbuf_,
recvbuf_.size(),
[self{shared_from_this()}, f{std::move(f)}](outcome::result<size_t> r) {
if (!r) {
return self->handler_(r.error());
@ -31,7 +32,8 @@ namespace libp2p::security {
self->recvbuf_.resize(r.value());
auto rpub = self->marshaller_->unmarshalPublicKey(self->recvbuf_);
auto rpub = self->marshaller_->unmarshalPublicKey(
crypto::ProtobufKey{self->recvbuf_});
if (!rpub) {
return self->handler_(rpub.error());
}
@ -46,9 +48,10 @@ namespace libp2p::security {
if (!r) {
return handler_(r.error());
}
sendbuf_ = r.value();
sendbuf_ = r.value().key;
conn_->write(sendbuf_, sendbuf_.size(),
conn_->write(sendbuf_,
sendbuf_.size(),
[self{this->shared_from_this()},
then{std::move(then)}](outcome::result<size_t> r) {
if (!r) {

1
test/acceptance/p2p/CMakeLists.txt

@ -16,4 +16,5 @@ target_link_libraries(all_muxers_acceptance_test
p2p_testutil
p2p_key_marshaller
p2p_identity_manager
p2p_literals
)

2
test/acceptance/p2p/host/CMakeLists.txt

@ -11,6 +11,7 @@ target_link_libraries(basic_host_test
p2p_basic_host
p2p_peer_id
p2p_multiaddress
p2p_literals
)
addtest(host_integration_test
@ -29,4 +30,5 @@ target_link_libraries(host_integration_test
p2p_test_peer
p2p_testutil
p2p_testutil_peer
p2p_literals
)

3
test/acceptance/p2p/host/basic_host_test.cpp

@ -15,11 +15,12 @@
#include "mock/libp2p/peer/identity_manager_mock.hpp"
#include "mock/libp2p/peer/peer_repository_mock.hpp"
#include <libp2p/common/literals.hpp>
#include "testutil/gmock_actions.hpp"
#include "testutil/literals.hpp"
#include "testutil/outcome.hpp"
using namespace libp2p;
using namespace common;
using ::testing::_;
using ::testing::Return;

37
test/acceptance/p2p/host/peer/test_peer.cpp

@ -6,29 +6,31 @@
#include "acceptance/p2p/host/peer/test_peer.hpp"
#include <gtest/gtest.h>
#include <libp2p/crypto/key_marshaller/key_marshaller_impl.hpp>
#include <libp2p/crypto/key_validator/key_validator_impl.hpp>
#include <libp2p/security/plaintext/exchange_message_marshaller_impl.hpp>
#include "acceptance/p2p/host/peer/tick_counter.hpp"
#include "acceptance/p2p/host/protocol/client_test_session.hpp"
#include "libp2p/security/plaintext/exchange_message_marshaller_impl.hpp"
using namespace libp2p; // NOLINT
Peer::Peer(Peer::Duration timeout)
: muxed_config_{1024576, 1000},
timeout_{timeout},
context_{std::make_shared<Context>()},
echo_{std::make_shared<protocol::Echo>()},
random_provider_{
std::make_shared<crypto::random::BoostRandomGenerator>()},
echo_{std::make_shared<Echo>()},
random_provider_{std::make_shared<BoostRandomGenerator>()},
key_generator_{
std::make_shared<crypto::KeyGeneratorImpl>(*random_provider_)} {
EXPECT_OUTCOME_TRUE_MSG(
keys, key_generator_->generateKeys(crypto::Key::Type::ED25519),
keys, key_generator_->generateKeys(crypto::Key::Type::Ed25519),
"failed to generate keys");
host_ = makeHost(std::move(keys));
host_->setProtocolHandler(echo_->getProtocolId(),
[this](std::shared_ptr<connection::Stream> result) {
echo_->handle(result);
});
host_->setProtocolHandler(
echo_->getProtocolId(),
[this](std::shared_ptr<Stream> result) { echo_->handle(result); });
}
void Peer::startServer(const multi::Multiaddress &address,
@ -82,12 +84,6 @@ void Peer::wait() {
}
Peer::sptr<host::BasicHost> Peer::makeHost(crypto::KeyPair keyPair) {
auto idmgr = std::make_shared<peer::IdentityManagerImpl>(keyPair);
auto multiselect = std::make_shared<protocol_muxer::Multiselect>();
auto router = std::make_shared<network::RouterImpl>();
auto key_generator =
std::make_shared<crypto::KeyGeneratorImpl>(*random_provider_);
@ -97,13 +93,20 @@ Peer::sptr<host::BasicHost> Peer::makeHost(crypto::KeyPair keyPair) {
auto key_marshaller = std::make_shared<crypto::marshaller::KeyMarshallerImpl>(
std::move(key_validator));
auto idmgr =
std::make_shared<peer::IdentityManagerImpl>(keyPair, key_marshaller);
auto multiselect = std::make_shared<protocol_muxer::Multiselect>();
auto router = std::make_shared<network::RouterImpl>();
auto exchange_msg_marshaller =
std::make_shared<security::plaintext::ExchangeMessageMarshallerImpl>(
std::move(key_marshaller));
key_marshaller);
std::vector<std::shared_ptr<security::SecurityAdaptor>> security_adaptors = {
std::make_shared<security::Plaintext>(std::move(exchange_msg_marshaller),
idmgr)};
idmgr, std::move(key_marshaller))};
std::vector<std::shared_ptr<muxer::MuxerAdaptor>> muxer_adaptors = {
std::make_shared<muxer::Yamux>(muxed_config_)};

39
test/acceptance/p2p/host/peer/test_peer.hpp

@ -14,8 +14,6 @@
#include "testutil/clock/impl/clock_impl.hpp"
#include "testutil/outcome.hpp"
using namespace libp2p;
struct TickCounter;
/**
@ -26,8 +24,18 @@ class Peer {
template <class T>
using sptr = std::shared_ptr<T>;
using Multiaddress = libp2p::multi::Multiaddress;
using PeerInfo = libp2p::peer::PeerInfo;
using Stream = libp2p::connection::Stream;
using BasicHost = libp2p::host::BasicHost;
using KeyPair = libp2p::crypto::KeyPair;
using MuxedConnectionConfig = libp2p::muxer::MuxedConnectionConfig;
using Host = libp2p::Host;
using Echo = libp2p::protocol::Echo;
using BoostRandomGenerator = libp2p::crypto::random::BoostRandomGenerator;
using KeyGenerator = libp2p::crypto::KeyGenerator;
using Context = boost::asio::io_context;
using Stream = connection::Stream;
public:
using Duration = libp2p::clock::SteadyClockImpl::Duration;
@ -43,8 +51,8 @@ class Peer {
* @param address address to listen
* @param pp promise to set when peer info is obtained
*/
void startServer(const multi::Multiaddress &address,
std::shared_ptr<std::promise<peer::PeerInfo>> promise);
void startServer(const Multiaddress &address,
std::shared_ptr<std::promise<PeerInfo>> promise);
/**
* @brief schedules start of client session
@ -52,7 +60,7 @@ class Peer {
* @param message_count number of messages to send
* @param tester object for testing purposes
*/
void startClient(const peer::PeerInfo &pinfo, size_t message_count,
void startClient(const PeerInfo &pinfo, size_t message_count,
sptr<TickCounter> tester);
/**
@ -61,17 +69,16 @@ class Peer {
void wait();
private:
sptr<host::BasicHost> makeHost(crypto::KeyPair keyPair);
sptr<BasicHost> makeHost(KeyPair keyPair);
muxer::MuxedConnectionConfig muxed_config_; ///< muxed connection config
const Duration timeout_; ///< operations timeout
sptr<Context> context_; ///< io context
std::thread thread_; ///< peer working thread
sptr<Host> host_; ///< host
sptr<protocol::Echo> echo_; ///< echo protocol
sptr<crypto::random::BoostRandomGenerator>
random_provider_; ///< random provider
sptr<crypto::KeyGenerator> key_generator_; ///< key generator
MuxedConnectionConfig muxed_config_; ///< muxed connection config
const Duration timeout_; ///< operations timeout
sptr<Context> context_; ///< io context
std::thread thread_; ///< peer working thread
sptr<Host> host_; ///< host
sptr<Echo> echo_; ///< echo protocol
sptr<BoostRandomGenerator> random_provider_; ///< random provider
sptr<KeyGenerator> key_generator_; ///< key generator
};
#endif // LIBP2P_HOST_TEST_PEER_HPP

33
test/acceptance/p2p/muxer.cpp

@ -7,6 +7,7 @@
#include <random>
#include <gtest/gtest.h>
#include <libp2p/common/literals.hpp>
#include <libp2p/connection/stream.hpp>
#include <libp2p/crypto/key_marshaller/key_marshaller_impl.hpp>
#include <libp2p/muxer/yamux.hpp>
@ -17,7 +18,6 @@
#include <mock/libp2p/crypto/key_validator_mock.hpp>
#include <mock/libp2p/transport/upgrader_mock.hpp>
#include "testutil/libp2p/peer.hpp"
#include "testutil/literals.hpp"
#include "testutil/outcome.hpp"
using namespace libp2p;
@ -30,6 +30,7 @@ using namespace peer;
using namespace crypto;
using namespace marshaller;
using namespace validator;
using namespace libp2p::common;
using ::testing::_;
using ::testing::Mock;
@ -96,7 +97,7 @@ struct Server : public std::enable_shared_from_this<Server> {
this->println("readSome ", read, " bytes");
this->streamReads++;
// echo back read data
// 01-echo back read data
stream->write(
*buf, read,
[buf, read, stream, this](outcome::result<size_t> rwrite) {
@ -272,22 +273,24 @@ TEST_P(MuxerAcceptanceTest, ParallelEcho) {
auto serverAddr = "/ip4/127.0.0.1/tcp/40312"_multiaddr;
KeyPair serverKeyPair = {{{Key::Type ::ED25519, {1}}},
{{Key::Type ::ED25519, {2}}}};
KeyPair serverKeyPair = {{{Key::Type::Ed25519, {1}}},
{{Key::Type::Ed25519, {2}}}};
auto muxer = GetParam();
auto idmgr = std::make_shared<IdentityManagerImpl>(serverKeyPair);
auto key_validator = std::make_shared<KeyValidatorMock>();
auto key_marshaller = std::make_shared<KeyMarshallerImpl>(key_validator);
EXPECT_CALL(*key_validator, validate(::testing::An<const PrivateKey &>()))
.WillRepeatedly(::testing::Return(outcome::success()));
EXPECT_CALL(*key_validator, validate(::testing::An<const PublicKey &>()))
.WillRepeatedly(::testing::Return(outcome::success()));
auto key_marshaller = std::make_shared<KeyMarshallerImpl>(key_validator);
auto muxer = GetParam();
auto idmgr =
std::make_shared<IdentityManagerImpl>(serverKeyPair, key_marshaller);
auto msg_marshaller =
std::make_shared<plaintext::ExchangeMessageMarshallerImpl>(
key_marshaller);
auto plaintext = std::make_shared<Plaintext>(msg_marshaller, idmgr);
auto plaintext =
std::make_shared<Plaintext>(msg_marshaller, idmgr, key_marshaller);
auto upgrader = std::make_shared<UpgraderSemiMock>(plaintext, muxer);
auto transport = std::make_shared<TcpTransport>(context, upgrader);
auto server = std::make_shared<Server>(transport);
@ -300,22 +303,26 @@ TEST_P(MuxerAcceptanceTest, ParallelEcho) {
clients.emplace_back([&, localSeed]() {
auto context = std::make_shared<boost::asio::io_context>(1);
KeyPair clientKeyPair = {{{Key::Type ::ED25519, {3}}},
{{Key::Type ::ED25519, {4}}}};
KeyPair clientKeyPair = {{{Key::Type::Ed25519, {3}}},
{{Key::Type::Ed25519, {4}}}};
auto muxer = GetParam();
auto idmgr = std::make_shared<IdentityManagerImpl>(clientKeyPair);
auto key_marshaller = std::make_shared<KeyMarshallerImpl>(key_validator);
auto idmgr =
std::make_shared<IdentityManagerImpl>(clientKeyPair, key_marshaller);
auto msg_marshaller =
std::make_shared<plaintext::ExchangeMessageMarshallerImpl>(
key_marshaller);
auto plaintext = std::make_shared<Plaintext>(msg_marshaller, idmgr);
auto plaintext =
std::make_shared<Plaintext>(msg_marshaller, idmgr, key_marshaller);
auto upgrader = std::make_shared<UpgraderSemiMock>(plaintext, muxer);
auto transport = std::make_shared<TcpTransport>(context, upgrader);
auto client = std::make_shared<Client>(transport, localSeed, context,
streams, rounds);
auto p = PeerId::fromPublicKey(serverKeyPair.publicKey);
EXPECT_OUTCOME_TRUE(marshalled_key,
key_marshaller->marshal(serverKeyPair.publicKey))
EXPECT_OUTCOME_TRUE(p, PeerId::fromPublicKey(marshalled_key))
client->connect(p, serverAddr);
context->run_for(2000ms);

1
test/libp2p/common/CMakeLists.txt

@ -8,4 +8,5 @@ addtest(hexutil_test
)
target_link_libraries(hexutil_test
p2p_hexutil
p2p_literals
)

2
test/libp2p/common/hexutil_test.cpp

@ -6,7 +6,7 @@
#include <libp2p/common/hexutil.hpp>
#include <gtest/gtest.h>
#include "testutil/literals.hpp"
#include <libp2p/common/literals.hpp>
using namespace libp2p::common;
using namespace std::string_literals;

1
test/libp2p/connection/security_conn/CMakeLists.txt

@ -10,4 +10,5 @@ target_link_libraries(plaintext_connection_test
p2p_plaintext
p2p_multiaddress
p2p_peer_id
p2p_literals
)

26
test/libp2p/connection/security_conn/plaintext_connection_test.cpp

@ -3,18 +3,20 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "libp2p/security/plaintext/plaintext_connection.hpp"
#include <libp2p/security/plaintext/plaintext_connection.hpp>
#include <gtest/gtest.h>
#include <libp2p/common/literals.hpp>
#include <testutil/outcome.hpp>
#include "mock/libp2p/connection/raw_connection_mock.hpp"
#include "mock/libp2p/crypto/key_marshaller_mock.hpp"
#include "testutil/gmock_actions.hpp"
#include "testutil/literals.hpp"
using namespace libp2p::connection;
using namespace libp2p::basic;
using namespace libp2p::crypto;
using namespace libp2p::peer;
using namespace libp2p::common;
using testing::_;
using testing::ByMove;
@ -23,14 +25,18 @@ using testing::Return;
class PlaintextConnectionTest : public testing::Test {
public:
PublicKey local{{Key::Type::SECP256K1, {1}}};
PublicKey remote{{Key::Type::ED25519, {2}}};
PublicKey local{{Key::Type::Secp256k1, {1}}};
PublicKey remote{{Key::Type::Ed25519, {2}}};
std::shared_ptr<RawConnectionMock> connection_ =
std::make_shared<RawConnectionMock>();
std::shared_ptr<marshaller::KeyMarshallerMock> key_marshaller_ =
std::make_shared<marshaller::KeyMarshallerMock>();
std::shared_ptr<SecureConnection> secure_connection_ =
std::make_shared<PlaintextConnection>(connection_, local, remote);
std::make_shared<PlaintextConnection>(connection_, local, remote,
key_marshaller_);
std::vector<uint8_t> bytes_{0x11, 0x22};
};
@ -41,7 +47,10 @@ class PlaintextConnectionTest : public testing::Test {
* @then method behaves as expected
*/
TEST_F(PlaintextConnectionTest, LocalPeer) {
ASSERT_EQ(secure_connection_->localPeer().value(), PeerId::fromPublicKey(local));
EXPECT_CALL(*key_marshaller_, marshal(local))
.WillOnce(Return(ProtobufKey{local.data}));
ASSERT_EQ(secure_connection_->localPeer().value(),
PeerId::fromPublicKey(ProtobufKey{local.data}).value());
}
/**
@ -50,7 +59,10 @@ TEST_F(PlaintextConnectionTest, LocalPeer) {
* @then method behaves as expected
*/
TEST_F(PlaintextConnectionTest, RemotePeer) {
ASSERT_EQ(secure_connection_->remotePeer().value(), PeerId::fromPublicKey(remote));
EXPECT_CALL(*key_marshaller_, marshal(remote))
.WillOnce(Return(ProtobufKey{remote.data}));
ASSERT_EQ(secure_connection_->remotePeer().value(),
PeerId::fromPublicKey(ProtobufKey{remote.data}).value());
}
/**

2
test/libp2p/crypto/CMakeLists.txt

@ -13,6 +13,7 @@ addtest(aes_test
target_link_libraries(aes_test
p2p_aes_provider
p2p_testutil
p2p_literals
)
addtest(hmac_test
@ -21,6 +22,7 @@ addtest(hmac_test
target_link_libraries(hmac_test
p2p_hmac_provider
p2p_testutil
p2p_literals
)
addtest(random_test

18
test/libp2p/crypto/aes_test.cpp

@ -5,13 +5,13 @@
#include "libp2p/crypto/aes_provider/aes_provider_impl.hpp"
#include <gtest/gtest.h>
#include <libp2p/common/literals.hpp>
#include <libp2p/common/types.hpp>
#include <libp2p/crypto/common.hpp>
#include <libp2p/outcome/outcome.hpp>
#include "testutil/literals.hpp"
using libp2p::common::ByteArray;
using namespace libp2p::crypto;
using namespace libp2p::common;
class AesTest : public testing::Test {
protected:
@ -25,20 +25,20 @@ class AesTest : public testing::Test {
plain_text_256.insert(plain_text_256.end(), msg2.begin(), msg2.end());
}
Buffer iv{"3dafba429d9eb430b422da802c9fac41"_unhex};
ByteArray iv{"3dafba429d9eb430b422da802c9fac41"_unhex};
Buffer key_128{"06a9214036b8a15b512e03d534120006"_unhex};
ByteArray key_128{"06a9214036b8a15b512e03d534120006"_unhex};
Buffer key_256{
ByteArray key_256{
"78dae34bc0eba813c09cec5c871f3ccb39dcbbe04a2fe1837e169fee896aa208"_unhex};
Buffer cipher_text_128{"d43130f652c4c81be62fdf5e72e48cbc"_unhex};
ByteArray cipher_text_128{"d43130f652c4c81be62fdf5e72e48cbc"_unhex};
Buffer cipher_text_256{
ByteArray cipher_text_256{
"586a49b4ba0336ffe130c5f27b80d3c9910d7f422687a60b1b833cff3d9ecbe03e4db5653a671fb1a7b2"_unhex};
Buffer plain_text_128;
Buffer plain_text_256;
ByteArray plain_text_128;
ByteArray plain_text_256;
aes::AesProviderImpl provider;
};

4
test/libp2p/crypto/hmac_test.cpp

@ -6,14 +6,14 @@
#include <libp2p/crypto/hmac_provider/hmac_provider_impl.hpp>
#include <gtest/gtest.h>
#include <libp2p/common/literals.hpp>
#include <libp2p/common/types.hpp>
#include <libp2p/crypto/common.hpp>
#include <libp2p/crypto/error.hpp>
#include <libp2p/outcome/outcome.hpp>
#include "testutil/literals.hpp"
using libp2p::common::ByteArray;
using namespace libp2p::crypto;
using namespace libp2p::common;
class HmacTest : public testing::Test {
protected:

24
test/libp2p/crypto/key_generator_test.cpp

@ -17,7 +17,6 @@ using libp2p::common::ByteArray;
using libp2p::crypto::Key;
using libp2p::crypto::KeyGeneratorError;
using libp2p::crypto::KeyGeneratorImpl;
using libp2p::crypto::common::RSAKeyType;
using libp2p::crypto::random::BoostRandomGenerator;
class KeyGeneratorTest : public ::testing::TestWithParam<Key::Type> {
@ -33,6 +32,10 @@ class KeyGeneratorTest : public ::testing::TestWithParam<Key::Type> {
*/
TEST_P(KeyGeneratorTest, GenerateKeyPairSuccess) {
auto key_type = GetParam();
if (key_type == Key::Type::RSA) {
return;
}
EXPECT_OUTCOME_TRUE_2(val, keygen_.generateKeys(key_type))
ASSERT_EQ(val.privateKey.type, key_type);
ASSERT_EQ(val.publicKey.type, key_type);
@ -45,6 +48,10 @@ TEST_P(KeyGeneratorTest, GenerateKeyPairSuccess) {
*/
TEST_P(KeyGeneratorTest, TwoKeysAreDifferent) {
auto key_type = GetParam();
if (key_type == Key::Type::RSA) {
return;
}
EXPECT_OUTCOME_TRUE_2(val1, keygen_.generateKeys(key_type));
EXPECT_OUTCOME_TRUE_2(val2, keygen_.generateKeys(key_type));
ASSERT_NE(val1.privateKey.data, val2.privateKey.data);
@ -60,6 +67,10 @@ TEST_P(KeyGeneratorTest, TwoKeysAreDifferent) {
*/
TEST_P(KeyGeneratorTest, DerivePublicKeySuccess) {
auto key_type = GetParam();
if (key_type == Key::Type::RSA) {
return;
}
EXPECT_OUTCOME_TRUE_2(keys, keygen_.generateKeys(key_type));
EXPECT_OUTCOME_TRUE_2(derived, keygen_.derivePublicKey(keys.privateKey));
ASSERT_EQ(derived.type, key_type);
@ -67,11 +78,8 @@ TEST_P(KeyGeneratorTest, DerivePublicKeySuccess) {
}
INSTANTIATE_TEST_CASE_P(TestAllKeyTypes, KeyGeneratorTest,
::testing::Values(Key::Type::RSA1024,
Key::Type::RSA2048,
Key::Type::RSA4096,
Key::Type::ED25519,
Key::Type::SECP256K1));
::testing::Values(Key::Type::RSA, Key::Type::Ed25519,
Key::Type::Secp256k1));
class KeyLengthTest
: public ::testing::TestWithParam<
@ -83,8 +91,8 @@ class KeyLengthTest
INSTANTIATE_TEST_CASE_P(
TestSomeKeyLengths, KeyLengthTest,
::testing::Values(std::tuple(Key::Type::ED25519, 32, 32),
std::tuple(Key::Type::SECP256K1, 32, 33)));
::testing::Values(std::tuple(Key::Type::Ed25519, 32, 32),
std::tuple(Key::Type::Secp256k1, 32, 33)));
/**
* @given key generator and tuple of <key type, private key length, public key

20
test/libp2p/crypto/key_validator_test.cpp

@ -51,6 +51,10 @@ class GeneratedKeysTest : public BaseKeyTest,
*/
TEST_P(GeneratedKeysTest, GeneratedKeysAreValid) {
Key::Type key_type = GetParam();
if (key_type == Key::Type::RSA) {
// RSA generation is not implemented yet
return;
}
EXPECT_OUTCOME_TRUE(key_pair, generator->generateKeys(key_type))
EXPECT_OUTCOME_TRUE_1(validator->validate(key_pair.publicKey))
EXPECT_OUTCOME_TRUE_1(validator->validate(key_pair.privateKey))
@ -90,6 +94,11 @@ TEST_P(GeneratedKeysTest, ArbitraryKeyInvalid) {
*/
TEST_P(GeneratedKeysTest, InvalidPublicKeyInvalidatesPair) {
Key::Type key_type = GetParam();
if (key_type == Key::Type::RSA) {
// RSA generation is not implemented yet
return;
}
EXPECT_OUTCOME_TRUE(key_pair, generator->generateKeys(key_type))
auto public_key = PublicKey{{key_type, random.randomBytes(64)}};
EXPECT_OUTCOME_FALSE_1(validator->validate(public_key))
@ -98,11 +107,8 @@ TEST_P(GeneratedKeysTest, InvalidPublicKeyInvalidatesPair) {
}
INSTANTIATE_TEST_CASE_P(GeneratedValidKeysCases, GeneratedKeysTest,
::testing::Values(Key::Type::RSA1024,
Key::Type::RSA2048,
Key::Type::RSA4096,
Key::Type::ED25519,
Key::Type::SECP256K1));
::testing::Values(Key::Type::RSA, Key::Type::Ed25519,
Key::Type::Secp256k1));
class RandomKeyTest : public BaseKeyTest,
public ::testing::TestWithParam<Key::Type> {};
@ -126,8 +132,8 @@ TEST_P(RandomKeyTest, Every32byteIsValidPrivateKey) {
}
INSTANTIATE_TEST_CASE_P(RandomSequencesCases, RandomKeyTest,
::testing::Values(Key::Type::ED25519,
Key::Type::SECP256K1));
::testing::Values(Key::Type::Ed25519,
Key::Type::Secp256k1));
class UnspecifiedKeyTest : public BaseKeyTest, public ::testing::Test {};

30
test/libp2p/crypto/marshaller_test.cpp

@ -3,16 +3,18 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "libp2p/crypto/key_marshaller/key_marshaller_impl.hpp"
#include <libp2p/crypto/key_marshaller/key_marshaller_impl.hpp>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <libp2p/crypto/common.hpp>
#include <libp2p/crypto/protobuf/protobuf_key.hpp>
#include "mock/libp2p/crypto/key_validator_mock.hpp"
using Buffer = std::vector<uint8_t>;
using libp2p::crypto::Key;
using libp2p::crypto::PrivateKey;
using libp2p::crypto::ProtobufKey;
using libp2p::crypto::PublicKey;
using libp2p::crypto::marshaller::KeyMarshallerImpl;
using libp2p::crypto::validator::KeyValidator;
@ -61,6 +63,11 @@ class Privkey : public testing::TestWithParam<KeyCase<PrivateKey>> {
TEST_P(Pubkey, Valid) {
auto [key, match_prefix] = GetParam();
if (key.type == Key::Type::UNSPECIFIED) {
// we can't marshal UNSPECIFIED keys
ASSERT_FALSE(marshaller_.marshal(key));
return;
}
Buffer match;
match.insert(match.begin(), match_prefix.begin(), match_prefix.end());
@ -71,10 +78,10 @@ TEST_P(Pubkey, Valid) {
ASSERT_TRUE(res);
auto &&val = res.value();
ASSERT_EQ(val, match);
ASSERT_EQ(val.key, match);
}
{
auto &&res = marshaller_.unmarshalPublicKey(match);
auto &&res = marshaller_.unmarshalPublicKey(ProtobufKey{match});
ASSERT_TRUE(res);
auto &&val = res.value();
ASSERT_EQ(val.type, key.type);
@ -84,6 +91,11 @@ TEST_P(Pubkey, Valid) {
TEST_P(Privkey, Valid) {
auto [key, match_prefix] = GetParam();
if (key.type == Key::Type::UNSPECIFIED) {
// we can't marshal UNSPECIFIED keys
ASSERT_FALSE(marshaller_.marshal(key));
return;
}
Buffer match;
match.insert(match.begin(), match_prefix.begin(), match_prefix.end());
@ -94,10 +106,10 @@ TEST_P(Privkey, Valid) {
ASSERT_TRUE(res);
auto &&val = res.value();
ASSERT_EQ(val, match);
ASSERT_EQ(val.key, match);
}
{
auto &&res = marshaller_.unmarshalPrivateKey(match);
auto &&res = marshaller_.unmarshalPrivateKey(ProtobufKey{match});
ASSERT_TRUE(res);
auto &&val = res.value();
ASSERT_EQ(val.type, key.type);
@ -110,11 +122,9 @@ auto makeTestCases() {
// clang-format off
return std::vector<KeyCase<T>>{
{{T{{Key::Type::UNSPECIFIED, randomBuffer(16)}}}, {18, 16}},
{{T{{Key::Type::RSA1024, randomBuffer(16)}}}, {8, 1, 18, 16}},
{{T{{Key::Type::RSA2048, randomBuffer(16)}}}, {8, 2, 18, 16}},
{{T{{Key::Type::RSA4096, randomBuffer(16)}}}, {8, 3, 18, 16}},
{{T{{Key::Type::ED25519, randomBuffer(16)}}}, {8, 4, 18, 16}},
{{T{{Key::Type::SECP256K1, randomBuffer(16)}}}, {8, 5, 18, 16}},
{{T{{Key::Type::RSA, randomBuffer(16)}}}, {8, 0, 18, 16}},
{{T{{Key::Type::Ed25519, randomBuffer(16)}}}, {8, 1, 18, 16}},
{{T{{Key::Type::Secp256k1, randomBuffer(16)}}}, {8, 2, 18, 16}},
};
// clang-format on
}

4
test/libp2p/injector/network_injector_test.cpp

@ -41,8 +41,8 @@ TEST(NetworkBuilder, DefaultBuilds) {
*/
TEST(NetworkBuilder, CustomKeyPairBuilds) {
KeyPair keyPair{
{{Key::Type::ED25519, {1}}},
{{Key::Type::ED25519, {2}}},
{{Key::Type::Ed25519, {1}}},
{{Key::Type::Ed25519, {2}}},
};
auto injector = makeNetworkInjector(useKeyPair(keyPair));

4
test/libp2p/multi/CMakeLists.txt

@ -11,14 +11,15 @@ addtest(multihash_test
)
target_link_libraries(multihash_test
p2p_multihash
p2p_literals
)
addtest(multiaddress_test
multiaddress_test.cpp
)
target_link_libraries(multiaddress_test
p2p_multiaddress
p2p_literals
)
addtest(multibase_codec_test
@ -26,4 +27,5 @@ addtest(multibase_codec_test
)
target_link_libraries(multibase_codec_test
p2p_multibase_codec
p2p_literals
)

4
test/libp2p/multi/multiaddress_test.cpp

@ -8,9 +8,9 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <libp2p/common/literals.hpp>
#include <libp2p/common/types.hpp>
#include <libp2p/multi/multiaddress_protocol_list.hpp>
#include "testutil/literals.hpp"
#include "testutil/outcome.hpp"
using libp2p::multi::Multiaddress;
@ -19,6 +19,8 @@ using libp2p::multi::ProtocolList;
using std::string_literals::operator""s;
using libp2p::common::ByteArray;
using namespace libp2p::common;
class MultiaddressTest : public ::testing::Test {
public:
const std::string_view valid_ip_udp = "/ip4/192.168.0.1/udp/228";

2
test/libp2p/multi/multibase_codec_test.cpp

@ -6,8 +6,8 @@
#include <libp2p/multi/multibase_codec/multibase_codec_impl.hpp>
#include <gtest/gtest.h>
#include <libp2p/common/literals.hpp>
#include <libp2p/common/types.hpp>
#include "testutil/literals.hpp"
using namespace libp2p::multi;
using namespace libp2p::common;

5
test/libp2p/multi/multihash_test.cpp

@ -6,12 +6,11 @@
#include <gtest/gtest.h>
#include <libp2p/common/hexutil.hpp>
#include <libp2p/common/literals.hpp>
#include <libp2p/multi/multihash.hpp>
#include <libp2p/multi/uvarint.hpp>
#include "testutil/literals.hpp"
using libp2p::common::ByteArray;
using libp2p::common::hex_upper;
using namespace libp2p::common;
using libp2p::multi::HashType;
using libp2p::multi::Multihash;

8
test/libp2p/multi/utils/string_from_to_bytes_test.cpp

@ -17,15 +17,15 @@ using libp2p::multi::converters::multiaddrToBytes;
#define VALID_STR_TO_BYTES(addr, bytes) \
{ \
EXPECT_OUTCOME_TRUE_name(r1, v1, multiaddrToBytes(addr)); \
EXPECT_OUTCOME_TRUE_name(r2, v2, unhex(bytes)); \
EXPECT_OUTCOME_TRUE_NAME(r1, v1, multiaddrToBytes(addr)); \
EXPECT_OUTCOME_TRUE_NAME(r2, v2, unhex(bytes)); \
ASSERT_EQ(v1, v2); \
}
#define VALID_BYTES_TO_STR(addr, bytes) \
{ \
EXPECT_OUTCOME_TRUE_name(r3, v1, unhex(bytes)); \
EXPECT_OUTCOME_TRUE_name(r4, v2, bytesToMultiaddrString(ByteArray{v1})); \
EXPECT_OUTCOME_TRUE_NAME(r3, v1, unhex(bytes)); \
EXPECT_OUTCOME_TRUE_NAME(r4, v2, bytesToMultiaddrString(ByteArray{v1})); \
ASSERT_EQ(v2, addr); \
}

3
test/libp2p/muxer/yamux/CMakeLists.txt

@ -12,6 +12,7 @@ target_link_libraries(yamux_integration_test
p2p_plaintext
p2p_tcp
p2p_testutil
p2p_literals
)
addtest(yamux_acceptance_test
@ -24,6 +25,7 @@ target_link_libraries(yamux_acceptance_test
p2p_plaintext
p2p_tcp
p2p_testutil
p2p_literals
)
addtest(yamux_frame_test
@ -32,4 +34,5 @@ addtest(yamux_frame_test
target_link_libraries(yamux_frame_test
p2p_yamuxed_connection
p2p_testutil
p2p_literals
)

4
test/libp2p/muxer/yamux/yamux_acceptance_test.cpp

@ -15,7 +15,7 @@
#include "mock/libp2p/transport/upgrader_mock.hpp"
#include "testutil/gmock_actions.hpp"
#include "testutil/libp2p/peer.hpp"
#include "testutil/literals.hpp"
#include <libp2p/common/literals.hpp>
#include "testutil/outcome.hpp"
using namespace libp2p::connection;
@ -142,7 +142,7 @@ TEST(YamuxAcceptanceTest, PingPong) {
});
// let the streams make their jobs
context->run_for(100ms);
context->run_for(500ms);
EXPECT_TRUE(stream_read);
EXPECT_TRUE(stream_wrote);

8
test/libp2p/muxer/yamux/yamux_frame_test.cpp

@ -6,7 +6,7 @@
#include "libp2p/muxer/yamux/yamux_frame.hpp"
#include <gtest/gtest.h>
#include "testutil/literals.hpp"
#include <libp2p/common/literals.hpp>
using namespace libp2p::connection;
using namespace libp2p::common;
@ -32,7 +32,7 @@ class YamuxFrameTest : public ::testing::Test {
auto frame = *frame_opt;
ASSERT_EQ(frame.version, version);
ASSERT_EQ(frame.type, type);
ASSERT_EQ(frame.flag, flag);
ASSERT_EQ(frame.flags, static_cast<uint16_t>(flag));
ASSERT_EQ(frame.stream_id, stream_id);
ASSERT_EQ(frame.length, length);
ASSERT_EQ(frame.data, frame_data);
@ -50,7 +50,7 @@ TEST_F(YamuxFrameTest, ParseFrameSuccess) {
SCOPED_TRACE("ParseFrameSuccess");
checkFrame(frame_opt, YamuxFrame::kDefaultVersion,
YamuxFrame::FrameType::DATA, YamuxFrame::Flag::SYN,
YamuxFrame::FrameType::DATA, YamuxFrame::Flag::NONE,
default_stream_id, data_length, data);
}
@ -166,7 +166,7 @@ TEST_F(YamuxFrameTest, GoAwayMsg) {
SCOPED_TRACE("GoAwayMsg");
checkFrame(frame_opt, YamuxFrame::kDefaultVersion,
YamuxFrame::FrameType::GO_AWAY, YamuxFrame::Flag::SYN, 0,
YamuxFrame::FrameType::GO_AWAY, YamuxFrame::Flag::NONE, 0,
static_cast<uint32_t>(YamuxFrame::GoAwayError::PROTOCOL_ERROR),
ByteArray{});
}

2
test/libp2p/muxer/yamux/yamux_integration_test.cpp

@ -7,6 +7,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <libp2p/common/literals.hpp>
#include <libp2p/multi/multiaddress.hpp>
#include <libp2p/muxer/yamux.hpp>
#include <libp2p/muxer/yamux/yamux_frame.hpp>
@ -17,7 +18,6 @@
#include "mock/libp2p/transport/upgrader_mock.hpp"
#include "testutil/gmock_actions.hpp"
#include "testutil/libp2p/peer.hpp"
#include "testutil/literals.hpp"
#include "testutil/outcome.hpp"
using namespace libp2p::connection;

4
test/libp2p/network/CMakeLists.txt

@ -19,6 +19,7 @@ addtest(transport_manager_test
target_link_libraries(transport_manager_test
p2p_transport_manager
p2p_multiaddress
p2p_literals
)
@ -32,6 +33,7 @@ target_link_libraries(connection_manager_test
p2p_peer_id
p2p_testutil
p2p_peer_errors
p2p_literals
)
@ -40,6 +42,7 @@ addtest(listener_manager_test
)
target_link_libraries(listener_manager_test
p2p_listener_manager
p2p_literals
)
@ -48,4 +51,5 @@ addtest(dialer_test
)
target_link_libraries(dialer_test
p2p_dialer
p2p_literals
)

11
test/libp2p/network/connection_manager_test.cpp

@ -5,6 +5,7 @@
#include <gtest/gtest.h>
#include <libp2p/common/literals.hpp>
#include "libp2p/network/connection_manager.hpp"
#include "libp2p/network/impl/connection_manager_impl.hpp"
#include "libp2p/peer/errors.hpp"
@ -13,13 +14,13 @@
#include "mock/libp2p/network/transport_manager_mock.hpp"
#include "mock/libp2p/transport/transport_mock.hpp"
#include "testutil/libp2p/peer.hpp"
#include "testutil/literals.hpp"
using namespace libp2p::network;
using namespace libp2p::transport;
using namespace libp2p::connection;
using namespace libp2p::peer;
using namespace libp2p;
using namespace network;
using namespace transport;
using namespace connection;
using namespace peer;
using namespace common;
using testing::_;
using testing::NiceMock;

3
test/libp2p/network/dialer_test.cpp

@ -6,6 +6,7 @@
#include "libp2p/network/impl/dialer_impl.hpp"
#include <gtest/gtest.h>
#include <libp2p/common/literals.hpp>
#include "mock/libp2p/connection/capable_connection_mock.hpp"
#include "mock/libp2p/connection/stream_mock.hpp"
#include "mock/libp2p/network/connection_manager_mock.hpp"
@ -15,7 +16,6 @@
#include "mock/libp2p/protocol_muxer/protocol_muxer_mock.hpp"
#include "mock/libp2p/transport/transport_mock.hpp"
#include "testutil/gmock_actions.hpp"
#include "testutil/literals.hpp"
#include "testutil/outcome.hpp"
using namespace libp2p;
@ -23,6 +23,7 @@ using namespace network;
using namespace connection;
using namespace transport;
using namespace protocol_muxer;
using namespace common;
using ::testing::_;
using ::testing::ContainerEq;

4
test/libp2p/network/listener_manager_test.cpp

@ -6,6 +6,7 @@
#include "libp2p/network/impl/listener_manager_impl.hpp"
#include <gtest/gtest.h>
#include <libp2p/common/literals.hpp>
#include "mock/libp2p/connection/stream_mock.hpp"
#include "mock/libp2p/network/connection_manager_mock.hpp"
#include "mock/libp2p/network/router_mock.hpp"
@ -15,7 +16,6 @@
#include "mock/libp2p/transport/transport_listener_mock.hpp"
#include "mock/libp2p/transport/transport_mock.hpp"
#include "testutil/gmock_actions.hpp"
#include "testutil/literals.hpp"
#include "testutil/outcome.hpp"
using namespace libp2p;
@ -24,6 +24,8 @@ using namespace protocol_muxer;
using namespace transport;
using namespace protocol;
using namespace connection;
using namespace common;
using ::testing::_;
using ::testing::Eq;
using ::testing::MockFunction;

3
test/libp2p/network/transport_manager_test.cpp

@ -6,12 +6,13 @@
#include "libp2p/network/impl/transport_manager_impl.hpp"
#include <gtest/gtest.h>
#include <libp2p/common/literals.hpp>
#include "mock/libp2p/transport/transport_mock.hpp"
#include "testutil/literals.hpp"
using namespace libp2p::network;
using namespace libp2p::multi;
using namespace libp2p::transport;
using namespace libp2p::common;
using testing::AtMost;
using testing::Return;

4
test/libp2p/peer/CMakeLists.txt

@ -8,6 +8,10 @@ addtest(peer_id_test
)
target_link_libraries(peer_id_test
p2p_peer_id
p2p_key_generator
p2p_key_marshaller
p2p_random_generator
p2p_key_validator
)
addtest(peer_address_test

1
test/libp2p/peer/address_repository/CMakeLists.txt

@ -6,4 +6,5 @@ addtest(libp2p_inmem_address_repository_test
)
target_link_libraries(libp2p_inmem_address_repository_test
p2p_inmem_address_repository
p2p_literals
)

4
test/libp2p/peer/address_repository/inmem_address_repository_test.cpp

@ -7,16 +7,16 @@
#include <gtest/gtest.h>
#include <thread>
#include <libp2p/common/literals.hpp>
#include <libp2p/peer/address_repository.hpp>
#include <libp2p/peer/address_repository/inmem_address_repository.hpp>
#include <libp2p/peer/errors.hpp>
#include "testutil/literals.hpp"
#include "testutil/outcome.hpp"
using namespace libp2p::peer;
using namespace libp2p::multi;
using namespace libp2p::common;
using libp2p::common::ByteArray;
using std::literals::chrono_literals::operator""ms;
struct InmemAddressRepository_Test : public ::testing::Test {

14
test/libp2p/peer/key_book/inmem_key_repository_test.cpp

@ -38,14 +38,14 @@ struct InmemKeyRepositoryTest : ::testing::Test {
};
TEST_F(InmemKeyRepositoryTest, PubkeyStore) {
EXPECT_OUTCOME_TRUE_1(db_->addPublicKey(p1_, {{Key::Type::ED25519, {'a'}}}));
EXPECT_OUTCOME_TRUE_1(db_->addPublicKey(p1_, {{Key::Type::ED25519, {'b'}}}));
EXPECT_OUTCOME_TRUE_1(db_->addPublicKey(p1_, {{Key::Type::Ed25519, {'a'}}}));
EXPECT_OUTCOME_TRUE_1(db_->addPublicKey(p1_, {{Key::Type::Ed25519, {'b'}}}));
// insert same pubkey. it should not be inserted
EXPECT_OUTCOME_TRUE_1(db_->addPublicKey(p1_, {{Key::Type::ED25519, {'b'}}}));
EXPECT_OUTCOME_TRUE_1(db_->addPublicKey(p1_, {{Key::Type::Ed25519, {'b'}}}));
// same pubkey but different type
EXPECT_OUTCOME_TRUE_1(db_->addPublicKey(p1_, {{Key::Type::RSA1024, {'b'}}}));
EXPECT_OUTCOME_TRUE_1(db_->addPublicKey(p1_, {{Key::Type::RSA, {'b'}}}));
// put pubkey to different peer
EXPECT_OUTCOME_TRUE_1(db_->addPublicKey(p2_, {{Key::Type::RSA4096, {'c'}}}));
EXPECT_OUTCOME_TRUE_1(db_->addPublicKey(p2_, {{Key::Type::RSA, {'c'}}}));
EXPECT_OUTCOME_TRUE(v, db_->getPublicKeys(p1_));
EXPECT_EQ(v->size(), 3);
@ -56,8 +56,8 @@ TEST_F(InmemKeyRepositoryTest, PubkeyStore) {
}
TEST_F(InmemKeyRepositoryTest, KeyPairStore) {
PublicKey pub = {{Key::Type::RSA1024, {'a'}}};
PrivateKey priv = {{Key::Type::RSA1024, {'b'}}};
PublicKey pub = {{Key::Type::RSA, {'a'}}};
PrivateKey priv = {{Key::Type::RSA, {'b'}}};
KeyPair kp{pub, priv};
EXPECT_OUTCOME_TRUE_1(db_->addKeyPair({pub, priv}));

8
test/libp2p/peer/peer_id_test.cpp

@ -6,6 +6,7 @@
#include "libp2p/peer/peer_id.hpp"
#include <gtest/gtest.h>
#include <libp2p/crypto/key_marshaller/key_marshaller_impl.hpp>
#include <libp2p/crypto/sha/sha256.hpp>
#include <libp2p/multi/multibase_codec/codecs/base58.hpp>
#include <testutil/outcome.hpp>
@ -17,7 +18,8 @@ using namespace libp2p::multi::detail;
class PeerIdTest : public ::testing::Test {
public:
const Buffer kBuffer{0x11, 0x22, 0x33};
const Buffer kBuffer =
Buffer(43, 1); // so that the key is not used as an "identity"
};
/**
@ -27,7 +29,7 @@ class PeerIdTest : public ::testing::Test {
*/
TEST_F(PeerIdTest, FromPubkeySuccess) {
PublicKey pubkey{};
pubkey.type = Key::Type::RSA1024;
pubkey.type = Key::Type::RSA;
pubkey.data = kBuffer;
auto hash = libp2p::crypto::sha256(pubkey.data);
@ -35,7 +37,7 @@ TEST_F(PeerIdTest, FromPubkeySuccess) {
Multihash::create(libp2p::multi::sha256,
Buffer{hash.begin(), hash.end()}))
auto peer_id = PeerId::fromPublicKey(pubkey);
EXPECT_OUTCOME_TRUE(peer_id, PeerId::fromPublicKey(ProtobufKey{pubkey.data}))
EXPECT_EQ(peer_id.toBase58(), encodeBase58(multihash.toBuffer()));
EXPECT_EQ(peer_id.toMultihash(), multihash);
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save