/
wallet.go
129 lines (98 loc) · 3.94 KB
/
wallet.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package pluggable
import (
"context"
"math/big"
"sync"
"time"
"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"
plugin "github.com/ethereum/go-ethereum/plugin/account"
)
type wallet struct {
url accounts.URL
mu sync.Mutex
pluginService plugin.Service
}
func (w *wallet) setPluginService(s plugin.Service) error {
w.mu.Lock()
defer w.mu.Unlock()
w.pluginService = s
return nil
}
func (w *wallet) URL() accounts.URL {
return w.url
}
func (w *wallet) Status() (string, error) {
return w.pluginService.Status(context.Background())
}
func (w *wallet) Open(passphrase string) error {
return w.pluginService.Open(context.Background(), passphrase)
}
func (w *wallet) Close() error {
return w.pluginService.Close(context.Background())
}
func (w *wallet) Accounts() []accounts.Account {
return w.pluginService.Accounts(context.Background())
}
func (w *wallet) Contains(account accounts.Account) bool {
return w.pluginService.Contains(context.Background(), account)
}
func (w *wallet) Derive(_ accounts.DerivationPath, _ bool) (accounts.Account, error) {
return accounts.Account{}, accounts.ErrNotSupported
}
func (w *wallet) SelfDerive(_ []accounts.DerivationPath, _ ethereum.ChainStateReader) {}
func (w *wallet) SignData(account accounts.Account, _ string, data []byte) ([]byte, error) {
return w.pluginService.Sign(context.Background(), account, crypto.Keccak256(data))
}
func (w *wallet) SignDataWithPassphrase(account accounts.Account, passphrase, _ string, data []byte) ([]byte, error) {
return w.pluginService.UnlockAndSign(context.Background(), account, crypto.Keccak256(data), passphrase)
}
func (w *wallet) SignText(account accounts.Account, text []byte) ([]byte, error) {
return w.pluginService.Sign(context.Background(), account, accounts.TextHash(text))
}
func (w *wallet) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) {
return w.pluginService.UnlockAndSign(context.Background(), account, accounts.TextHash(text), passphrase)
}
func (w *wallet) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
toSign, signer := prepareTxForSign(tx, chainID)
sig, err := w.pluginService.Sign(context.Background(), account, toSign.Bytes())
if err != nil {
return nil, err
}
return tx.WithSignature(signer, sig)
}
func (w *wallet) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
toSign, signer := prepareTxForSign(tx, chainID)
sig, err := w.pluginService.UnlockAndSign(context.Background(), account, toSign.Bytes(), passphrase)
if err != nil {
return nil, err
}
return tx.WithSignature(signer, sig)
}
func (w *wallet) timedUnlock(account accounts.Account, password string, duration time.Duration) error {
return w.pluginService.TimedUnlock(context.Background(), account, password, duration)
}
func (w *wallet) lock(account accounts.Account) error {
return w.pluginService.Lock(context.Background(), account)
}
func (w *wallet) newAccount(newAccountConfig interface{}) (accounts.Account, error) {
return w.pluginService.NewAccount(context.Background(), newAccountConfig)
}
func (w *wallet) importRawKey(rawKey string, newAccountConfig interface{}) (accounts.Account, error) {
return w.pluginService.ImportRawKey(context.Background(), rawKey, newAccountConfig)
}
// prepareTxForSign determines which Signer to use for the given tx and chainID, and returns the Signer's hash of the tx and the Signer itself
func prepareTxForSign(tx *types.Transaction, chainID *big.Int) (common.Hash, types.Signer) {
var s types.Signer
if tx.IsPrivate() {
s = types.QuorumPrivateTxSigner{}
} else if chainID == nil {
s = types.HomesteadSigner{}
} else {
s = types.NewEIP155Signer(chainID)
}
return s.Hash(tx), s
}