replaces dependency on go-ethereum "cmd/*" packages. Fixes #72
This commit is contained in:
parent
09d021e598
commit
e5bb6a24f7
5
Makefile
5
Makefile
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
429
geth/node.go
429
geth/node.go
|
@ -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 := ð.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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue