我是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);
}
}
}
}
}
}
这是我的货
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`.
我尝试按照this论坛的建议,并得到以下错误:
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)
我在#[derive(NetworkBehaviour)]
上也一直收到一个add reference here
错误。什么可能导致这个错误?我该怎么修复它?我用的是rust-analyzer。
Link到教程的github存储库。
Link到我的github repo。整个代码相当大,但应该只有前面提到的错误。
1条答案
按热度按时间mnemlml81#
这个问题已经存在将近一年了,但也许将来还会遇到这个问题。
我在学习同一个教程时遇到了同样的问题,有趣的是,新版本的libp2p似乎要求您做两件本教程所用版本似乎没有要求的事情:
AppBehaviour
结构指定#[behaviour(out_event="Event")]
StructName<Event>
。AppBehaviour
的结构成员发出的所有事件实现枚举Event
的traitFrom<>
,因为结构成员发出的事件 Package 在event
枚举中。我为此添加了两个新的枚举值,如libp2p文档中所示: