aboutsummaryrefslogtreecommitdiff
path: root/accounts/keystore/keystore.go
diff options
context:
space:
mode:
Diffstat (limited to 'accounts/keystore/keystore.go')
-rw-r--r--accounts/keystore/keystore.go29
1 files changed, 23 insertions, 6 deletions
diff --git a/accounts/keystore/keystore.go b/accounts/keystore/keystore.go
index a3ce33f..cb4df04 100644
--- a/accounts/keystore/keystore.go
+++ b/accounts/keystore/keystore.go
@@ -24,7 +24,6 @@ import (
"crypto/ecdsa"
crand "crypto/rand"
"errors"
- "fmt"
"math/big"
"os"
"path/filepath"
@@ -35,15 +34,19 @@ import (
"github.com/ava-labs/coreth/accounts"
"github.com/ava-labs/coreth/core/types"
- "github.com/ava-labs/go-ethereum/common"
- "github.com/ava-labs/go-ethereum/crypto"
- "github.com/ava-labs/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/event"
)
var (
ErrLocked = accounts.NewAuthNeededError("password or unlock")
ErrNoMatch = errors.New("no key for given address or file")
ErrDecrypt = errors.New("could not decrypt key with given password")
+
+ // ErrAccountAlreadyExists is returned if an account attempted to import is
+ // already present in the keystore.
+ ErrAccountAlreadyExists = errors.New("account already exists")
)
// KeyStoreType is the reflect type of a keystore backend.
@@ -67,7 +70,8 @@ type KeyStore struct {
updateScope event.SubscriptionScope // Subscription scope tracking current live listeners
updating bool // Whether the event notification loop is running
- mu sync.RWMutex
+ mu sync.RWMutex
+ importMu sync.Mutex // Import Mutex locks the import to prevent two insertions from racing
}
type unlocked struct {
@@ -443,14 +447,27 @@ func (ks *KeyStore) Import(keyJSON []byte, passphrase, newPassphrase string) (ac
if err != nil {
return accounts.Account{}, err
}
+ ks.importMu.Lock()
+ defer ks.importMu.Unlock()
+
+ if ks.cache.hasAddress(key.Address) {
+ return accounts.Account{
+ Address: key.Address,
+ }, ErrAccountAlreadyExists
+ }
return ks.importKey(key, newPassphrase)
}
// ImportECDSA stores the given key into the key directory, encrypting it with the passphrase.
func (ks *KeyStore) ImportECDSA(priv *ecdsa.PrivateKey, passphrase string) (accounts.Account, error) {
+ ks.importMu.Lock()
+ defer ks.importMu.Unlock()
+
key := newKeyFromECDSA(priv)
if ks.cache.hasAddress(key.Address) {
- return accounts.Account{}, fmt.Errorf("account already exists")
+ return accounts.Account{
+ Address: key.Address,
+ }, ErrAccountAlreadyExists
}
return ks.importKey(key, passphrase)
}