github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/accounts/keystore/wallet.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package keystore 18 19 import ( 20 "crypto/ecdsa" 21 blscrypto "github.com/ethereum/go-ethereum/crypto/bls" 22 "github.com/ethereum/go-ethereum/log" 23 "math/big" 24 25 ethereum "github.com/ethereum/go-ethereum" 26 "github.com/ethereum/go-ethereum/accounts" 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/core/types" 29 ) 30 31 // keystoreWallet implements the accounts.Wallet interface for the original 32 // keystore. 33 type keystoreWallet struct { 34 account accounts.Account // Single account contained in this wallet 35 keystore *KeyStore // Keystore where the account originates from 36 } 37 38 // URL implements accounts.Wallet, returning the URL of the account within. 39 func (w *keystoreWallet) URL() accounts.URL { 40 return w.account.URL 41 } 42 43 // Status implements accounts.Wallet, returning whether the account held by the 44 // keystore wallet is unlocked or not. 45 func (w *keystoreWallet) Status() (string, error) { 46 w.keystore.mu.RLock() 47 defer w.keystore.mu.RUnlock() 48 49 if _, ok := w.keystore.unlocked[w.account.Address]; ok { 50 return "Unlocked", nil 51 } 52 return "Locked", nil 53 } 54 55 // Open implements accounts.Wallet, but is a noop for plain wallets since there 56 // is no connection or decryption step necessary to access the list of accounts. 57 func (w *keystoreWallet) Open(passphrase string) error { return nil } 58 59 // Close implements accounts.Wallet, but is a noop for plain wallets since there 60 // is no meaningful open operation. 61 func (w *keystoreWallet) Close() error { return nil } 62 63 // Accounts implements accounts.Wallet, returning an account list consisting of 64 // a single account that the plain kestore wallet contains. 65 func (w *keystoreWallet) Accounts() []accounts.Account { 66 return []accounts.Account{w.account} 67 } 68 69 // Contains implements accounts.Wallet, returning whether a particular account is 70 // or is not wrapped by this wallet instance. 71 func (w *keystoreWallet) Contains(account accounts.Account) bool { 72 return account.Address == w.account.Address && (account.URL == (accounts.URL{}) || account.URL == w.account.URL) 73 } 74 75 // Decrypt decrypts an ECIES ciphertext. 76 func (w *keystoreWallet) Decrypt(account accounts.Account, c, s1, s2 []byte) ([]byte, error) { 77 if account.Address != w.account.Address { 78 log.Debug(accounts.ErrUnknownAccount.Error(), "account", account) 79 return nil, accounts.ErrUnknownAccount 80 } 81 if account.URL != (accounts.URL{}) && account.URL != w.account.URL { 82 log.Debug(accounts.ErrUnknownAccount.Error(), "account", account) 83 return nil, accounts.ErrUnknownAccount 84 } 85 // Account seems valid, request the keystore to sign 86 return w.keystore.Decrypt(account, c, s1, s2) 87 } 88 89 // Derive implements accounts.Wallet, but is a noop for plain wallets since there 90 // is no notion of hierarchical account derivation for plain keystore accounts. 91 func (w *keystoreWallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) { 92 return accounts.Account{}, accounts.ErrNotSupported 93 } 94 95 // SelfDerive implements accounts.Wallet, but is a noop for plain wallets since 96 // there is no notion of hierarchical account derivation for plain keystore accounts. 97 func (w *keystoreWallet) SelfDerive(base accounts.DerivationPath, chain ethereum.ChainStateReader) {} 98 99 // SignHash implements accounts.Wallet, attempting to sign the given hash with 100 // the given account. If the wallet does not wrap this particular account, an 101 // error is returned to avoid account leakage (even though in theory we may be 102 // able to sign via our shared keystore backend). 103 func (w *keystoreWallet) SignHash(account accounts.Account, hash []byte) ([]byte, error) { 104 // Make sure the requested account is contained within 105 if !w.Contains(account) { 106 log.Debug(accounts.ErrUnknownAccount.Error(), "account", account) 107 return nil, accounts.ErrUnknownAccount 108 } 109 // Account seems valid, request the keystore to sign 110 return w.keystore.SignHash(account, hash) 111 } 112 113 func (w *keystoreWallet) GetPublicKey(account accounts.Account) (*ecdsa.PublicKey, error) { 114 // Make sure the requested account is contained within 115 if !w.Contains(account) { 116 log.Debug(accounts.ErrUnknownAccount.Error(), "account", account) 117 return nil, accounts.ErrUnknownAccount 118 } 119 // Account seems valid, request the public key 120 return w.keystore.GetPublicKey(account) 121 } 122 123 func (w *keystoreWallet) SignHashBLS(account accounts.Account, hash []byte) (blscrypto.SerializedSignature, error) { 124 // Make sure the requested account is contained within 125 if !w.Contains(account) { 126 log.Debug(accounts.ErrUnknownAccount.Error(), "account", account) 127 return blscrypto.SerializedSignature{}, accounts.ErrUnknownAccount 128 } 129 // Account seems valid, request the keystore to sign 130 return w.keystore.SignHashBLS(account, hash) 131 } 132 133 func (w *keystoreWallet) SignMessageBLS(account accounts.Account, msg []byte, extraData []byte) (blscrypto.SerializedSignature, error) { 134 // Make sure the requested account is contained within 135 if !w.Contains(account) { 136 log.Debug(accounts.ErrUnknownAccount.Error(), "account", account) 137 return blscrypto.SerializedSignature{}, accounts.ErrUnknownAccount 138 } 139 // Account seems valid, request the keystore to sign 140 return w.keystore.SignMessageBLS(account, msg, extraData) 141 } 142 143 func (w *keystoreWallet) GenerateProofOfPossession(account accounts.Account, address common.Address) ([]byte, []byte, error) { 144 // Make sure the requested account is contained within 145 if !w.Contains(account) { 146 log.Debug(accounts.ErrUnknownAccount.Error(), "account", account) 147 return nil, nil, accounts.ErrUnknownAccount 148 } 149 // Account seems valid, request the keystore to sign 150 return w.keystore.GenerateProofOfPossession(account, address) 151 } 152 153 func (w *keystoreWallet) GenerateProofOfPossessionBLS(account accounts.Account, address common.Address) ([]byte, []byte, error) { 154 // Make sure the requested account is contained within 155 if !w.Contains(account) { 156 log.Debug(accounts.ErrUnknownAccount.Error(), "account", account) 157 return nil, nil, accounts.ErrUnknownAccount 158 } 159 // Account seems valid, request the keystore to sign 160 return w.keystore.GenerateProofOfPossessionBLS(account, address) 161 } 162 163 // SignTx implements accounts.Wallet, attempting to sign the given transaction 164 // with the given account. If the wallet does not wrap this particular account, 165 // an error is returned to avoid account leakage (even though in theory we may 166 // be able to sign via our shared keystore backend). 167 func (w *keystoreWallet) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { 168 // Make sure the requested account is contained within 169 if !w.Contains(account) { 170 log.Debug(accounts.ErrUnknownAccount.Error(), "account", account) 171 return nil, accounts.ErrUnknownAccount 172 } 173 // Account seems valid, request the keystore to sign 174 return w.keystore.SignTx(account, tx, chainID) 175 } 176 177 // SignHashWithPassphrase implements accounts.Wallet, attempting to sign the 178 // given hash with the given account using passphrase as extra authentication. 179 func (w *keystoreWallet) SignHashWithPassphrase(account accounts.Account, passphrase string, hash []byte) ([]byte, error) { 180 // Make sure the requested account is contained within 181 if !w.Contains(account) { 182 log.Debug(accounts.ErrUnknownAccount.Error(), "account", account) 183 return nil, accounts.ErrUnknownAccount 184 } 185 // Account seems valid, request the keystore to sign 186 return w.keystore.SignHashWithPassphrase(account, passphrase, hash) 187 } 188 189 // SignTxWithPassphrase implements accounts.Wallet, attempting to sign the given 190 // transaction with the given account using passphrase as extra authentication. 191 func (w *keystoreWallet) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { 192 // Make sure the requested account is contained within 193 if !w.Contains(account) { 194 log.Debug(accounts.ErrUnknownAccount.Error(), "account", account) 195 return nil, accounts.ErrUnknownAccount 196 } 197 // Account seems valid, request the keystore to sign 198 return w.keystore.SignTxWithPassphrase(account, passphrase, tx, chainID) 199 }