0

我是 Rust 的初学者,我一直在学习使用 Rust 创建简单区块链的本教程。

chain.rs

use byteorder::{BigEndian, ReadBytesExt};
use chrono::offset::Utc;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use std::io::Cursor;

//  Represents the entire chain in the network
pub struct Chain {
    //  Actual chain
    pub blocks: Vec<Block>,
}

//  Represents a single block in the blockchain
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Block {
    pub id: u64,

    //  Hash representing block
    pub hash: String,

    //  Hash of the previous block
    pub previous_hash: String,

    //  Time of creation in UTC
    pub timestamp: i64,

    //  Data contained in the block
    pub data: String,

    //  Value for hashing the block(PoW)
    pub nonce: u64,
}

p2p.rs

use std::collections::HashSet;

use super::chain::{Block, Chain};
use libp2p::{
    floodsub::{Floodsub, FloodsubEvent, Topic},
    identity::Keypair,
    mdns::{Mdns, MdnsEvent},
    swarm::{NetworkBehaviourEventProcess, Swarm},
    NetworkBehaviour, PeerId,
};
use log::{error, info};
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use serde_json;
use tokio::sync::mpsc;

//  Topics for pub/sub protocol
//  Impairements: Broadcasts on each request thus extremely inefficient
pub static BLOCK_TOPIC: Lazy<Topic> = Lazy::new(|| Topic::new("blocks"));
pub static CHAIN_TOPIC: Lazy<Topic> = Lazy::new(|| Topic::new("chains"));

//  Key Pair for peer identification on network
pub static KEYS: Lazy<Keypair> = Lazy::new(Keypair::generate_ed25519);

//  Peer id for peer identification on network
pub static PEER_ID: Lazy<PeerId> = Lazy::new(|| PeerId::from(KEYS.public()));

 ...
//  Defines overall NetworkBehaviour for the chain
#[derive(NetworkBehaviour)]
pub struct ChainBehaviour {
    //  Chain
    #[behaviour(ignore)]
    pub chain: Chain,

    //  Handles FloodSub protocol
    pub floodsub: Floodsub,

    //  Sends response to the UnboundedReceiver
    #[behaviour(ignore)]
    pub init_sender: mpsc::UnboundedSender<bool>,

    //  Handles automatic discovery of peers on the local network
    //  and adds them to the topology
    pub mdns: Mdns,

    //  Sends response to the UnboundedReceiver
    #[behaviour(ignore)]
    pub response_sender: mpsc::UnboundedSender<ChainResponse>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct ChainResponse {
    pub blocks: Vec<Block>,
    pub receiver: String,
}

//  Triggers chain communication for requested ID
#[derive(Debug, Deserialize, Serialize)]
pub struct LocalChainRequest {
    pub from_peer_id: String,
}

//  Keep states for handling incoming messages, lazy init
//  and keyboard input by the client's user
pub enum EventType {
    LocalChainRequest(ChainResponse),
    Input(String),
    Init,
}

//  Implemnt FloodsubEvent for ChainBehaviour
impl NetworkBehaviourEventProcess<FloodsubEvent> for ChainBehaviour {
    fn inject_event(&mut self, event: FloodsubEvent) {
        if let FloodsubEvent::Message(msg) = event {
            //  If message is of type ChainResponse and that the message is ours,
            //  we execute our consensus.
            if let Ok(response) = serde_json::from_slice::<ChainResponse>(&msg.data) {
                if response.receiver == PEER_ID.to_string() {
                    info!("Response from {}:", msg.source);
                    response.blocks.iter().for_each(|r| info!("{:?}", r));

                    self.chain.blocks = self
                        .chain
                        .choose(self.chain.blocks.clone(), response.blocks);
                }
            } else if let Ok(response) = serde_json::from_slice::<LocalChainRequest>(&msg.data) {
                //  If of type LocalChainRequest, we send ChainResponse to
                //  initiator
                info!("sending local chain to {}", msg.source.to_string());
                let peer_id = response.from_peer_id;

                if PEER_ID.to_string() == peer_id {
                    if let Err(e) = self.response_sender.send(ChainResponse {
                        blocks: self.chain.blocks.clone(),
                        receiver: msg.source.to_string(),
                    }) {
                        error!("error sending response via channel, {}", e);
                    };
                }
            } else if let Ok(block) = serde_json::from_slice::<Block>(&msg.data) {
                //  If of type Block, we try adding the block if valid
                info!("received new block from {}", msg.source.to_string());
                self.chain.try_add_block(block);
            }
        }
    }
}

//  Implement MdnsEvents for ChainBehaviour
impl NetworkBehaviourEventProcess<MdnsEvent> for ChainBehaviour {
    fn inject_event(&mut self, event: MdnsEvent) {
        match event {
            //  Add node to list of nodes when discovered
            MdnsEvent::Discovered(nodes) => {
                for (peer, _) in nodes {
                    self.floodsub.add_node_to_partial_view(peer)
                }
            }
            //  Remove node from list of nodes when TTL expires and
            //  address hasn't been refreshed
            MdnsEvent::Expired(nodes) => {
                for (peer, _) in nodes {
                    if !self.mdns.has_node(&peer) {
                        self.floodsub.remove_node_from_partial_view(&peer);
                    }
                }
            }
        }
    }
}

这是我的 cargo.toml:

byteorder = "1"
chrono = "0.4.19"
getrandom = "0.2.3"
hex = "0.4.3"
libp2p = {version = "0.41.0", features = ['tcp-tokio', "mdns"]}
log = "0.4.14"
once_cell = "1.9.0"
oorandom = "11.1.3"
pretty_env_logger = "0.4.0"
serde = {version = "1.0.133", features = ["derive"]}
serde_json = "1.0.74"
sha2 = "0.10.0"
tokio = { version = "1.15.0", features = ["io-util", "io-std", "macros", "rt", "rt-multi-thread", "sync", "time"] }

我在这个结构上不断收到以下错误:

error[E0277]: the trait bound `(): From<MdnsEvent>` is not satisfied
  --> src/p2p.rs:30:10
   |
30 | #[derive(NetworkBehaviour)]
   |          ^^^^^^^^^^^^^^^^ the trait `From<MdnsEvent>` is not implemented for `()`
   |
   = help: see issue #48214
   = note: this error originates in the derive macro `NetworkBehaviour` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `(): From<FloodsubEvent>` is not satisfied
  --> src/p2p.rs:30:10
   |
30 | #[derive(NetworkBehaviour)]
   |          ^^^^^^^^^^^^^^^^ the trait `From<FloodsubEvent>` is not implemented for `()`
   |
   = help: see issue #48214
   = note: this error originates in the derive macro `NetworkBehaviour` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0277`.

我尝试遵循论坛的建议并收到以下错误:

error[E0599]: no method named `into_inner` found for struct `OneShotHandler` in the current scope
  --> src/p2p.rs:30:10
   |
30 | #[derive(NetworkBehaviour)]
   |          ^^^^^^^^^^^^^^^^ method not found in `OneShotHandler<FloodsubProtocol, FloodsubRpc, floodsub::layer::InnerMessage>`
   |
   = note: this error originates in the derive macro `NetworkBehaviour` (in Nightly builds, run with -Z macro-backtrace for more info)

我也不断收到add reference here错误#[derive(NetworkBehaviour)]。什么可能导致错误,我该如何解决?我正在使用生锈分析仪。

链接到教程的 github repo。

链接到我的 github 仓库。整个代码相当大,但应该只有上述错误。

4

0 回答 0