Integrate keystore with chain/wallet
License: MIT Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
This commit is contained in:
parent
cb9bf4200c
commit
710f87fdf4
155
chain/wallet.go
155
chain/wallet.go
@ -4,25 +4,36 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
"github.com/filecoin-project/go-lotus/chain/types"
|
||||
"github.com/filecoin-project/go-lotus/lib/bls-signatures"
|
||||
"github.com/filecoin-project/go-lotus/lib/crypto"
|
||||
|
||||
"github.com/minio/blake2b-simd"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
const (
|
||||
KNamePrefix = "wallet-"
|
||||
|
||||
KTSecp256k1 = "secp256k1"
|
||||
KTBLS = "bls"
|
||||
)
|
||||
|
||||
type Wallet struct {
|
||||
keys map[address.Address]*KeyInfo
|
||||
keys map[address.Address]*Key
|
||||
keystore types.KeyStore
|
||||
}
|
||||
|
||||
func NewWallet() *Wallet {
|
||||
return &Wallet{keys: make(map[address.Address]*KeyInfo)}
|
||||
func NewWallet(keystore types.KeyStore) (*Wallet, error) {
|
||||
w := &Wallet{
|
||||
keys: make(map[address.Address]*Key),
|
||||
keystore: keystore,
|
||||
}
|
||||
|
||||
return w, nil
|
||||
}
|
||||
|
||||
type Signature struct {
|
||||
@ -118,12 +129,21 @@ func (w *Wallet) Sign(addr address.Address, msg []byte) (*Signature, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Wallet) findKey(addr address.Address) (*KeyInfo, error) {
|
||||
ki, ok := w.keys[addr]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("key not for given address not found in wallet")
|
||||
func (w *Wallet) findKey(addr address.Address) (*Key, error) {
|
||||
k, ok := w.keys[addr]
|
||||
if ok {
|
||||
return k, nil
|
||||
}
|
||||
return ki, nil
|
||||
ki, err := w.keystore.Get(KNamePrefix + addr.String())
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("getting from keystore: %w", err)
|
||||
}
|
||||
k, err = NewKey(ki)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("decoding from keystore: %w", err)
|
||||
}
|
||||
w.keys[k.Address] = k
|
||||
return k, nil
|
||||
}
|
||||
|
||||
func (w *Wallet) Export(addr address.Address) ([]byte, error) {
|
||||
@ -134,74 +154,99 @@ func (w *Wallet) Import(kdata []byte) (address.Address, error) {
|
||||
panic("nyi")
|
||||
}
|
||||
|
||||
func (w *Wallet) ListAddrs() []address.Address {
|
||||
var out []address.Address
|
||||
for a := range w.keys {
|
||||
out = append(out, a)
|
||||
func (w *Wallet) ListAddrs() ([]address.Address, error) {
|
||||
all, err := w.keystore.List()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("listing keystore: %w", err)
|
||||
}
|
||||
sort.Slice(out, func(i, j int) bool {
|
||||
return out[i].String() < out[j].String()
|
||||
})
|
||||
return out
|
||||
|
||||
sort.Strings(all)
|
||||
|
||||
out := make([]address.Address, 0, len(all))
|
||||
for _, a := range all {
|
||||
if strings.HasPrefix(a, KNamePrefix) {
|
||||
name := strings.TrimPrefix(a, KNamePrefix)
|
||||
addr, err := address.NewFromString(name)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("converting name to address: %w", err)
|
||||
}
|
||||
out = append(out, addr)
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (w *Wallet) GenerateKey(typ string) (address.Address, error) {
|
||||
var k *Key
|
||||
switch typ {
|
||||
case KTSecp256k1:
|
||||
k, err := crypto.GenerateKey()
|
||||
priv, err := crypto.GenerateKey()
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
ki := &KeyInfo{
|
||||
PrivateKey: k,
|
||||
Type: typ,
|
||||
}
|
||||
|
||||
addr := ki.Address()
|
||||
w.keys[addr] = ki
|
||||
return addr, nil
|
||||
k, err = NewKey(types.KeyInfo{typ, priv})
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
case KTBLS:
|
||||
priv := bls.PrivateKeyGenerate()
|
||||
|
||||
ki := &KeyInfo{
|
||||
PrivateKey: priv[:],
|
||||
Type: KTBLS,
|
||||
}
|
||||
|
||||
addr := ki.Address()
|
||||
w.keys[addr] = ki
|
||||
return addr, nil
|
||||
default:
|
||||
return address.Undef, fmt.Errorf("invalid key type: %s", typ)
|
||||
}
|
||||
}
|
||||
|
||||
type KeyInfo struct {
|
||||
PrivateKey []byte
|
||||
|
||||
Type string
|
||||
}
|
||||
|
||||
func (ki *KeyInfo) Address() address.Address {
|
||||
switch ki.Type {
|
||||
case KTSecp256k1:
|
||||
pub := crypto.PublicKey(ki.PrivateKey)
|
||||
addr, err := address.NewSecp256k1Address(pub)
|
||||
var err error
|
||||
k, err = NewKey(types.KeyInfo{typ, priv[:]})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return address.Undef, err
|
||||
}
|
||||
default:
|
||||
return address.Undef, xerrors.Errorf("invalid key type: %s", typ)
|
||||
}
|
||||
|
||||
err := w.keystore.Put(KNamePrefix+k.Address.String(), k.KeyInfo)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("saving to keystore: %w", err)
|
||||
}
|
||||
w.keys[k.Address] = k
|
||||
return k.Address, nil
|
||||
}
|
||||
|
||||
type Key struct {
|
||||
types.KeyInfo
|
||||
|
||||
PublicKey []byte
|
||||
Address address.Address
|
||||
}
|
||||
|
||||
func NewKey(keyinfo types.KeyInfo) (*Key, error) {
|
||||
k := &Key{
|
||||
KeyInfo: keyinfo,
|
||||
}
|
||||
|
||||
switch k.Type {
|
||||
case KTSecp256k1:
|
||||
k.PublicKey = crypto.PublicKey(k.PrivateKey)
|
||||
|
||||
var err error
|
||||
k.Address, err = address.NewSecp256k1Address(k.PublicKey)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err)
|
||||
}
|
||||
|
||||
return addr
|
||||
case KTBLS:
|
||||
var pk bls.PrivateKey
|
||||
copy(pk[:], ki.PrivateKey)
|
||||
copy(pk[:], k.PrivateKey)
|
||||
pub := bls.PrivateKeyPublicKey(pk)
|
||||
a, err := address.NewBLSAddress(pub[:])
|
||||
k.PublicKey = pub[:]
|
||||
|
||||
var err error
|
||||
k.Address, err = address.NewBLSAddress(k.PublicKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return nil, xerrors.Errorf("converting BLS to address: %w", err)
|
||||
}
|
||||
return a
|
||||
|
||||
default:
|
||||
panic("unsupported key type")
|
||||
return nil, xerrors.Errorf("unknown key type")
|
||||
}
|
||||
return k, nil
|
||||
|
||||
}
|
||||
|
1
go.mod
1
go.mod
@ -66,6 +66,7 @@ require (
|
||||
go4.org v0.0.0-20190313082347-94abd6928b1d // indirect
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522
|
||||
google.golang.org/appengine v1.4.0 // indirect
|
||||
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8
|
||||
launchpad.net/gocheck v0.0.0-20140225173054-000000000087 // indirect
|
||||
)
|
||||
|
@ -110,7 +110,7 @@ func (a *API) WalletNew(ctx context.Context, typ string) (address.Address, error
|
||||
}
|
||||
|
||||
func (a *API) WalletList(ctx context.Context) ([]address.Address, error) {
|
||||
return a.Wallet.ListAddrs(), nil
|
||||
return a.Wallet.ListAddrs()
|
||||
}
|
||||
|
||||
func (a *API) NetConnect(ctx context.Context, p peer.AddrInfo) error {
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-lotus/api"
|
||||
"github.com/filecoin-project/go-lotus/chain"
|
||||
"github.com/filecoin-project/go-lotus/chain/types"
|
||||
"github.com/filecoin-project/go-lotus/node/config"
|
||||
"github.com/filecoin-project/go-lotus/node/hello"
|
||||
"github.com/filecoin-project/go-lotus/node/modules"
|
||||
@ -213,6 +214,10 @@ func Repo(r repo.Repo) Option {
|
||||
if err != nil {
|
||||
return Error(err)
|
||||
}
|
||||
kstore, err := lr.KeyStore()
|
||||
if err != nil {
|
||||
return Error(err)
|
||||
}
|
||||
|
||||
return Options(
|
||||
Config(cfg),
|
||||
@ -227,6 +232,8 @@ func Repo(r repo.Repo) Option {
|
||||
Override(new(ci.PrivKey), pk),
|
||||
Override(new(ci.PubKey), ci.PrivKey.GetPublic),
|
||||
Override(new(peer.ID), peer.IDFromPublicKey),
|
||||
|
||||
Override(new(types.KeyStore), kstore),
|
||||
)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user