replaces dependency on go-ethereum "cmd/*" packages. Fixes #72

This commit is contained in:
Victor Farazdagi 2016-12-08 00:07:08 +03:00
parent 09d021e598
commit e5bb6a24f7
17 changed files with 574 additions and 321 deletions

View File

@ -81,6 +81,11 @@ test-extkeys:
@build/env.sh go tool cover -html=coverage.out -o coverage.html @build/env.sh go tool cover -html=coverage.out -o coverage.html
@build/env.sh go tool cover -func=coverage.out @build/env.sh go tool cover -func=coverage.out
test-cmd:
build/env.sh go test -v -coverprofile=coverage.out ./cmd/status
@build/env.sh go tool cover -html=coverage.out -o coverage.html
@build/env.sh go tool cover -func=coverage.out
clean: clean:
rm -fr build/bin/* rm -fr build/bin/*
rm coverage.out coverage-all.out coverage.html rm coverage.out coverage-all.out coverage.html

View File

@ -9,5 +9,5 @@ fi
# set gitCommit when running from a Git checkout. # set gitCommit when running from a Git checkout.
if [ -f ".git/HEAD" ]; then if [ -f ".git/HEAD" ]; then
echo "-ldflags '-X github.com/status-im/status-go/geth.UseTestnet=false -X main.buildStamp=`date -u '+%Y-%m-%d.%H:%M:%S'` -X main.gitCommit=$(git rev-parse HEAD)'"; echo "-ldflags '-X github.com/status-im/status-go/geth.UseTestnetFlag=false -X main.buildStamp=`date -u '+%Y-%m-%d.%H:%M:%S'` -X main.gitCommit=$(git rev-parse HEAD)'";
fi fi

View File

@ -9,5 +9,5 @@ fi
# set gitCommit when running from a Git checkout. # set gitCommit when running from a Git checkout.
if [ -f ".git/HEAD" ]; then if [ -f ".git/HEAD" ]; then
echo "-ldflags '-X github.com/status-im/status-go/geth.UseTestnet=true -X main.buildStamp=`date -u '+%Y-%m-%d.%H:%M:%S'` -X main.gitCommit=$(git rev-parse HEAD)'"; echo "-ldflags '-X github.com/status-im/status-go/geth.UseTestnetFlag=true -X main.buildStamp=`date -u '+%Y-%m-%d.%H:%M:%S'` -X main.gitCommit=$(git rev-parse HEAD)'";
fi fi

View File

@ -235,7 +235,7 @@ func Call(chatId *C.char, path *C.char, params *C.char) *C.char {
//export AddPeer //export AddPeer
func AddPeer(url *C.char) *C.char { func AddPeer(url *C.char) *C.char {
success, err := geth.GetNodeManager().AddPeer(C.GoString(url)) success, err := geth.NodeManagerInstance().AddPeer(C.GoString(url))
errString := "" errString := ""
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)

View File

@ -8,23 +8,18 @@ import (
var ( var (
gitCommit = "rely on linker: -ldflags -X main.GitCommit" gitCommit = "rely on linker: -ldflags -X main.GitCommit"
buildStamp = "rely on linker: -ldflags -X main.buildStamp" buildStamp = "rely on linker: -ldflags -X main.buildStamp"
versionMajor = 1 // Major version component of the current release
versionMinor = 1 // Minor version component of the current release
versionPatch = 0 // Patch version component of the current release
versionMeta = "unstable" // Version metadata to append to the version string
) )
func main() { func main() {
verString := fmt.Sprintf("%d.%d.%d", versionMajor, versionMinor, versionPatch) verString := fmt.Sprintf("%d.%d.%d", geth.VersionMajor, geth.VersionMinor, geth.VersionPatch)
if versionMeta != "" { if geth.VersionMeta != "" {
verString += "-" + versionMeta verString += "-" + geth.VersionMeta
} }
if gitCommit != "" { if gitCommit != "" {
verString += "-" + gitCommit[:8] verString += "-" + gitCommit[:8]
} }
netVersion := "mainnet" netVersion := "mainnet"
if geth.UseTestnet == "true" { if geth.UseTestnet {
netVersion = "testnet" netVersion = "testnet"
} }
fmt.Printf("Status\nGit Commit: %s\nBuild Time: %s\nVersion: %s\nNetwork: %s\n", fmt.Printf("Status\nGit Commit: %s\nBuild Time: %s\nVersion: %s\nNetwork: %s\n",

View File

@ -11,7 +11,6 @@ import (
"testing" "testing"
"time" "time"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/les/status" "github.com/ethereum/go-ethereum/les/status"
@ -90,7 +89,7 @@ func testExportedAPI(t *testing.T, done chan struct{}) {
func testCreateChildAccount(t *testing.T) bool { func testCreateChildAccount(t *testing.T) bool {
geth.Logout() // to make sure that we start with empty account (which might get populated during previous tests) geth.Logout() // to make sure that we start with empty account (which might get populated during previous tests)
accountManager, err := geth.GetNodeManager().AccountManager() accountManager, err := geth.NodeManagerInstance().AccountManager()
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return false return false
@ -112,7 +111,7 @@ func testCreateChildAccount(t *testing.T) bool {
address, pubKey, mnemonic := createAccountResponse.Address, createAccountResponse.PubKey, createAccountResponse.Mnemonic address, pubKey, mnemonic := createAccountResponse.Address, createAccountResponse.PubKey, createAccountResponse.Mnemonic
t.Logf("Account created: {address: %s, key: %s, mnemonic:%s}", address, pubKey, mnemonic) t.Logf("Account created: {address: %s, key: %s, mnemonic:%s}", address, pubKey, mnemonic)
account, err := utils.MakeAddress(accountManager, address) account, err := geth.ParseAccountString(accountManager, address)
if err != nil { if err != nil {
t.Errorf("can not get account from address: %v", err) t.Errorf("can not get account from address: %v", err)
return false return false
@ -221,7 +220,7 @@ func testCreateChildAccount(t *testing.T) bool {
} }
func testRecoverAccount(t *testing.T) bool { func testRecoverAccount(t *testing.T) bool {
accountManager, _ := geth.GetNodeManager().AccountManager() accountManager, _ := geth.NodeManagerInstance().AccountManager()
// create an account // create an account
address, pubKey, mnemonic, err := geth.CreateAccount(newAccountPassword) address, pubKey, mnemonic, err := geth.CreateAccount(newAccountPassword)
@ -250,7 +249,7 @@ func testRecoverAccount(t *testing.T) bool {
} }
// now test recovering, but make sure that account/key file is removed i.e. simulate recovering on a new device // now test recovering, but make sure that account/key file is removed i.e. simulate recovering on a new device
account, err := utils.MakeAddress(accountManager, address) account, err := geth.ParseAccountString(accountManager, address)
if err != nil { if err != nil {
t.Errorf("can not get account from address: %v", err) t.Errorf("can not get account from address: %v", err)
} }
@ -312,7 +311,7 @@ func testRecoverAccount(t *testing.T) bool {
} }
// time to login with recovered data // time to login with recovered data
whisperService, err := geth.GetNodeManager().WhisperService() whisperService, err := geth.NodeManagerInstance().WhisperService()
if err != nil { if err != nil {
t.Errorf("whisper service not running: %v", err) t.Errorf("whisper service not running: %v", err)
} }
@ -335,7 +334,7 @@ func testRecoverAccount(t *testing.T) bool {
func testAccountSelect(t *testing.T) bool { func testAccountSelect(t *testing.T) bool {
// test to see if the account was injected in whisper // test to see if the account was injected in whisper
whisperService, err := geth.GetNodeManager().WhisperService() whisperService, err := geth.NodeManagerInstance().WhisperService()
if err != nil { if err != nil {
t.Errorf("whisper service not running: %v", err) t.Errorf("whisper service not running: %v", err)
} }
@ -418,7 +417,7 @@ func testAccountSelect(t *testing.T) bool {
} }
func testAccountLogout(t *testing.T) bool { func testAccountLogout(t *testing.T) bool {
whisperService, err := geth.GetNodeManager().WhisperService() whisperService, err := geth.NodeManagerInstance().WhisperService()
if err != nil { if err != nil {
t.Errorf("whisper service not running: %v", err) t.Errorf("whisper service not running: %v", err)
return false return false
@ -472,7 +471,7 @@ func testAccountLogout(t *testing.T) bool {
func testCompleteTransaction(t *testing.T) bool { func testCompleteTransaction(t *testing.T) bool {
// obtain reference to status backend // obtain reference to status backend
lightEthereum, err := geth.GetNodeManager().LightEthereumService() lightEthereum, err := geth.NodeManagerInstance().LightEthereumService()
if err != nil { if err != nil {
t.Errorf("Test failed: LES service is not running: %v", err) t.Errorf("Test failed: LES service is not running: %v", err)
return false return false
@ -551,7 +550,7 @@ func testCompleteTransaction(t *testing.T) bool {
func testCompleteMultipleQueuedTransactions(t *testing.T) bool { func testCompleteMultipleQueuedTransactions(t *testing.T) bool {
// obtain reference to status backend // obtain reference to status backend
lightEthereum, err := geth.GetNodeManager().LightEthereumService() lightEthereum, err := geth.NodeManagerInstance().LightEthereumService()
if err != nil { if err != nil {
t.Errorf("Test failed: LES service is not running: %v", err) t.Errorf("Test failed: LES service is not running: %v", err)
return false return false
@ -680,7 +679,7 @@ func testCompleteMultipleQueuedTransactions(t *testing.T) bool {
func testDiscardTransaction(t *testing.T) bool { func testDiscardTransaction(t *testing.T) bool {
// obtain reference to status backend // obtain reference to status backend
lightEthereum, err := geth.GetNodeManager().LightEthereumService() lightEthereum, err := geth.NodeManagerInstance().LightEthereumService()
if err != nil { if err != nil {
t.Errorf("Test failed: LES service is not running: %v", err) t.Errorf("Test failed: LES service is not running: %v", err)
return false return false
@ -794,7 +793,7 @@ func testDiscardTransaction(t *testing.T) bool {
func testDiscardMultipleQueuedTransactions(t *testing.T) bool { func testDiscardMultipleQueuedTransactions(t *testing.T) bool {
// obtain reference to status backend // obtain reference to status backend
lightEthereum, err := geth.GetNodeManager().LightEthereumService() lightEthereum, err := geth.NodeManagerInstance().LightEthereumService()
if err != nil { if err != nil {
t.Errorf("Test failed: LES service is not running: %v", err) t.Errorf("Test failed: LES service is not running: %v", err)
return false return false

View File

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/status-im/status-go/extkeys" "github.com/status-im/status-go/extkeys"
@ -20,6 +19,7 @@ var (
ErrWhisperNoIdentityFound = errors.New("failed to locate identity previously injected into Whisper") ErrWhisperNoIdentityFound = errors.New("failed to locate identity previously injected into Whisper")
ErrNoAccountSelected = errors.New("no account has been selected, please login") ErrNoAccountSelected = errors.New("no account has been selected, please login")
ErrInvalidMasterKeyCreated = errors.New("can not create master extended key") ErrInvalidMasterKeyCreated = errors.New("can not create master extended key")
ErrInvalidAccountAddressOrKey = errors.New("cannot parse address or key to valid account address")
) )
// CreateAccount creates an internal geth account // CreateAccount creates an internal geth account
@ -53,7 +53,7 @@ func CreateAccount(password string) (address, pubKey, mnemonic string, err error
// CKD#2 is used as root for master accounts (when parentAddress is ""). // CKD#2 is used as root for master accounts (when parentAddress is "").
// Otherwise (when parentAddress != ""), child is derived directly from parent. // Otherwise (when parentAddress != ""), child is derived directly from parent.
func CreateChildAccount(parentAddress, password string) (address, pubKey string, err error) { func CreateChildAccount(parentAddress, password string) (address, pubKey string, err error) {
nodeManager := GetNodeManager() nodeManager := NodeManagerInstance()
accountManager, err := nodeManager.AccountManager() accountManager, err := nodeManager.AccountManager()
if err != nil { if err != nil {
return "", "", err return "", "", err
@ -67,7 +67,7 @@ func CreateChildAccount(parentAddress, password string) (address, pubKey string,
return "", "", ErrNoAccountSelected return "", "", ErrNoAccountSelected
} }
account, err := utils.MakeAddress(accountManager, parentAddress) account, err := ParseAccountString(accountManager, parentAddress)
if err != nil { if err != nil {
return "", "", ErrAddressToAccountMappingFailure return "", "", ErrAddressToAccountMappingFailure
} }
@ -128,13 +128,13 @@ func RecoverAccount(password, mnemonic string) (address, pubKey string, err erro
// using provided password. Once verification is done, decrypted key is injected into Whisper (as a single identity, // using provided password. Once verification is done, decrypted key is injected into Whisper (as a single identity,
// all previous identities are removed). // all previous identities are removed).
func SelectAccount(address, password string) error { func SelectAccount(address, password string) error {
nodeManager := GetNodeManager() nodeManager := NodeManagerInstance()
accountManager, err := nodeManager.AccountManager() accountManager, err := nodeManager.AccountManager()
if err != nil { if err != nil {
return err return err
} }
account, err := utils.MakeAddress(accountManager, address) account, err := ParseAccountString(accountManager, address)
if err != nil { if err != nil {
return ErrAddressToAccountMappingFailure return ErrAddressToAccountMappingFailure
} }
@ -169,7 +169,7 @@ func SelectAccount(address, password string) error {
// Logout clears whisper identities // Logout clears whisper identities
func Logout() error { func Logout() error {
nodeManager := GetNodeManager() nodeManager := NodeManagerInstance()
whisperService, err := nodeManager.WhisperService() whisperService, err := nodeManager.WhisperService()
if err != nil { if err != nil {
return err return err
@ -195,7 +195,7 @@ func UnlockAccount(address, password string, seconds int) error {
// importExtendedKey processes incoming extended key, extracts required info and creates corresponding account key. // importExtendedKey processes incoming extended key, extracts required info and creates corresponding account key.
// Once account key is formed, that key is put (if not already) into keystore i.e. key is *encoded* into key file. // Once account key is formed, that key is put (if not already) into keystore i.e. key is *encoded* into key file.
func importExtendedKey(extKey *extkeys.ExtendedKey, password string) (address, pubKey string, err error) { func importExtendedKey(extKey *extkeys.ExtendedKey, password string) (address, pubKey string, err error) {
accountManager, err := GetNodeManager().AccountManager() accountManager, err := NodeManagerInstance().AccountManager()
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
@ -218,7 +218,7 @@ func importExtendedKey(extKey *extkeys.ExtendedKey, password string) (address, p
} }
func onAccountsListRequest(entities []accounts.Account) []accounts.Account { func onAccountsListRequest(entities []accounts.Account) []accounts.Account {
nodeManager := GetNodeManager() nodeManager := NodeManagerInstance()
if nodeManager.SelectedAccount == nil { if nodeManager.SelectedAccount == nil {
return []accounts.Account{} return []accounts.Account{}
@ -246,7 +246,7 @@ func onAccountsListRequest(entities []accounts.Account) []accounts.Account {
// refreshSelectedAccount re-populates list of sub-accounts of the currently selected account (if any) // refreshSelectedAccount re-populates list of sub-accounts of the currently selected account (if any)
func refreshSelectedAccount() { func refreshSelectedAccount() {
nodeManager := GetNodeManager() nodeManager := NodeManagerInstance()
if nodeManager.SelectedAccount == nil { if nodeManager.SelectedAccount == nil {
return return
@ -273,7 +273,7 @@ func refreshSelectedAccount() {
// that belong to the currently selected account. // that belong to the currently selected account.
// The extKey is CKD#2 := root of sub-accounts of the main account // The extKey is CKD#2 := root of sub-accounts of the main account
func findSubAccounts(extKey *extkeys.ExtendedKey, subAccountIndex uint32) ([]accounts.Account, error) { func findSubAccounts(extKey *extkeys.ExtendedKey, subAccountIndex uint32) ([]accounts.Account, error) {
nodeManager := GetNodeManager() nodeManager := NodeManagerInstance()
accountManager, err := nodeManager.AccountManager() accountManager, err := nodeManager.AccountManager()
if err != nil { if err != nil {
return []accounts.Account{}, err return []accounts.Account{}, err

View File

@ -5,7 +5,6 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/status-im/status-go/geth" "github.com/status-im/status-go/geth"
@ -18,7 +17,7 @@ func TestAccountsList(t *testing.T) {
return return
} }
les, err := geth.GetNodeManager().LightEthereumService() les, err := geth.NodeManagerInstance().LightEthereumService()
if err != nil { if err != nil {
t.Errorf("expected LES service: %v", err) t.Errorf("expected LES service: %v", err)
} }
@ -130,7 +129,7 @@ func TestCreateChildAccount(t *testing.T) {
geth.Logout() // to make sure that we start with empty account (which might get populated during previous tests) geth.Logout() // to make sure that we start with empty account (which might get populated during previous tests)
accountManager, err := geth.GetNodeManager().AccountManager() accountManager, err := geth.NodeManagerInstance().AccountManager()
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
@ -144,7 +143,7 @@ func TestCreateChildAccount(t *testing.T) {
} }
t.Logf("Account created: {address: %s, key: %s, mnemonic:%s}", address, pubKey, mnemonic) t.Logf("Account created: {address: %s, key: %s, mnemonic:%s}", address, pubKey, mnemonic)
account, err := utils.MakeAddress(accountManager, address) account, err := geth.ParseAccountString(accountManager, address)
if err != nil { if err != nil {
t.Errorf("can not get account from address: %v", err) t.Errorf("can not get account from address: %v", err)
return return
@ -217,7 +216,7 @@ func TestRecoverAccount(t *testing.T) {
return return
} }
accountManager, _ := geth.GetNodeManager().AccountManager() accountManager, _ := geth.NodeManagerInstance().AccountManager()
// create an account // create an account
address, pubKey, mnemonic, err := geth.CreateAccount(newAccountPassword) address, pubKey, mnemonic, err := geth.CreateAccount(newAccountPassword)
@ -238,7 +237,7 @@ func TestRecoverAccount(t *testing.T) {
} }
// now test recovering, but make sure that account/key file is removed i.e. simulate recovering on a new device // now test recovering, but make sure that account/key file is removed i.e. simulate recovering on a new device
account, err := utils.MakeAddress(accountManager, address) account, err := geth.ParseAccountString(accountManager, address)
if err != nil { if err != nil {
t.Errorf("can not get account from address: %v", err) t.Errorf("can not get account from address: %v", err)
} }
@ -284,7 +283,7 @@ func TestRecoverAccount(t *testing.T) {
} }
// time to login with recovered data // time to login with recovered data
whisperService, err := geth.GetNodeManager().WhisperService() whisperService, err := geth.NodeManagerInstance().WhisperService()
if err != nil { if err != nil {
t.Errorf("whisper service not running: %v", err) t.Errorf("whisper service not running: %v", err)
} }
@ -312,7 +311,7 @@ func TestAccountSelect(t *testing.T) {
} }
// test to see if the account was injected in whisper // test to see if the account was injected in whisper
whisperService, err := geth.GetNodeManager().WhisperService() whisperService, err := geth.NodeManagerInstance().WhisperService()
if err != nil { if err != nil {
t.Errorf("whisper service not running: %v", err) t.Errorf("whisper service not running: %v", err)
} }
@ -377,7 +376,7 @@ func TestAccountLogout(t *testing.T) {
return return
} }
whisperService, err := geth.GetNodeManager().WhisperService() whisperService, err := geth.NodeManagerInstance().WhisperService()
if err != nil { if err != nil {
t.Errorf("whisper service not running: %v", err) t.Errorf("whisper service not running: %v", err)
} }

View File

@ -1,304 +1,249 @@
package geth package geth
/*
#include <stddef.h>
#include <stdbool.h>
extern bool StatusServiceSignalEvent( const char *jsonEvent );
*/
import "C"
import ( import (
"encoding/json"
"errors" "errors"
"flag"
"fmt" "fmt"
"io/ioutil" "io"
"math/big"
"os"
"path/filepath" "path/filepath"
"reflect"
"runtime" "runtime"
"sync" "strings"
"syscall"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/les" "github.com/ethereum/go-ethereum/les"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
whisper "github.com/ethereum/go-ethereum/whisper/whisperv2" whisper "github.com/ethereum/go-ethereum/whisper/whisperv2"
"gopkg.in/urfave/cli.v1"
) )
const ( const (
clientIdentifier = "Geth" // Client identifier to advertise over the network ClientIdentifier = "StatusIM" // Client identifier to advertise over the network
versionMajor = 1 // Major version component of the current release VersionMajor = 1 // Major version component of the current release
versionMinor = 5 // Minor version component of the current release VersionMinor = 1 // Minor version component of the current release
versionPatch = 0 // Patch version component of the current release VersionPatch = 0 // Patch version component of the current release
versionMeta = "unstable" // Version metadata to append to the version string VersionMeta = "unstable" // Version metadata to append to the version string
RPCPort = 8545 // RPC port (replaced in unit tests) RPCPort = 8545 // RPC port (replaced in unit tests)
NetworkPort = 30303 NetworkPort = 30303
MaxPeers = 25
MaxLightPeers = 20
MaxPendingPeers = 0
ProcessFileDescriptorLimit = uint64(2048)
DatabaseCacheSize = 128 // Megabytes of memory allocated to internal caching (min 16MB / database forced)
EventNodeStarted = "node.started" EventNodeStarted = "node.started"
) )
// Gas price settings
var ( var (
ErrDataDirPreprocessingFailed = errors.New("failed to pre-process data directory") GasPrice = new(big.Int).Mul(big.NewInt(20), common.Shannon) // Minimal gas price to accept for mining a transactions
ErrInvalidGethNode = errors.New("no running geth node detected") GpoMinGasPrice = new(big.Int).Mul(big.NewInt(20), common.Shannon) // Minimum suggested gas price
ErrInvalidAccountManager = errors.New("could not retrieve account manager") GpoMaxGasPrice = new(big.Int).Mul(big.NewInt(500), common.Shannon) // Maximum suggested gas price
ErrInvalidWhisperService = errors.New("whisper service is unavailable") GpoFullBlockRatio = 80 // Full block threshold for gas price calculation (%)
ErrInvalidLightEthereumService = errors.New("can not retrieve LES service") GpobaseStepDown = 10 // Suggested gas price base step down ratio (1/1000)
ErrInvalidClient = errors.New("RPC client is not properly initialized") GpobaseStepUp = 100 // Suggested gas price base step up ratio (1/1000)
ErrInvalidJailedRequestQueue = errors.New("Jailed request queue is not properly initialized") GpobaseCorrectionFactor = 110 // Suggested gas price base correction factor (%)
ErrNodeStartFailure = errors.New("could not create the in-memory node object")
) )
type SelectedExtKey struct { // default node configuration options
Address common.Address
AccountKey *accounts.Key
SubAccounts []accounts.Account
}
type NodeManager struct {
currentNode *node.Node // currently running geth node
ctx *cli.Context // the CLI context used to start the geth node
lightEthereum *les.LightEthereum // LES service
accountManager *accounts.Manager // the account manager attached to the currentNode
jailedRequestQueue *JailedRequestQueue // bridge via which jail notifies node of incoming requests
SelectedAccount *SelectedExtKey // account that was processed during the last call to SelectAccount()
whisperService *whisper.Whisper // Whisper service
client *rpc.Client // RPC client
nodeStarted chan struct{} // channel to wait for node to start
}
var ( var (
UseTestnet = "true" // can be overridden via -ldflags '-X geth.UseTestnet' UseTestnetFlag = "true" // to be overridden via -ldflags '-X geth.UseTestnetFlag'
nodeManagerInstance *NodeManager UseTestnet = false
createOnce sync.Once
) )
func NewNodeManager(datadir string, rpcport int) *NodeManager { func init() {
createOnce.Do(func() { if UseTestnetFlag == "true" { // set at compile time, here we make sure to set corresponding boolean flag
nodeManagerInstance = &NodeManager{ UseTestnet = true
jailedRequestQueue: NewJailedRequestsQueue(),
} }
nodeManagerInstance.MakeNode(datadir, rpcport)
})
return nodeManagerInstance
} }
func GetNodeManager() *NodeManager { // node-related errors
return nodeManagerInstance var (
ErrRLimitRaiseFailure = errors.New("failed to register the whisper service")
ErrDatabaseAccessFailure = errors.New("could not open database")
ErrChainConfigurationFailure = errors.New("could not make chain configuration")
ErrEthServiceRegistrationFailure = errors.New("failed to register the Ethereum service")
ErrSshServiceRegistrationFailure = errors.New("failed to register the Whisper service")
ErrLightEthRegistrationFailure = errors.New("failed to register the LES service")
)
type Node struct {
geth *node.Node // reference to the running Geth node
started chan struct{} // channel to wait for node to start
} }
// createAndStartNode creates a node entity and starts the // Inited checks whether status node has been properly initialized
// node running locally exposing given RPC port func (n *Node) Inited() bool {
func CreateAndRunNode(datadir string, rpcport int) error { return n != nil && n.geth != nil
nodeManager := NewNodeManager(datadir, rpcport)
if nodeManager.HasNode() {
nodeManager.RunNode()
<-nodeManager.nodeStarted // block until node is ready
return nil
}
return ErrNodeStartFailure
} }
// MakeNode create a geth node entity // MakeNode create a geth node entity
func (m *NodeManager) MakeNode(datadir string, rpcport int) *node.Node { func MakeNode(dataDir string, rpcPort int) *Node {
// TODO remove admin rpcapi flag glog.CopyStandardLogTo("INFO")
set := flag.NewFlagSet("test", 0) glog.SetToStderr(true)
set.Bool("lightkdf", true, "Reduce key-derivation RAM & CPU usage at some expense of KDF strength")
set.Bool("shh", true, "whisper")
set.Bool("light", true, "enable light client mode")
if UseTestnet == "true" {
set.Bool("testnet", true, "test network")
}
set.Bool("rpc", true, "enable rpc")
set.String("rpcaddr", "localhost", "host for RPC")
set.Int("rpcport", rpcport, "rpc port")
set.String("rpccorsdomain", "*", "allow all domains")
set.String("verbosity", "3", "verbosity level")
set.String("rpcapi", "db,eth,net,web3,shh,personal,admin", "rpc api(s)")
set.String("datadir", datadir, "data directory for geth")
set.String("logdir", datadir, "log dir for glog")
set.Int("port", NetworkPort, "network listening port")
m.ctx = cli.NewContext(nil, set, nil)
utils.DebugSetup(m.ctx) bootstrapNodes := params.MainnetBootnodes
if UseTestnet {
// create node and start requested protocols dataDir = filepath.Join(dataDir, "testnet")
m.currentNode = utils.MakeNode(m.ctx, clientIdentifier, "") bootstrapNodes = params.TestnetBootnodes
utils.RegisterEthService(m.ctx, m.currentNode, makeDefaultExtra())
// Whisper must be explicitly enabled, but is auto-enabled in --dev mode.
shhEnabled := m.ctx.GlobalBool(utils.WhisperEnabledFlag.Name)
shhAutoEnabled := !m.ctx.GlobalIsSet(utils.WhisperEnabledFlag.Name) && m.ctx.GlobalIsSet(utils.DevModeFlag.Name)
if shhEnabled || shhAutoEnabled {
utils.RegisterShhService(m.currentNode)
} }
m.accountManager = m.currentNode.AccountManager() // configure required node (should you need to update node's config, e.g. add bootstrap nodes, see node.Config)
m.nodeStarted = make(chan struct{}) config := &node.Config{
DataDir: dataDir,
return m.currentNode UseLightweightKDF: true,
} Name: ClientIdentifier,
Version: fmt.Sprintf("%d.%d.%d-%s", VersionMajor, VersionMinor, VersionPatch, VersionMeta),
// StartNode starts a geth node entity NoDiscovery: true,
func (m *NodeManager) RunNode() { DiscoveryV5: true,
go func() { DiscoveryV5Addr: fmt.Sprintf(":%d", NetworkPort+1),
utils.StartNode(m.currentNode) BootstrapNodes: bootstrapNodes,
BootstrapNodesV5: params.DiscoveryV5Bootnodes,
if m.currentNode.AccountManager() == nil { ListenAddr: fmt.Sprintf(":%d", NetworkPort),
glog.V(logger.Warn).Infoln("cannot get account manager") MaxPeers: MaxPeers,
} MaxPendingPeers: MaxPendingPeers,
if err := m.currentNode.Service(&m.whisperService); err != nil { HTTPHost: node.DefaultHTTPHost,
glog.V(logger.Warn).Infoln("cannot get whisper service:", err) HTTPPort: rpcPort,
} HTTPCors: "*",
if err := m.currentNode.Service(&m.lightEthereum); err != nil { HTTPModules: strings.Split("db,eth,net,web3,shh,personal,admin", ","), // TODO remove "admin" on main net
glog.V(logger.Warn).Infoln("cannot get light ethereum service:", err)
} }
// setup handlers stack, err := node.New(config)
m.lightEthereum.StatusBackend.SetTransactionQueueHandler(onSendTransactionRequest)
m.lightEthereum.StatusBackend.SetAccountsFilterHandler(onAccountsListRequest)
m.lightEthereum.StatusBackend.SetTransactionReturnHandler(onSendTransactionReturn)
var err error
m.client, err = m.currentNode.Attach()
if err != nil { if err != nil {
glog.V(logger.Warn).Infoln("cannot get RPC client service:", ErrInvalidClient) Fatalf(ErrNodeMakeFailure)
} }
// @TODO Remove after LES supports discover out of box // start Ethereum service
m.populateStaticPeers() if err := activateEthService(stack, makeDefaultExtra()); err != nil {
Fatalf(fmt.Errorf("%v: %v", ErrEthServiceRegistrationFailure, err))
}
m.onNodeStarted() // node started, notify listeners // start Whisper service
m.currentNode.Wait() if err := activateShhService(stack); err != nil {
}() Fatalf(fmt.Errorf("%v: %v", ErrSshServiceRegistrationFailure, err))
}
return &Node{
geth: stack,
started: make(chan struct{}),
}
} }
func (m *NodeManager) onNodeStarted() { // activateEthService configures and registers the eth.Ethereum service with a given node.
// notify local listener func activateEthService(stack *node.Node, extra []byte) error {
m.nodeStarted <- struct{}{} ethConf := &eth.Config{
close(m.nodeStarted) Etherbase: common.Address{},
ChainConfig: makeChainConfig(stack),
// send signal up to native app FastSync: false,
event := GethEvent{ LightMode: true,
Type: EventNodeStarted, LightServ: 60,
Event: struct{}{}, LightPeers: MaxLightPeers,
MaxPeers: MaxPeers,
DatabaseCache: DatabaseCacheSize,
DatabaseHandles: makeDatabaseHandles(),
NetworkId: 1, // Olympic
MinerThreads: runtime.NumCPU(),
GasPrice: GasPrice,
GpoMinGasPrice: GpoMinGasPrice,
GpoMaxGasPrice: GpoMaxGasPrice,
GpoFullBlockRatio: GpoFullBlockRatio,
GpobaseStepDown: GpobaseStepDown,
GpobaseStepUp: GpobaseStepUp,
GpobaseCorrectionFactor: GpobaseCorrectionFactor,
SolcPath: "solc",
AutoDAG: false,
} }
body, _ := json.Marshal(&event) if UseTestnet {
C.StatusServiceSignalEvent(C.CString(string(body))) ethConf.NetworkId = 3
ethConf.Genesis = core.DefaultTestnetGenesisBlock()
}
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
return les.New(ctx, ethConf)
}); err != nil {
return fmt.Errorf("%v: %v", ErrLightEthRegistrationFailure, err)
}
return nil
} }
func (m *NodeManager) AddPeer(url string) (bool, error) { // activateShhService configures Whisper and adds it to the given node.
if m == nil || !m.HasNode() { func activateShhService(stack *node.Node) error {
return false, ErrInvalidGethNode serviceConstructor := func(*node.ServiceContext) (node.Service, error) {
return whisper.New(), nil
}
if err := stack.Register(serviceConstructor); err != nil {
return err
} }
server := m.currentNode.Server() return nil
if server == nil {
return false, errors.New("node not started")
}
// Try to add the url as a static peer and return
parsedNode, err := discover.ParseNode(url)
if err != nil {
return false, fmt.Errorf("invalid enode: %v", err)
}
server.AddPeer(parsedNode)
return true, nil
} }
func (m *NodeManager) HasNode() bool { // makeChainConfig reads the chain configuration from the database in the datadir.
return m != nil && m.currentNode != nil func makeChainConfig(stack *node.Node) *params.ChainConfig {
} config := new(params.ChainConfig)
func (m *NodeManager) HasAccountManager() bool { if UseTestnet {
return m.accountManager != nil config = params.TestnetChainConfig
} } else {
// Homestead fork
config.HomesteadBlock = params.MainNetHomesteadBlock
// DAO fork
config.DAOForkBlock = params.MainNetDAOForkBlock
config.DAOForkSupport = true
func (m *NodeManager) AccountManager() (*accounts.Manager, error) { // DoS reprice fork
if m == nil || !m.HasNode() { config.EIP150Block = params.MainNetHomesteadGasRepriceBlock
return nil, ErrInvalidGethNode config.EIP150Hash = params.MainNetHomesteadGasRepriceHash
// DoS state cleanup fork
config.EIP155Block = params.MainNetSpuriousDragon
config.EIP158Block = params.MainNetSpuriousDragon
config.ChainId = params.MainNetChainID
} }
if !m.HasAccountManager() { return config
return nil, ErrInvalidAccountManager
}
return m.accountManager, nil
} }
func (m *NodeManager) HasWhisperService() bool { // makeDatabaseHandles makes sure that enough file descriptors are available to the process
return m.whisperService != nil // (and returns half of them for node's database to use)
} func makeDatabaseHandles() int {
// current limit
func (m *NodeManager) WhisperService() (*whisper.Whisper, error) { var limit syscall.Rlimit
if m == nil || !m.HasNode() { if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
return nil, ErrInvalidGethNode Fatalf(err)
} }
if !m.HasWhisperService() { // increase limit
return nil, ErrInvalidWhisperService limit.Cur = limit.Max
if limit.Cur > ProcessFileDescriptorLimit {
limit.Cur = ProcessFileDescriptorLimit
}
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
Fatalf(err)
} }
return m.whisperService, nil // re-query limit
} if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
Fatalf(err)
func (m *NodeManager) HasLightEthereumService() bool {
return m.lightEthereum != nil
}
func (m *NodeManager) LightEthereumService() (*les.LightEthereum, error) {
if m == nil || !m.HasNode() {
return nil, ErrInvalidGethNode
} }
if !m.HasLightEthereumService() { // cap limit
return nil, ErrInvalidLightEthereumService if limit.Cur > ProcessFileDescriptorLimit {
limit.Cur = ProcessFileDescriptorLimit
} }
return m.lightEthereum, nil return int(limit.Cur) / 2
}
func (m *NodeManager) HasRPCClient() bool {
return m.client != nil
}
func (m *NodeManager) RPCClient() (*rpc.Client, error) {
if m == nil || !m.HasNode() {
return nil, ErrInvalidGethNode
}
if !m.HasRPCClient() {
return nil, ErrInvalidClient
}
return m.client, nil
}
func (m *NodeManager) HasJailedRequestQueue() bool {
return m.jailedRequestQueue != nil
}
func (m *NodeManager) JailedRequestQueue() (*JailedRequestQueue, error) {
if m == nil || !m.HasNode() {
return nil, ErrInvalidGethNode
}
if !m.HasJailedRequestQueue() {
return nil, ErrInvalidJailedRequestQueue
}
return m.jailedRequestQueue, nil
} }
func makeDefaultExtra() []byte { func makeDefaultExtra() []byte {
@ -307,7 +252,7 @@ func makeDefaultExtra() []byte {
Name string Name string
GoVersion string GoVersion string
Os string Os string
}{uint(versionMajor<<16 | versionMinor<<8 | versionPatch), clientIdentifier, runtime.Version(), runtime.GOOS} }{uint(VersionMajor<<16 | VersionMinor<<8 | VersionPatch), ClientIdentifier, runtime.Version(), runtime.GOOS}
extra, err := rlp.EncodeToBytes(clientInfo) extra, err := rlp.EncodeToBytes(clientInfo)
if err != nil { if err != nil {
glog.V(logger.Warn).Infoln("error setting canonical miner information:", err) glog.V(logger.Warn).Infoln("error setting canonical miner information:", err)
@ -322,18 +267,22 @@ func makeDefaultExtra() []byte {
return extra return extra
} }
func (m *NodeManager) populateStaticPeers() { func Fatalf(reason interface{}, args ...interface{}) {
// manually add static nodes (LES auto-discovery is not stable yet) // decide on output stream
configFile, err := ioutil.ReadFile(filepath.Join("../data", "static-nodes.json")) w := io.MultiWriter(os.Stdout, os.Stderr)
if err != nil { outf, _ := os.Stdout.Stat()
return errf, _ := os.Stderr.Stat()
} if outf != nil && errf != nil && os.SameFile(outf, errf) {
var enodes []string w = os.Stderr
if err = json.Unmarshal(configFile, &enodes); err != nil {
return
} }
for _, enode := range enodes { // find out whether error or string has been passed as a reason
m.AddPeer(enode) r := reflect.ValueOf(reason)
if r.Kind() == reflect.String {
fmt.Fprintf(w, "Fatal Failure: "+reason.(string)+"\n", args)
} else {
fmt.Fprintf(w, "Fatal Failure: %v\n", reason.(error))
} }
os.Exit(1)
} }

289
geth/node_manager.go Normal file
View File

@ -0,0 +1,289 @@
package geth
/*
#include <stddef.h>
#include <stdbool.h>
extern bool StatusServiceSignalEvent( const char *jsonEvent );
*/
import "C"
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"os/signal"
"path/filepath"
"sync"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/les"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/rpc"
whisper "github.com/ethereum/go-ethereum/whisper/whisperv2"
)
// SelectedExtKey is a container for currently selected (logged in) account
type SelectedExtKey struct {
Address common.Address
AccountKey *accounts.Key
SubAccounts []accounts.Account
}
// NodeManager manages Status node (which abstracts contained geth node)
type NodeManager struct {
node *Node // reference to Status node
services *NodeServiceStack // default stack of services running on geth node
SelectedAccount *SelectedExtKey // account that was processed during the last call to SelectAccount()
}
// NodeServiceStack contains "standard" node services (which are always available)
type NodeServiceStack struct {
lightEthereum *les.LightEthereum // LES service
whisperService *whisper.Whisper // Whisper service
rpcClient *rpc.Client // RPC client
jailedRequestQueue *JailedRequestQueue // bridge via which jail notifies node of incoming requests
}
var (
ErrDataDirPreprocessingFailed = errors.New("failed to pre-process data directory")
ErrInvalidGethNode = errors.New("no running geth node detected")
ErrInvalidAccountManager = errors.New("could not retrieve account manager")
ErrInvalidWhisperService = errors.New("whisper service is unavailable")
ErrInvalidLightEthereumService = errors.New("can not retrieve LES service")
ErrInvalidClient = errors.New("RPC client is not properly initialized")
ErrInvalidJailedRequestQueue = errors.New("jailed request queue is not properly initialized")
ErrNodeMakeFailure = errors.New("error creating p2p node")
ErrNodeStartFailure = errors.New("error starting p2p node")
)
var (
nodeManagerInstance *NodeManager
createOnce sync.Once
)
// CreateAndRunNode creates and starts running Geth node locally (exposing given RPC port along the way)
func CreateAndRunNode(dataDir string, rpcPort int) error {
nodeManager := NewNodeManager(dataDir, rpcPort)
if nodeManager.NodeInited() {
nodeManager.RunNode()
<-nodeManager.node.started // block until node is ready
return nil
}
return ErrNodeStartFailure
}
// NewNodeManager makes new instance of node manager
func NewNodeManager(dataDir string, rpcPort int) *NodeManager {
createOnce.Do(func() {
nodeManagerInstance = &NodeManager{
services: &NodeServiceStack{
jailedRequestQueue: NewJailedRequestsQueue(),
},
}
nodeManagerInstance.node = MakeNode(dataDir, rpcPort)
})
return nodeManagerInstance
}
// NodeManagerInstance exposes node manager instance
func NodeManagerInstance() *NodeManager {
return nodeManagerInstance
}
// RunNode starts Geth node
func (m *NodeManager) RunNode() {
go func() {
m.StartNode()
if _, err := m.AccountManager(); err != nil {
glog.V(logger.Warn).Infoln(ErrInvalidAccountManager)
}
if err := m.node.geth.Service(&m.services.whisperService); err != nil {
glog.V(logger.Warn).Infoln("cannot get whisper service:", err)
}
if err := m.node.geth.Service(&m.services.lightEthereum); err != nil {
glog.V(logger.Warn).Infoln("cannot get light ethereum service:", err)
}
// setup handlers
lightEthereum, err := m.LightEthereumService()
if err != nil {
panic("service stack misses LES")
}
lightEthereum.StatusBackend.SetTransactionQueueHandler(onSendTransactionRequest)
lightEthereum.StatusBackend.SetAccountsFilterHandler(onAccountsListRequest)
lightEthereum.StatusBackend.SetTransactionReturnHandler(onSendTransactionReturn)
m.services.rpcClient, err = m.node.geth.Attach()
if err != nil {
glog.V(logger.Warn).Infoln("cannot get RPC client service:", ErrInvalidClient)
}
// @TODO Remove after LES supports discover out of box
m.populateStaticPeers()
m.onNodeStarted() // node started, notify listeners
m.node.geth.Wait()
}()
}
// StartNode starts running P2P node
func (m *NodeManager) StartNode() {
if m == nil || !m.NodeInited() {
panic(ErrInvalidGethNode)
}
if err := m.node.geth.Start(); err != nil {
panic(fmt.Sprintf("%v: %v", ErrNodeStartFailure, err))
}
// allow interrupting running nodes
go func() {
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, os.Interrupt)
defer signal.Stop(sigc)
<-sigc
glog.V(logger.Info).Infoln("Got interrupt, shutting down...")
go m.node.geth.Stop()
for i := 3; i > 0; i-- {
<-sigc
if i > 1 {
glog.V(logger.Info).Infof("Already shutting down, interrupt %d more times for panic.", i-1)
}
}
panic("interrupted!")
}()
}
// HasNode checks whether manager has initialized node attached
func (m *NodeManager) NodeInited() bool {
if m == nil || !m.node.Inited() {
return false
}
return true
}
// AccountManager exposes reference to accounts manager
func (m *NodeManager) AccountManager() (*accounts.Manager, error) {
if m == nil || !m.NodeInited() {
return nil, ErrInvalidGethNode
}
return m.node.geth.AccountManager(), nil
}
// LightEthereumService exposes LES
func (m *NodeManager) LightEthereumService() (*les.LightEthereum, error) {
if m == nil || !m.NodeInited() {
return nil, ErrInvalidGethNode
}
if m.services.lightEthereum == nil {
return nil, ErrInvalidLightEthereumService
}
return m.services.lightEthereum, nil
}
// WhisperService exposes Whisper service
func (m *NodeManager) WhisperService() (*whisper.Whisper, error) {
if m == nil || !m.NodeInited() {
return nil, ErrInvalidGethNode
}
if m.services.whisperService == nil {
return nil, ErrInvalidWhisperService
}
return m.services.whisperService, nil
}
// RPCClient exposes Geth's RPC client
func (m *NodeManager) RPCClient() (*rpc.Client, error) {
if m == nil || !m.NodeInited() {
return nil, ErrInvalidGethNode
}
if m.services.rpcClient == nil {
return nil, ErrInvalidClient
}
return m.services.rpcClient, nil
}
// JailedRequestQueue exposes reference to queue of jailed requests
func (m *NodeManager) JailedRequestQueue() (*JailedRequestQueue, error) {
if m == nil || !m.NodeInited() {
return nil, ErrInvalidGethNode
}
if m.services.jailedRequestQueue == nil {
return nil, ErrInvalidJailedRequestQueue
}
return m.services.jailedRequestQueue, nil
}
// AddPeer adds new peer node
func (m *NodeManager) AddPeer(url string) (bool, error) {
if m == nil || !m.NodeInited() {
return false, ErrInvalidGethNode
}
server := m.node.geth.Server()
if server == nil {
return false, ErrInvalidGethNode
}
// Try to add the url as a static peer and return
parsedNode, err := discover.ParseNode(url)
if err != nil {
return false, fmt.Errorf("invalid enode: %v", err)
}
server.AddPeer(parsedNode)
return true, nil
}
// onNodeStarted sends upward notification letting the app know that Geth node is ready to be used
func (m *NodeManager) onNodeStarted() {
// notify local listener
m.node.started <- struct{}{}
close(m.node.started)
// send signal up to native app
event := GethEvent{
Type: EventNodeStarted,
Event: struct{}{},
}
body, _ := json.Marshal(&event)
C.StatusServiceSignalEvent(C.CString(string(body)))
}
// populateStaticPeers connects current node with our publicly available LES cluster
func (m *NodeManager) populateStaticPeers() {
// manually add static nodes (LES auto-discovery is not stable yet)
configFile, err := ioutil.ReadFile(filepath.Join("../data", "static-nodes.json"))
if err != nil {
return
}
var enodes []string
if err = json.Unmarshal(configFile, &enodes); err != nil {
return
}
for _, enode := range enodes {
m.AddPeer(enode)
}
}

View File

@ -92,7 +92,7 @@ func sendTransactionErrorCode(err error) string {
} }
func CompleteTransaction(id, password string) (common.Hash, error) { func CompleteTransaction(id, password string) (common.Hash, error) {
lightEthereum, err := GetNodeManager().LightEthereumService() lightEthereum, err := NodeManagerInstance().LightEthereumService()
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
@ -125,7 +125,7 @@ func CompleteTransactions(ids, password string) map[string]RawCompleteTransactio
} }
func DiscardTransaction(id string) error { func DiscardTransaction(id string) error {
lightEthereum, err := GetNodeManager().LightEthereumService() lightEthereum, err := NodeManagerInstance().LightEthereumService()
if err != nil { if err != nil {
return err return err
} }
@ -195,7 +195,7 @@ func (q *JailedRequestQueue) PostProcessRequest(vm *otto.Otto, req RPCCall, mess
func (q *JailedRequestQueue) ProcessSendTransactionRequest(vm *otto.Otto, req RPCCall) (common.Hash, error) { func (q *JailedRequestQueue) ProcessSendTransactionRequest(vm *otto.Otto, req RPCCall) (common.Hash, error) {
// obtain status backend from LES service // obtain status backend from LES service
lightEthereum, err := GetNodeManager().LightEthereumService() lightEthereum, err := NodeManagerInstance().LightEthereumService()
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }

View File

@ -21,7 +21,7 @@ func TestQueuedTransactions(t *testing.T) {
} }
// obtain reference to status backend // obtain reference to status backend
lightEthereum, err := geth.GetNodeManager().LightEthereumService() lightEthereum, err := geth.NodeManagerInstance().LightEthereumService()
if err != nil { if err != nil {
t.Errorf("Test failed: LES service is not running: %v", err) t.Errorf("Test failed: LES service is not running: %v", err)
return return
@ -91,7 +91,7 @@ func TestDoubleCompleteQueuedTransactions(t *testing.T) {
} }
// obtain reference to status backend // obtain reference to status backend
lightEthereum, err := geth.GetNodeManager().LightEthereumService() lightEthereum, err := geth.NodeManagerInstance().LightEthereumService()
if err != nil { if err != nil {
t.Errorf("Test failed: LES service is not running: %v", err) t.Errorf("Test failed: LES service is not running: %v", err)
return return
@ -212,7 +212,7 @@ func TestDiscardQueuedTransactions(t *testing.T) {
} }
// obtain reference to status backend // obtain reference to status backend
lightEthereum, err := geth.GetNodeManager().LightEthereumService() lightEthereum, err := geth.NodeManagerInstance().LightEthereumService()
if err != nil { if err != nil {
t.Errorf("Test failed: LES service is not running: %v", err) t.Errorf("Test failed: LES service is not running: %v", err)
return return
@ -327,7 +327,7 @@ func TestCompleteMultipleQueuedTransactions(t *testing.T) {
} }
// obtain reference to status backend // obtain reference to status backend
lightEthereum, err := geth.GetNodeManager().LightEthereumService() lightEthereum, err := geth.NodeManagerInstance().LightEthereumService()
if err != nil { if err != nil {
t.Errorf("Test failed: LES service is not running: %v", err) t.Errorf("Test failed: LES service is not running: %v", err)
return return
@ -452,7 +452,7 @@ func TestDiscardMultipleQueuedTransactions(t *testing.T) {
} }
// obtain reference to status backend // obtain reference to status backend
lightEthereum, err := geth.GetNodeManager().LightEthereumService() lightEthereum, err := geth.NodeManagerInstance().LightEthereumService()
if err != nil { if err != nil {
t.Errorf("Test failed: LES service is not running: %v", err) t.Errorf("Test failed: LES service is not running: %v", err)
return return
@ -653,7 +653,7 @@ func TestEvictionOfQueuedTransactions(t *testing.T) {
} }
// obtain reference to status backend // obtain reference to status backend
lightEthereum, err := geth.GetNodeManager().LightEthereumService() lightEthereum, err := geth.NodeManagerInstance().LightEthereumService()
if err != nil { if err != nil {
t.Errorf("Test failed: LES service is not running: %v", err) t.Errorf("Test failed: LES service is not running: %v", err)
return return

View File

@ -12,10 +12,11 @@ import (
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
"strconv"
"sync" "sync"
"time" "time"
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
@ -86,8 +87,8 @@ func PrepareTestNode() (err error) {
muPrepareTestNode.Lock() muPrepareTestNode.Lock()
defer muPrepareTestNode.Unlock() defer muPrepareTestNode.Unlock()
manager := GetNodeManager() manager := NodeManagerInstance()
if manager.HasNode() { if manager.NodeInited() {
return nil return nil
} }
@ -117,17 +118,17 @@ func PrepareTestNode() (err error) {
// internally once.Do() is used, so call below is thread-safe // internally once.Do() is used, so call below is thread-safe
CreateAndRunNode(dataDir, 8546) // to avoid conflicts with running react-native app, run on different port CreateAndRunNode(dataDir, 8546) // to avoid conflicts with running react-native app, run on different port
manager = GetNodeManager() manager = NodeManagerInstance()
if !manager.HasNode() { if !manager.NodeInited() {
panic(ErrInvalidGethNode) panic(ErrInvalidGethNode)
} }
if !manager.HasRPCClient() { if service, err := manager.RPCClient(); err != nil || service == nil {
panic(ErrInvalidGethNode) panic(ErrInvalidGethNode)
} }
if !manager.HasWhisperService() { if service, err := manager.WhisperService(); err != nil || service == nil {
panic(ErrInvalidGethNode) panic(ErrInvalidGethNode)
} }
if !manager.HasLightEthereumService() { if service, err := manager.LightEthereumService(); err != nil || service == nil {
panic(ErrInvalidGethNode) panic(ErrInvalidGethNode)
} }
@ -181,12 +182,12 @@ func PanicAfter(waitSeconds time.Duration, abort chan struct{}, desc string) {
} }
func FromAddress(accountAddress string) common.Address { func FromAddress(accountAddress string) common.Address {
accountManager, err := GetNodeManager().AccountManager() accountManager, err := NodeManagerInstance().AccountManager()
if err != nil { if err != nil {
return common.Address{} return common.Address{}
} }
from, err := utils.MakeAddress(accountManager, accountAddress) from, err := ParseAccountString(accountManager, accountAddress)
if err != nil { if err != nil {
return common.Address{} return common.Address{}
} }
@ -195,15 +196,31 @@ func FromAddress(accountAddress string) common.Address {
} }
func ToAddress(accountAddress string) *common.Address { func ToAddress(accountAddress string) *common.Address {
accountManager, err := GetNodeManager().AccountManager() accountManager, err := NodeManagerInstance().AccountManager()
if err != nil { if err != nil {
return nil return nil
} }
to, err := utils.MakeAddress(accountManager, accountAddress) to, err := ParseAccountString(accountManager, accountAddress)
if err != nil { if err != nil {
return nil return nil
} }
return &to.Address return &to.Address
} }
// parseAccount parses hex encoded string or key index in the accounts key store
// and converts it to an internal account representation.
func ParseAccountString(accman *accounts.Manager, account string) (accounts.Account, error) {
// valid address, convert to account
if common.IsHexAddress(account) {
return accounts.Account{Address: common.HexToAddress(account)}, nil
}
// valid key index, return account referenced by that key
index, err := strconv.Atoi(account)
if err != nil {
return accounts.Account{}, ErrInvalidAccountAddressOrKey
}
return accman.AccountByIndex(index)
}

View File

@ -36,7 +36,7 @@ func onWhisperMessage(message *whisper.Message) {
} }
func AddWhisperFilter(args whisper.NewFilterArgs) int { func AddWhisperFilter(args whisper.NewFilterArgs) int {
whisperService, err := GetNodeManager().WhisperService() whisperService, err := NodeManagerInstance().WhisperService()
if err != nil { if err != nil {
return -1 return -1
} }
@ -54,7 +54,7 @@ func AddWhisperFilter(args whisper.NewFilterArgs) int {
} }
func RemoveWhisperFilter(idFilter int) { func RemoveWhisperFilter(idFilter int) {
whisperService, err := GetNodeManager().WhisperService() whisperService, err := NodeManagerInstance().WhisperService()
if err != nil { if err != nil {
return return
} }

View File

@ -18,7 +18,7 @@ func TestWhisperMessaging(t *testing.T) {
return return
} }
whisperService, err := geth.GetNodeManager().WhisperService() whisperService, err := geth.NodeManagerInstance().WhisperService()
if err != nil { if err != nil {
t.Errorf("whisper service not running: %v", err) t.Errorf("whisper service not running: %v", err)
} }

View File

@ -260,8 +260,8 @@ func (jail *Jail) RPCClient() (*rpc.Client, error) {
return jail.client, nil return jail.client, nil
} }
nodeManager := geth.GetNodeManager() nodeManager := geth.NodeManagerInstance()
if !nodeManager.HasNode() { if !nodeManager.NodeInited() {
return nil, geth.ErrInvalidGethNode return nil, geth.ErrInvalidGethNode
} }
@ -284,8 +284,8 @@ func (jail *Jail) RequestQueue() (*geth.JailedRequestQueue, error) {
return jail.requestQueue, nil return jail.requestQueue, nil
} }
nodeManager := geth.GetNodeManager() nodeManager := geth.NodeManagerInstance()
if !nodeManager.HasNode() { if !nodeManager.NodeInited() {
return nil, geth.ErrInvalidGethNode return nil, geth.ErrInvalidGethNode
} }