mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
add use.getUseAddress function
This commit is contained in:
parent
f8346a2457
commit
a11a67260f
13 changed files with 306 additions and 29 deletions
|
|
@ -149,6 +149,9 @@ type Wallet interface {
|
|||
|
||||
// SignTxWithPassphrase is identical to SignTx, but also takes a password
|
||||
SignTxWithPassphrase(account Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error)
|
||||
|
||||
// GetUseAddress represents the wallet to retrieve corresponding wanchain public address for a specific ordinary account/address
|
||||
GetUseAddress(account Account) (common.UAddress, error)
|
||||
}
|
||||
|
||||
// Backend is a "wallet provider" that may contain a batch of accounts they can
|
||||
|
|
|
|||
5
accounts/external/backend.go
vendored
5
accounts/external/backend.go
vendored
|
|
@ -203,6 +203,11 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
|
|||
return res.Tx, nil
|
||||
}
|
||||
|
||||
// TODO: TBI
|
||||
func (api *ExternalSigner) GetUseAddress(account accounts.Account) (common.UAddress, error) {
|
||||
return common.UAddress{}, nil
|
||||
}
|
||||
|
||||
func (api *ExternalSigner) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) {
|
||||
return []byte{}, fmt.Errorf("password-operations not supported on external signers")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ type keyStore interface {
|
|||
GetKey(addr common.Address, filename string, auth string) (*Key, error)
|
||||
// Writes and encrypts the key.
|
||||
StoreKey(filename string, k *Key, auth string) error
|
||||
// Loads an encrypted keyfile from disk
|
||||
GetEncryptedKey(addr common.Address, filename string) (*Key, error)
|
||||
// Joins filename with the key directory unless it is already absolute.
|
||||
JoinPath(filename string) string
|
||||
}
|
||||
|
|
|
|||
|
|
@ -486,6 +486,38 @@ func (ks *KeyStore) ImportPreSaleKey(keyJSON []byte, passphrase string) (account
|
|||
return a, nil
|
||||
}
|
||||
|
||||
// getEncryptedKey loads an encrypted keyfile from the disk
|
||||
func (ks *KeyStore) getEncryptedKey(a accounts.Account) (accounts.Account, *Key, error) {
|
||||
a, err := ks.Find(a)
|
||||
if err != nil {
|
||||
return a, nil, err
|
||||
}
|
||||
key, err := ks.storage.GetEncryptedKey(a.Address, a.URL.Path)
|
||||
if err != nil {
|
||||
return a, nil, err
|
||||
}
|
||||
return a, key, nil
|
||||
|
||||
}
|
||||
|
||||
// GetUseAddress represents the keystore to retrieve corresponding usechain public address for a specific ordinary account/address
|
||||
func (ks *KeyStore) GetUseAddress(account accounts.Account) (common.UAddress, error) {
|
||||
ks.mu.RLock()
|
||||
defer ks.mu.RUnlock()
|
||||
|
||||
unlockedKey, found := ks.unlocked[account.Address]
|
||||
if !found {
|
||||
_, ksen, err := ks.getEncryptedKey(account)
|
||||
if err != nil {
|
||||
return common.UAddress{}, ErrLocked
|
||||
}
|
||||
return ksen.UAddress, nil
|
||||
}
|
||||
|
||||
ret := unlockedKey.UAddress
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// zeroKey zeroes a private key in memory.
|
||||
func zeroKey(k *ecdsa.PrivateKey) {
|
||||
b := k.D.Bits()
|
||||
|
|
|
|||
|
|
@ -139,6 +139,49 @@ func (ks keyStorePassphrase) StoreKey(filename string, key *Key, auth string) er
|
|||
return os.Rename(tmpName, filename)
|
||||
}
|
||||
|
||||
// Implements GetEncryptedKey method of keystore interface
|
||||
func (ks keyStorePassphrase) GetEncryptedKey(a common.Address, filename string) (*Key, error) {
|
||||
// load the encrypted json keyfile
|
||||
keyjson, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key, err := GenerateKeyWithUAddress(keyjson)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key.Address = a
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// Generate a Key initialized with UAddress field
|
||||
func GenerateKeyWithUAddress(keyjson []byte) (*Key, error) {
|
||||
// parse the json blob into a simple map to fetch the key version
|
||||
m := make(map[string]interface{})
|
||||
if err := json.Unmarshal(keyjson, &m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
uaddress, ok := m["uaddress"].(string)
|
||||
|
||||
if !ok || uaddress == "" {
|
||||
return nil, ErrUAddressFieldNotExist
|
||||
}
|
||||
|
||||
uaddressRaw, err := hex.DecodeString(uaddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(uaddressRaw) != common.UAddressLength {
|
||||
return nil, ErrUAddressInvalid
|
||||
}
|
||||
|
||||
key := new(Key)
|
||||
copy(key.UAddress[:], uaddressRaw)
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func (ks keyStorePassphrase) JoinPath(filename string) string {
|
||||
if filepath.IsAbs(filename) {
|
||||
return filename
|
||||
|
|
@ -288,32 +331,59 @@ func DecryptKey(keyjson []byte, auth string) (*Key, error) {
|
|||
}
|
||||
// Depending on the version try to parse one way or another
|
||||
var (
|
||||
keyBytes, keyId []byte
|
||||
keyBytes, keyBytes2, keyId []byte
|
||||
err error
|
||||
uaddressStr *string
|
||||
)
|
||||
if version, ok := m["version"].(string); ok && version == "1" {
|
||||
k := new(encryptedKeyJSONV1)
|
||||
if err := json.Unmarshal(keyjson, k); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keyBytes, keyId, err = decryptKeyV1(k, auth)
|
||||
key, err := crypto.ToECDSA(keyBytes)
|
||||
if err != nil || key == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Key{
|
||||
Id: uuid.UUID(keyId),
|
||||
Address: crypto.PubkeyToAddress(key.PublicKey),
|
||||
PrivateKey: key,
|
||||
}, nil
|
||||
} else {
|
||||
k := new(encryptedKeyJSONV3)
|
||||
if err := json.Unmarshal(keyjson, k); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keyBytes, keyId, err = decryptKeyV3(k, auth)
|
||||
keyBytes, keyBytes2, keyId, err = decryptKeyV3(k, auth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
uaddressStr = &k.UAddress
|
||||
}
|
||||
// Handle any decryption errors and return the key
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key := crypto.ToECDSAUnsafe(keyBytes)
|
||||
key2 := crypto.ToECDSAUnsafe(keyBytes2)
|
||||
uaddressRaw, err := hex.DecodeString(*uaddressStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var uaddress common.UAddress
|
||||
copy(uaddress[:], uaddressRaw)
|
||||
|
||||
return &Key{
|
||||
Id: uuid.UUID(keyId),
|
||||
Address: crypto.PubkeyToAddress(key.PublicKey),
|
||||
PrivateKey: key,
|
||||
PrivateKey2: key2,
|
||||
UAddress: uaddress,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -353,16 +423,64 @@ func DecryptDataV3(cryptoJson CryptoJSON, auth string) ([]byte, error) {
|
|||
return plainText, err
|
||||
}
|
||||
|
||||
func decryptKeyV3(keyProtected *encryptedKeyJSONV3, auth string) (keyBytes []byte, keyId []byte, err error) {
|
||||
func decryptKeyV3(keyProtected *encryptedKeyJSONV3, auth string) (keyBytes []byte, keyBytes2 []byte, keyId []byte, err error) {
|
||||
if keyProtected.Version != version {
|
||||
return nil, nil, fmt.Errorf("Version not supported: %v", keyProtected.Version)
|
||||
return nil, nil, nil, fmt.Errorf("Version not supported: %v", keyProtected.Version)
|
||||
}
|
||||
keyId = uuid.Parse(keyProtected.Id)
|
||||
plainText, err := DecryptDataV3(keyProtected.Crypto, auth)
|
||||
plainText, err := decryptKeyV3Item(keyProtected.Crypto, auth)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
return plainText, keyId, err
|
||||
|
||||
plainText2, err2 := decryptKeyV3Item(keyProtected.Crypto2, auth)
|
||||
if err2 != nil {
|
||||
if "" == keyProtected.Crypto2.Cipher {
|
||||
plainText2 = make([]byte, 0)
|
||||
} else {
|
||||
return nil, nil, nil, err2
|
||||
}
|
||||
}
|
||||
|
||||
return plainText, plainText2, keyId, err
|
||||
}
|
||||
|
||||
func decryptKeyV3Item(cryptoItem CryptoJSON, auth string) (keyBytes []byte, err error) {
|
||||
if cryptoItem.Cipher != "aes-128-ctr" {
|
||||
return nil, fmt.Errorf("Cipher not supported: %v", cryptoItem.Cipher)
|
||||
}
|
||||
|
||||
mac, err := hex.DecodeString(cryptoItem.MAC)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iv, err := hex.DecodeString(cryptoItem.CipherParams.IV)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cipherText, err := hex.DecodeString(cryptoItem.CipherText)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
derivedKey, err := getKDFKey(cryptoItem, auth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
calculatedMAC := crypto.Keccak256(derivedKey[16:32], cipherText)
|
||||
if !bytes.Equal(calculatedMAC, mac) {
|
||||
return nil, ErrDecrypt
|
||||
}
|
||||
|
||||
plainText, err := aesCTRXOR(derivedKey[:16], cipherText, iv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return plainText, err
|
||||
}
|
||||
|
||||
func decryptKeyV1(keyProtected *encryptedKeyJSONV1, auth string) (keyBytes []byte, keyId []byte, err error) {
|
||||
|
|
|
|||
|
|
@ -59,3 +59,8 @@ func (ks keyStorePlain) JoinPath(filename string) string {
|
|||
}
|
||||
return filepath.Join(ks.keysDirPath, filename)
|
||||
}
|
||||
|
||||
// TODO: to be implemented
|
||||
func (ks keyStorePlain) GetEncryptedKey(a common.Address, filename string) (*Key, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,12 @@
|
|||
package keystore
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
ethereum "github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
)
|
||||
|
|
@ -146,3 +148,25 @@ func (w *keystoreWallet) SignTxWithPassphrase(account accounts.Account, passphra
|
|||
// Account seems valid, request the keystore to sign
|
||||
return w.keystore.SignTxWithPassphrase(account, passphrase, tx, chainID)
|
||||
}
|
||||
|
||||
// GetUseAddress represents the wallet to retrieve corresponding usechain public address for a specific ordinary account/address
|
||||
func (w *keystoreWallet) GetUseAddress(account accounts.Account) (common.UAddress, error) {
|
||||
// Make sure the requested account is contained within
|
||||
if account.Address != w.account.Address {
|
||||
return common.UAddress{}, accounts.ErrUnknownAccount
|
||||
}
|
||||
if account.URL != (accounts.URL{}) && account.URL != w.account.URL {
|
||||
return common.UAddress{}, accounts.ErrUnknownAccount
|
||||
}
|
||||
// Account seems valid, request the keystore to retrieve
|
||||
return w.keystore.GetUseAddress(account)
|
||||
}
|
||||
|
||||
func (w *keystoreWallet) GetUnlockedKey(address common.Address) (*Key, error) {
|
||||
value, ok := w.keystore.unlocked[address]
|
||||
if !ok {
|
||||
return nil, errors.New("can not found a unlock key of: " + address.Hex())
|
||||
}
|
||||
|
||||
return value.Key, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -788,6 +788,11 @@ func (w *Wallet) findAccountPath(account accounts.Account) (accounts.DerivationP
|
|||
return accounts.ParseDerivationPath(parts[1])
|
||||
}
|
||||
|
||||
// TODO: TBI
|
||||
func (w *Wallet) GetUseAddress(account accounts.Account) (common.UAddress, error) {
|
||||
return common.UAddress{}, nil
|
||||
}
|
||||
|
||||
// Session represents a secured communication session with the wallet.
|
||||
type Session struct {
|
||||
Wallet *Wallet // A handle to the wallet that opened the session
|
||||
|
|
|
|||
|
|
@ -593,3 +593,8 @@ func (w *wallet) SignTextWithPassphrase(account accounts.Account, passphrase str
|
|||
func (w *wallet) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
|
||||
return w.SignTx(account, tx, chainID)
|
||||
}
|
||||
|
||||
// TODO: TBI
|
||||
func (w *wallet) GetUseAddress(account accounts.Account) (common.UAddress, error) {
|
||||
return common.UAddress{}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1805,3 +1805,20 @@ func (s *PublicNetAPI) PeerCount() hexutil.Uint {
|
|||
func (s *PublicNetAPI) Version() string {
|
||||
return fmt.Sprintf("%d", s.networkVersion)
|
||||
}
|
||||
|
||||
////////////////////added for privacy tx ////////////////////////////////////////
|
||||
// GetUseAddress returns corresponding UAddress of an ordinary account
|
||||
func (s *PublicTransactionPoolAPI) GetUseAddress(ctx context.Context, a common.Address) (string, error) {
|
||||
account := accounts.Account{Address: a}
|
||||
// first fetch the wallet/keystore, and then retrieve the useaddress
|
||||
wallet, err := s.b.AccountManager().Find(account)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
useAddr, err := wallet.GetUseAddress(account)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return hexutil.Encode(useAddr[:]), nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,11 +96,21 @@ func GetAPIs(apiBackend Backend) []rpc.API {
|
|||
Version: "1.0",
|
||||
Service: NewPublicBlockChainAPI(apiBackend),
|
||||
Public: true,
|
||||
}, {
|
||||
Namespace: "use",
|
||||
Version: "1.0",
|
||||
Service: NewPublicBlockChainAPI(apiBackend),
|
||||
Public: true,
|
||||
},{
|
||||
Namespace: "eth",
|
||||
Version: "1.0",
|
||||
Service: NewPublicTransactionPoolAPI(apiBackend, nonceLock),
|
||||
Public: true,
|
||||
},{
|
||||
Namespace: "use",
|
||||
Version: "1.0",
|
||||
Service: NewPublicTransactionPoolAPI(apiBackend, nonceLock),
|
||||
Public: true,
|
||||
},{
|
||||
Namespace: "txpool",
|
||||
Version: "1.0",
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -2509,6 +2509,7 @@ module.exports={
|
|||
var RequestManager = require('./web3/requestmanager');
|
||||
var Iban = require('./web3/iban');
|
||||
var Eth = require('./web3/methods/eth');
|
||||
var Use = require('./web3/methods/use');
|
||||
var DB = require('./web3/methods/db');
|
||||
var Shh = require('./web3/methods/shh');
|
||||
var Net = require('./web3/methods/net');
|
||||
|
|
@ -2531,6 +2532,7 @@ function Web3 (provider) {
|
|||
this._requestManager = new RequestManager(provider);
|
||||
this.currentProvider = provider;
|
||||
this.eth = new Eth(this);
|
||||
this.use = new Use(this);
|
||||
this.db = new DB(this);
|
||||
this.shh = new Shh(this);
|
||||
this.net = new Net(this);
|
||||
|
|
@ -2632,7 +2634,7 @@ Web3.prototype.createBatch = function () {
|
|||
module.exports = Web3;
|
||||
|
||||
|
||||
},{"./utils/sha3":19,"./utils/utils":20,"./version.json":21,"./web3/batch":24,"./web3/extend":28,"./web3/httpprovider":32,"./web3/iban":33,"./web3/ipcprovider":34,"./web3/methods/db":37,"./web3/methods/eth":38,"./web3/methods/net":39,"./web3/methods/personal":40,"./web3/methods/shh":41,"./web3/methods/swarm":42,"./web3/property":45,"./web3/requestmanager":46,"./web3/settings":47,"bignumber.js":"bignumber.js"}],23:[function(require,module,exports){
|
||||
},{"./utils/sha3":19,"./utils/utils":20,"./version.json":21,"./web3/batch":24,"./web3/extend":28,"./web3/httpprovider":32,"./web3/iban":33,"./web3/ipcprovider":34,"./web3/methods/db":37,"./web3/methods/eth":38,"./web3/methods/use":87,"./web3/methods/net":39,"./web3/methods/personal":40,"./web3/methods/shh":41,"./web3/methods/swarm":42,"./web3/property":45,"./web3/requestmanager":46,"./web3/settings":47,"bignumber.js":"bignumber.js"}],23:[function(require,module,exports){
|
||||
/*
|
||||
This file is part of web3.js.
|
||||
|
||||
|
|
@ -5358,6 +5360,13 @@ var methods = function () {
|
|||
outputFormatter: utils.toDecimal
|
||||
});
|
||||
|
||||
var getUseAddress = new Method({
|
||||
name: 'getUseAddress',
|
||||
call: 'eth_getUseAddress',
|
||||
params: 1,
|
||||
inputFormatter: [formatters.inputAddressFormatter]
|
||||
});
|
||||
|
||||
var sendRawTransaction = new Method({
|
||||
name: 'sendRawTransaction',
|
||||
call: 'eth_sendRawTransaction',
|
||||
|
|
@ -5444,6 +5453,7 @@ var methods = function () {
|
|||
getTransactionFromBlock,
|
||||
getTransactionReceipt,
|
||||
getTransactionCount,
|
||||
getUseAddress,
|
||||
call,
|
||||
estimateGas,
|
||||
sendRawTransaction,
|
||||
|
|
@ -13608,7 +13618,44 @@ module.exports = transfer;
|
|||
},{}],86:[function(require,module,exports){
|
||||
module.exports = XMLHttpRequest;
|
||||
|
||||
},{}],"bignumber.js":[function(require,module,exports){
|
||||
},{}],87:[function(require,module,exports){
|
||||
/* use.js */
|
||||
var Method = require('../method');
|
||||
var formatters = require('../formatters');
|
||||
|
||||
function Use(web3) {
|
||||
this._requestManager = web3._requestManager;
|
||||
|
||||
var self = this;
|
||||
|
||||
methods().forEach(function(method) {
|
||||
method.attachToObject(self);
|
||||
method.setRequestManager(self._requestManager);
|
||||
});
|
||||
|
||||
properties().forEach(function(p) {
|
||||
p.attachToObject(self);
|
||||
p.setRequestManager(self._requestManager);
|
||||
});
|
||||
}
|
||||
|
||||
var methods = function () {
|
||||
var getUseAddress = new Method({
|
||||
name: 'getUseAddress',
|
||||
call: 'use_getUseAddress',
|
||||
params: 1,
|
||||
inputFormatter: [formatters.inputAddressFormatter]
|
||||
});
|
||||
|
||||
return [
|
||||
getUseAddress,
|
||||
];
|
||||
};
|
||||
var properties = function () {
|
||||
return [];
|
||||
};
|
||||
module.exports = Use;
|
||||
},{"../formatters":30,"../method":36}],"bignumber.js":[function(require,module,exports){
|
||||
'use strict';
|
||||
|
||||
module.exports = BigNumber; // jshint ignore:line
|
||||
|
|
|
|||
Loading…
Reference in a new issue