Go-Ethereum

當我嘗試使用 web3 連接到 geth 時出現問題

  • December 1, 2016

程式碼

  • 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 種不同的可能場景:

  1. 一切正常。腳本輸出:
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
  1. 我無法連接到節點: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
  1. 此行的連接失敗:
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')

刪除此導入並在另一個腳本中編譯我的契約可解決此問題。

引用自:https://ethereum.stackexchange.com/questions/9796