以太坊私链部署
项目地址:https://github.com/ethereum/go-ethereum
cd /Users/apple/Documents/app/go_project/src/github.com/ethereum/go-ethereum
安装依赖项后,运行
或者,构建全套实用程序:
安装 Ethereum:这里用的是 ethereum 的 go语言客户端
brew tap ethereum/ethereum
brew install ethereum
安装好了之后运行:geth version
1 2 3 4 5 6 7 8 9 10 11 geth version Geth Version: 1.9.16-unstable Git Commit: 6d8e51ab8850770925f3aaf79186f0398f24a702 Git Commit Date: 20200707 Architecture: amd64 Protocol Versions: [65 64 63] Go Version: go1.14 Operating System: darwin GOPATH=/Users/apple/Documents/app/go_project GOROOT=/usr/local/go
安装以太坊编程语言Solidity —— brew install solidity
nodejs 环境 —— 自行百度,推荐使用nvm
安装 truffle —— npm install –g truffle
准备以太坊私链节点
创建个目录:比如 ethereum,然后创建一个json文件 genesis.json
创世块配置文件:genesis.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 { "config": { "chainId": 1, "homesteadBlock": 0, "eip150Block": 0, "eip155Block": 0, "eip158Block": 0, "byzantiumBlock": 0, "constantinopleBlock": 0, "petersburgBlock": 0, "istanbulBlock": 0 }, "alloc": {}, "coinbase": "0x0000000000000000000000000000000000000000", "difficulty": "0x20000", "extraData": "", "gasLimit": "0x2fefd8", "nonce": "0x0000000000000042", "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "timestamp": "0x00" }
这里要特别注意:byzantiumBlock,constantinopleBlock,petersburgBlock几个都要放进去。最新的以太坊版本已经在用byzantiumBlock了。如果不加的话,合约编译的时候就要指定拜占庭。否则合约执行的时候会返回莫名其妙的错误,这个坑我踩了很久。
1 geth --datadir data init data/genesis.json
启动节点
各选项含义如下:**
--identity:
指定节点 ID;
--rpc:
表示开启 HTTP-RPC 服务;
--rpcaddr:
HTTP-RPC 服务ip地址;
--rpcport:
指定 HTTP-RPC 服务监听端口号(默认为 8545);
--datadir:
指定区块链数据的存储位置;
--port:
指定和其他节点连接所用的端口号(默认为 30303);
--nodiscover:
关闭节点发现机制,防止加入有同样初始配置的陌生节点
1 2 3 4 5 geth --networkid 1 --dev --mine --datadir data --identity "mychain1" --rpc --rpcaddr 0.0.0.0 --rpcport 8545 --port 30303 --http.corsdomain "*" --rpcapi eth,net,web3,personal --allow-insecure-unlock console INFO [07-12|13:32:22.857] Initialised chain configuration config="{ChainID: 1337 Homestead: 0 DAO: <nil> DAOSupport: false EIP150: 0 EIP155: 0 EIP158: 0 Byzantium: 0 Constantinople: 0 Petersburg: 0 Istanbul: 0, Muir Glacier: <nil>, YOLO v1: <nil>, Engine: clique}"
ChainID: 1337 注意后面MERAMASK使用时会用到否则会报错
命令创建账号 进入console之后,创建账号:personal.newAccount('123456') # 123456是密码
1 2 3 4 5 > personal.newAccount('123456') INFO [07-12|01:17:25.091] Your new key was generated address=0x413668277Fd91E8F58d1B751Ec61198f178404d5 WARN [07-12|01:17:25.093] Please backup your key file! path=/Users/apple/Documents/app/go_project/src/github.com/ethereum/go-ethereum/build/bin/data/keystore/UTC--2020-07-11T17-17-22.670563000Z--413668277fd91e8f58d1b751ec61198f178404d5 WARN [07-12|01:17:25.093] Please remember your password! "0x413668277fd91e8f58d1b751ec61198f178404d5"
查看当前节点下面是否有账号存在
1 2 3 4 5 > personal.listAccounts ["0xed73e8786b1bb7becec87b61bec8edc5944bf4a2", "0x413668277fd91e8f58d1b751ec61198f178404d5"] > eth.coinbase "0xed73e8786b1bb7becec87b61bec8edc5944bf4a2" 0x585603d82bcF96B521772B3D7D5Dd70B6705AE76
挖矿 执行设置挖矿miner地址:
1 2 > miner.setEtherbase(eth.coinbase) true
开始挖矿,输入 miner.start()
,出现下面这种图标就算挖到了。
转账 转账前需要解锁
1 personal.unlockAccount(eth.coinbase, '')
转账
1 2 3 eth.sendTransaction({from:eth.coinbase, to:eth.accounts[1], value: web3.toWei(99999, "ether")}) eth.sendTransaction({from:eth.accounts[1], to:eth.accounts[2], value: web3.toWei(100, "ether")}) eth.sendTransaction({from:"0xed73e8786b1bb7becec87b61bec8edc5944bf4a2", to:"0x413668277fd91e8f58d1b751ec61198f178404d5", value: web3.toWei(10, "ether")})
MERAMASK 插件使用
网络名称 :mychain1
新增 RPC URL: http://127.0.0.1:8545/
ChainID: 1337 //上面已经提到,如果不对会得倒以下错误
1 2 3 EthQuery - RPC Error - Error: [ethjs-rpc] rpc error with payload {"id":7020279539214,"jsonrpc":"2.0","params":["0xf8690180825208944005c7b1e11d1864c583a43f27cb80043484ec4a8829a2241af62c000080820a96a0337725da801de5ddf4ed45afa084d1d03917398ee0110aa3652368c399f93739a04f94d25a566a08117acf6dce48c6d7d9d38dd804900b93b7b37860bbe6819425"],"method":"eth_sendRawTransaction"} [object Object] err="invalid sender"
如果从eth.coinbase账户转币需要解锁
personal.unlockAccount(eth.coinbase, ‘’)
否则会出现以下错误
1 err="authentication needed: password or unlock"
remix 使用
环境 ENVIRONMENT : Injected Web3
JavaScript VM
:所有交易将在浏览器的沙盒区块链中执行。这意味着您在重新加载页面时不会保留任何内容。JsVM是其自己的区块链,每次重新加载时,它将启动一个新的区块链,旧的区块链将不会保存。
Injected Web3
:Remix将连接到注入的Web3提供程序。Metamask
是注入web3的提供程序的示例。
Web3 Provider
:Remix将连接到远程节点。您需要将URL提供给选定的提供商:geth,奇偶校验或任何以太坊客户端。
MERAMASK 插件选择连接
1 2 3 4 5 6 Published DemeterContract's Metadata Metadata of "demetercontract" was published successfully. browser/tests/DemeterContract.sol : dweb:/ipfs/QmNQNYDRwQzRnhA5LKraQmcExEjuuFepAs1wxF4vv9Fd1Z metadata.json : dweb:/ipfs/QmUSXV97L4Z7P5EguEZ3urkX8x3yHzL39knaQcSKFL31in
启动第二个节点 启动节点
1 geth --networkid 1 --dev --mine --datadir tmpdata1 --identity "mychain1" --rpc --rpcaddr 0.0.0.0 --rpcport 8101 --port 30301 --http.corsdomain "*" --rpcapi eth,net,web3,personal --allow-insecure-unlock console 1>> tmpdata1/01.log
从另一个终端窗口连接到节点上的IPC控制台
1 geth attach ipc:tmpdata1/geth.ipc
要检查geth使用的端口并找到您的enode URI,请运行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 > admin.nodeInfo { enode: "enode://82fc36da840a160bf80de90aa23132ac22eb53fc60ab62ac051e80a811b2e92b356886d3e6dbdd8f11f034d067eb2ecd149122c3e8493341184edd2f555bc311@127.0.0.1:30303?discport=0", enr: "enr:-JC4QB_kvZUsRnwuMU8GLs2Z0HIapvg3ShgkduDSRtaQyGYWGaHF372_nfP6PB63QYTFkZBK9FtSRv9utCeTTcSr1MAJg2V0aMfGhOZyIzeAgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQOC_DbahAoWC_gN6QqiMTKsIutT_GCrYqwFHoCoEbLpK4N0Y3CCdl8", id: "10adfd90e75461577e292b7df8c5c1153fffaad628fa62a3df0ae29175f30731", ip: "127.0.0.1", listenAddr: "[::]:30303", name: "Geth/111/v1.9.16-unstable-6d8e51ab-20200707/darwin-amd64/go1.14", ports: { discovery: 0, listener: 30303 }, protocols: { eth: { config: { byzantiumBlock: 0, chainId: 1337, clique: {...}, constantinopleBlock: 0, eip150Block: 0, eip150Hash: "0x0000000000000000000000000000000000000000000000000000000000000000", eip155Block: 0, eip158Block: 0, homesteadBlock: 0, istanbulBlock: 0, petersburgBlock: 0 }, difficulty: 21, genesis: "0xf5e67f9f05de71cb3d0740331ef211ad9f9e32b7f709fa0d28dcf8675dfd65ad", head: "0x3562d50b915960920180c1439c5ee732136c2e39f20569c97fa578140cbca39e", network: 111 } } } > admin.nodeInfo.enode "enode://82fc36da840a160bf80de90aa23132ac22eb53fc60ab62ac051e80a811b2e92b356886d3e6dbdd8f11f034d067eb2ecd149122c3e8493341184edd2f555bc311@127.0.0.1:30303?discport=0"
第一种连接方式 如果要将此实例连接到先前启动的节点,则可以使用从控制台将其添加为对等实例admin.addPeer(enodeUrlOfFirstInstance)
节点2通过节点1的enode连接网络
1 2 > admin.addPeer("enode://82fc36da840a160bf80de90aa23132ac22eb53fc60ab62ac051e80a811b2e92b356886d3e6dbdd8f11f034d067eb2ecd149122c3e8493341184edd2f555bc311@192.168.43.52:30303") true
第二种连接方式设置引导节点
1 2 3 4 5 6 7 > bootnode -genkey bootnode.key > cat bootnode.key 11042159d89a7a42ac23463ae4b02881c8ac73e2f99cffd0f88cf32b7e186306 bootnode -nodekey bootnode.key enode://840dd3574337a628c9b38c6faca48f6fbb24e5f53662e7229eac553624b7ad8bafc910092ec9bb7b6072386d2d14cd88b0de8dfbae811d2b999f2d1750845933@127.0.0.1:0?discport=30301
在测试2节点个节点联通时,发现联不通可能是在命令里加了 –dev 参数的原因
第三种连接方式使用相同的创世纪区块初始化genesis.json文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 { "config": { "chainId": 111, "homesteadBlock": 0, "eip150Block": 0, "eip155Block": 0, "eip158Block": 0, "byzantiumBlock": 0, "constantinopleBlock": 0, "petersburgBlock": 0, "istanbulBlock": 0 }, "alloc": {}, "coinbase": "0x0000000000000000000000000000000000000000", "difficulty": "0x01", "extraData": "0x0", "gasLimit": "0x2fefd8", "nonce": "0x0000000000000042", "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "timestamp": "0x00" }
区块参数释义:
参数 说明 chainId 指定了独立的区块链网络ID。网络ID在连接到其他节点的时候会用到,以太坊公网的网络ID是 1,为了不与公有链网络冲突,运行私有链节点的时候要指定自己的网络ID。不同ID网络的节点无法相互连接。 homesteadBlock homestead 算法块 eip150Block eip150 算法块 eip155Block eip155 算法块 eip158Block eip158 算法块 alloc 用来预置账号以及账号的以太币数量 coinbase 矿工账号 extraData 附加信息 difficulty 设置设置当前区块的难度,值越大挖矿就越难。 gasLimit 该值设置对GAS的消耗总量限制,用来限制区块能包含的交易信息总和 nonce 挖矿用的64位随机数 mixhash 与 nonce 配合挖矿,与上一个区块的 hash 有关 parentHash 上一个区块的hash,创世块就为0 timestamp 设置创世块的时间戳
1 2 3 geth account new Public address of the key: 0x2E82C574603da92489B6514D0f4DAE6bc5BC61E5 Path of the secret key file: /Users/apple/Library/Ethereum/keystore/UTC--2020-07-12T15-56-33.495853000Z--2e82c574603da92489b6514d0f4dae6bc5bc61e5
启动节点1
1 2 geth --datadir data1 init data1/genesis.json geth --datadir data1 --networkid 15 --ipcdisable --port 61911 --rpcport 8101 --nodiscover console
发现账户是空的
创建账户
将创建后的账户添加到genesis.json文件的 “alloc”: {},
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 { "config": { "chainId": 111, "homesteadBlock": 0, "eip150Block": 0, "eip155Block": 0, "eip158Block": 0, "byzantiumBlock": 0, "constantinopleBlock": 0, "petersburgBlock": 0, "istanbulBlock": 0 }, "alloc": { "0x510f1cdce4f3dd7ecc0c84099bf7f40bbe38fdc6":{ "balance":"1000000000000000000000000" } }, "coinbase": "0x0000000000000000000000000000000000000000", "difficulty": "0x01", "extraData": "", "gasLimit": "0x2fefd8", "nonce": "0x0000000000000042", "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "timestamp": "0x00" }
再次启动节点1 可以看到账户及余额
1 2 3 4 5 6 7 8 9 geth --syncmode "full" --datadir data1 --networkid 15 --rpc --rpcaddr 0.0.0.0 --port 61911 --rpcport 8101 --http.corsdomain "*" --rpcapi eth,net,web3,personal --allow-insecure-unlock console //开始挖矿 miner.start(); > web3.eth.coinbase "0x510f1cdce4f3dd7ecc0c84099bf7f40bbe38fdc6" > eth.getBalance(web3.eth.coinbase) 9.9999195e+23
查看节点1的enode
1 2 > admin.nodeInfo.enode "enode://f5454bb17ebaad5125c4db97036329972822ff13d1d481cfdb1c9e1b3569050880d382363d85f7548837203ed524296e272440fc6ff2cd70f81636985d96c36d@127.0.0.1:61911"
启动节点2 带上–bootnodes 节点1的enode
1 2 3 4 5 6 7 8 9 geth --datadir data2 init data2/genesis.json geth --syncmode "full" --datadir data2 --networkid 15 --rpc --rpcaddr 0.0.0.0 --port 61910 --rpcport 8100 console > personal.newAccount() //创建账户,不创建账户无法启动挖矿功能 //创建账户后再次启动节点2 节点2还没有账户,先不开启挖矿,去掉 --mine; 两个节点初始化的创世区块必须要一模一样 节点2"alloc"为空 geth --syncmode "full" --datadir data2 --networkid 15 --rpc --rpcaddr 0.0.0.0 --port 61910 --rpcport 8100 --http.corsdomain "*" --rpcapi eth,net,web3,personal --allow-insecure-unlock --bootnodes "enode://f5454bb17ebaad5125c4db97036329972822ff13d1d481cfdb1c9e1b3569050880d382363d85f7548837203ed524296e272440fc6ff2cd70f81636985d96c36d@127.0.0.1:61911" console
查看网络
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 > net.peerCount > admin.peers [{ caps: ["eth/62", "eth/63", "par/1", "par/2", "par/3", "pip/1"], enode: "enode://4b9b92e32084ce52253a4b2f5f34a2c8e7f7379aed45924ba2a4aa1be8d0cf469cd4cd7ac9955f3f2e9d0b8937503c8359fa14afdf3168d81e8cbc70ba6c1c6b@209.126.69.171:30303", id: "e7b99d68ac3e1f85b21e1b2f024811815f4297f72b0b5014dcfe8d5cb6dda64d", name: "Parity-Ethereum/v2.4.6-stable-94164e1-20190514/x86_64-linux-gnu/rustc1.34.1", network: { inbound: false, localAddress: "192.168.43.52:60970", remoteAddress: "209.126.69.171:30303", static: false, trusted: false }, protocols: { eth: "handshake" } }]
终端1账户0向账户1转账
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 //解锁账户0(密码为空) personal.unlockAccount(personal.listAccounts[0]); //以太币转wei amount = web3.toWei(5,'ether'); //转账 eth.sendTransaction({from:personal.listAccounts[0],to:personal.listAccounts[1],value:amount}); //查看交易状态 txpool.status //查看区块信息 eth.getBlock("pending",true); { difficulty: 2, extraData: "0xd783010910846765746886676f312e31348664617277696e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", gasLimit: 6301605, gasUsed: 0, hash: null, logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", miner: null, mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000", nonce: null, number: 3, parentHash: "0x1100bb5dbf6803d444b79ddc128ebb21485879cc5d6ad563e6ff97cb2a49b841", receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", size: 606, stateRoot: "0x0f2bff95db3fcaefdce401685cdddd5780b47e054e427611e3bebd37612e04cb", timestamp: 1594311926, totalDifficulty: 0, transactions: [], transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", uncles: [] } //开始挖矿 miner.start(); //停止挖矿 miner.stop(); //查看交易状态 txpool.status //查看账户1的余额 eth.getBalance(personal.listAccounts[0]) eth.getBalance(personal.listAccounts[1]) //转账成功!!! //查看区块数 eth.blockNumber //查看交易信息 eth.getTransaction("0x7811782799fb175f9576848f1928031dcc25248c4ebf218764ee6296159f53c4") { blockHash: "0x1100bb5dbf6803d444b79ddc128ebb21485879cc5d6ad563e6ff97cb2a49b841", blockNumber: 2, from: "0x0caad1f289fdfdf0a0988d2f4239caa2453d73cc", gas: 21000, gasPrice: 1, hash: "0x7811782799fb175f9576848f1928031dcc25248c4ebf218764ee6296159f53c4", input: "0x", nonce: 1, r: "0x8e08d5260f970e0879525ae515b47508f358a84cdda053110bcc3062f380fea7", s: "0x4a8d2c63aa5bba7af84d84fdbe59a79620dd67e72f9a1ca40cd9a2ab8471d87", to: "0xd981f82235febaa46d23a6c4be45abccb9310a95", transactionIndex: 0, v: "0xa96", value: 5000000000000000000 } //查看区块信息(区块号) eth.getBlock(1)
Ω