1. 程式人生 > >.net開發以太坊區塊鏈如何與Nethereum互動

.net開發以太坊區塊鏈如何與Nethereum互動

最近,我有時間在以太坊區塊鏈上玩智慧合約。此示例將重點關注使用Nethereum庫與智慧合約進行互動。

最初我想看看Eth Gas Station上發現的合約0x2a0c0dbecc7e4d658f48e01e3fa353f44050c208中發生的事件,但是在輕模式下獲得geth同步被證明是一個非常大的挑戰。在快速模式下同步也很慢:幾個小時取決於你的連線速度。由於我希望我的示例儘可能無縫地工作,因此在測試區塊鏈上部署起來更容易:ganache-cli

因此,示例的第一部分是使用ganache-cli本地區塊鏈,並從Nethereum文件部署示例合約。

ganache-cli

Ganache-cli將在每次執行時生成測試帳戶。為了確保它們不會更改(更容易進行測試,但從不在生產中使用這些帳戶!),使用助記符引數。不要忘記對映用於連線節點的埠8545。

docker run --rm -ti -p 8545:8545 trufflesuite/ganache-cli --mnemonic "johnny mnemonic"

這個命令的結果是:

Ganache CLI v6.1.0 (ganache-core: 2.1.0)

Available Accounts
==================
(0) 0x4efd4ab8293b3b8179d9dbf9ade1ae00d83eb314
(1) 0xaffe3d426b8517b17b54290c882f0827f65ec187
(2) 0x6824385051e746ef4c1c6b4ae7e56a381a95d54a
(3) 0x338da826cf7a3c9a68f00a9e922eeed5ca1e8211
(4) 0x8dcc6e12c380a80329e6108ad9b04b78e561d65a
(5) 0xcee6938394b0fa55c45d08ad588cd84af89a14df
(6) 0x70ab1d88d6980b0d192f3521f8862ac4dca68567
(7) 0xe20547f96055fbd2c3a2263e71cd4adb74b69349
(8) 0x79bef342f6bc8e0b34bcf51e55bf73611aeeb2c4
(9) 0xa24982b1e3c6be086465971c9e7e7e8ad44fdf48

Private Keys
==================
(0) 3f22cc3e1757c4a69de7e249c99e4217d4a0017157247a863cc7fb61e5a16ec8
(1) 8cfce94fa87c2e937d2c901b6193802900e3a9b15bdfe9aaeb1cbb9e9b46d485
(2) 3b9f3f9087260beb3c81a7fa105e0c0714cf30964d726a25cafb883bf3589c2e
(3) 14886ce9c977b5b181cfc01ded5a9f4753f4340623bed643cd7ea89a777e36e7
(4) c8486cd25cb5278481eef49cb689905511f0ebd77101c3f87bb25c152d8a248a
(5) 6ba903be3121fdacb40b677f8f5c0a400e9ff06d0632f4f9c0fcaf5ef4cf989e
(6) 3141fae5ba12e4a00260f9aec8fafa0d60e0339a4d68145c4950eaab67e55e79
(7) cb3a94619a4ced15e0efea940e74c8b5c45b4af7dddc38ad50a0b474cc633ed1
(8) a3b3c325cb77497c5f6ac65a169aa9bdbdc1387d9367f5ab4d83c76b18ed2651
(9) 59b034e79634893393a58ed2be861c459c200be8622a04c267f90ad7a44607ca

HD Wallet
==================
Mnemonic:      johnny mnemonic
Base HD Path:  m/44'/60'/0'/0/{account_index}

Listening on localhost:8545

現在我們已準備好本地測試區塊鏈並等待合約。

Nethereum客戶端

與以太坊區塊鏈互動涉及幾個步驟。

  • 建立合約程式碼
  • 編譯二進位制檔案
  • 解鎖帳戶以傳送要處理的交易
  • 部署二進位制檔案
  • 與合約互動

合約程式碼

我們將使用Nethereum文件中的示例:

contract test {
    uint _multiplier;

    event Multiplied(uint indexed a, address indexed sender, uint result);

    function test(uint multiplier){
        _multiplier = multiplier;
    }

    function multiply(uint a) returns(uint r) {
        r = a * _multiplier;
        emit Multiplied(a, msg.sender, r);
        return r;
    }
}

程式碼編譯將成為下一篇文章的一部分。目前我只需複製並貼上應用程式二進位制介面(ABI)和位元組碼:)

解鎖帳戶

如果你要傳送需要支付費用的交易,則需要解鎖該帳戶。這筆費用是以gas支付的,gas價格各不相同。

在此示例中,帳戶已解鎖30分鐘,但在現實生活中,這應該更少:)

Log($"Using geth node {node}");
var web3 = new Web3(node);

Log($"Unlocking account {senderAddress}");
var unlockAccountResult = await web3.Personal.UnlockAccount.SendRequestAsync(senderAddress, senderPassword, 1200).ConfigureAwait(false);
Log($"-> Success: {unlockAccountResult}");

var funds = await web3.Eth.GetBalance.SendRequestAsync(senderAddress).ConfigureAwait(false);
Log($"Account {senderAddress} has {UnitConversion.Convert.FromWei(funds.Value)} eth");

gas估算和部署

Nethereum提供了一種方便的功能來估算函式和合約部署的gas成本。否則你需要提供任意金額(希望足夠高)。

傳送交易後,我們將等待它被挖掘:然後我們可以獲得包含交易資訊的收據:

  • 區塊號
  • 合約地址
  • 用過的gas
var gasPrice = await web3.Eth.GasPrice.SendRequestAsync().ConfigureAwait(false);
Log($"Gas price is {gasPrice.Value} wei");

var multiplier = 7;
var gasDeploy = await web3.Eth.DeployContract.EstimateGasAsync(abi, contractByteCode, senderAddress, multiplier).ConfigureAwait(false);

Log($"Deploying contract with multiplier {multiplier} using {gasDeploy.Value} gas");
var receipt = await web3.Eth.DeployContract.SendRequestAndWaitForReceiptAsync(abi, contractByteCode, senderAddress, gasDeploy, null, multiplier).ConfigureAwait(false);
Log($"-> Done at block {receipt.BlockNumber.Value} using {receipt.CumulativeGasUsed.Value} gas");
Log($"-> Contract address is {receipt.ContractAddress}");

呼叫函式

函式呼叫遵循相同的模式:估計gas,傳送交易並等待接收。

var contract = web3.Eth.GetContract(abi, receipt.ContractAddress);

var multiplyFunction = contract.GetFunction("multiply");

var gas7 = await multiplyFunction.EstimateGasAsync(7).ConfigureAwait(false);
Log($"Multiply 7 by {multiplier} using {gas7.Value} gas");
var receipt7 = await multiplyFunction.SendTransactionAndWaitForReceiptAsync(senderAddress, gas7, null, null, 7).ConfigureAwait(false);
Log($"-> Done at block {receipt7.BlockNumber.Value} using {receipt7.CumulativeGasUsed.Value} gas");

監聽事件

在監聽事件之前,我們需要為它建立一個過濾器。之後,將檢索在建立過濾器之後(或在最後一次呼叫GetFilterChanges之後)發生的事件。

Log($"Creating filter for all events");
var filterAll = await multiplyEvent.CreateFilterAsync().ConfigureAwait(false);

Log("Get all events");
var log = await multiplyEvent.GetFilterChanges<MultipliedEvent>(filterAll).ConfigureAwait(false);
Log($"-> Got {log.Count}");

foreach (var evt in log)
{
    Log($"-> Block {evt.Log.BlockNumber.Value} : {evt.Event.MultiplicationInput} * {multiplier} = {evt.Event.Result}");
}

執行客戶端和節點

執行docker-compose up --build --abort-on-container-exit將啟動兩個容器,並在客戶端完成後停止。

Attaching to samplenethereumtruffle_geth_1, samplenethereumtruffle_client_1
client_1  | Waiting 5 seconds.
geth_1    | Ganache CLI v6.1.0 (ganache-core: 2.1.0)
geth_1    |
geth_1    | Available Accounts
geth_1    | ==================
geth_1    | (0) 0x4efd4ab8293b3b8179d9dbf9ade1ae00d83eb314
geth_1    | (1) 0xaffe3d426b8517b17b54290c882f0827f65ec187
geth_1    | (2) 0x6824385051e746ef4c1c6b4ae7e56a381a95d54a
geth_1    | (3) 0x338da826cf7a3c9a68f00a9e922eeed5ca1e8211
geth_1    | (4) 0x8dcc6e12c380a80329e6108ad9b04b78e561d65a
geth_1    | (5) 0xcee6938394b0fa55c45d08ad588cd84af89a14df
geth_1    | (6) 0x70ab1d88d6980b0d192f3521f8862ac4dca68567
geth_1    | (7) 0xe20547f96055fbd2c3a2263e71cd4adb74b69349
geth_1    | (8) 0x79bef342f6bc8e0b34bcf51e55bf73611aeeb2c4
geth_1    | (9) 0xa24982b1e3c6be086465971c9e7e7e8ad44fdf48
geth_1    |
geth_1    | Private Keys
geth_1    | ==================
geth_1    | (0) 3f22cc3e1757c4a69de7e249c99e4217d4a0017157247a863cc7fb61e5a16ec8
geth_1    | (1) 8cfce94fa87c2e937d2c901b6193802900e3a9b15bdfe9aaeb1cbb9e9b46d485
geth_1    | (2) 3b9f3f9087260beb3c81a7fa105e0c0714cf30964d726a25cafb883bf3589c2e
geth_1    | (3) 14886ce9c977b5b181cfc01ded5a9f4753f4340623bed643cd7ea89a777e36e7
geth_1    | (4) c8486cd25cb5278481eef49cb689905511f0ebd77101c3f87bb25c152d8a248a
geth_1    | (5) 6ba903be3121fdacb40b677f8f5c0a400e9ff06d0632f4f9c0fcaf5ef4cf989e
geth_1    | (6) 3141fae5ba12e4a00260f9aec8fafa0d60e0339a4d68145c4950eaab67e55e79
geth_1    | (7) cb3a94619a4ced15e0efea940e74c8b5c45b4af7dddc38ad50a0b474cc633ed1
geth_1    | (8) a3b3c325cb77497c5f6ac65a169aa9bdbdc1387d9367f5ab4d83c76b18ed2651
geth_1    | (9) 59b034e79634893393a58ed2be861c459c200be8622a04c267f90ad7a44607ca
geth_1    |
geth_1    | HD Wallet
geth_1    | ==================
geth_1    | Mnemonic:      johnny mnemonic
geth_1    | Base HD Path:  m/44'/60'/0'/0/{account_index}
geth_1    |
geth_1    | Listening on localhost:8545
client_1  | Using geth node http://geth:8545
client_1  | Unlocking account 0xaffe3d426b8517b17b54290c882f0827f65ec187
geth_1    | personal_unlockAccount
client_1  | -> Success: True
geth_1    | eth_getBalance
client_1  | Account 0xaffe3d426b8517b17b54290c882f0827f65ec187 has 100 eth
geth_1    | eth_gasPrice
client_1  | Gas price is 20000000000 wei
geth_1    | eth_estimateGas
client_1  | Deploying contract with multiplier 7 using 128999 gas
geth_1    | eth_sendTransaction
geth_1    |
geth_1    |   Transaction: 0xd22f0cca420a4fb1771f800e143aec97792e71d4b3fba2b35b428bac86746c0e
geth_1    |   Contract created: 0xc080107e84a8bc84c914cd738f2c280dd3bdf693
geth_1    |   Gas usage: 128999
geth_1    |   Block Number: 1
geth_1    |   Block Time: Wed Apr 25 2018 21:38:55 GMT+0000 (UTC)
geth_1    |
geth_1    | eth_getTransactionReceipt
geth_1    | eth_getCode
client_1  | -> Done at block 1 using 128999 gas
client_1  | -> Contract address is 0xc080107e84a8bc84c914cd738f2c280dd3bdf693
client_1  | Creating filter for all events
geth_1    | eth_newFilter
geth_1    | eth_estimateGas
client_1  | Multiply 7 by 7 using 23711 gas
geth_1    | eth_sendTransaction
geth_1    |
geth_1    |   Transaction: 0x01f20d02da08cb41db016d7247e26b5bfde5908cd1d9e77634aff590b4189fd5
geth_1    |   Gas usage: 23711
geth_1    |   Block Number: 2
geth_1    |   Block Time: Wed Apr 25 2018 21:38:56 GMT+0000 (UTC)
geth_1    |
geth_1    | eth_getTransactionReceipt
client_1  | -> Done at block 2 using 23711 gas
geth_1    | eth_estimateGas
client_1  | Multiply 8 by 7 using 23711 gas
geth_1    | eth_sendTransaction
geth_1    |
geth_1    |   Transaction: 0x976f1812f5adc0c16e9625535eded5ad5ef1d396d7c99963cd138bf19d9af421
geth_1    |   Gas usage: 23711
geth_1    |   Block Number: 3
geth_1    |   Block Time: Wed Apr 25 2018 21:38:56 GMT+0000 (UTC)
geth_1    |
geth_1    | eth_getTransactionReceipt
client_1  | -> Done at block 2 using 23711 gas
client_1  | Get all events
client_1  | -> No event received
geth_1    | eth_getFilterChanges
client_1  | Done. Exiting.

沒有收到任何事件…看起來像正在實施的功能。雖然我不想等待它,但我決定看一下執行私有Geth節點。

私有geth節點

第1步:建立genesis檔案

雖然ganache-cli預設提供100eth,但是在私有Geth節點中為帳戶提供資金是通過在genesis.json檔案中新增它們來完成的。為簡單起見,我們將重用ganache帳戶。

{
  "config": {
    "chainId": 0,
    "homesteadBlock": 0,
    "eip155Block": 0,
    "eip158Block": 0
  },
  "coinbase": "0x0000000000000000000000000000000000000000",
  "difficulty": "0x20000",
  "extraData": "",
  "gasLimit": "0x2fefd8",
  "nonce": "0x0000000000000042",
  "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "timestamp": "0x00",
  "alloc": {
    "0xaffe3d426b8517b17b54290c882f0827f65ec187": {
      "balance": "0xF00000000000000000"
    }
  }
}

第2步:初始化geth節點

然後需要使用geth init命令初始化節點。如果你的網路中還有其他節點,則還需要初始化它們。

RUN geth init data/genesis_clique.json

第3步:匯入帳戶

我們需要使用geth account import命令匯入帳戶,帳戶私鑰和密碼。

RUN geth account import data/account1.key --password data/account1.pass

第4步:使用挖掘執行geth

該節點以--maxpeers = 0--nodiscover啟動,以確保沒有人可以連線到它,並且它不會分別嘗試發現。

ENTRYPOINT [ "geth", "--nodiscover", "--maxpeers=0", "--rpc", "--rpcapi=eth,web3,personal,net,miner,admin,debug", "--rpcvhosts=geth", "--rpcaddr=0.0.0.0", "--mine"

現在我們可以構建並啟動docker映象:

INFO [04-25|21:44:28] Maximum peer count                       ETH=0 LES=0 total=0
INFO [04-25|21:44:28] Starting peer-to-peer node               instance=Geth/v1.8.6-stable/linux-amd64/go1.10.1
INFO [04-25|21:44:28] Allocated cache and file handles         database=/root/.ethereum/geth/chaindata cache=768 handles=1024
WARN [04-25|21:44:28] Upgrading database to use lookup entries
INFO [04-25|21:44:28] Initialised chain configuration          config="{ChainID: 0 Homestead: 0 DAO: <nil> DAOSupport: false EIP150: <nil> EIP155: 0 EIP158: 0 Byzantium: <nil> Constantinople: <nil> Engine: unknown}"
INFO [04-25|21:44:28] Database deduplication successful        deduped=0
INFO [04-25|21:44:28] Disk storage enabled for ethash caches   dir=/root/.ethereum/geth/ethash count=3
INFO [04-25|21:44:28] Disk storage enabled for ethash DAGs     dir=/root/.ethash               count=2
INFO [04-25|21:44:28] Initialising Ethereum protocol           versions="[63 62]" network=1
INFO [04-25|21:44:28] Loaded most recent local header          number=0 hash=1092ae…35e2af td=131072
INFO [04-25|21:44:28] Loaded most recent local full block      number=0 hash=1092ae…35e2af td=131072
INFO [04-25|21:44:28] Loaded most recent local fast block      number=0 hash=1092ae…35e2af td=131072
INFO [04-25|21:44:28] Regenerated local transaction journal    transactions=0 accounts=0
INFO [04-25|21:44:28] Starting P2P networking
INFO [04-25|21:44:28] RLPx listener up                         self="enode://2c62fe87d0f270b5fe143235b471d224ad59859ba8ede6272c183f13f168014f9[email protected][::]:30303?discport=0"
INFO [04-25|21:44:28] IPC endpoint opened                      url=/root/.ethereum/geth.ipc
INFO [04-25|21:44:28] HTTP endpoint opened                     url=http://0.0.0.0:8545      cors= vhosts=geth
INFO [04-25|21:44:30] Unlocked account                         address=0x4EFD4Ab8293b3B8179d9DBF9Ade1Ae00D83EB314
INFO [04-25|21:44:30] Transaction pool price threshold updated price=18000000000
INFO [04-25|21:44:30] Etherbase automatically configured       address=0x4EFD4Ab8293b3B8179d9DBF9Ade1Ae00D83EB314
INFO [04-25|21:44:30] Starting mining operation
INFO [04-25|21:44:30] Commit new mining work                   number=1 txs=0 uncles=0 elapsed=1.633ms
INFO [04-25|21:44:33] Generating ethash verification cache     epoch=0 percentage=34 elapsed=3.025s
INFO [04-25|21:44:36] Generated ethash verification cache      epoch=0 elapsed=5.832s
INFO [04-25|21:44:41] Generating DAG in progress               epoch=0 percentage=0  elapsed=4.700s
INFO [04-25|21:44:45] Generating DAG in progress               epoch=0 percentage=1  elapsed=9.534s
INFO [04-25|21:44:50] Generating DAG in progress               epoch=0 percentage=2  elapsed=14.181s
INFO [04-25|21:44:55] Generating DAG in progress               epoch=0 percentage=3  elapsed=18.879s
INFO [04-25|21:45:00] Generating DAG in progress               epoch=0 percentage=4  elapsed=23.663s
INFO [04-25|21:45:04] Generating DAG in progress               epoch=0 percentage=5  elapsed=28.397s
INFO [04-25|21:45:11] Generating DAG in progress               epoch=0 percentage=6  elapsed=34.842s

看起來需要花一些時間…

準備以太坊DAG(定向非迴圈圖)需要花費大量時間。當然,不是我的樣本開始時我願意等待的。希望有另一種共識演算法可用!

用geth進行許可權挖掘的證明

這種設定更復雜,但是由於這篇很棒的文章,它也被記錄下來了。

第1步:更新genesis檔案

最簡單的是使用puppeth建立genesis.json檔案。我們將使用PoA和兩個帳戶。其中一個將是用於驗證塊的1個帳戶。

不帶引數執行會開啟一個shell,我們就可以開始玩弄了。

$ docker run -ti mathieubrun/geth-alltools
/ # puppeth
+-----------------------------------------------------------+
| Welcome to puppeth, your Ethereum private network manager |
|                                                           |
| This tool lets you create a new Ethereum network down to  |
| the genesis block, bootnodes, miners and ethstats servers |
| without the hassle that it would normally entail.         |
|                                                           |
| Puppeth uses SSH to dial in to remote servers, and builds |
| its network components out of Docker containers using the |
| docker-compose toolset.                                   |
+-----------------------------------------------------------+

Please specify a network name to administer (no spaces or hyphens, please)
> SampleNet

Sweet, you can set this via --network=SampleNet next time!

INFO [04-26|22:59:43] Administering Ethereum network           name=SampleNet
WARN [04-26|22:59:43] No previous configurations found         path=/root/.puppeth/SampleNet

What would you like to do? (default = stats)
 1. Show network stats
 2. Configure new genesis
 3. Track new remote server
 4. Deploy network components
> 2

Which consensus engine to use? (default = clique)
 1. Ethash - proof-of-work
 2. Clique - proof-of-authority
> 2

How many seconds should blocks take? (default = 15)
> 5

Which accounts are allowed to seal? (mandatory at least one)
> 0x4efd4ab8293b3b8179d9dbf9ade1ae00d83eb314
> 0xaffe3d426b8517b17b54290c882f0827f65ec187
> 0x

Which accounts should be pre-funded? (advisable at least one)
> 0xaffe3d426b8517b17b54290c882f0827f65ec187
> 0x

Specify your chain/network ID if you want an explicit one (default = random)
>
INFO [04-26|23:00:44] Configured new genesis block

What would you like to do? (default = stats)
 1. Show network stats
 2. Manage existing genesis
 3. Track new remote server
 4. Deploy network components
> ^C
/ #

建立的genesis檔案將位於~/.puppeth資料夾中。你可以注意到帳戶是在extradata欄位中設定的。

{
  "config": {
    "chainId": 26341,
    "homesteadBlock": 1,
    "eip150Block": 2,
    "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "eip155Block": 3,
    "eip158Block": 3,
    "byzantiumBlock": 4,
    "clique": {
      "period": 5,
      "epoch": 30000
    }
  },
  "nonce": "0x0",
  "timestamp": "0x5ae0e24c",
  "extraData": "0x00000000000000000000000000000000000000000000000000000000000000004efd4ab8293b3b8179d9dbf9ade1ae00d83eb3140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "gasLimit": "0x47b760",
  "difficulty": "0x1",
  "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "coinbase": "0x0000000000000000000000000000000000000000",
  "alloc": {
    "0x4efd4ab8293b3b8179d9dbf9ade1ae00d83eb314": {
      "balance": "0x1"
    },
    "0xaffe3d426b8517b17b54290c882f0827f65ec187": {
      "balance": "0xF00000000000000000"
    }
  }
}

第2步:匯入帳戶

要重新使用帳戶,我們需要使用geth account import命令匯入帳戶,並使用帳戶私鑰和密碼。

RUN geth account import data/account1.key --password data/account1.pass
RUN geth account import data/account2.key --password data/account2.pass

第3步:使用挖掘執行geth

在執行geth時必須解鎖用於塊的帳戶,因此我們將其新增到geth引數中。

ENTRYPOINT [ "geth", "--nodiscover", "-unlock=4efd4ab8293b3b8179d9dbf9ade1ae00d83eb314", "--password=data/account1.pass", "--maxpeers=0", "--rpc", "--rpcapi=eth,web3,personal,net,miner,admin,debug", "--rpcvhosts=geth", "--rpcaddr=0.0.0.0", "--mine" ]

封裝

再次執行客戶端和節點:

Attaching to samplenethereumtruffle_client_1, samplenethereumtruffle_geth_1
geth_1    | INFO [04-25|22:01:06] Maximum peer count                       ETH=0 LES=0 total=0
geth_1    | INFO [04-25|22:01:06] Starting peer-to-peer node               instance=Geth/v1.8.6-stable/linux-amd64/go1.10.1
geth_1    | INFO [04-25|22:01:06] Allocated cache and file handles         database=/root/.ethereum/geth/chaindata cache=768 handles=1024
geth_1    | WARN [04-25|22:01:06] Upgrading database to use lookup entries
geth_1    | INFO [04-25|22:01:06] Initialised chain configuration          config="{ChainID: 26341 Homestead: 1 DAO: <nil> DAOSupport: false EIP150: 2 EIP155: 3 EIP158: 3 Byzantium: 4 Constantinople: <nil> Engine: clique}"
geth_1    | INFO [04-25|22:01:06] Initialising Ethereum protocol           versions="[63 62]" network=1
geth_1    | INFO [04-25|22:01:06] Loaded most recent local header          number=0 hash=030bd8…18932b td=1
geth_1    | INFO [04-25|22:01:06] Loaded most recent local full block      number=0 hash=030bd8…18932b td=1
geth_1    | INFO [04-25|22:01:06] Loaded most recent local fast block      number=0 hash=030bd8…18932b td=1
geth_1    | INFO [04-25|22:01:06] Database deduplication successful        deduped=0
geth_1    | INFO [04-25|22:01:06] Regenerated local transaction journal    transactions=0 accounts=0
geth_1    | INFO [04-25|22:01:06] Starting P2P networking
geth_1    | INFO [04-25|22:01:06] RLPx listener up                         self="enode://2ffed0c407c0e73cfd16379cb74acb022848079bde49102abff6359466fbf416c[email protected][::]:30303?discport=0"
geth_1    | INFO [04-25|22:01:06] IPC endpoint opened                      url=/root/.ethereum/geth.ipc
geth_1    | INFO [04-25|22:01:06] HTTP endpoint opened                     url=http://0.0.0.0:8545      cors= vhosts=geth
client_1  | Waiting 5 seconds.
geth_1    | INFO [04-25|22:01:08] Unlocked account                         address=0x4EFD4Ab8293b3B8179d9DBF9Ade1Ae00D83EB314
geth_1    | INFO [04-25|22:01:08] Transaction pool price threshold updated price=18000000000
geth_1    | INFO [04-25|22:01:08] Etherbase automatically configured       address=0x4EFD4Ab8293b3B8179d9DBF9Ade1Ae00D83EB314
geth_1    | INFO [04-25|22:01:08] Starting mining operation
geth_1    | INFO [04-25|22:01:08] Commit new mining work                   number=1 txs=0 uncles=0 elapsed=883.6µs
geth_1    | INFO [04-25|22:01:08] Successfully sealed new block            number=1 hash=bfacd2…60b0f4
geth_1    | INFO [04-25|22:01:08] ? mined potential block                  number=1 hash=bfacd2…60b0f4
geth_1    | INFO [04-25|22:01:08] Commit new mining work                   number=2 txs=0 uncles=0 elapsed=1.900ms
client_1  | Using geth node http://geth:8545
client_1  | Unlocking account 0xaffe3d426b8517b17b54290c882f0827f65ec187
geth_1    | INFO [04-25|22:01:13] Successfully sealed new block            number=2 hash=4848c2…ac8e4c
geth_1    | INFO [04-25|22:01:13] ? mined potential block                  number=2 hash=4848c2…ac8e4c
geth_1    | INFO [04-25|22:01:13] Commit new mining work                   number=3 txs=0 uncles=0 elapsed=1.515ms
client_1  | -> Success: True
client_1  | Account 0xaffe3d426b8517b17b54290c882f0827f65ec187 has 4427.21857769029238784 eth
client_1  | Gas price is 18000000000 wei
geth_1    | INFO [04-25|22:01:18] Successfully sealed new block            number=3 hash=83444a…1d4845
geth_1    | INFO [04-25|22:01:18] ? mined potential block                  number=3 hash=83444a…1d4845
geth_1    | INFO [04-25|22:01:18] Commit new mining work                   number=4 txs=0 uncles=0 elapsed=1.38ms
client_1  | Deploying contract with multiplier 7 using 128999 gas
geth_1    | INFO [04-25|22:01:18] Submitted contract creation              fullhash=0xd76e791c4e2066b84a2786a392859575d32ca7075019ed54e5179f79236cb3dc contract=0xc080107e84a8bc84C914cd738f2c280dd3Bdf693
geth_1    | INFO [04-25|22:01:23] Successfully sealed new block            number=4 hash=5447bc…dc83df
geth_1    | INFO [04-25|22:01:23] ? mined potential block                  number=4 hash=5447bc…dc83df
geth_1    | INFO [04-25|22:01:23] Commit new mining work                   number=5 txs=1 uncles=0 elapsed=3.755ms
geth_1    | INFO [04-25|22:01:28] Successfully sealed new block            number=5 hash=630233…aadcd8
geth_1    | INFO [04-25|22:01:28] ? mined potential block                  number=5 hash=630233…aadcd8
geth_1    | INFO [04-25|22:01:28] Commit new mining work                   number=6 txs=0 uncles=0 elapsed=2.605ms
client_1  | -> Done at block 5 using 128999 gas
client_1  | -> Contract address is 0xc080107e84a8bc84c914cd738f2c280dd3bdf693
client_1  | Creating filter for all events
client_1  | Multiply 7 by 7 using 23711 gas
geth_1    | INFO [04-25|22:01:28] Submitted transaction                    fullhash=0x4bfe9e2b033709a2d0738a79915debd3434f0c19acc004111e6b57bb3ea2aa6b recipient=0xc080107e84a8bc84C914cd738f2c280dd3Bdf693
geth_1    | INFO [04-25|22:01:33] Successfully sealed new block            number=6 hash=5bec46…9c0871
geth_1    | INFO [04-25|22:01:33] ? block reached canonical chain          number=1 hash=bfacd2…60b0f4
geth_1    | INFO [04-25|22:01:33] ? mined potential block                  number=6 hash=5bec46…9c0871
geth_1    | INFO [04-25|22:01:33] Commit new mining work                   number=7 txs=1 uncles=0 elapsed=3.344ms
geth_1    | INFO [04-25|22:01:38] Successfully sealed new block            number=7 hash=82325a…b6dfaa
geth_1    | INFO [04-25|22:01:38] ? block reached canonical chain          number=2 hash=4848c2…ac8e4c
geth_1    | INFO [04-25|22:01:38] ? mined potential block                  number=7 hash=82325a…b6dfaa
geth_1    | INFO [04-25|22:01:38] Commit new mining work                   number=8 txs=0 uncles=0 elapsed=3.350ms
client_1  | -> Done at block 7 using 23711 gas
client_1  | Multiply 8 by 7 using 23711 gas
geth_1    | INFO [04-25|22:01:38] Submitted transaction                    fullhash=0x41c620c8003cfe15054b061e6178241bf3478fb5ac0ece2d9b1b4afea8d597ce recipient=0xc080107e84a8bc84C914cd738f2c280dd3Bdf693
geth_1    | INFO [04-25|22:01:43] Successfully sealed new block            number=8 hash=ce5a93…c20a2d
geth_1    | INFO [04-25|22:01:43] ? block reached canonical chain          number=3 hash=83444a…1d4845
geth_1    | INFO [04-25|22:01:43] ? mined potential block                  number=8 hash=ce5a93…c20a2d
geth_1    | INFO [04-25|22:01:43] Commit new mining work                   number=9 txs=1 uncles=0 elapsed=1.869ms
geth_1    | INFO [04-25|22:01:48] Successfully sealed new block            number=9 hash=96fc79…d8a93e
geth_1    | INFO [04-25|22:01:48] ? block reached canonical chain          number=4 hash=5447bc…dc83df
geth_1    | INFO [04-25|22:01:48] ? mined potential block                  number=9 hash=96fc79…d8a93e
geth_1    | INFO [04-25|22:01:48] Commit new mining work                   number=10 txs=0 uncles=0 elapsed=1.492ms
client_1  | -> Done at block 7 using 23711 gas
client_1  | Get all events
client_1  | -> Block 7 : 7 * 7 = 49
client_1  | -> Block 9 : 8 * 7 = 56
client_1  | Done. Exiting.

最後!我們現在有一個非常簡單的專案,它可以部署合約,與之互動,並監聽事件!

本文的原始碼庫位於Github上。

如果希望快速進行以太坊開發,那請看我們精心打造的教程:

C#以太坊

其他區塊鏈教程如下:

  • 以太坊開發進階教程,主要是介紹使用node.js、mongodb、區塊鏈、ipfs實現去中心化電商DApp實戰,適合進階。
  • java以太坊開發教程,主要是針對java和android程式設計師進行區塊鏈以太坊開發的web3j詳解。
  • python以太坊,主要是針對python工程師使用web3.py進行區塊鏈以太坊開發的詳解。
  • php以太坊,主要是介紹使用php進行智慧合約開發互動,進行賬號建立、交易、轉賬、代幣開發以及過濾器和事件等內容。
  • 以太坊入門教程,主要介紹智慧合約與dapp應用開發,適合入門。,主要講解如何使用C#開發基於.Net的以太坊應用,包括賬戶管理、狀態與交易、智慧合約開發與互動、過濾器和事件等。
  • php比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈儲存、去中心化共識機制、金鑰與指令碼、交易與UTXO等,同時也詳細講解如何在Php程式碼中整合比特幣支援功能,例如建立地址、管理錢包、構造裸交易等,是Php工程師不可多得的比特幣開發學習課程。
  • java比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈儲存、去中心化共識機制、金鑰與指令碼、交易與UTXO等,同時也詳細講解如何在Java程式碼中整合比特幣支援功能,例如建立地址、管理錢包、構造裸交易等,是Java工程師不可多得的比特幣開發學習課程。
  • EOS入門教程,本課程幫助你快速入門EOS區塊鏈去中心化應用的開發,內容涵蓋EOS工具鏈、賬戶與錢包、發行代幣、智慧合約開發與部署、使用程式碼與智慧合約互動等核心知識點,最後綜合運用各知識點完成一個便籤DApp的開發。

匯智網原創翻譯,轉載請標明出處。這裡是原文