一、以太坊是什么
以太坊(Ethereum)是一个建立在区块链技术之上, 去中心化应用平台。它允许任何人在平台中建立去中心化应用和使用这些应用。
说人话,以太坊就是区块链世界的安卓和ios,他是一个开发平台,你按照它的规则开发应用,并将应用部署到以太坊区块链中。这就像你基于安卓平台或者iOS平台开发应用,然后发布到应用商店一样。
在没有以太坊之前,写区块链应用是这样的:拷贝一份比特币代码,然后去改底层代码如加密算法,共识机制,网络协议等等(很多山寨币就是这样,改改就出来一个新币)。
以太坊对这些底层技术进行了封装,开发者只用专注于应用本身开发,大大降低了开发难度。
二、智能合约
智能合约就是以太坊上运行的程序。
智能合约可以理解为在区块链上可以自动执行的(由事件驱动的)、以代码形式编写的合同(特殊的交易)。
详细了解智能合约可以看以前的文章《5分钟区块链 | 理解智能合约》。
比特币的交易也是可编程的,但是比特币脚本有很多限制,不是图灵完备的。而以太坊脚本是图灵完备的,可以像许多高级语言一样,编写复杂的程序。
三、编程语言:Solidity
Solidity是以太坊智能合约的开发语言,它的语法和javascript类似。以后会详细介绍Solidity语言。它的语法相对简单。
Browser-Solidity是一个浏览器的Solidity IDE, 大家可以点进去看看
四、运行环境:EVM
EVM(Ethereum Virtual Machine)以太坊虚拟机是以太坊中智能合约的运行环境。
智能合约程序都运行在EVM中,就像java程序运行在JVM中一样。
EVM运行在以太坊节点上,当我们把智能合约部署到以太坊网络,合约就可以在以太坊中运行。
五、 以太坊客户端(钱包)
以太坊客户端,其实我们可以把它理解为一个开发者工具,它提供账户管理、挖矿、转账、智能合约的部署和执行等等功能。
常用客户端有两种Geth和Mist:
Geth是一个基于命令行的客户端
Mist是一个基于图形化操作界面的客户端
注意:
Ethereum Wallet是编译后的以太坊钱包 Mist是一个图形化的客户端,使用方便,推荐使用。
Mist = Ethereum Wallet + Web3 浏览器
在下载页面 会有Ethereum Wallet和Mist的下载
如果只下载Ethereum Wallet后只能使用命令行方式(相当于源码编译后的执行方式),而带UI的客户端需要另行想办法
下载地址:https://github.com/ethereum/mist/releases/
以上简介内容来自链接:https://www.jianshu.com/p/46c2d375bdee
下载源码
cd GO_PATH\github.com\
mkdir ethereum
cd ethereum
git clone https://github.com/ethereum/go-ethereum.git
下载 http://www.mingw.org/编译器gcc
安装好后在cmd输入gcc -v
提示gcc version x.x.x表示安装成功
cmd输入编译源码
go install -v github.com/ethereum/go-ethereum/cmd/geth
go install -v github.com/ethereum/go-ethereum/cmd/evm
就可以在go/bin文件中找到生成的文件
evm.exe
geth.exe
检查是否安装成功
geth --help
配置初始状态
初始化:写入创世区块
mkdir pchain
cd pchain
mkdir data0
vi genesis.json
genesis.json是初始区块的配置信息
{
"config": {
"chainId": 10,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc" : {},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x20000",
"extraData" : "",
"gasLimit" : "0x2fefd8",
"nonce" : "0x0000000000000042",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00"
}
chainId : 以太坊区块链网络Id,ethereum主链是1,私有链只用不要与主链冲突即可。
alloc : 预留账户,如下
“alloc”:{
“0x0000000000000000000000000000000000000001”:{“balance”:”121312321”},
“0x0000000000000000000000000000000000000002”:{“balance”:”121312321”},
}
Coinbase: 旷工账户
Difficulty: 挖矿难度,0x400,这个是简单。
extraData:相当于备注
gasLimit:最小消耗gas
nonce : 64位随机数,用于挖矿,注意他和mixhash的设置需要满足以太坊黄皮书中的要求
parentHash : 上一个区块的Hash值,因为是创世块,石头里蹦出来的,没有在它前面的,所以是0
Timestamp : 时间戳
执行初始化命令
# pwd
D:\go\bin\pchain
# geth --datadir data0 init genesis.json
上面的命令的主体是 geth init,表示初始化区块链,命令可以带有选项和参数,其中 --datadir 选项后面跟一个目录名,这里为 data0,表示指定数据存放目录为 data0,genesis.json 是 init 命令的参数
如果看到以下的输出内容,说明初始化成功了。
INFO [01-29|21:21:13] Successfully wrote genesis state database=lightchaindata hash=5e1fc7…d790e0
文件路径如下
pchain
├── data0
│ ├── geth
│ │ ├── chaindata
│ │ │ ├── 000001.log
│ │ │ ├── CURRENT
│ │ │ ├── LOCK
│ │ │ ├── LOG
│ │ │ └── MANIFEST-000000
│ │ └── lightchaindata
│ │ ├── 000001.log
│ │ ├── CURRENT
│ │ ├── LOCK
│ │ ├── LOG
│ │ └── MANIFEST-000000
│ └── keystore
└── genesis.json
启动私有链节点
geth --rpc --rpccorsdomain "*" --datadir ./data0 --port "30303" --rpcapi "db,eth,net,web3" --networkid 110 console 2>>geth.log
上面命令的主体是 geth console,表示启动节点并进入交互式控制台,–datadir选项指定使用data0作为数据目录,–networkid 选项后面跟一个数字,这里是110,表示指定这个私有链的网络id为110。网络id在连接到其他节点的时候会用到,以太坊公网的网络id是1,为了不与公有链网络冲突,运行私有链节点的时候要指定自己的网络id。
使用命令 geth -h 可以查看geth 相关的帮助文档。这里我说几个常用的属性。
--Identity : 节点身份标识,起个名字
--datadir : 指定节点存在位置,“data”
--rpc : 启用http-rpc服务器
--rpcapi : 基于http-rpc提供的api接口。eth,net,web3,db…
--rpcaddr : http-rpc服务器接口地址:默认“127.0.0.1”
--rpcport : http-rpc 端口(多节点时,不要重复)
--port : 节点端口号(多节点时,不要重复)
--networkid : 网络标识符 随便指定一个id(确保多节点是统一网络,保持一致)
这是一个交互式的 JavaScript 执行环境,在这里面可以执行 JavaScript 代码,其中 > 是命令提示符。在这个环境里也内置了一些用来操作以太坊的 JavaScript 对象,可以直接使用这些对象。这些对象主要包括:
eth:包含一些跟操作区块链相关的方法;
net:包含一些查看p2p网络状态的方法;
admin:包含一些与管理节点相关的方法;
miner:包含启动&停止挖矿的一些方法;
personal:主要包含一些管理账户的方法;
txpool:包含一些查看交易内存池的方法;
web3:包含了以上对象,还包含一些单位换算的方法。
控制台操作
进入以太坊 Javascript Console 后,就可以使用里面的内置对象做一些操作,这些内置对象提供的功能很丰富,比如查看区块和交易、创建账户、挖矿、发送交易、部署智能合约等。
常用命令有:
personal.newAccount():创建账户;
personal.unlockAccount():解锁账户;
eth.accounts:枚举系统中的账户;
eth.getBalance():查看账户余额,返回值的单位是 Wei(Wei 是以太坊中最小货币面额单位,类似比特币中的聪,1 ether = 10^18 Wei);
eth.blockNumber:列出区块总数;
eth.getTransaction():获取交易;
eth.getBlock():获取区块;
miner.start():开始挖矿;
miner.stop():停止挖矿;
eth.coinbase:挖矿奖励的账户
web3.fromWei():Wei 换算成以太币;
web3.toWei():以太币换算成 Wei;
txpool.status:交易池中的状态;
admin.addPeer():连接到其他节点;
启动私有块后,默认是没有账户的
查询账户
> eth.accounts
[]
> personal.newAccount()
Passphrase:
Repeat passphrase:
"0xfb9cc019fc650a1699d05b7fb564b83c3a72b64d"
Passphrase 表示输入密码,Repeat passphrase 表示输入确认密码
再次创建一个账户
> personal.newAccount()
Passphrase:
Repeat passphrase:
"0xc6b5702b15a3794374e28f41f36e1e8dbdd564df"
这里我们创建了两个账号
账户默认会保存在数据目录的 data0/keystore 文件夹中。可以查看其中的文件
通过 eth.getBalance() 可以查看账户余额
> eth.getBalance(eth.accounts[0])
0
> eth.getBalance(eth.accounts[1])
0
通过 miner.start() 启动挖矿
> miner.start(3)
其中 start 的参数表示挖矿使用的线程数。第一次启动挖矿会先生成挖矿所需的 DAG 文件,这个过程有点慢,等进度达到 100% 后,就会开始挖矿,此时屏幕会被挖矿信息刷屏。
停止挖矿,在 console 中输入:
miner.stop()
挖到一个区块会奖励5个以太币,挖矿所得的奖励会进入矿工的账户,这个账户叫做coinbase,默认情况下coinbase是本地账户中的第一个账户:
> eth.coinbase
"0xfb9cc019fc650a1699d05b7fb564b83c3a72b64d"
可以通过 miner.setEtherbase() 将其他账户设置成 coinbase 即可
> miner.setEtherbase(eth.accounts[1])
true
> eth.coinbase
"0xc6b5702b15a3794374e28f41f36e1e8dbdd564df"
重新启动挖矿,查看 eth.accounts[1] 是否可以获得以太币
> miner.start(3)
//等待几秒后
> miner.stop()
查询账户余额:
> eth.getBalance(eth.accounts[0])
280000000000000000000
> eth.getBalance(eth.accounts[1])
210000000000000000000
发现账户0 和 账号1 都有以太币,说明 miner.setEtherbase() 设置成功。
getBalance() 返回值的单位是wei,wei是以太币的最小单位,1个以太币=10的18次方个wei。要查看有多少个以太币,可以用web3.fromWei()将返回值换算成以太币:
> web3.fromWei(eth.getBalance(eth.accounts[0]),'ether')
280
> web3.fromWei(eth.getBalance(eth.accounts[1]),'ether')
210
我们从账户0转移10个以太币到账户1,
首先要解锁账户 0,才能发起交易(新版的console客户端已经不支持解锁账户了,会提示Error: account unlock with HTTP access is forbidden,直接使用Mis客户端转账),我这使用的是新版本的(2019-0-30下载的版本),因此直接看我后面的截图转账即可即可
控制台方式
> personal.unlockAccount(eth.accounts[0])
Unlock account 0xfb9cc019fc650a1699d05b7fb564b83c3a72b64d
Passphrase:
true
发起交易
> amount = web3.toWei(10,'ether')
"10000000000000000000"
> eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:amount})
INFO [05-29|22:37:32] Submitted transaction fullhash=0x493e8aa2bcb6b2a362bdbd86b2c454279e14beea43b444aeb45c7f667bf572e2 recipient=0xc6b5702B15a3794374e28f41F36e1E8dBDd564DF
"0x493e8aa2bcb6b2a362bdbd86b2c454279e14beea43b444aeb45c7f667bf572e2
查询 账户1 的余额:
> web3.fromWei(eth.getBalance(eth.accounts[1]),'ether')
210
客户端方式
则更加直观,直接点SEND,选择转出方账号,填写接收方的钱包地址(可以去账号中复制地址),填写额度然后确认输入转出方密码确认即可。
无论是控制台方式还是客户端方式:发现账户余额没有发生改变,此时交易已经提交到区块链,但还未被处理,这可以通过用 txpool.status 命令可以看到本地交易池中有一个待确认的交易:
> txpool.status
{
pending: 1,
queued: 0
}
其中有一条pending的交易,pending表示已提交但还未被处理的交易。
要使交易被处理,必须要挖矿。这里我们启动挖矿,然后等待挖到一个区块之后就停止挖矿:
>miner.start(1);admin.sleepBlocks(1);miner.stop()
> web3.fromWei(eth.getBalance(eth.accounts[1]),'ether')
225.000378
发现账户收到了账户的钱,还多了5个以太币。其实多出的5个以太币是挖矿奖励。
查看当前区块总数:
> eth.blockNumber
99
通过区块号查看区块:
> eth.getBlock(6)
{
difficulty: 131328,
extraData: "0xd98301080a846765746888676f312e31302e328664617277696e",
gasLimit: 3160033,
gasUsed: 0,
hash: "0x9679d0dc01045c3d15cbf29241ae1cd6de2e5661d3387c0980f6397e3fd9ed2c",
logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
miner: "0xfb9cc019fc650a1699d05b7fb564b83c3a72b64d",
mixHash: "0x05c369134eac2cb6227860b4ed11527b11825af3541712c5704914576c37c0a0",
nonce: "0x00168a9831624417",
number: 6,
parentHash: "0xad68f0a581cf2144b8a05190b6310c7a9d945d9c338fd16b4708651b8813ad8b",
receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
size: 537,
stateRoot: "0xfaa0a4ffe160a2937b967f9780ae0de51a465bcce6a3f6f3aa24b903df3d44a0",
timestamp: 1527602736,
totalDifficulty: 918144,
transactions: [],
transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
uncles: []
}
通过交易hash(hash 值包含在上面交易返回值中)查看交易:
eth.getTransaction("0x493e8aa2bcb6b2a362bdbd86b2c454279e14beea43b444aeb45c7f667bf572e2")
{
blockHash: "0xbe60f7ccddcb7cab39a7b932c0d89d37ac13ae14521cfdcb8ac359a5b6773655",
blockNumber: 99,
from: "0xfb9cc019fc650a1699d05b7fb564b83c3a72b64d",
gas: 90000,
gasPrice: 18000000000,
hash: "0x493e8aa2bcb6b2a362bdbd86b2c454279e14beea43b444aeb45c7f667bf572e2",
input: "0x",
nonce: 0,
r: "0x8da41e865d399fc4d8f813a39116e486db7658a04ea1f89ca0b7f44c02dd3c57",
s: "0x15edd22404460cfc5e86c9735774a02aad024bc8c369ec531e4485f1012cbcf6",
to: "0xc6b5702b15a3794374e28f41f36e1e8dbdd564df",
transactionIndex: 0,
v: "0x37",
value: 10000000000000000000
}
以太坊私有链多节点搭建
https://blog.csdn.net/easylover/article/details/82733922