A tiny blockchain for demonstraion.

Overview

tinychain

Substrate入门课 Office Hour 演示项目。

项目介绍

本项目旨在介绍区块链基本原理,重点关注如何生成区块和如何与其他节点达成共识,会简化其他逻辑。

  • 只有转账功能,不包含智能合约,也不包含Substrate相关内容
  • 共识机制:PoW
  • 网络协议:使用HTTP模拟P2P
  • 存储:文件存储
  • 账户管理:为了简化演示流程,所有账户密码、地址、公私钥均存储在后端,用户只持有account_id(UUID格式)。用户发送Tx(即Transaction)时不需要签署,节点在生成区块时自动签署。

代码结构

src
├── database       # 数据层
│   ├── block.rs   # 区块相关
│   ├── genesis.rs # 区块链的初始状态
│   ├── mod.rs     # 入口
│   ├── state.rs   # 区块链的当前状态(所有账户的余额、Nonce,最新的区块,当前挖矿难度等)
│   └── tx.rs      # Transaction相关
├── main.rs        # 入口。命令行解析,执行对应的命令
├── node           # TODO 生成区块、Peers管理、Peers间的共识、区块同步等
└── wallet         # 钱包。账户管理、签名、验签

代码导读

main | 命令行解析

相关依赖

  • clap: 命令行解析

演示

cargo build
./target/debug/tinychain
./target/debug/tinychain new-account -h
./target/debug/tinychain run -h

wallet | 账户管理

相关依赖

演示

cargo build
RUST_LOG=debug ./target/debug/tinychain new-account

演示账户说明:

  • Treasury: "2bde5a91-6411-46ba-9173-c3e075d32100"
  • Alice: "3d211869-2505-4394-bd99-0c76eb761bf9"
  • Bob: "16d5e01e-709a-4536-a4f2-9f069070c51a"
  • Miner: "346b4cd8-10b6-47ba-a091-6a57bb1afcf9"

关键代码

  1. 如果想定义堆上常量或运行时才能确定值的常量,怎么办?
  • once_cell 或 lazy_static
  • once_cell可能会被纳入std: https://github.com/rust-lang/rfcs/pull/2788

比如如下代码,编译器会提示你应该使用once_cell

use std::collections::HashMap;

static M: HashMap<String, u64> = HashMap::new();

fn main() {
    println!("{:?}", M);
}

  • 什么是const fn?简单理解为可以在编译器求值的fn
static M: u64 = num();

fn main() {
    println!("{:?}", M);
}

const fn num() -> u64 {
    10
}
  1. 如何优雅地处理错误?
  • 先上结论

    • anyhow: 不关心错误类型,只想简单地处理错误 —— 适用于bin
    • thiserror: 定义清晰的错误类型 —— 适用于lib
  • 使用?传播错误,前提是?处的错误可以自动转为返回值声明的ErrorType

    • 使用anyhow::Error: 任意错误类型均可转为anyhow::Error(示例如下)
    • 自定义错误类型: 需要实现From trait来进行类型转换
// wallet/mod.rs
use anyhow::Result;

pub fn sign(msg: &str, account: &str) -> Result<String> {
    let sig = get_wallet(account)?
        .sign_hash(hash_message(msg))
        .to_string();

    Ok(sig)
}

database | 状态(state)管理

相关依赖

演示

cargo build
RUST_LOG=debug ./target/debug/tinychain run -m "346b4cd8-10b6-47ba-a091-6a57bb1afcf9"

关键代码

  1. builder模式(node/mod.rs
let tx1 = Tx::builder()
    .from(TREASURY)
    .to(ALICE)
    .value(100)
    .nonce(next_nonce)
    .build()
    .sign();
  1. derive macro派生宏怎么用?(几乎所有struct都用到了派生宏)
  • 初始状态:一个都不不需要
  • 在写代码过程中根据编译器提示逐个添加
  1. 如何从一个结构体实例中“拿走”一个字段的所有权?(state.rs,block.rs
// block.rs
impl BlockKV {
    pub fn take_block(&mut self) -> Block {
        mem::take(&mut self.value)
    }
}
// state.rs
let mut block_kv: BlockKV = serde_json::from_str(block_str)?;
let block = block_kv.take_block();
self.apply_block(block)?;
  1. Rust中如何使用HashMap?(state.rs
// balances: HashMap<String, u64>,
// account2nonce: HashMap<String, u64>,

// 确定key一定存在
*self.balances.get_mut(&tx.from).unwrap() -= tx.cost();
// key可能不存在
*self.balances.entry(tx.to.to_owned()).or_default() += tx.value;
*self.account2nonce.entry(tx.from.to_owned()).or_default() = tx.nonce;
  1. slice的比较(state.rs
  • slice依附于具体的数据结构,就像数据库中视图的关系
  • 两个slice对比,或者 slice与具体的数据结构对比,只取决于长度内容,比如下面这块代码:
fn main() {
    let arr = [1, 2, 3, 4, 5];
    let vec = vec![1, 2, 3, 4, 5];
    let s1 = &arr[..2];
    let s2 = &vec[..2];
    // &[T] 和 &[T] 是否相等取决于长度和内容是否相等
    assert_eq!(s1, s2);
    // &[T] 可以和 Vec<T>/[T;n] 比较,也会看长度和内容
    assert_eq!(&arr[..], vec);
    assert_eq!(&vec[..], arr);
}
// state.rs
fn is_valid_hash(&self, hash: &H256) -> bool {
    // 不需要构造一个H256类型和hash对比
    // 只需要构造一个slice类型是[u8]的任意类型即可,然后比较两个slice
    let hash_prefix = vec![0u8; self.mining_difficulty];
    hash_prefix[..] == hash[..self.mining_difficulty]
}
  1. 更精细的可见性控制(struct中的字段)
  1. 在iterator上执行map/filter/take等骚操作(block.rs
// Iterator
fn main() {
    let result = vec![1, 2, 3, 4, 5]
        .iter()
        .map(|v| v * v)
        .filter(|v| *v < 16)
        .take(2)
        .collect::<Vec<_>>();

    println!("{:?}", result); // [1, 4]
}
// block.rs
pub fn block_reward(&self) -> u64 {
    let gas_reward: u64 = self.txs.iter().map(|tx| tx.gas_cost()).sum();
    gas_reward + BLOCK_REWORD
}
  1. 生命周期入门,思路同派生宏(block.rs
  • 初始状态:不用
  • 大部分情况下,编译器可以自己推断
  • 当编译器无法推断时,它会提示你,按照编译器的提示加上生命周期注解

You might also like...
A value transfer bridge between the Monero blockchain and the Secret Network.

Secret-Monero-Bridge A value transfer bridge between the Monero blockchain and the Secret Network. Proof-of-Concept Video Demonstration: https://ipfs.

C++ `std::unique_ptr` that represents each object as an NFT on the Ethereum blockchain
C++ `std::unique_ptr` that represents each object as an NFT on the Ethereum blockchain

C++ `std::unique_ptr` that represents each object as an NFT on the Ethereum blockchain

HyperCube is a free and open source blockchain project for everyone to use.

XPZ Public Chain HyperCube is a free and open source blockchain project for everyone to use. 日本語 简体中文 正體中文 HyperCube Wiki Wha is HyperCube HyperCube i

🌍 The Earth Blockchain on Polkadot (archived)

Social Network Blockchain · The Social Network blockchain is a next-generation governance, economic, and social system for humanity built on Polkadot

High Performance Blockchain Deserializer

bitcoin-explorer bitcoin_explorer is an efficient library for reading bitcoin-core binary blockchain file as a database (utilising multi-threading). D

Substrate blockchain generated with Substrate Startkit

Substrate Node Template A new FRAME-based Substrate node, ready for hacking 🚀 Getting Started This project contains some configuration files to help

Substrate blockchain generated with Substrate Startkit

Substrate Node Template A new FRAME-based Substrate node, ready for hacking 🚀 Getting Started This project contains some configuration files to help

Trinci blockchain node

TRINCI TRINCI Blockchain Node. Requirements The required dependencies to build correctly the project are the following: clang libclang-dev (ver. 11 su

A lightweight and flexible framework to build your tailored blockchain applications.

TRINCI Blockchain Core A lightweight and flexible framework to build your tailored blockchain applications. Requirements The required dependencies to

Owner
Che Kwas
STAY CURIOUS
Che Kwas
Tiny CLI for submitting large calldata transactions to EVM networks to stress test the networking layer. Main motivation: EIP4844blobs.

stress4844 Tiny CLI for submitting large calldata transactions to EVM networks to stress test the networking layer. Main motivation: EIP4844 blobs. ca

Paradigm 50 Jan 4, 2023
Tiny CLI for submitting large calldata transactions to EVM networks to stress test the networking layer

Tiny CLI for submitting large calldata transactions to EVM networks to stress test the networking layer. Main motivation: EIP4844blobs.

Paradigm 50 Jan 4, 2023
Tiny media transcoding utility for node 🎶

Mediaplex Tiny media transcoding utility for node. ??️ This package is a work in progress. Installation $ npm install --save mediaplex Example const m

AndrozDev 5 Jul 22, 2023
Bijou is a tiny yet fast encrypted file system.

Bijou ✨??✨ Bijou (['bi:ʒu], French for "jewel") is a tiny yet fast encrypted filesystem, built upon RocksDB. Bijou provides a FUSE interface, as well

Mivik 5 Sep 27, 2023
A high performance blockchain kernel for enterprise users.

English | 简体中文 What is CITA CITA is a fast and scalable blockchain kernel for enterprises. CITA supports both native contract and EVM contract, by whi

CITAHub 1.3k Dec 22, 2022
The Nervos CKB is a public permissionless blockchain, and the layer 1 of Nervos network.

Nervos CKB - The Common Knowledge Base master develop About CKB CKB is the layer 1 of Nervos Network, a public/permissionless blockchain. CKB uses Pro

Nervos Network 1k Dec 30, 2022
The Phala Network Blockchain, pRuntime and the bridge.

Phala Blockchain Phala Network is a TEE-Blockchain hybrid architecture implementing Confidential Contract. This repo includes: node/: the main blockch

Phala Network 314 Jan 6, 2023
Substrate: The platform for blockchain innovators

Substrate · Substrate is a next-generation framework for blockchain innovation ?? . Trying it out Simply go to substrate.dev and follow the installati

Parity Technologies 7.7k Dec 30, 2022
An extensible open-source framework for creating private/permissioned blockchain applications

Exonum Status: Project info: Community: Exonum is an extensible open-source framework for creating blockchain applications. Exonum can be used to crea

Exonum 1.2k Jan 1, 2023
Local blockchain for Free TON DApp development and testing.

TON OS Startup Edition Local blockchain for Free TON DApp development and testing. Have a question? Get quick help in our channel: TON OS Startup Edit

TON Labs 35 Jan 2, 2023