diff options
author | Péter Szilágyi <peterke@gmail.com> | 2017-02-07 18:47:34 +0800 |
---|---|---|
committer | Péter Szilágyi <peterke@gmail.com> | 2017-02-13 20:00:07 +0800 |
commit | fad5eb0a87abfc12812647344a26de8a43830182 (patch) | |
tree | a679f37933a85edade15ee69b385b6705cc94043 /internal/ethapi | |
parent | b3c0e9d3ccb0bb326646aea47dda391a9552b122 (diff) | |
download | dexon-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.go | 121 |
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)) } } |