用Rust实现区块链 - 6 点对点网络(P2P)

这篇具有很好参考价值的文章主要介绍了用Rust实现区块链 - 6 点对点网络(P2P)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

截止到目前,我们在单机上实现了区块链的几乎所有关键特性:随机生成的地址、安全、持久化、工作量证明、UTXO交易。接下来我们将使用rust-libp2p库来实现区块链的p2p网络。

P2P网络

P2P 网络拓扑结构有很多种,有些是中心化拓扑,有些是半中心化拓扑,有些是全分布式拓扑结构。

区块链网络中的全节点就是全分布式拓扑结构,即去中心化的,端到端的网络,节点直接连接到其他节点,它的拓扑结构是扁平的。

SPV节点(简单支付验证节点),随机选择一个全节点进行连接,依赖这个全节点来获取数据,更接近半中心化的拓扑结构。

在这里我们先实现全节点,后面再逐渐完善矿工节点和SPV节点,在本地网络中通过 MDNS 做节点发现,使用 Gossip协议 做消息传播。

数据结构

Node

Node节点的功能包括启动P2P网络节点的消息监听,处理来自命令行的命令消息及其他节点的请求消息。

pub struct Node<T = SledDb> {
    bc: Blockchain<T>,
    utxos: UTXOSet<T>,
    msg_receiver: mpsc::UnboundedReceiver<Messages>,
    swarm: Swarm<BlockchainBehaviour>,
}
  • bc:区块链

  • utxos:UTXO集合

  • msg_receiver:通道的接收端,接收其他节点的请求消息。

  • swarm:rust-libp2p的Swarm

BlockchainBehaviour

接收到其他节点的请求消息

#[derive(NetworkBehaviour)]
#[behaviour(event_process = true)]
pub struct BlockchainBehaviour {
    pub gossipsub: Gossipsub,
    pub mdns: Mdns,
    #[behaviour(ignore)]
    pub msg_sender: mpsc::UnboundedSender<Messages>,
}
  • gossipsub:使用 Gossip协议 做消息传播

  • mdns:节点发现

  • msg_sender:接收到其他节点的请求消息后,发送到通道中。

命令行消息

#[derive(Debug, Serialize, Deserialize)]
pub enum Commands {
    Genesis(String),
    Blocks(String),
    Sync(String),
    CreateWallet(String),
    GetAddress(String),
    Trans {
        from: String,
        to: String,
        amount: String,
    },
}
  • Genesis:创建区块链

  • Blocks:显示区块链信息

  • Sync:同步区块

  • CreateWallet:创建钱包

  • GetAddress:获取地址

  • Trans:创建交易

节点消息

#[derive(Debug, Serialize, Deserialize)]
pub enum Messages {
    Version {
        best_height: usize,
        from_addr: String,
    },
    Blocks {
        blocks: Vec<Block>,
        height: usize,
        to_addr: String,
    },
    Block {
        block: Block,
    }
}
  • Version:向其他节点发送本地节点的区块链高度,同步本地节点。

  • Blocks:向其他节点发送本地区块链信息。

  • Block:向其他节点发送新加入的区块。

消息处理

无论是命令行消息,还是节点消息都采用serde_json进行序列化处理。

创建区块链

Commands::Genesis(addr) => {
    if self.bc.get_tip().is_empty() {
        self.bc.create_genesis_block(addr.as_str());
        self.utxos.reindex(&self.bc)?;
        info!("Genesis block was created success!");
    }else {
        info!("Already exists blockchain, don't need genesis block!");
        continue;
    }
},

同步区块

处理命令行的同步命令

async fn sync(&mut self) -> Result<()> {
    let version = Messages::Version { 
        best_height: self.bc.get_height(), 
        from_addr: PEER_ID.to_string(),
    };
    
    let line = serde_json::to_vec(&version)?;
    self.swarm.behaviour_mut().gossipsub
        .publish(BLOCK_TOPIC.clone(), line).unwrap();

    Ok(())
}

节点接收到Version消息,如果本地区块链的高度大于其他节点的高度,则向其发送区块链信息。

async fn process_version_msg(&mut self, best_height: usize, from_addr: String) -> Result<()> {
    if self.bc.get_height() > best_height {
        let blocks = Messages::Blocks { 
            blocks: self.bc.get_blocks(),
            height: self.bc.get_height(),
            to_addr: from_addr,
        };
        let msg = serde_json::to_vec(&blocks)?;
        self.swarm.behaviour_mut().gossipsub
            .publish(BLOCK_TOPIC.clone(), msg).unwrap();
    }
    Ok(())
}

节点接收到区块链信息后,同步到本地节点。

async fn process_blocks_msg(&mut self, blocks: Vec<Block>, to_addr: String, height: usize) -> Result<()> {
    if PEER_ID.to_string() == to_addr && self.bc.get_height() < height {
        for block in blocks {
            self.bc.add_block(block)?;
        }

        self.utxos.reindex(&self.bc).unwrap();
    }
    Ok(())
}

创建交易、挖矿

由于是全节点,为了简便,在这里交易的创建与挖矿放在一起处理了。

async fn mine_block(&mut self, from: &str, to: &str, amount: i32) -> Result<()> {
    let tx = Transaction::new_utxo(from, to, amount, &self.utxos, &self.bc);
    let txs = vec![tx];
    let block = self.bc.mine_block(&txs);
    self.utxos.reindex(&self.bc).unwrap();

    let b = Messages::Block { block };
    let line = serde_json::to_vec(&b)?;
    self.swarm.behaviour_mut().gossipsub
        .publish(BLOCK_TOPIC.clone(), line).unwrap();        
    Ok(())
}

验证

启动第一个节点

RUST_LOG=info cargo run --quiet  server data
Local peer id: PeerId("12D3KooWHn6sTgQU7bwKfPQHXi2oo4dDUEneoVFWtfur7bufXuZ7")
Listening on "/ip4/127.0.0.1/tcp/53664"

执行命令后,可以看到节点已经启动,生成了唯一的节点ID,在本地53664端口监听消息。

1,查看区块链信息

{"Blocks":""}
INFO blockchain_rust_part_6::networks::node: tip: 
INFO blockchain_rust_part_6::networks::node: height: 0

可以看到这个节点上还没有区块链。

2,创建一个用户的钱包地址

{"CreateWallet":"justin"} 
INFO blockchain_rust_part_6::networks::node: justin's address is 1KooomKwhgPCfB2YfnKT7yMUxGcVWqS3ns

地址已经创建,我们把这个地址记录下来。

3,下面执行创建区块链命令

{"Genesis":"1KooomKwhgPCfB2YfnKT7yMUxGcVWqS3ns"}
INFO blockchain_rust_part_6::networks::node: Genesis block was created success!

区块链创建成功。

再次查看

{"Blocks":""}
INFO blockchain_rust_part_6::blocks::blockchain: Block {
    header: BlockHeader {
        ......
    },
    tranxs: [
        Transaction {
            id: "24cde4a1782d23fda6ec353959f9197450078a1d79126c82e83898d92015ec96",
            vin: [
                Txinput {
                    txid: "",
                    vout: 0,
                    signature: [],
                    pub_key: [],
                },
            ],
            vout: [
                Txoutput {
                    value: 10,
                    pub_key_hash: [
                        ......
                    ],
                },
            ],
        },
    ],
    hash: "00ca23fdb684b0ebf29eb344e2f9c1ee2ba8325aceba8a7474dbcb77549a2bc9",
}
INFO blockchain_rust_part_6::networks::node: tip: 00ca23fdb684b0ebf29eb344e2f9c1ee2ba8325aceba8a7474dbcb77549a2bc9
INFO blockchain_rust_part_6::networks::node: height: 1

启动第二个节点

RUST_LOG=info cargo run --quiet server data1
PeerId("12D3KooWDknz5ScSw8Ye2ULheq3DHUexhRkH9z1y7N7a27XyWphs")
Listening on "/ip4/127.0.0.1/tcp/53891"

第二个节点节点启动成功,生成了唯一的节点ID,在本地53891端口监听消息。

1,查看区块链信息

{"Blocks":""}
INFO blockchain_rust_part_6::networks::node: tip: 
INFO blockchain_rust_part_6::networks::node: height: 0

在第二个节点上还没有区块链。

2,同步区块链

{"Sync":""}
INFO blockchain_rust_part_6::networks::behaviour: Got message with id: 37343836383930393039373131393933343631 from peer: PeerId("12D3KooWHn6sTgQU7bwKfPQHXi2oo4dDUEneoVFWtfur7bufXuZ7")

从第一个节点:12D3KooWHn6sTgQU7bwKfPQHXi2oo4dDUEneoVFWtfur7bufXuZ7,同步区块链成功。

再次查看

{"Blocks":""}
Apr 19 14:00:53.136  INFO blockchain_rust_part_6::blocks::blockchain: Block {
    header: BlockHeader {
        ......
    },
    tranxs: [
        Transaction {
            id: "24cde4a1782d23fda6ec353959f9197450078a1d79126c82e83898d92015ec96",
            vin: [
                Txinput {
                    txid: "",
                    vout: 0,
                    signature: [],
                    pub_key: [],
                },
            ],
            vout: [
                Txoutput {
                    value: 10,
                    pub_key_hash: [
                       ......
                    ],
                },
            ],
        },
    ],
    hash: "00ca23fdb684b0ebf29eb344e2f9c1ee2ba8325aceba8a7474dbcb77549a2bc9",
}
Apr 19 14:00:53.136  INFO blockchain_rust_part_6::networks::node: tip: 00ca23fdb684b0ebf29eb344e2f9c1ee2ba8325aceba8a7474dbcb77549a2bc9
Apr 19 14:00:53.137  INFO blockchain_rust_part_6::networks::node: height: 1

与第一个节点的区块链一致。

启动第三个节点,步骤同第二个节点

创建交易

1,在第二个节点创建一个用户的钱包地址

{"CreateWallet":"Bob"}
INFO blockchain_rust_part_6::networks::node: Bob's address is 1EuM1UEhJFTDR5UfWzfghzv82bCdwRWk9E

2,在第一个节点创建交易

由Justin向Bob发送4单位货币

{"Trans": {"from":"1KooomKwhgPCfB2YfnKT7yMUxGcVWqS3ns","to":"1EuM1UEhJFTDR5UfWzfghzv82bCdwRWk9E","amount":"4"}}

3,在所有节点查看区块链信息

{"Blocks":""}
Apr 19 14:11:38.410  INFO blockchain_rust_part_6::blocks::blockchain: Block {
    header: BlockHeader {
        ......
    },
    tranxs: [
        Transaction {
            id: "1578eda9b3ba5f5be584ddb65389ac5172befa1ba50cf03a90fcdafdb5ce4bea",
            vin: [
                Txinput {
                    txid: "24cde4a1782d23fda6ec353959f9197450078a1d79126c82e83898d92015ec96",
                    vout: 0,
                    signature: [
                       ......
                    ],
                    pub_key: [
                       ......
                    ],
                },
            ],
            vout: [
                Txoutput {
                    value: 4,
                    pub_key_hash: [
                        ......
                    ],
                },
                Txoutput {
                    value: 6,
                    pub_key_hash: [
                        ......
                    ],
                },
            ],
        },
    ],
    hash: "0056d99918490fd8d650d247722234c1d17f18d9073a39d2eacb16550d9737df",
}
Apr 19 14:11:38.411  INFO blockchain_rust_part_6::blocks::blockchain: Block {
    header: BlockHeader {
        ......
    },
    tranxs: [
        Transaction {
            id: "24cde4a1782d23fda6ec353959f9197450078a1d79126c82e83898d92015ec96",
            vin: [
                Txinput {
                    txid: "",
                    vout: 0,
                    signature: [],
                    pub_key: [],
                },
            ],
            vout: [
                Txoutput {
                    value: 10,
                    pub_key_hash: [
                        ......
                    ],
                },
            ],
        },
    ],
    hash: "00ca23fdb684b0ebf29eb344e2f9c1ee2ba8325aceba8a7474dbcb77549a2bc9",
}
INFO blockchain_rust_part_6::networks::node: tip: 0056d99918490fd8d650d247722234c1d17f18d9073a39d2eacb16550d9737df
INFO blockchain_rust_part_6::networks::node: height: 2

所有节点都已经同步了区块信息。

工程结构

rust-libp2p,区块链,Rust,区块链,rust

完整代码: 

https://github.com/Justin02180218/blockchain_rust


更多文章,请关注公众号:coding到灯火阑珊

rust-libp2p,区块链,Rust,区块链,rust文章来源地址https://www.toymoban.com/news/detail-798673.html

到了这里,关于用Rust实现区块链 - 6 点对点网络(P2P)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 区块链入门系列之P2P

    区块链基本概念和名词解释 P2P 共识算法 梅克尔-帕特里夏树 从零开始搭建区块链 为什么前面讲过P2P的概念了这里还要单独起一篇文章来讲解,因为前面只是讲解了P2P的基本概念,即各网络节点间是直接或间接连接起来的。但这里面还涉及到很多网络知识,如果不清楚,是没

    2023年04月19日
    浏览(20)
  • 区块链(6):p2p去中心化介绍

    1 互联网中中心化的服务和去中心化服务的概念介绍 目前的互联网公司大都是中心化的 区块链网络大多是去中心化的 去中心化 2 p2p的简单介绍 java 网络编程:socket编程,netty编程,websoket简单介绍 2.1 节点是如何提供服务的(web编程实现)

    2024年02月08日
    浏览(24)
  • 【区块链 | 智能合约】Ethereum源代码(8)- Ethereum服务和以太坊P2P协议发送广播源码分析

    在“【区块链 | 智能合约】Ethereum源代码(2)- go-ethereum 客户端入口代码和Node分析”一文中,我们提到Ethereum作为一个service,被Node 注册进去。Node start的时候会启动其注册的所有服务,Ethereum service也是一样。 初始化方法

    2024年01月21日
    浏览(31)
  • 阿里云服务器搭建FRP实现内网穿透-P2P

    在了解frp - p2p之前,请先了解阿里云服务器搭建FRP实现内网穿透-转发: 文章地址    frp(Fast Reverse Proxy)是一个开源的反向代理工具,它提供了多种功能,包括端口映射、流量转发和内网穿透等。在frp中,P2P(Peer-to-Peer)功能允许直接将数据从一个客户端传输到另一个客户

    2024年02月10日
    浏览(23)
  • P2P 应用

    ·在 P2P 工作方式下,所有的音频/视频文件都是在普通的互联网 用户之间传输 。 ·Napster 最早 使用 P2P 技术,提供免费下载 MP3 音乐。 ·Napster 将所有音乐文件的索引信息都集中存放在 Napster 目录服务器中。 ·使用者只要查找目录服务器,就可知道应从何处下载所要的 MP3 文件

    2024年02月19日
    浏览(21)
  • 什么是P2P?

    P2P (Peer-to-Peer) 是一种分布式的网络架构,其中各个节点(通常被称为“peers”或“节点”)直接进行数据共享和交换,而无需依赖中央服务器。P2P 网络强调平等的参与和共享,每个节点既可以是数据的消费者(下载者),也可以是提供者(上传者)。 以下是 P2P 协议和技术的

    2024年02月13日
    浏览(25)
  • P2P通信基本原理

    在数字世界的脉络中,点对点(P2P)技术如同一条悄无声息的河流,流经信息的每个角落,连接着世界各地的计算机和设备。这种去中心化的网络模型,不仅打破了传统的客户端-服务器架构的界限,还赋予了数据传输一种前所未有的自由和效率。通过P2P,每个参与者既是消费

    2024年04月16日
    浏览(19)
  • P2P协议的传输艺术

    TP 采用两个 TCP 连接来传输一个文件。 控制连接:服务器以被动的方式,打开众所周知用于 FTP 的端口 21,客户端则主动发起连接。该连接将命令从客户端传给服务器,并传回服务器的应答。常用的命令有:list——获取文件目录;reter——取一个文件;store——存一个文件。

    2024年02月07日
    浏览(24)
  • P2P 网络,PING程序。

    没有废话,直接上版本号和代码,以及讲解。 crate 版本号 libp2p 0.52.1 tokio 1.30.0 Peer-to-Peer是一种网络技术。一种点对点的通讯技术。没有client-service概念。 在P2P网络中,节点标识被成为PeerId。

    2024年02月12日
    浏览(22)
  • P2P DMA发展全景分析解读

    P2P DMA(Peer-to-Peer Direct Memory Access)技术是一种允许连接到PCIe总线上的不同设备之间直接进行数据交换的机制,无需通过CPU和系统内存中转。这一特性极大地提升了数据传输效率,减少了CPU负载,并在特定场景下优化了系统性能。 历史和发展: P2P DMA的概念早在NVMe SSD和RDMA技

    2024年01月21日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包