status-go/src/gethdep.go

228 lines
6.5 KiB
Go
Raw Normal View History

package main
/*
#include <stddef.h>
#include <stdbool.h>
extern bool GethServiceSignalEvent( const char *jsonEvent );
*/
import "C"
import (
"encoding/json"
2016-06-20 15:21:45 +00:00
"errors"
"fmt"
2016-06-21 18:29:38 +00:00
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
2016-06-21 14:34:38 +00:00
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/les/status"
2016-07-04 16:00:29 +00:00
"github.com/ethereum/go-ethereum/p2p/discover"
2016-06-21 14:34:38 +00:00
errextra "github.com/pkg/errors"
"github.com/status-im/status-go/src/extkeys"
)
var (
ErrInvalidGethNode = errors.New("no running node detected for account unlock")
ErrInvalidWhisperService = errors.New("whisper service is unavailable")
ErrInvalidAccountManager = errors.New("could not retrieve account manager")
ErrAddressToAccountMappingFailure = errors.New("cannot retreive a valid account for a given address")
ErrAccountToKeyMappingFailure = errors.New("cannot retreive a valid key for a given account")
ErrUnlockCalled = errors.New("no need to unlock accounts, use Login() instead")
ErrWhisperIdentityInjectionFailure = errors.New("failed to inject identity into Whisper")
2016-08-29 00:31:16 +00:00
ErrWhisperClearIdentitiesFailure = errors.New("failed to clear whisper identities")
)
// createAccount creates an internal geth account
func createAccount(password string) (string, string, string, error) {
2016-06-29 11:32:04 +00:00
if currentNode != nil {
w := true
if accountManager != nil {
// generate mnemonic phrase
m := extkeys.NewMnemonic()
mnemonic, err := m.MnemonicPhrase(128, extkeys.EnglishLanguage)
if err != nil {
return "", "", "", errextra.Wrap(err, "Can not create mnemonic seed")
}
// generate extended master key (see BIP32)
extKey, err := extkeys.NewMaster(m.MnemonicSeed(mnemonic, password), []byte(extkeys.Salt))
if err != nil {
return "", "", "", errextra.Wrap(err, "Can not create master extended key")
}
// derive hardened child (see BIP44)
extChild1, err := extKey.BIP44Child(extkeys.CoinTypeETH, 0)
if err != nil {
return "", "", "", errextra.Wrap(err, "Can not derive hardened child key (#1)")
}
// generate the account
account, err := accountManager.NewAccountUsingExtendedKey(extChild1, password, w)
if err != nil {
return "", "", "", errextra.Wrap(err, "Account manager could not create the account")
}
address := fmt.Sprintf("%x", account.Address)
// recover the public key to return
account, key, err := accountManager.AccountDecryptedKey(account, password)
if err != nil {
return address, "", "", errextra.Wrap(err, "Could not recover the key")
}
pubKey := common.ToHex(crypto.FromECDSAPub(&key.PrivateKey.PublicKey))
return address, pubKey, mnemonic, nil
2016-06-29 11:32:04 +00:00
}
return "", "", "", errors.New("Could not retrieve account manager")
2016-06-21 14:34:38 +00:00
}
return "", "", "", errors.New("No running node detected for account creation")
}
func recoverAccount(password, mnemonic string) (string, string, error) {
if currentNode != nil {
if accountManager != nil {
m := extkeys.NewMnemonic()
// re-create extended key (see BIP32)
extKey, err := extkeys.NewMaster(m.MnemonicSeed(mnemonic, password), []byte(extkeys.Salt))
if err != nil {
return "", "", errextra.Wrap(err, "Can not create master extended key")
}
// derive hardened child (see BIP44)
extChild1, err := extKey.BIP44Child(extkeys.CoinTypeETH, 0)
if err != nil {
return "", "", errextra.Wrap(err, "Can not derive hardened child key (#1)")
}
privateKeyECDSA := extChild1.ToECDSA()
address := fmt.Sprintf("%x", crypto.PubkeyToAddress(privateKeyECDSA.PublicKey))
pubKey := common.ToHex(crypto.FromECDSAPub(&privateKeyECDSA.PublicKey))
accountManager.ImportECDSA(privateKeyECDSA, password) // try caching key, ignore errors
return address, pubKey, nil
}
return "", "", errors.New("Could not retrieve account manager")
}
return "", "", errors.New("No running node detected for account unlock")
}
2016-06-20 15:21:45 +00:00
func selectAccount(address, password string) error {
if currentNode == nil {
return ErrInvalidGethNode
}
2016-06-21 18:29:38 +00:00
if accountManager == nil {
return ErrInvalidAccountManager
}
account, err := utils.MakeAddress(accountManager, address)
if err != nil {
return ErrAddressToAccountMappingFailure
}
2016-06-21 18:29:38 +00:00
account, accountKey, err := accountManager.AccountDecryptedKey(account, password)
if err != nil {
return fmt.Errorf("%s: %v", ErrAccountToKeyMappingFailure.Error(), err)
}
if whisperService == nil {
return ErrInvalidWhisperService
2016-06-21 18:29:38 +00:00
}
if err := whisperService.InjectIdentity(accountKey.PrivateKey); err != nil {
return ErrWhisperIdentityInjectionFailure
}
return nil
}
2016-06-21 18:29:38 +00:00
2016-08-29 00:31:16 +00:00
// logout clears whisper identities
func logout() error {
if currentNode == nil {
return ErrInvalidGethNode
}
if whisperService == nil {
return ErrInvalidWhisperService
}
err := whisperService.ClearIdentities()
if err != nil {
return fmt.Errorf("%s: %v", ErrWhisperClearIdentitiesFailure, err)
}
return nil
}
// unlockAccount unlocks an existing account for a certain duration and
// inject the account as a whisper identity if the account was created as
// a whisper enabled account
func unlockAccount(address, password string, seconds int) error {
if currentNode == nil {
return ErrInvalidGethNode
}
2016-06-21 18:29:38 +00:00
return ErrUnlockCalled
2016-06-21 18:29:38 +00:00
}
// createAndStartNode creates a node entity and starts the
// node running locally
func createAndStartNode(inputDir string) error {
2016-06-20 15:21:45 +00:00
currentNode = MakeNode(inputDir)
2016-06-20 15:21:45 +00:00
if currentNode != nil {
2016-06-29 11:32:04 +00:00
RunNode(currentNode)
2016-06-20 15:21:45 +00:00
return nil
}
return errors.New("Could not create the in-memory node object")
}
2016-07-04 16:00:29 +00:00
func doAddPeer(url string) (bool, error) {
server := currentNode.Server()
if server == nil {
return false, errors.New("node not started")
}
// Try to add the url as a static peer and return
node, err := discover.ParseNode(url)
if err != nil {
return false, fmt.Errorf("invalid enode: %v", err)
}
server.AddPeer(node)
return true, nil
}
func onSendTransactionRequest(queuedTx status.QueuedTx) {
event := GethEvent{
Type: "sendTransactionQueued",
Event: SendTransactionEvent{
Id: string(queuedTx.Id),
Args: queuedTx.Args,
},
}
body, _ := json.Marshal(&event)
C.GethServiceSignalEvent(C.CString(string(body)))
}
func completeTransaction(id, password string) (common.Hash, error) {
if currentNode != nil {
if lightEthereum != nil {
backend := lightEthereum.StatusBackend
2016-08-09 16:41:42 +00:00
return backend.CompleteQueuedTransaction(status.QueuedTxId(id), password)
}
2016-08-09 16:41:42 +00:00
return common.Hash{}, errors.New("can not retrieve LES service")
}
2016-08-09 16:41:42 +00:00
return common.Hash{}, errors.New("can not complete transaction: no running node detected")
}