区块链基础 - 以太坊
1、搭建私链,能够挖矿。
创世区块
# geth --datadir /data/eth init genesis.json genesis.json { "config": { "chainId": 11, #公共预测试发布网络 "homesteadBlock": 0, #Homestead 硬分叉区块高度,填写官网的默认值即可,后续硬分叉时才需要调整 "eip150Block": 0, "eip155Block": 0, #EIP 155 硬分叉高度,填写官网的默认值即可,后续硬分叉时才需要调整 "eip158Block": 0 #EIP 158 硬分叉高度,填写官网的默认值即可,后续硬分叉时才需要调整 }, "alloc" : {}, #预设账号以及账号的以太币数量,私有链挖矿比较容易可以不配置 "coinbase" : "0x0000000000000000000000000000000000000000", #矿工账号 "difficulty" : "0x20000", # 难度值,越大越难 "extraData" : "", # 附加信息,以0x开头填写,可以不填 "gasLimit" : "0x2fefd8", # gas 的消耗总量限制,用来限制区块能包含的交易信息总和,因为我们是私有链,所以填的很大 "nonce" : "0x0000000000000042", # 64 位随机数,默认即可 "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", #与 nonce 配合用于挖矿,由上一个区块的一部分生成的 hash,默认即可。因为是第一个区块,因此,默认就是0了。 "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", #上一个区块的 hash 值,默认即可。因为是第一个区块,因此,默认就是0了。 "timestamp" : "0x00" }
启动geth
geth \ --nodiscover \ --maxpeers 300 \ --identity "rh_test" \ --rpc --rpccorsdomain "*" --rpcport 8545 \ --datadir "/data/eth" \ --port "30303" \ --allow-insecure-unlock \ --rpcapi "eth,net,web3,personal" \ --networkid 11 \ --cache 512 \ --verbosity 4 \ --shh nodiscover 关闭节点自动发现 maxpeers 最大节点连接数 identity 设置节点名称 rpc组 --rpc --rpccorsdomain "" --rpcport 8545,这是一组参数,rpc端口默认就是8545,访问域如果写的话代表是任何域名都可以访问,也可以指定特殊的域名访问。 datadir geth安装的目录,这个与初始化时候的路径一样即可 port geth节点的端口,默认也是30303 rpcapi 允许rpc接入的方式 networkid 网络id,该值与创世纪区块中的chainId一致即可,否则就会连到别人的服务上去了 cache 调整内存分配 最小16MB,默认128MB verbosity 日志等级:0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail (default: 3)
进入控制台
geth attach ipc:/data/eth/geth.ipc
> eth.getBlock(0) { difficulty: 131072, extraData: "0x", gasLimit: 3141592, gasUsed: 0, hash: "0x5e1fc79cb4ffa4739177b5408045cd5d51c6cf766133f23f7cd72ee1f8d790e0", logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", miner: "0x0000000000000000000000000000000000000000", mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000", nonce: "0x0000000000000042", number: 0, parentHash: "0x0000000000000000000000000000000000000000000000000000000000000000", receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", size: 507, stateRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", timestamp: 0, totalDifficulty: 131072, transactions: [], transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", uncles: [] } difficulty 挖矿难度,这里转化为 10 进制,等于”0x2000”,后面区块难度会随着区块高度升高而提高 extraData 当前区块附加信息,若创世区 块该值为空,在第二个区块中会保存,创建该私有链时的 geth,go,及操作系统版本,保存信息为第一个挖到该区块的矿工信息,例如:0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 gasLimit 十进制的 gasLimit 值,会随之区块高度提高而提高 gasUsed gas 花费,在以太坊中交易和部署智能合约会消耗 gas,暂时可以理解为以太币 hash 当前区块hash值 logsBloom 保存当前区块日志 miner 挖到该区块的矿工地址,当前尚未分配矿工,因此,无挖矿矿工信息 mixHash 与 nonce 配合用于挖矿,由上一个区块的一部分生成的 hash nonce 工作量证明的随机数,因为是第一块,这个是由我们人工创建的 number 当前区块高度 parentHash 上一个区块 hash 值 receiptsRoot 块的收益树根结果 sha3Uncles 对树区块进行 hash 运算的结果 size 区块大小,以字节为单位 stateRoot 块的状态树根结果 timestamp 时间戳 totalDifficulty 达到该区块的难度总数 transactions 以数组的形式保存交易的 tx 值 transactionsRoot 交易的默克尔树根 uncles 以数组表示数区块的哈希
查看账户 > eth.accounts 创建账户 > personal.newAccount() 查看余额 > web3.fromWei(eth.getBalance(eth.accounts[0]),'ether')
2、掌握节点api。怎么查询最新高度,区块详情,交易详情。
查询最新高度 curl -s -X POST -H "Content-Type":application/json --data '{"jsonrpc":"2.0", "method":"eth_blockNumber","params":[],"id":67}' localhost:8545
查询区块详情 curl -s -X POST -H "Content-Type":application/json --data '{"jsonrpc":"2.0","method":"eth_getBlockByHash","params":["0x5e1fc79cb4ffa4739177b5408045cd5d51c6cf766133f23f7cd72ee1f8d790e0", false],"id":1}' localhost:8545
查询交易详情 curl -s -X POST -H "Content-Type":application/json --data '{"jsonrpc":"2.0","method":"eth_getTransactionByHash","params":["0x377373a7056a25a10e7d747adede9f51bdb7dd101de515953f4a56ef9488a3e9"],"id":1}' localhost:8545
解锁账户 > personal.unlockAccount(eth.accounts[0]) Unlock account 0xcb49271b7d64de18053c79708fdd45565a8515ed Passphrase: true 发起交易 > eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei("0.1", "ether")}) > web3.fromWei(eth.getBalance(eth.accounts[1]),'ether') 0 > miner.start() null > miner.stop() null > eth.getBalance(eth.accounts[1]) 100000000000000000 >
3、使用节点工具完成生成地址和转账
# geth account new 创建账户 > personal.newAccount() 解锁账户 > personal.unlockAccount(eth.accounts[0]) Unlock account 0xcb49271b7d64de18053c79708fdd45565a8515ed Passphrase: true 发起交易 > eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei("0.1", "ether")}) > web3.fromWei(eth.getBalance(eth.accounts[1]),'ether') 0 > miner.start() null > miner.stop() null > eth.getBalance(eth.accounts[1]) 100000000000000000 >
4. 判断eth交易是否成功
transactionHash: DATA, 32字节 - 交易哈希 transactionIndex: QUANTITY - 交易在块内的索引序号 blockHash: DATA, 32字节 - 交易所在块的哈希 blockNumber: QUANTITY - 交易所在块的编号 from: DATA, 20字节 - 交易发送方地址 to: DATA, 20字节 - 交易接收方地址,对于合约创建交易该值为null cumulativeGasUsed: QUANTITY - 交易所在块消耗的gas总量 gasUsed: QUANTITY - 该次交易消耗的gas用量 contractAddress: DATA, 20字节 - 对于合约创建交易,该值为新创建的合约地址,否则为null logs: Array - 本次交易生成的日志对象数组 logsBloom: DATA, 256字节 - bloom过滤器,轻客户端用来快速提取相关日志
5、使用任何编程语言,完成生成地址、构造交易、离线签名、广播并上链。不准使用钱包功能。
from web3 import Web3 w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545')) # # print(w3.geth.shh.new_key_pair()) # new_account = w3.eth.account.create() # print(new_account.privateKey) # print(new_account.address) key_file = "/data/eth/keystore/UTC--2020-10-08T04-03-04.009027274Z--cb49271b7d64de18053c79708fdd45565a8515ed" with open(key_file) as keyfile: encrypted_key = keyfile.read() private_key = w3.eth.account.decrypt(encrypted_key,'12345') print(private_key) signed_txn = w3.eth.account.signTransaction(dict( nonce=w3.eth.getTransactionCount(w3.eth.coinbase), gasPrice=w3.eth.gasPrice, gas=100000, to='0xaC6D80856Dc3e8abe7DEafa46703DEb89c019517', value=1000000000000000000, data=b'', ), b'\x97\xf5@\xa8\xce\x1c\xc5\x8a\xcbt\x82,b\xa3\xccj\xe26\xcb$\xb1\xc5y\x91\xfb\xaf^X\xae\x7f:\xe3', ) res = w3.eth.sendRawTransaction(signed_txn.rawTransaction) print(res.hex()) print(w3.eth.getTransactionReceipt("0x904b4e5337f396bdcf34528a92cc17dd7ae82bcbbba0948bf01e28b62481568f"))
本博客内容都是博主试验通过的方案与方法.
如需交流,请发邮件至qjyyn#qq.com