主页 > imtoken苹果手机不能下载 > 使用 Rust 的区块链 - 6 点对点网络 (P2P)

使用 Rust 的区块链 - 6 点对点网络 (P2P)

imtoken苹果手机不能下载 2023-05-10 06:15:18

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

P2P 网络

P2P网络拓扑有很多种,有些是集中式拓扑,有些是半集中式拓扑,有些是全分布式拓扑。

区块链网络中的全节点是一个完全分布式的拓扑,即去中心化的端到端网络,其中节点与其他节点直接相连,其拓扑是扁平的。

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

这里我们先实现全节点,然后逐步完善矿工节点和SPV节点,在本地网络中使用MDNS进行节点发现,使用Gossip协议进行消息传播。

数据结构

节点

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

pub struct Node {
    bc: Blockchain,
    utxos: UTXOSet,
    msg_receiver: mpsc::UnboundedReceiver,
    swarm: Swarm,
}

区块链行为

收到来自其他节点的请求消息

#[derive(NetworkBehaviour)]
#[behaviour(event_process = true)]
pub struct BlockchainBehaviour {
    pub gossipsub: Gossipsub,
    pub mdns: Mdns,
    #[behaviour(ignore)]
    pub msg_sender: mpsc::UnboundedSender,
}

命令行消息

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

节点消息

#[derive(Debug, Serialize, Deserialize)]
pub enum Messages {
    Version {
        best_height: usize,
        from_addr: String,
    },
    Blocks {
        blocks: Vec,
        height: usize,
        to_addr: String,
    },
    Block {
        block: Block,
    }
}

消息处理

p>

命令行消息和节点消息都使用 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, 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"

第二个node节点启动成功比特币节点搭建,生成唯一的node 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、在第二个节点上创建一个用户的钱包地址

p>

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

2、在第一个节点上创建一个事务

贾斯汀向鲍勃发送 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

所有节点都有同步的区块信息。

项目结构

完整代码: