以太坊(Ethereum)是一提供个智能合约(smart contract)功能的公共区块链平台。在以太坊上开发应用,首先需要安装其客户端基于Go语言的Geth, 官网为:https://github.com/ethereum/go-ethereum。
geth --datadir "E:\geth\devchain" --dev console
输入命令后,它会在指定目录下存放数据
C:\Users>geth --datadir "E:\geth\devchain" --dev console
INFO [11-26|14:25:03.001] Maximum peer count ETH=50 LES=0 total=50
INFO [11-26|14:25:08.333] Using developer account address=0x823356EF65d2f7004a15368f18cb5964F1f28bd9
INFO [11-26|14:25:08.574] Starting peer-to-peer node instance=Geth/v1.9.6-stable-bd059680/windows-amd64/go1.13
INFO [11-26|14:25:08.837] Allocated trie memory caches clean=256.00MiB dirty=256.00MiB
INFO [11-26|14:25:10.175] Writing custom genesis block
INFO [11-26|14:25:10.291] Persisted trie from memory database nodes=11 size=1.67KiB time=0s gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [11-26|14:25:10.365] Initialised chain configuration config="{ChainID: 1337 Homestead: 0 DAO: DAOSupport: false EIP150: 0 EIP155: 0 EIP158: 0 Byzantium: 0 Constantinople: 0 Petersburg: 0 Istanbul: 0 Engine: clique}"
INFO [11-26|14:25:10.420] Initialising Ethereum protocol versions=[63] network=1337 dbversion=<nil>
WARN [11-26|14:25:10.425] Upgrade blockchain database version from=<nil> to=7
INFO [11-26|14:25:10.780] Loaded most recent local header number=0 hash=9f0eb4…1822a6 td=1 age=50y7mo2w
INFO [11-26|14:25:10.883] Loaded most recent local full block number=0 hash=9f0eb4…1822a6 td=1 age=50y7mo2w
INFO [11-26|14:25:10.932] Loaded most recent local fast block number=0 hash=9f0eb4…1822a6 td=1 age=50y7mo2w
INFO [11-26|14:25:10.979] Regenerated local transaction journal transactions=0 accounts=0
INFO [11-26|14:25:11.579] Allocated fast sync bloom size=512.00MiB
INFO [11-26|14:25:11.713] Initialized fast sync bloom items=11 errorrate=0.000 elapsed=9.985ms
INFO [11-26|14:25:15.374] Stored checkpoint snapshot to disk number=0 hash=9f0eb4…1822a6
INFO [11-26|14:25:18.258] started whisper v.6.0
INFO [11-26|14:25:18.489] New local node record seq=1 id=502f3b6c782c5e42 ip=127.0.0.1 udp=0 tcp=52422
INFO [11-26|14:25:18.515] Started P2P networking self="enode://9a94b0762370d1ab0e1e8de35d5d0256c980db27430c3923030d2f1cd05fc7d4323808d4b5fff87cb40ec4fa49bdb262dcd846b6bdbcbd8930f50e163ffd46b4@127.0.0.1:52422?discport=0"
INFO [11-26|14:25:20.882] IPC endpoint opened url=\\\\.\\pipe\\geth.ipc
INFO [11-26|14:25:21.060] Transaction pool price threshold updated price=1000000000
INFO [11-26|14:25:21.223] Transaction pool price threshold updated price=1
INFO [11-26|14:25:21.226] Etherbase automatically configured address=0x823356EF65d2f7004a15368f18cb5964F1f28bd9
INFO [11-26|14:25:21.232] Sealing paused, waiting for transactions
INFO [11-26|14:25:21.278] Commit new mining work number=1 sealhash=48dcd2…3382e5 uncles=0 txs=0 gas=0 fees=0 elapsed=45.969ms
Welcome to the Geth JavaScript console!
instance: Geth/v1.9.6-stable-bd059680/windows-amd64/go1.13
coinbase: 0x823356ef65d2f7004a15368f18cb5964f1f28bd9
at block: 0 (Thu, 01 Jan 1970 08:00:00 CST)
datadir: E:\geth\devchain
modules: admin:1.0 clique:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 shh:1.0 txpool:1.0 web3:1.0
–dev启用开发者网络(模式),开发者网络会使用POA共识机制,默认预先分配一个开发者账户并且会再交易后自动开启挖矿。
–datadir后面的参数是区块数据及秘钥存放目录。
console 进入控制台
也可以使用–allow-insecure-unlock ,这样的话在部署智能合约时就不需要先解锁了
查看账户
> eth.accounts
["0x823356ef65d2f7004a15368f18cb5964f1f28bd9"]
查看账户余额
> eth.getBalance(eth.accounts[0])
1.15792089237316195423570985008687907853269984665640564039457584007913129639927e+77
创建账户
> personal.newAccount("123")
INFO [11-26|14:26:45.801] Your new key was generated address=0x77B18fE27482c8AaECd42155947aDe0f5ad6390e
WARN [11-26|14:26:45.839] Please backup your key file! path=E:\\geth\\devchain\\keystore\\UTC--2019-11-26T06-26-42.313627400Z--77b18fe27482c8aaecd42155947ade0f5ad6390e
WARN [11-26|14:26:45.846] Please remember your password!
"0x77b18fe27482c8aaecd42155947ade0f5ad6390e"
0x77b18fe27482c8aaecd42155947ade0f5ad6390e为账户地址
查看此时账户
> eth.accounts
["0x823356ef65d2f7004a15368f18cb5964f1f28bd9", "0x77b18fe27482c8aaecd42155947ade0f5ad6390e"]
查看新账户的余额
> eth.getBalance(eth.accounts[1])
0
没有余额的账户是没法部署合约的,从默认账户转100以太币给新账户
> eth.sendTransaction({from:'0x823356ef65d2f7004a15368f18cb5964f1f28bd9',to:'0x77b18fe27482c8aaecd42155947ade0f5ad6390e',value:web3.toWei(100,"ether")})
INFO [11-26|14:28:43.282] Setting new local account address=0x823356EF65d2f7004a15368f18cb5964F1f28bd9
INFO [11-26|14:28:43.335] Submitted transaction fullhash=0x745842598d25bedbf991a55132d0c9b91fa7cd14d09b8df020a2cebe10e830e2 recipient=0x77B18fE27482c8AaECd42155947aDe0f5ad6390e
"0x745842598d25bedbf991a55132d0c9b91fa7cd14d09b8df020a2cebe10e830e2"
> INFO [11-26|14:28:43.424] Commit new mining work number=1 sealhash=a6917a…9587b4 uncles=0 txs=1 gas=21000 fees=2.1e-14 elapsed=111.993ms
INFO [11-26|14:28:43.565] Successfully sealed new block number=1 sealhash=a6917a…9587b4 hash=3675fd…18b7ec elapsed=140.952ms
INFO [11-26|14:28:43.581] mined potential block number=1 hash=3675fd…18b7ec
INFO [11-26|14:28:43.591] Sealing paused, waiting for transactions
INFO [11-26|14:28:43.600] Commit new mining work number=2 sealhash=260aea…e9c8d5 uncles=0 txs=0 gas=0 fees=0 elapsed=27.993ms
信息提示生成新的区块,交易被确认了。查看新账户的余额,以ether为单位。
> web3.fromWei(web3.eth.getBalance(eth.accounts[1]), 'ether')
100
在部署合约前需要先解锁账户(就像银行转账要输入密码一样)
> personal.unlockAccount(eth.accounts[1],"123")
true
pragma solidity ^0.4.4;
contract HelloWorld
{
address creator;
string greeting;
function HelloWorld(string _greeting) public
{
creator = msg.sender;
greeting = _greeting;
}
function greet() constant returns (string)
{
return greeting;
}
function setGreeting(string _newgreeting)
{
greeting = _newgreeting;
}
function kill()
{
if (msg.sender == creator)
suicide(creator); // kills this contract and sends remaining funds back to creator
}
}
设置Compiler并开始Compile
查看Compilation Details
把上面这个代码粘贴到文本文档,并改一下:var _greeting = "Hello World"
var _greeting = "Hello World" ;
var helloworldContract = web3.eth.contract([{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"type":"function","stateMutability":"nonpayable"},{"constant":false,"inputs":[{"name":"_newgreeting","type":"string"}],"name":"setGreeting","outputs":[],"payable":false,"type":"function","stateMutability":"nonpayable"},{"constant":true,"inputs":[],"name":"greet","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function","stateMutability":"view"},{"inputs":[{"name":"_greeting","type":"string"}],"type":"constructor","payable":true,"stateMutability":"payable"}]);
var helloworld = helloworldContract.new(
_greeting,
{
from: web3.eth.accounts[0],
data: '0x6060604052604051610460380380610460833981016040528080518201919060200150505b33600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690836c010000000000000000000000009081020402179055508060016000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100b057805160ff19168380011785556100e1565b828001600101855582156100e1579182015b828111156100e05782518260005055916020019190600101906100c2565b5b50905061010c91906100ee565b8082111561010857600081815060009055506001016100ee565b5090565b50505b506103428061011e6000396000f360606040526000357c01000000000000000000000000000000000000000000000000000000009004806341c0e1b514610052578063a413686214610066578063cfae3217146100c15761004d565b610002565b34610002576100646004805050610141565b005b34610002576100bf6004808035906020019082018035906020019191908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509090919050506101d5565b005b34610002576100d36004805050610286565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156101335780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156101d257600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b5b565b8060016000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061022457805160ff1916838001178555610255565b82800160010185558215610255579182015b82811115610254578251826000505591602001919060010190610236565b5b5090506102809190610262565b8082111561027c5760008181506000905550600101610262565b5090565b50505b50565b602060405190810160405280600081526020015060016000508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103335780601f1061030857610100808354040283529160200191610333565b820191906000526020600020905b81548152906001019060200180831161031657829003601f168201915b5050505050905061033f565b9056',
gas: '4700000'
}, function (e, contract){
console.log(e, contract);
if (typeof contract.address !== 'undefined') {
console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
}
})
将改好的复制到命令行窗口就会出现Contract mined! address…, 表明合约代码发布成功
INFO [11-26|15:12:46.630] Submitted contract creation fullhash=0xb25f88646f07f54f1759697fa61a7f3fbab77055a587c0000cca47bf06bf1514 contract=0xF3838630CB4f5a7902AD0846cf32477811133C2c
INFOnull [object Object]
[11-26|15:12:46.631] Commit new mining work u n de f innedumber
=> 4 sealhash=8bb0bf…0757f5 uncles=0 txs=1 gas=279365 fees=2.79365e-13 elapsed=995.2µs
INFO [11-26|15:12:46.632] Successfully sealed new block number=4 sealhash=8bb0bf…0757f5 hash=0e5e53…5e296b elapsed=1.000ms
INFO [11-26|15:12:46.653] mined potential block number=4 hash=0e5e53…5e296b
INFO [11-26|15:12:46.670] Commit new mining work number=5 sealhash=f8f519…39b38b uncles=0 txs=0 gas=0 fees=0 elapsed=16.996ms
INFO [11-26|15:12:46.670] Sealing paused, waiting for transactions
null [object Object]
Contract mined! address: 0xf3838630cb4f5a7902ad0846cf32477811133c2c transactionHash: 0xb25f88646f07f54f1759697fa61a7f3fbab77055a587c0000cca47bf06bf1514
address:0xf3838630cb4f5a7902ad0846cf32477811133c2c为智能合约的账户地址 transactionHash:0xb25f88646f07f54f1759697fa61a7f3fbab77055a587c0000cca47bf06bf1514 为交易号(部署智能合约也是一笔交易)
查看此时新账户的余额
> eth.getBalance(eth.accounts[1])
99999999999999971135
消耗掉一些gas
> helloworld.greet() "Hello World"
但是运行helloworld.setGreeting()就会报错,因为运行setGreetin()有改变greeting值(也可理解为状态),则需要进行交易。
> helloworld.setGreeting('hi')
Error: invalid address
at web3.js:3930:15
at web3.js:3756:20
at web3.js:5025:28
at map (<native code>)
at web3.js:5024:12
at web3.js:5050:18
at web3.js:5075:23
at web3.js:4137:16
at apply (<native code>)
at web3.js:4223:16
> helloworld.setGreeting('hi',{from:eth.accounts[1],gas:4700000})
WARN [11-26|15:29:47.052] Served eth_sendTransaction reqid=56 t=0s err="authentication needed: password or unlock"
Error: authentication needed: password or unlock
at web3.js:3143:20
at web3.js:6347:15
at web3.js:5081:36
at web3.js:4137:16
at apply (<native code>)
at web3.js:4223:16
at <anonymous>:1:1
忘记解锁了,交易之前要解锁
> personal.unlockAccount(eth.accounts[1],"123")
true
> helloworld.setGreeting('hi',{from:eth.accounts[1],gas:4700000})
INFO [11-26|15:32:30.233] Submitted transaction fullhash=0x4aee60569da5be10e8124276b1cb8bfdd0b5a2a4bb842c872df51576b05b6109 recipient=0xF3838630CB4f5a7902AD0846cf32477811133C2c
INFO "0x4aee60569d[a5be10e812427611-26|15:32:30.234] Commit new mib1cb8bfdd0b5a2a4bb842c872df51576b0n5b6109"ing
work > number=5 sealhash=ff197e…b345ae uncles=0 txs=1 gas=28780 fees=2.878e-14 elapsed=1.014ms
INFO [11-26|15:32:30.235] Successfully sealed new block number=5 sealhash=ff197e…b345ae hash=a48322…49fea9 elapsed=984µs
INFO [11-26|15:32:30.255] mined potential block number=5 hash=a48322…49fea9
INFO [11-26|15:32:30.256] Sealing paused, waiting for transactions
INFO [11-26|15:32:30.258] Commit new mining work number=6 sealhash=e268a9…f9db10 uncles=0 txs=0 gas=0 fees=0 elapsed=2.995ms
交易成功,得到交易号fullhash=0x4aee60569da5be10e8124276b1cb8bfdd0b5a2a4bb842c872df51576b05b6109
查询交易信息
> eth.getTransactionReceipt('0x4aee60569da5be10e8124276b1cb8bfdd0b5a2a4bb842c872df51576b05b6109')
{
blockHash: "0xa48322e3180cf7da131435132fcb4b1af92cec08f4de285da21b28728b49fea9",
blockNumber: 5,
contractAddress: null,
cumulativeGasUsed: 28780,
from: "0x77b18fe27482c8aaecd42155947ade0f5ad6390e",
gasUsed: 28780,
logs: [],
logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
status: "0x1",
to: "0xf3838630cb4f5a7902ad0846cf32477811133c2c",
transactionHash: "0x4aee60569da5be10e8124276b1cb8bfdd0b5a2a4bb842c872df51576b05b6109",
transactionIndex: 0
}
实际消耗了28780wei的gas。
验证交易
> eth.getBalance(eth.accounts[1])
99999999999999942355
> helloworld.greet()
"hi"