区块链系列教程——创建属于自己的区块链

区块链系列教程以以太坊区块链为基础,主要包括若干以太坊区块链的创建使用等,还包括部分原理说明,后期还会加入对其的改进。
本文是区块链系列教程的第一章,主要内容是使用以太坊区块链创建私链,并使用控制台进行一些基本操作。

1. 区块链简介

    在正文之前,先简单介绍一下区块链的基本概念。
    区块链,顾名思义,其存储形式是若干个区块组成,区块之间通过某种方式联系在一起。如图所示:
区块链示意图
    实际上,除了区块(区块头)结构,区块链可以抽象出更多的技术,比如共识机制、密码学机制、P2P网络、Hash树、智能合约等,这些可以统称为区块链技术,后续教程会涉及到其中部分的原理。
    以太坊区块链的区块结构较为复杂,远远不止示意图中的结构,有兴趣的读者可以去其github上查看详细源码,这是go语言实现版本,也是官方主推的版本。此处大概说明以太坊区块链的区块结构,以太坊的区块结构主要定义在go-ethereum/core/types/block.go文件中,其区块结构为:

type Block struct {
	header       *Header
	uncles       []*Header
	transactions Transactions
	// caches
	hash atomic.Value
	size atomic.Value
	// Td is used by package core to store the total difficulty
	// of the chain up to and including the block.
	td *big.Int
	// These fields are used by package eth to track
	// inter-peer block relay.
	ReceivedAt   time.Time
	ReceivedFrom interface{}
}

    区块结构中,header表示区块头,是非常重要的参数,其具体结构后面会说明 ;uncles表示该区块的叔块,也就是父区块的兄弟区块(因为以太坊的区块发行时间只有10秒左右,所以矿工之间会存在竞争,两个同时发行的区块将成为兄弟区块);transactions表示区块中装载的交易信息,这也是一个非常重要的参数,在区块链中交易是最为重要的功能。
    以太坊区块头格式为:

type Header struct {
	ParentHash  common.Hash    `json:"parentHash"       gencodec:"required"`
	UncleHash   common.Hash    `json:"sha3Uncles"       gencodec:"required"`
	Coinbase    common.Address `json:"miner"            gencodec:"required"`
	Root        common.Hash    `json:"stateRoot"        gencodec:"required"`
	TxHash      common.Hash    `json:"transactionsRoot" gencodec:"required"`
	ReceiptHash common.Hash    `json:"receiptsRoot"     gencodec:"required"`
	Bloom       Bloom          `json:"logsBloom"        gencodec:"required"`
	Difficulty  *big.Int       `json:"difficulty"       gencodec:"required"`
	Number      *big.Int       `json:"number"           gencodec:"required"`
	GasLimit    uint64         `json:"gasLimit"         gencodec:"required"`
	GasUsed     uint64         `json:"gasUsed"          gencodec:"required"`
	Time        uint64         `json:"timestamp"        gencodec:"required"`
	Extra       []byte         `json:"extraData"        gencodec:"required"`
	MixDigest   common.Hash    `json:"mixHash"`
	Nonce       BlockNonce     `json:"nonce"`
}
  • ParentHash表示父区块的Hash值,该值实际上就是所谓的链,用于实现区块链数据不可逆的特性。
  • UncleHash是区块结构中uncles经过hash运算得到的结果,用于验证区块数据的正确性。
  • Coinbase用于记录该区块的发行者,其可获得区块奖励和矿工费奖励。
  • Root用于验证当前区块链的状态,其中状态使用MPT(Merkle-Patricia-Tree)结构存储。
  • TxHash用于验证当前区块的交易信息,所有交易使用
    MPT结构组织存储。
  • ReceiptHash用于验证当前区块的交易收据信息,对于一个交易执行完成后会有相应的收据,其组织形式也是MPT。
  • Bloom是当前区块交易执行日志的布隆过滤器,用于快速确定某交易是否存在。
  • Difficulty是当前区块链POW的难度值,这与共识机制有关,后文会详细介绍。
  • Number是当前区块高度,即区块id,创世区块为0,逐一递增。
  • GasLimit是当前区块大小,以太坊使用gas机制来控制区块大小,每个交易(包括转账交易和智能合约交易)都会消耗相应的gas,特别是智能合约交易,消耗的gas大小与其执行步骤和存储消耗有关,因为以太坊是图灵完备的,所以需要此措施来防止出现死循环。
  • GasUsed是当前区块所消耗的总的gas大小。
  • Time是区块打包时间。
  • Extra是额外附加信息。
  • MixDigest和Nonce是POW共识机制的结果证明。

2. 开始实践

    本文主要使用以太坊geth客户端来创建私链,并基于console进行部分简单操作,让读者可以对区块链有一个大概的直观的感觉。

1.1 安装geth客户端
方法1

可以直接去官网下载对应操作系统的客户端。

方法2

Ubuntu的读者可以通过命令来安装:

sudo add-apt-repository -y ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install ethereum

macOS的读者可以通过brew进行安装:

brew tap ethereum/ethereum
brew install ethereum
1.2 创世块文件

    在创建私链时,由于我们是从创世块开始,其他区块的内容和创世块会有很大的关系,而创世块是需要我们来设定其中的字段信息的。此处,设置genesis.json文件:

{
  "config": {
      "chainId": 10,
      "homesteadBlock": 0,
      "eip155Block": 0,
      "eip158Block": 0
  },
  "alloc"      : {},
  "coinbase"   : "0x0000000000000000000000000000000000000000",
  "difficulty" : "0x2000000",
  "extraData"  : "",
  "gasLimit"   : "0x33450",
  "nonce"      : "0x0000000000000042",
  "mixhash"    : "0x0000000000000000000000000000000000000000000000000000000000000000",
  "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
  "timestamp"  : "0x00"
 17 } 
1.3 创建数据文件夹

使用命令创建数据文件夹test:创建数据文件夹

1.4 初始化区块链

使用命令初始化区块链:

geth --datadir test/ init genesis.json 

得到结果:

INFO [05-01|21:27:32.575] Maximum peer count                       ETH=25 LES=0 total=25
INFO [05-01|21:27:32.576] Allocated cache and file handles         database=/home/hadoop/blockchain/test/geth/chaindata cache=16 handles=16
INFO [05-01|21:27:32.581] Writing custom genesis block 
INFO [05-01|21:27:32.581] Persisted trie from memory database      nodes=0 size=0.00B time=3.104µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [05-01|21:27:32.581] Successfully wrote genesis state         database=chaindata                                   hash=b123b8…4077eb
INFO [05-01|21:27:32.581] Allocated cache and file handles         database=/home/hadoop/blockchain/test/geth/lightchaindata cache=16 handles=16
INFO [05-01|21:27:32.584] Writing custom genesis block 
INFO [05-01|21:27:32.584] Persisted trie from memory database      nodes=0 size=0.00B time=2.105µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [05-01|21:27:32.585] Successfully wrote genesis state         database=lightchaindata                                   hash=b123b8…4077eb
1.5 创建区块链私链

使用命令创建区块链私链:

geth --datadir test/ --networkid 10 console

得到结果:

INFO [05-01|21:29:06.015] Maximum peer count                       ETH=25 LES=0 total=25
INFO [05-01|21:29:06.016] Starting peer-to-peer node               instance=Geth/v1.8.17-stable-8bbe7207/linux-amd64/go1.10
INFO [05-01|21:29:06.016] Allocated cache and file handles         database=/home/hadoop/blockchain/test/geth/chaindata cache=768 handles=512
INFO [05-01|21:29:06.024] Initialised chain configuration          config="{ChainID: 10 Homestead: 0 DAO: <nil> DAOSupport: false EIP150: <nil> EIP155: 0 EIP158: 0 Byzantium: <nil> Constantinople: <nil> Engine: unknown}"
INFO [05-01|21:29:06.024] Disk storage enabled for ethash caches   dir=/home/hadoop/blockchain/test/geth/ethash count=3
INFO [05-01|21:29:06.024] Disk storage enabled for ethash DAGs     dir=/home/hadoop/.ethash                     count=2
INFO [05-01|21:29:06.024] Initialising Ethereum protocol           versions="[63 62]" network=10
INFO [05-01|21:29:06.025] Loaded most recent local header          number=0 hash=b123b8…4077eb td=33554432 age=50y2w3d
INFO [05-01|21:29:06.025] Loaded most recent local full block      number=0 hash=b123b8…4077eb td=33554432 age=50y2w3d
INFO [05-01|21:29:06.025] Loaded most recent local fast block      number=0 hash=b123b8…4077eb td=33554432 age=50y2w3d
INFO [05-01|21:29:06.025] Regenerated local transaction journal    transactions=0 accounts=0
INFO [05-01|21:29:06.025] Starting P2P networking 
INFO [05-01|21:29:08.150] UDP listener up                          self=enode://21d2a8209dc9aeadd15d94c2df30128dd7bd4b772f34e61e8f76afb893a2f7735a77c9061b64076ca61b5635b5d434fa32600af0e56f833fd7e582bff94e679d@222.201.145.179:30303
INFO [05-01|21:29:08.151] RLPx listener up                         self=enode://21d2a8209dc9aeadd15d94c2df30128dd7bd4b772f34e61e8f76afb893a2f7735a77c9061b64076ca61b5635b5d434fa32600af0e56f833fd7e582bff94e679d@222.201.145.179:30303
INFO [05-01|21:29:08.155] IPC endpoint opened                      url=/home/hadoop/blockchain/test/geth.ipc
INFO [05-01|21:29:08.169] Mapped network port                      proto=udp extport=30303 intport=30303 interface="UPNP IGDv1-IP1"
INFO [05-01|21:29:08.189] Mapped network port                      proto=tcp extport=30303 intport=30303 interface="UPNP IGDv1-IP1"
Welcome to the Geth JavaScript console!

instance: Geth/v1.8.17-stable-8bbe7207/linux-amd64/go1.10
 modules: admin:1.0 debug:1.0 eth:1.0 ethash:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

> 
1.6 使用区块链

    完成步骤1.5后,区块链已经可以使用,1.5中的console命令是指开启控制台用于与区块链进行交互——具体的geth命令后面教程将会详细说明。此处,我们可以控制当前区块链节点做一些操作了。

  1. 创建一个账户
> personal.newAccount()
Passphrase: 
Repeat passphrase: 
"0x6393bb737b95465ccd9e4597df0647cdcd09775f"
  1. 挖矿
> miner.start()
INFO [05-01|21:34:33.568] Updated mining threads                   threads=8
INFO [05-01|21:34:33.568] Transaction pool price threshold updated price=1000000000
INFO [05-01|21:34:33.568] Etherbase automatically configured       address=0x6393Bb737b95465cCD9E4597dF0647CdcD09775f
null
> INFO [05-01|21:34:33.569] Commit new mining work                   number=1 sealhash=0fcb98…71f1eb uncles=0 txs=0 gas=0 fees=0 elapsed=299.471µs
  1. 查看余额
> eth.getBalance(eth.coinbase)
5000000000000000000
  1. 解锁账户
> personal.unlockAccount(eth.coinbase)
Unlock account 0x6393bb737b95465ccd9e4597df0647cdcd09775f
Passphrase: 
true
  1. 转账
        需要注意的是,转账操作前需要将账户解锁,在转账操作发起成功后,需要等待一段时间,矿工将该转账交易打包进入新的发行区块后才会生效。
> eth.sendTransaction({from:eth.coinbase, to:personal.listAccounts[1], value:100})
INFO [05-01|21:37:28.223] Setting new local account                address=0x6393Bb737b95465cCD9E4597dF0647CdcD09775f
INFO [05-01|21:37:28.223] Submitted transaction                    fullhash=0xc2479ec79713c9a7bd638146fabf5175eeaad8df87939af83be91ce4218a7c6c recipient=0x5eDcF2B2eFa9500C9F056f58E9C032B375b877E0
"0xc2479ec79713c9a7bd638146fabf5175eeaad8df87939af83be91ce4218a7c6c"
> INFO [05-01|21:37:29.194] Commit new mining work                   number=6 sealhash=47fb15…84b362 uncles=0 txs=1 gas=21000 fees=2.1e-05 elapsed=601.799µs

随后,检查两者的余额,发现已经转账成功:

> eth.getBalance(eth.coinbase)
29999999999999999900
> eth.getBalance(personal.listAccounts[1])
100

联系与交流

欢迎小伙伴与我讨论哦~

邮箱:[email protected]

本文欢迎转载,请注明本文地址:https://blog.csdn.net/m0_37595562/article/details/89763685

猜你喜欢

转载自blog.csdn.net/m0_37595562/article/details/89763685