aboutsummaryrefslogtreecommitdiffstats
path: root/internal/ethapi
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2017-02-07 18:47:34 +0800
committerPéter Szilágyi <peterke@gmail.com>2017-02-13 20:00:07 +0800
commitfad5eb0a87abfc12812647344a26de8a43830182 (patch)
treea679f37933a85edade15ee69b385b6705cc94043 /internal/ethapi
parentb3c0e9d3ccb0bb326646aea47dda391a9552b122 (diff)
downloaddexon-fad5eb0a87abfc12812647344a26de8a43830182.tar.gz
dexon-fad5eb0a87abfc12812647344a26de8a43830182.tar.zst
dexon-fad5eb0a87abfc12812647344a26de8a43830182.zip
accounts, cmd, eth, internal, miner, node: wallets and HD APIs
Diffstat (limited to 'internal/ethapi')
-rw-r--r--internal/ethapi/api.go121
1 files changed, 102 insertions, 19 deletions
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index 7962f8b17..0e75eb0e0 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -188,8 +188,14 @@ func NewPublicAccountAPI(am *accounts.Manager) *PublicAccountAPI {
}
// Accounts returns the collection of accounts this node manages
-func (s *PublicAccountAPI) Accounts() []accounts.Account {
- return s.am.Accounts()
+func (s *PublicAccountAPI) Accounts() []common.Address {
+ var addresses []common.Address
+ for _, wallet := range s.am.Wallets() {
+ for _, account := range wallet.Accounts() {
+ addresses = append(addresses, account.Address)
+ }
+ }
+ return addresses
}
// PrivateAccountAPI provides an API to access accounts managed by this node.
@@ -210,14 +216,51 @@ func NewPrivateAccountAPI(b Backend) *PrivateAccountAPI {
// ListAccounts will return a list of addresses for accounts this node manages.
func (s *PrivateAccountAPI) ListAccounts() []common.Address {
- accounts := s.am.Accounts()
- addresses := make([]common.Address, len(accounts))
- for i, acc := range accounts {
- addresses[i] = acc.Address
+ var addresses []common.Address
+ for _, wallet := range s.am.Wallets() {
+ for _, account := range wallet.Accounts() {
+ addresses = append(addresses, account.Address)
+ }
}
return addresses
}
+// rawWallet is a JSON representation of an accounts.Wallet interface, with its
+// data contents extracted into plain fields.
+type rawWallet struct {
+ Type string `json:"type"`
+ URL string `json:"url"`
+ Status string `json:"status"`
+ Accounts []accounts.Account `json:"accounts"`
+}
+
+// ListWallets will return a list of wallets this node manages.
+func (s *PrivateAccountAPI) ListWallets() []rawWallet {
+ var wallets []rawWallet
+ for _, wallet := range s.am.Wallets() {
+ wallets = append(wallets, rawWallet{
+ Type: wallet.Type(),
+ URL: wallet.URL(),
+ Status: wallet.Status(),
+ Accounts: wallet.Accounts(),
+ })
+ }
+ return wallets
+}
+
+// DeriveAccount requests a HD wallet to derive a new account, optionally pinning
+// it for later reuse.
+func (s *PrivateAccountAPI) DeriveAccount(url string, path string, pin *bool) (accounts.Account, error) {
+ wallet, err := s.am.Wallet(url)
+ if err != nil {
+ return accounts.Account{}, err
+ }
+ if pin == nil {
+ pin = new(bool)
+ }
+ return wallet.Derive(path, *pin)
+}
+
// NewAccount will create a new account and returns the address for the new account.
func (s *PrivateAccountAPI) NewAccount(password string) (common.Address, error) {
acc, err := fetchKeystore(s.am).NewAccount(password)
@@ -229,7 +272,7 @@ func (s *PrivateAccountAPI) NewAccount(password string) (common.Address, error)
// fetchKeystore retrives the encrypted keystore from the account manager.
func fetchKeystore(am *accounts.Manager) *keystore.KeyStore {
- return am.Backend(keystore.BackendType).(*keystore.KeyStore)
+ return am.Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
}
// ImportRawKey stores the given hex encoded ECDSA key into the key directory,
@@ -270,16 +313,25 @@ func (s *PrivateAccountAPI) LockAccount(addr common.Address) bool {
// tries to sign it with the key associated with args.To. If the given passwd isn't
// able to decrypt the key it fails.
func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs, passwd string) (common.Hash, error) {
+ // Set some sanity defaults and terminate on failure
if err := args.setDefaults(ctx, s.b); err != nil {
return common.Hash{}, err
}
+ // Look up the wallet containing the requested signer
+ account := accounts.Account{Address: args.From}
+
+ wallet, err := s.am.Find(account)
+ if err != nil {
+ return common.Hash{}, err
+ }
+ // Assemble the transaction and sign with the wallet
tx := args.toTransaction()
var chainID *big.Int
if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) {
chainID = config.ChainId
}
- signed, err := s.am.SignTxWithPassphrase(accounts.Account{Address: args.From}, passwd, tx, chainID)
+ signed, err := wallet.SignTxWithPassphrase(account, passwd, tx, chainID)
if err != nil {
return common.Hash{}, err
}
@@ -308,7 +360,15 @@ func signHash(data []byte) []byte {
//
// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign
func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr common.Address, passwd string) (hexutil.Bytes, error) {
- signature, err := s.b.AccountManager().SignHashWithPassphrase(accounts.Account{Address: addr}, passwd, signHash(data))
+ // Look up the wallet containing the requested signer
+ account := accounts.Account{Address: addr}
+
+ wallet, err := s.b.AccountManager().Find(account)
+ if err != nil {
+ return nil, err
+ }
+ // Assemble sign the data with the wallet
+ signature, err := wallet.SignHashWithPassphrase(account, passwd, signHash(data))
if err != nil {
return nil, err
}
@@ -521,16 +581,15 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
if state == nil || err != nil {
return nil, common.Big0, err
}
-
// Set sender address or use a default if none specified
addr := args.From
if addr == (common.Address{}) {
- accounts := s.b.AccountManager().Accounts()
- if len(accounts) > 0 {
- addr = accounts[0].Address
+ if wallets := s.b.AccountManager().Wallets(); len(wallets) > 0 {
+ if accounts := wallets[0].Accounts(); len(accounts) > 0 {
+ addr = accounts[0].Address
+ }
}
}
-
// Set default gas & gas price if none were set
gas, gasPrice := args.Gas.ToInt(), args.GasPrice.ToInt()
if gas.BitLen() == 0 {
@@ -539,7 +598,6 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
if gasPrice.BitLen() == 0 {
gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon)
}
-
// Create new call message
msg := types.NewMessage(addr, args.To, 0, args.Value.ToInt(), gas, gasPrice, args.Data, false)
@@ -1032,11 +1090,19 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(txHash common.Hash) (ma
// sign is a helper function that signs a transaction with the private key of the given address.
func (s *PublicTransactionPoolAPI) sign(addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
+ // Look up the wallet containing the requested signer
+ account := accounts.Account{Address: addr}
+
+ wallet, err := s.b.AccountManager().Find(account)
+ if err != nil {
+ return nil, err
+ }
+ // Request the wallet to sign the transaction
var chainID *big.Int
if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) {
chainID = config.ChainId
}
- return s.b.AccountManager().SignTx(accounts.Account{Address: addr}, tx, chainID)
+ return wallet.SignTx(account, tx, chainID)
}
// SendTxArgs represents the arguments to sumbit a new transaction into the transaction pool.
@@ -1101,16 +1167,25 @@ func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c
// SendTransaction creates a transaction for the given argument, sign it and submit it to the
// transaction pool.
func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs) (common.Hash, error) {
+ // Set some sanity defaults and terminate on failure
if err := args.setDefaults(ctx, s.b); err != nil {
return common.Hash{}, err
}
+ // Look up the wallet containing the requested signer
+ account := accounts.Account{Address: args.From}
+
+ wallet, err := s.b.AccountManager().Find(account)
+ if err != nil {
+ return common.Hash{}, err
+ }
+ // Assemble the transaction and sign with the wallet
tx := args.toTransaction()
var chainID *big.Int
if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) {
chainID = config.ChainId
}
- signed, err := s.b.AccountManager().SignTx(accounts.Account{Address: args.From}, tx, chainID)
+ signed, err := wallet.SignTx(account, tx, chainID)
if err != nil {
return common.Hash{}, err
}
@@ -1154,7 +1229,15 @@ func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encod
//
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
func (s *PublicTransactionPoolAPI) Sign(addr common.Address, data hexutil.Bytes) (hexutil.Bytes, error) {
- signature, err := s.b.AccountManager().SignHash(accounts.Account{Address: addr}, signHash(data))
+ // Look up the wallet containing the requested signer
+ account := accounts.Account{Address: addr}
+
+ wallet, err := s.b.AccountManager().Find(account)
+ if err != nil {
+ return nil, err
+ }
+ // Sign the requested hash with the wallet
+ signature, err := wallet.SignHash(account, signHash(data))
if err == nil {
signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
}
@@ -1200,7 +1283,7 @@ func (s *PublicTransactionPoolAPI) PendingTransactions() ([]*RPCTransaction, err
signer = types.NewEIP155Signer(tx.ChainId())
}
from, _ := types.Sender(signer, tx)
- if s.b.AccountManager().HasAddress(from) {
+ if _, err := s.b.AccountManager().Find(accounts.Account{Address: from}); err == nil {
transactions = append(transactions, newRPCPendingTransaction(tx))
}
}