From 833e4d1319336fbb66fd8f1e473c24472d65b17b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= <peterke@gmail.com>
Date: Tue, 24 Jan 2017 11:49:20 +0200
Subject: accounts, cmd, eth, internal, mobile, node: split account backends

---
 internal/ethapi/api.go       | 75 +++++++++++++++++++++++---------------------
 internal/guide/guide_test.go | 35 +++++++++++----------
 2 files changed, 57 insertions(+), 53 deletions(-)

(limited to 'internal')

diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index 4c8e784c5..7962f8b17 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -28,6 +28,7 @@ import (
 
 	"github.com/ethereum/ethash"
 	"github.com/ethereum/go-ethereum/accounts"
+	"github.com/ethereum/go-ethereum/accounts/keystore"
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/common/hexutil"
 	"github.com/ethereum/go-ethereum/core"
@@ -219,13 +220,18 @@ func (s *PrivateAccountAPI) ListAccounts() []common.Address {
 
 // 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 := s.am.NewAccount(password)
+	acc, err := fetchKeystore(s.am).NewAccount(password)
 	if err == nil {
 		return acc.Address, nil
 	}
 	return common.Address{}, err
 }
 
+// fetchKeystore retrives the encrypted keystore from the account manager.
+func fetchKeystore(am *accounts.Manager) *keystore.KeyStore {
+	return am.Backend(keystore.BackendType).(*keystore.KeyStore)
+}
+
 // ImportRawKey stores the given hex encoded ECDSA key into the key directory,
 // encrypting it with the passphrase.
 func (s *PrivateAccountAPI) ImportRawKey(privkey string, password string) (common.Address, error) {
@@ -234,7 +240,7 @@ func (s *PrivateAccountAPI) ImportRawKey(privkey string, password string) (commo
 		return common.Address{}, err
 	}
 
-	acc, err := s.am.ImportECDSA(crypto.ToECDSA(hexkey), password)
+	acc, err := fetchKeystore(s.am).ImportECDSA(crypto.ToECDSA(hexkey), password)
 	return acc.Address, err
 }
 
@@ -251,13 +257,13 @@ func (s *PrivateAccountAPI) UnlockAccount(addr common.Address, password string,
 	} else {
 		d = time.Duration(*duration) * time.Second
 	}
-	err := s.am.TimedUnlock(accounts.Account{Address: addr}, password, d)
+	err := fetchKeystore(s.am).TimedUnlock(accounts.Account{Address: addr}, password, d)
 	return err == nil, err
 }
 
 // LockAccount will lock the account associated with the given address when it's unlocked.
 func (s *PrivateAccountAPI) LockAccount(addr common.Address) bool {
-	return s.am.Lock(addr) == nil
+	return fetchKeystore(s.am).Lock(addr) == nil
 }
 
 // SendTransaction will create a transaction from the given arguments and
@@ -268,13 +274,16 @@ func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs
 		return common.Hash{}, err
 	}
 	tx := args.toTransaction()
-	signer := types.MakeSigner(s.b.ChainConfig(), s.b.CurrentBlock().Number())
-	signature, err := s.am.SignWithPassphrase(accounts.Account{Address: args.From}, passwd, signer.Hash(tx).Bytes())
+
+	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)
 	if err != nil {
 		return common.Hash{}, err
 	}
-
-	return submitTransaction(ctx, s.b, tx, signature)
+	return submitTransaction(ctx, s.b, signed)
 }
 
 // signHash is a helper function that calculates a hash for the given message that can be
@@ -299,7 +308,7 @@ 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().SignWithPassphrase(accounts.Account{Address: addr}, passwd, signHash(data))
+	signature, err := s.b.AccountManager().SignHashWithPassphrase(accounts.Account{Address: addr}, passwd, signHash(data))
 	if err != nil {
 		return nil, err
 	}
@@ -1023,13 +1032,11 @@ 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) {
-	signer := types.MakeSigner(s.b.ChainConfig(), s.b.CurrentBlock().Number())
-
-	signature, err := s.b.AccountManager().Sign(addr, signer.Hash(tx).Bytes())
-	if err != nil {
-		return nil, err
+	var chainID *big.Int
+	if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) {
+		chainID = config.ChainId
 	}
-	return tx.WithSignature(signer, signature)
+	return s.b.AccountManager().SignTx(accounts.Account{Address: addr}, tx, chainID)
 }
 
 // SendTxArgs represents the arguments to sumbit a new transaction into the transaction pool.
@@ -1076,27 +1083,19 @@ func (args *SendTxArgs) toTransaction() *types.Transaction {
 }
 
 // submitTransaction is a helper function that submits tx to txPool and logs a message.
-func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction, signature []byte) (common.Hash, error) {
-	signer := types.MakeSigner(b.ChainConfig(), b.CurrentBlock().Number())
-
-	signedTx, err := tx.WithSignature(signer, signature)
-	if err != nil {
+func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (common.Hash, error) {
+	if err := b.SendTx(ctx, tx); err != nil {
 		return common.Hash{}, err
 	}
-
-	if err := b.SendTx(ctx, signedTx); err != nil {
-		return common.Hash{}, err
-	}
-
-	if signedTx.To() == nil {
-		from, _ := types.Sender(signer, signedTx)
-		addr := crypto.CreateAddress(from, signedTx.Nonce())
-		glog.V(logger.Info).Infof("Tx(%s) created: %s\n", signedTx.Hash().Hex(), addr.Hex())
+	if tx.To() == nil {
+		signer := types.MakeSigner(b.ChainConfig(), b.CurrentBlock().Number())
+		from, _ := types.Sender(signer, tx)
+		addr := crypto.CreateAddress(from, tx.Nonce())
+		glog.V(logger.Info).Infof("Tx(%s) created: %s\n", tx.Hash().Hex(), addr.Hex())
 	} else {
-		glog.V(logger.Info).Infof("Tx(%s) to: %s\n", signedTx.Hash().Hex(), tx.To().Hex())
+		glog.V(logger.Info).Infof("Tx(%s) to: %s\n", tx.Hash().Hex(), tx.To().Hex())
 	}
-
-	return signedTx.Hash(), nil
+	return tx.Hash(), nil
 }
 
 // SendTransaction creates a transaction for the given argument, sign it and submit it to the
@@ -1106,12 +1105,16 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen
 		return common.Hash{}, err
 	}
 	tx := args.toTransaction()
-	signer := types.MakeSigner(s.b.ChainConfig(), s.b.CurrentBlock().Number())
-	signature, err := s.b.AccountManager().Sign(args.From, signer.Hash(tx).Bytes())
+
+	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)
 	if err != nil {
 		return common.Hash{}, err
 	}
-	return submitTransaction(ctx, s.b, tx, signature)
+	return submitTransaction(ctx, s.b, signed)
 }
 
 // SendRawTransaction will add the signed transaction to the transaction pool.
@@ -1151,7 +1154,7 @@ 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().Sign(addr, signHash(data))
+	signature, err := s.b.AccountManager().SignHash(accounts.Account{Address: addr}, signHash(data))
 	if err == nil {
 		signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
 	}
diff --git a/internal/guide/guide_test.go b/internal/guide/guide_test.go
index 8f89037bd..9c7ad16d1 100644
--- a/internal/guide/guide_test.go
+++ b/internal/guide/guide_test.go
@@ -24,13 +24,14 @@ package guide
 
 import (
 	"io/ioutil"
+	"math/big"
 	"os"
 	"path/filepath"
 	"testing"
 	"time"
 
-	"github.com/ethereum/go-ethereum/accounts"
-	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/accounts/keystore"
+	"github.com/ethereum/go-ethereum/core/types"
 )
 
 // Tests that the account management snippets work correctly.
@@ -42,59 +43,59 @@ func TestAccountManagement(t *testing.T) {
 	}
 	defer os.RemoveAll(workdir)
 
-	// Create an encrypted keystore manager with standard crypto parameters
-	am := accounts.NewManager(filepath.Join(workdir, "keystore"), accounts.StandardScryptN, accounts.StandardScryptP)
+	// Create an encrypted keystore with standard crypto parameters
+	ks := keystore.NewKeyStore(filepath.Join(workdir, "keystore"), keystore.StandardScryptN, keystore.StandardScryptP)
 
 	// Create a new account with the specified encryption passphrase
-	newAcc, err := am.NewAccount("Creation password")
+	newAcc, err := ks.NewAccount("Creation password")
 	if err != nil {
 		t.Fatalf("Failed to create new account: %v", err)
 	}
 	// Export the newly created account with a different passphrase. The returned
 	// data from this method invocation is a JSON encoded, encrypted key-file
-	jsonAcc, err := am.Export(newAcc, "Creation password", "Export password")
+	jsonAcc, err := ks.Export(newAcc, "Creation password", "Export password")
 	if err != nil {
 		t.Fatalf("Failed to export account: %v", err)
 	}
 	// Update the passphrase on the account created above inside the local keystore
-	if err := am.Update(newAcc, "Creation password", "Update password"); err != nil {
+	if err := ks.Update(newAcc, "Creation password", "Update password"); err != nil {
 		t.Fatalf("Failed to update account: %v", err)
 	}
 	// Delete the account updated above from the local keystore
-	if err := am.Delete(newAcc, "Update password"); err != nil {
+	if err := ks.Delete(newAcc, "Update password"); err != nil {
 		t.Fatalf("Failed to delete account: %v", err)
 	}
 	// Import back the account we've exported (and then deleted) above with yet
 	// again a fresh passphrase
-	if _, err := am.Import(jsonAcc, "Export password", "Import password"); err != nil {
+	if _, err := ks.Import(jsonAcc, "Export password", "Import password"); err != nil {
 		t.Fatalf("Failed to import account: %v", err)
 	}
 	// Create a new account to sign transactions with
-	signer, err := am.NewAccount("Signer password")
+	signer, err := ks.NewAccount("Signer password")
 	if err != nil {
 		t.Fatalf("Failed to create signer account: %v", err)
 	}
-	txHash := common.HexToHash("0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")
+	tx, chain := new(types.Transaction), big.NewInt(1)
 
 	// Sign a transaction with a single authorization
-	if _, err := am.SignWithPassphrase(signer, "Signer password", txHash.Bytes()); err != nil {
+	if _, err := ks.SignTxWithPassphrase(signer, "Signer password", tx, chain); err != nil {
 		t.Fatalf("Failed to sign with passphrase: %v", err)
 	}
 	// Sign a transaction with multiple manually cancelled authorizations
-	if err := am.Unlock(signer, "Signer password"); err != nil {
+	if err := ks.Unlock(signer, "Signer password"); err != nil {
 		t.Fatalf("Failed to unlock account: %v", err)
 	}
-	if _, err := am.Sign(signer.Address, txHash.Bytes()); err != nil {
+	if _, err := ks.SignTx(signer, tx, chain); err != nil {
 		t.Fatalf("Failed to sign with unlocked account: %v", err)
 	}
-	if err := am.Lock(signer.Address); err != nil {
+	if err := ks.Lock(signer.Address); err != nil {
 		t.Fatalf("Failed to lock account: %v", err)
 	}
 	// Sign a transaction with multiple automatically cancelled authorizations
-	if err := am.TimedUnlock(signer, "Signer password", time.Second); err != nil {
+	if err := ks.TimedUnlock(signer, "Signer password", time.Second); err != nil {
 		t.Fatalf("Failed to time unlock account: %v", err)
 	}
-	if _, err := am.Sign(signer.Address, txHash.Bytes()); err != nil {
+	if _, err := ks.SignTx(signer, tx, chain); err != nil {
 		t.Fatalf("Failed to sign with time unlocked account: %v", err)
 	}
 }
-- 
cgit v1.2.3