Go-Ethereum
當我嘗試使用 web3 連接到 geth 時出現問題
程式碼
- geth 版本:v1.4.18-stable/linux/go1.5.1
- web3 版本:0.17.0-alpha
這是我在 docker 容器中啟動以執行 geth 的腳本:
#! /bin/bash genesis_json_file=development/genesis_config/genesis_block.json default_password=development/genesis_config/default_password # contain the password "toto" datadir=data rm -rf $datadir/* geth --datadir $datadir init $genesis_json_file geth --password $default_password --datadir $datadir account new geth --datadir $datadir --mine --minerthreads 1 --rpc --rpcaddr "0.0.0.0" --rpcapi "eth,web3,personal"
現在,我可以從我的主機系統訪問 geth API:
$ curl http://0.0.0.0:8545 > {"jsonrpc":"2.0","error":{"code":-32600,"message":"EOF"}}
當我嘗試使用 web3 連接到 geth 時,有時會出現問題。這是我的 js 腳本:
function connect(host, port) { uri = 'http://' + host + ':' + port; if (typeof web3 !== 'undefined') { web3 = new Web3(web3.currentProvider); } else { /* set the provider you want from Web3.providers */ process.stdout.write('Setting Http provider : ' + uri + "\n") var prov = new Web3.providers.HttpProvider(uri); web3 = new Web3(prov); } if(!web3.isConnected()) { process.stdout.write('Cannot reach ' + uri + "\n"); return false; } else { process.stdout.write('Connected to ' + uri + "\n"); return true; } } function compile_contract(file_path) { # No problem here # This return the compiled contract ... } function send_contract_handler(e, contract) { if (e){ console.log('send contract ERR : ' + e); } else if (typeof contract.address === 'undefined') { console.log("Contract transaction send. Hash: " + contract.transactionHash); console.log('Waiting for mining process'); } else{ console.log('Contract mined! address: ' + contract.address); } } function send_contract(from_addr, contract) { /* Unlock account */ web3.eth.defaultAccount = from_addr; var ret = web3.personal.unlockAccount(from_addr, 'toto'); /* Get account balance */ var balance = web3.eth.getBalance(from_addr); /* Ask for a gas price estimation to send the contract */ var estimation = web3.eth.estimateGas({ from: from_addr, data: contract.bytecode }); /* Check if the sender account has enough gas */ if (estimation > parseInt(balance.toString(10))) console.log('estimation to high : not enought gas'); /* Send the contract creation transaction to the block chain */ return web3.eth.contract(JSON.parse(contract.interface)).new( { from: from_addr, data: contract.bytecode, gas: estimation }, send_contract_handler ); } if (require.main === module) { /* Connect to a running node */ while (!connect('0.0.0.0', 8545)); /* Compile contract */ var output = compile_contract(contractPath); if (!output) return 2; /* Send contract using the coinbase addr */ return send_contract(web3.eth.coinbase, output); }
問題
當我執行這個腳本時,對於相同的程式碼,我有 3 種不同的可能場景:
- 一切正常。腳本輸出:
Setting Http provider : http://0.0.0.0:8545 Connected to http://0.0.0.0:8545 ./contract/simple.sol will be compiled from_addr : 0x5b481d0f036af15ec3025fed428cdd49b45b4a3e Contract transaction send. Hash: 0x95cf8c756860605cefd5ef89fe673fa3a267dfb66766cf4a0d38b94194053935 Waiting for mining process Contract mined! address: 0x4af7d1639f590dfc9e5594a3ba0bb9ead17a14bc
- 我無法連接到節點:web3.isConnected() 總是返回 false。腳本輸出:
Cannot reach http://0.0.0.0:8545 Cannot reach http://0.0.0.0:8545 ... Cannot reach http://0.0.0.0:8545
- 此行的連接失敗:
var balance = web3.eth.getBalance(from_addr);
腳本輸出:
Setting Http provider : http://0.0.0.0:8545 Connected to http://0.0.0.0:8545 ./contract/simple.sol will be compiled from_addr : 0x5b481d0f036af15ec3025fed428cdd49b45b4a3e /home/xxx/node_modules/solc/soljson.js:1 (function (exports, require, module, __filename, __dirname) { var Module;if(!Module)Module=(typeof Module!=="undefined"?Module:null)||{};var moduleOverrides={};for(var key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var ENVIRONMENT_IS_WEB=typeof window==="object";var ENVIRONMENT_IS_WORKER=typeof importScripts==="function";var ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof require==="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;var ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(ENVIRONMENT_IS_NODE){if(!Module["print"])Module["print"]=function print(x){process["stdout"].write(x+"\n")};if(!Module["printErr"])Module["printErr"]=function printErr(x){process["stderr"].write(x+"\n")};var nodeFS=require("fs");var nodePath=require("path");Module["read"]=function read(filename,binary){filename=nodePath["normalize"](filename);var ret=nodeFS["readFileSync"](fi Error: CONNECTION ERROR: Couldn't connect to node http://0.0.0.0:8545. at Object.InvalidConnection (/home/xxx/node_modules/web3/lib/web3/errors.js:28:16) at HttpProvider.send (/home/xxx/node_modules/web3/lib/web3/httpprovider.js:75:22) at RequestManager.send (/home/xxx/node_modules/web3/lib/web3/requestmanager.js:58:32) at Eth.send [as getBalance] (/home/xxx/node_modules/web3/lib/web3/method.js:145:58) at send_contract (/home/xxx/myscript.js:76:26) at Object.<anonymous> (/home/xxx/myscript.js:108:10) at Module._compile (module.js:556:32) at Object.Module._extensions..js (module.js:565:10) at Module.load (module.js:473:32) at tryModuleLoad (module.js:432:12)
提示
- 場景 1 是最常見的場景。這通常發生在我剛重新啟動電腦時
- 場景 2 - 3 通常在一些成功嘗試後出現
- 即使在場景 2 - 3 中,我也可以使用 curl 或 telnet 訪問 get API
這似乎是網路問題或geth中的不良狀態……
很抱歉這個冗長且不精確的問題。如果有人知道為什麼會發生這種情況,或者調試它的好方法,他將受到歡迎!
我沒有具體的解釋,但我注意到如果執行了以下行,則會出現此錯誤:
var solc = require('solc')
刪除此導入並在另一個腳本中編譯我的契約可解決此問題。