Add configuration system.

This commit is contained in:
David Craven 2019-02-05 18:13:52 +01:00
parent 7da347fc86
commit adce8eb288
No known key found for this signature in database
GPG Key ID: DF438712EA50DBB1
7 changed files with 133 additions and 68 deletions

12
Cargo.lock generated
View File

@ -609,9 +609,15 @@ dependencies = [
"libp2p 0.3.0",
"multibase 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"multihash 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-multiaddr 0.1.0",
"parity-multihash 0.1.0",
"protobuf 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.86 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.86 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
"xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -2136,6 +2142,11 @@ dependencies = [
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "xdg"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "yamux"
version = "0.1.6"
@ -2360,4 +2371,5 @@ dependencies = [
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
"checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
"checksum yamux 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e25561b512df3c287cf52404cab0b07ea43d095cb96230e9e2cb635db72d75f0"

View File

@ -10,6 +10,12 @@ futures = "*"
libp2p = { version = "*", path = "../rust-libp2p" }
multibase = "*"
multihash = "*"
parity-multiaddr = { version = "*", path = "../rust-libp2p/misc/multiaddr" }
parity-multihash = { version = "*", path = "../rust-libp2p/misc/multihash" }
protobuf = "2.0.2"
rand = "0.6"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
tokio = "*"
xdg = "*"

94
src/config.rs Normal file
View File

@ -0,0 +1,94 @@
use libp2p::{Multiaddr, PeerId};
use libp2p::multiaddr::Protocol;
use libp2p::secio::SecioKeyPair;
use rand::{Rng, rngs::EntropyRng};
use serde_derive::{Serialize, Deserialize};
use std::fs;
use std::path::Path;
const APP_NAME: &'static str = "rust-ipfs";
const CONFIG_FILE: &'static str = "config.json";
const BOOTSTRAP_NODES: &[&'static str] = &[
"/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
"/ip4/104.236.179.241/tcp/4001/p2p/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM",
"/ip4/104.236.76.40/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64",
"/ip4/128.199.219.111/tcp/4001/p2p/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu",
"/ip4/178.62.158.247/tcp/4001/p2p/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd",
"/ip6/2400:6180:0:d0::151:6001/tcp/4001/p2p/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu",
"/ip6/2604:a880:1:20::203:d001/tcp/4001/p2p/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM",
"/ip6/2604:a880:800:10::4a:5001/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64",
"/ip6/2a03:b0c0:0:1010::23:1001/tcp/4001/p2p/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd",
];
#[derive(Serialize, Deserialize)]
pub struct Configuration {
raw_key: [u8; 32],
bootstrap: Vec<Multiaddr>,
}
impl Configuration {
pub fn new() -> Self {
let xdg_dirs = xdg::BaseDirectories::with_prefix(APP_NAME).unwrap();
let path = xdg_dirs.place_config_file(CONFIG_FILE).unwrap();
Configuration::from_file(path)
}
pub fn secio_key_pair(&self) -> SecioKeyPair {
SecioKeyPair::ed25519_raw_key(&self.raw_key).unwrap()
}
pub fn bootstrap(&self) -> Vec<(Multiaddr, PeerId)> {
let mut bootstrap = Vec::new();
for addr in &self.bootstrap {
let mut addr = addr.to_owned();
let peer_id = match addr.pop() {
Some(Protocol::P2p(hash)) => PeerId::from_multihash(hash).unwrap(),
_ => panic!("No peer id for addr"),
};
bootstrap.push((addr, peer_id));
}
bootstrap
}
pub fn generate() -> Self {
let raw_key: [u8; 32] = EntropyRng::new().gen();
let bootstrap = BOOTSTRAP_NODES.iter().map(|node| {
node.parse().unwrap()
}).collect();
Configuration {
raw_key,
bootstrap,
}
}
pub fn from_file<P: AsRef<Path>>(path: P) -> Self {
fs::read_to_string(&path).map(|content| {
serde_json::from_str(&content).unwrap()
}).unwrap_or_else(|_| {
let config = Configuration::generate();
let string = serde_json::to_string(&config).unwrap();
fs::write(path, string).unwrap();
config
})
}
}
pub struct NetworkConfig {
pub key_pair: SecioKeyPair,
pub peer_id: PeerId,
pub bootstrap: Vec<(Multiaddr, PeerId)>,
}
impl From<&Configuration> for NetworkConfig {
fn from(config: &Configuration) -> Self {
let key_pair = config.secio_key_pair();
let peer_id = key_pair.to_peer_id();
let bootstrap = config.bootstrap();
NetworkConfig {
key_pair,
peer_id,
bootstrap,
}
}
}

View File

@ -4,16 +4,17 @@
#![feature(drain_filter)]
use futures::prelude::*;
use futures::try_ready;
use libp2p::secio::SecioKeyPair;
mod bitswap;
pub mod block;
mod config;
mod future;
mod p2p;
mod repo;
use self::bitswap::{strategy::AltruisticStrategy, Strategy};
pub use self::block::{Block, Cid};
use self::config::{Configuration, NetworkConfig};
use self::future::BlockFuture;
use self::p2p::{create_swarm, Swarm};
use self::repo::Repo;
@ -30,10 +31,10 @@ pub struct Ipfs {
impl Ipfs {
/// Creates a new ipfs node.
pub fn new() -> Self {
let config = Configuration::new();
let repo = Repo::new();
let local_key = SecioKeyPair::ed25519_generated().unwrap();
let strategy = AltruisticStrategy::new(repo.clone());
let swarm = create_swarm(local_key);
let swarm = create_swarm(NetworkConfig::from(&config));
Ipfs {
repo,

View File

@ -1,5 +1,6 @@
use crate::bitswap::{Bitswap, BitswapEvent};
use crate::block::{Block, Cid};
use crate::config::NetworkConfig;
use libp2p::{NetworkBehaviour, PeerId};
use libp2p::core::swarm::NetworkBehaviourEventProcess;
use libp2p::core::muxing::{StreamMuxerBox, SubstreamRef};
@ -8,46 +9,6 @@ use parity_multihash::Multihash;
use std::sync::Arc;
use tokio::prelude::*;
/// IPFS bootstrap nodes.
const BOOTSTRAP_NODES: &[(&'static str, &'static str)] = &[
(
"QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
"/ip4/104.131.131.82/tcp/4001",
),
(
"QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM",
"/ip4/104.236.179.241/tcp/4001",
),
(
"QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64",
"/ip4/104.236.76.40/tcp/4001",
),
(
"QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu",
"/ip4/128.199.219.111/tcp/4001",
),
(
"QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd",
"/ip4/178.62.158.247/tcp/4001",
),
/*(
"QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu",
"/ip6/2400:6180:0:d0::151:6001/tcp/4001",
),
(
"QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM",
"/ip6/2604:a880:1:20::203:d001/tcp/4001",
),
(
"QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64",
"/ip6/2604:a880:800:10::4a:5001/tcp/4001",
),
(
"QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd",
"/ip6/2a03:b0c0:0:1010::23:1001/tcp/4001",
),*/
];
/// Behaviour type.
#[derive(NetworkBehaviour)]
pub struct Behaviour<TSubstream: AsyncRead + AsyncWrite> {
@ -103,21 +64,13 @@ impl<TSubstream: AsyncRead + AsyncWrite>
impl<TSubstream: AsyncRead + AsyncWrite> Behaviour<TSubstream>
{
/// Create a Kademlia behaviour with the IPFS bootstrap nodes.
pub fn new(local_peer_id: PeerId) -> Self {
println!("Local peer id: {}", &local_peer_id.to_base58());
pub fn new(config: &NetworkConfig) -> Self {
println!("Local peer id: {}", config.peer_id.to_base58());
// Note that normally the Kademlia process starts by performing lots of
// request in order to insert our local node in the DHT. However here we use
// `without_init` because this example is very ephemeral and we don't want
// to pollute the DHT. In a real world application, you want to use `new`
// instead.
let mut kademlia = Kademlia::without_init(local_peer_id);
let mut kademlia = Kademlia::new(config.peer_id.to_owned());
for (identity, location) in BOOTSTRAP_NODES {
kademlia.add_address(
&identity.parse().unwrap(),
location.parse().unwrap(),
);
for (addr, peer_id) in &config.bootstrap {
kademlia.add_address(peer_id, addr.to_owned());
}
let bitswap = Bitswap::new();
@ -153,6 +106,6 @@ impl<TSubstream: AsyncRead + AsyncWrite> Behaviour<TSubstream>
pub type TBehaviour = Behaviour<SubstreamRef<Arc<StreamMuxerBox>>>;
/// Create a IPFS behaviour with the IPFS bootstrap nodes.
pub fn build_behaviour(local_peer_id: PeerId) -> TBehaviour {
Behaviour::new(local_peer_id)
pub fn build_behaviour(config: &NetworkConfig) -> TBehaviour {
Behaviour::new(config)
}

View File

@ -1,5 +1,5 @@
//! P2P handling for IPFS nodes.
pub use libp2p::secio::SecioKeyPair;
use crate::config::NetworkConfig;
mod behaviour;
mod transport;
@ -7,15 +7,13 @@ mod transport;
pub type Swarm = libp2p::core::Swarm<transport::TTransport, behaviour::TBehaviour>;
/// Creates a new IPFS swarm.
pub fn create_swarm(local_private_key: SecioKeyPair) -> Swarm {
let local_peer_id = local_private_key.to_peer_id();
pub fn create_swarm(config: NetworkConfig) -> Swarm {
// Set up an encrypted TCP transport over the Mplex protocol.
let transport = transport::build_transport(local_private_key);
let transport = transport::build_transport(&config);
// Create a Kademlia behaviour
let behaviour = behaviour::build_behaviour(local_peer_id.clone());
let behaviour = behaviour::build_behaviour(&config);
// Create a Swarm
libp2p::core::Swarm::new(transport, behaviour, local_peer_id)
libp2p::core::Swarm::new(transport, behaviour, config.peer_id)
}

View File

@ -1,10 +1,11 @@
use crate::config::NetworkConfig;
use futures::future::Future;
use libp2p::{PeerId, Transport};
use libp2p::core::muxing::StreamMuxerBox;
use libp2p::core::transport::boxed::Boxed;
use libp2p::core::upgrade::{self, InboundUpgradeExt, OutboundUpgradeExt};
use libp2p::mplex::MplexConfig;
use libp2p::secio::{SecioConfig, SecioKeyPair};
use libp2p::secio::SecioConfig;
use libp2p::tcp::TcpConfig;
use std::io::{Error, ErrorKind};
use std::time::Duration;
@ -15,9 +16,9 @@ pub type TTransport = Boxed<(PeerId, StreamMuxerBox), Error>;
/// Builds the transport that serves as a common ground for all connections.
///
/// Set up an encrypted TCP transport over the Mplex protocol.
pub fn build_transport(local_private_key: SecioKeyPair) -> TTransport {
pub fn build_transport(config: &NetworkConfig) -> TTransport {
let transport = TcpConfig::new();
let secio_config = SecioConfig::new(local_private_key);
let secio_config = SecioConfig::new(config.key_pair.to_owned());
let mplex_config = MplexConfig::new();
transport