IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 区块链 -> 用Rust实现区块链 - 5 钱包 -> 正文阅读

[区块链]用Rust实现区块链 - 5 钱包

上一篇我们实现了交易,在这一部分我们通过非对称加密算法生成密钥对、对交易进行签名、验签等操作。

钱包

包含公钥和私钥两个字段

#[derive(Serialize, Deserialize, Clone)]
pub struct Wallet {
    pkcs8: Vec<u8>,
    public_key: Vec<u8>,
}
  • pkcs8:私钥

  • public_key:公钥

impl Wallet {
    pub fn new() -> Self {
        let pkcs8 = new_private_key();
        let key_pair = EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, pkcs8.as_ref()).unwrap();
        let public_key = key_pair.public_key().as_ref().to_vec();

        Self { pkcs8, public_key }
    }
    ......
}

密钥对

pub fn new_private_key() -> Vec<u8> {
    let rng = SystemRandom::new();
    let pkcs8 = EcdsaKeyPair::generate_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, &rng).unwrap();
    pkcs8.as_ref().to_vec()
}

使用椭圆曲线来产生私钥,通过私钥产生密钥对,然后通过密钥对导出公钥。

地址

生成地址

pub fn get_address(&self) -> String {
    let pub_key_hash = hash_pub_key(self.public_key.as_slice());
    let mut payload = vec![];
    payload.push(VERSION);
    payload.extend(pub_key_hash.as_slice());
    let checksum = checksum(payload.as_slice());
    payload.extend(checksum.as_slice());
    base58_encode(payload.as_slice())
}

pub fn hash_pub_key(pub_key: &[u8]) -> Vec<u8> {
    let pub_key_sha256 = sha256_digest(pub_key);
    let pub_key_ripemd160 = ripemd160_digest(&pub_key_sha256);
    pub_key_ripemd160
}

pub fn checksum(payload: &[u8]) -> Vec<u8> {
    let first_sha = sha256_digest(payload);
    let second_sha = sha256_digest(&first_sha);
    second_sha[0..ADDRESS_CHECKSUM_LEN].to_vec()
}
  • 先使用SHA256对公钥进行一次哈希,对结果使用RIPEMD160进行二次哈希。

  • 给哈希值加上版本前缀,这里硬编码为 const VERSION: u8 = 0x00。

  • 对上一步生成的结果,使用 SHA256进行两次哈希。取结果的前四个字节作为校验和。

  • 将校验和附加到 version+PubKeyHash 的组合中。

  • 使用 Base58 对 version+PubKeyHash+checksum 组合进行编码。

定义一个Wallets结构体,将wallet保存到本地文件wallet.dat中。

修改交易

交易输入

#[derive(Debug, Serialize, Deserialize, Clone, Default)]
pub struct Txinput {
    txid: String,
    vout: usize,
    signature: Vec<u8>,
    pub_key: Vec<u8>
}
  • signature:交易发起方私钥对交易进行的签名

  • pub_key:交易发起方公钥

签名和验签

fn sign(&mut self, bc: &Blockchain, pkcs8: &[u8]) {
    let mut tx_copy = self.trimmed_copy();

    for (idx, vin) in self.vin.iter_mut().enumerate() {
        // 查找输入引用的交易
        let prev_tx_option = bc.find_transaction(vin.get_txid());
        if prev_tx_option.is_none() {
            panic!("ERROR: Previous transaction is not correct")
        }
        let prev_tx = prev_tx_option.unwrap();
        tx_copy.vin[idx].set_signature(vec![]);
        tx_copy.vin[idx].set_pub_key(prev_tx.vout[vin.get_vout()].get_pub_key_hash());
        tx_copy.set_hash();

        tx_copy.vin[idx].set_pub_key(&vec![]);

        // 使用私钥对数据签名
        let signature = ecdsa_p256_sha256_sign_digest(pkcs8, tx_copy.id.as_bytes());
        vin.set_signature(signature);
    }
}

pub fn verify<T: Storage>(&self, bc: &Blockchain<T>) -> bool {
    if self.is_coinbase() {
        return true;
    }
    let mut tx_copy = self.trimmed_copy();
    for (idx, vin) in self.vin.iter().enumerate() {
        let prev_tx_option = bc.find_transaction(vin.get_txid());
        if prev_tx_option.is_none() {
            panic!("ERROR: Previous transaction is not correct")
        }
        let prev_tx = prev_tx_option.unwrap();
        tx_copy.vin[idx].set_signature(vec![]);
        tx_copy.vin[idx].set_pub_key(prev_tx.vout[vin.get_vout()].get_pub_key_hash());
        tx_copy.set_hash();

        tx_copy.vin[idx].set_pub_key(&vec![]);

        // 使用公钥验证签名
        let verify = ecdsa_p256_sha256_sign_verify(
            vin.get_pub_key(),
            vin.get_signature(),
            tx_copy.id.as_bytes(),
        );
        if !verify {
            return false;
        }
    }
    true
}

验证

先创建地址,将地址记录下来。

let mut wallets = Wallets::new().unwrap();
let genesis_addr = wallets.create_wallet();
println!("==> genesis address: {}", genesis_addr);

==> genesis address: 1M684nX5dTNQYi2ELSCazjyz5dgegJ3mVD

使用这个地址进行一笔交易

let justin_addr = "1M684nX5dTNQYi2ELSCazjyz5dgegJ3mVD";

let mut wallets = Wallets::new().unwrap();
let bob_addr = wallets.create_wallet();

let path = current_dir().unwrap().join("data");
let storage = Arc::new(SledDb::new(path));

let mut bc = Blockchain::new(storage.clone(), justin_addr);
let utxos = UTXOSet::new(storage);

let tx_1 = Transaction::new_utxo(justin_addr, &bob_addr, 4, &utxos, &bc);
let txs = vec![tx_1];

bc.mine_block(&txs);
utxos.reindex(&bc).unwrap();

bc.blocks_info();

执行结果就不贴了,大家自行验证。

工程结构

完整代码:

https://github.com/Justin02180218/blockchain_rust


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

  区块链 最新文章
盘点具备盈利潜力的几大加密板块,以及潜在
阅读笔记|让区块空间成为商品,打造Web3云
区块链1.0-比特币的数据结构
Team Finance被黑分析|黑客自建Token“瞒天
区块链≠绿色?波卡或成 Web3“生态环保”标
期货从入门到高深之手动交易系列D1课
以太坊基础---区块验证
进入以太坊合并的五个数字
经典同态加密算法Paillier解读 - 原理、实现
IPFS/Filecoin学习知识科普(四)
上一篇文章      下一篇文章      查看所有文章
加:2022-05-06 11:06:11  更:2022-05-06 11:06:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:26:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码