Merge pull request #294 from filecoin-project/feat/wallet-importing
implement key import and export
This commit is contained in:
commit
ed78894d20
@ -65,7 +65,7 @@ type FullNode interface {
|
|||||||
// messages
|
// messages
|
||||||
|
|
||||||
MpoolPending(context.Context, *types.TipSet) ([]*types.SignedMessage, error)
|
MpoolPending(context.Context, *types.TipSet) ([]*types.SignedMessage, error)
|
||||||
MpoolPush(context.Context, *types.SignedMessage) error // TODO: remove
|
MpoolPush(context.Context, *types.SignedMessage) error // TODO: remove
|
||||||
MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error) // get nonce, sign, push
|
MpoolPushMessage(context.Context, *types.Message) (*types.SignedMessage, error) // get nonce, sign, push
|
||||||
MpoolGetNonce(context.Context, address.Address) (uint64, error)
|
MpoolGetNonce(context.Context, address.Address) (uint64, error)
|
||||||
|
|
||||||
@ -89,6 +89,8 @@ type FullNode interface {
|
|||||||
WalletSign(context.Context, address.Address, []byte) (*types.Signature, error)
|
WalletSign(context.Context, address.Address, []byte) (*types.Signature, error)
|
||||||
WalletSignMessage(context.Context, address.Address, *types.Message) (*types.SignedMessage, error)
|
WalletSignMessage(context.Context, address.Address, *types.Message) (*types.SignedMessage, error)
|
||||||
WalletDefaultAddress(context.Context) (address.Address, error)
|
WalletDefaultAddress(context.Context) (address.Address, error)
|
||||||
|
WalletExport(context.Context, address.Address) (*types.KeyInfo, error)
|
||||||
|
WalletImport(context.Context, *types.KeyInfo) (address.Address, error)
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
|
|
||||||
|
@ -67,7 +67,10 @@ type FullNodeStruct struct {
|
|||||||
WalletSign func(context.Context, address.Address, []byte) (*types.Signature, error) `perm:"sign"`
|
WalletSign func(context.Context, address.Address, []byte) (*types.Signature, error) `perm:"sign"`
|
||||||
WalletSignMessage func(context.Context, address.Address, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
|
WalletSignMessage func(context.Context, address.Address, *types.Message) (*types.SignedMessage, error) `perm:"sign"`
|
||||||
WalletDefaultAddress func(context.Context) (address.Address, error) `perm:"write"`
|
WalletDefaultAddress func(context.Context) (address.Address, error) `perm:"write"`
|
||||||
MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"`
|
WalletExport func(context.Context, address.Address) (*types.KeyInfo, error) `perm:"admin"`
|
||||||
|
WalletImport func(context.Context, *types.KeyInfo) (address.Address, error) `perm:"admin"`
|
||||||
|
|
||||||
|
MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"`
|
||||||
|
|
||||||
ClientImport func(ctx context.Context, path string) (cid.Cid, error) `perm:"write"`
|
ClientImport func(ctx context.Context, path string) (cid.Cid, error) `perm:"write"`
|
||||||
ClientListImports func(ctx context.Context) ([]Import, error) `perm:"write"`
|
ClientListImports func(ctx context.Context) ([]Import, error) `perm:"write"`
|
||||||
@ -268,6 +271,14 @@ func (c *FullNodeStruct) WalletDefaultAddress(ctx context.Context) (address.Addr
|
|||||||
return c.Internal.WalletDefaultAddress(ctx)
|
return c.Internal.WalletDefaultAddress(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *FullNodeStruct) WalletExport(ctx context.Context, a address.Address) (*types.KeyInfo, error) {
|
||||||
|
return c.Internal.WalletExport(ctx, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *FullNodeStruct) WalletImport(ctx context.Context, ki *types.KeyInfo) (address.Address, error) {
|
||||||
|
return c.Internal.WalletImport(ctx, ki)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *FullNodeStruct) MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error) {
|
func (c *FullNodeStruct) MpoolGetNonce(ctx context.Context, addr address.Address) (uint64, error) {
|
||||||
return c.Internal.MpoolGetNonce(ctx, addr)
|
return c.Internal.MpoolGetNonce(ctx, addr)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-bls-sigs"
|
"github.com/filecoin-project/go-bls-sigs"
|
||||||
"github.com/filecoin-project/go-lotus/node/repo"
|
"github.com/filecoin-project/go-lotus/node/repo"
|
||||||
@ -23,6 +24,8 @@ const (
|
|||||||
type Wallet struct {
|
type Wallet struct {
|
||||||
keys map[address.Address]*Key
|
keys map[address.Address]*Key
|
||||||
keystore types.KeyStore
|
keystore types.KeyStore
|
||||||
|
|
||||||
|
lk sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWallet(keystore types.KeyStore) (*Wallet, error) {
|
func NewWallet(keystore types.KeyStore) (*Wallet, error) {
|
||||||
@ -71,6 +74,9 @@ func (w *Wallet) Sign(ctx context.Context, addr address.Address, msg []byte) (*t
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wallet) findKey(addr address.Address) (*Key, error) {
|
func (w *Wallet) findKey(addr address.Address) (*Key, error) {
|
||||||
|
w.lk.Lock()
|
||||||
|
defer w.lk.Unlock()
|
||||||
|
|
||||||
k, ok := w.keys[addr]
|
k, ok := w.keys[addr]
|
||||||
if ok {
|
if ok {
|
||||||
return k, nil
|
return k, nil
|
||||||
@ -90,12 +96,29 @@ func (w *Wallet) findKey(addr address.Address) (*Key, error) {
|
|||||||
return k, nil
|
return k, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wallet) Export(addr address.Address) ([]byte, error) {
|
func (w *Wallet) Export(addr address.Address) (*types.KeyInfo, error) {
|
||||||
panic("nyi")
|
k, err := w.findKey(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.Errorf("failed to find key to export: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &k.KeyInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wallet) Import(kdata []byte) (address.Address, error) {
|
func (w *Wallet) Import(ki *types.KeyInfo) (address.Address, error) {
|
||||||
panic("nyi")
|
w.lk.Lock()
|
||||||
|
defer w.lk.Unlock()
|
||||||
|
|
||||||
|
k, err := NewKey(*ki)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("failed to make key: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := w.keystore.Put(KNamePrefix+k.Address.String(), k.KeyInfo); err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("saving to keystore: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return k.Address, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wallet) ListAddrs() ([]address.Address, error) {
|
func (w *Wallet) ListAddrs() ([]address.Address, error) {
|
||||||
@ -148,6 +171,9 @@ func GenerateKey(typ string) (*Key, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wallet) GenerateKey(typ string) (address.Address, error) {
|
func (w *Wallet) GenerateKey(typ string) (address.Address, error) {
|
||||||
|
w.lk.Lock()
|
||||||
|
defer w.lk.Unlock()
|
||||||
|
|
||||||
k, err := GenerateKey(typ)
|
k, err := GenerateKey(typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return address.Undef, err
|
return address.Undef, err
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
package cli
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-lotus/chain/address"
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
|
types "github.com/filecoin-project/go-lotus/chain/types"
|
||||||
"gopkg.in/urfave/cli.v2"
|
"gopkg.in/urfave/cli.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,6 +20,8 @@ var walletCmd = &cli.Command{
|
|||||||
walletNew,
|
walletNew,
|
||||||
walletList,
|
walletList,
|
||||||
walletBalance,
|
walletBalance,
|
||||||
|
walletExport,
|
||||||
|
walletImport,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,3 +105,84 @@ var walletBalance = &cli.Command{
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var walletExport = &cli.Command{
|
||||||
|
Name: "export",
|
||||||
|
Usage: "export keys",
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
api, closer, err := GetFullNodeAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer closer()
|
||||||
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
|
if !cctx.Args().Present() {
|
||||||
|
return fmt.Errorf("must specify key to export")
|
||||||
|
}
|
||||||
|
|
||||||
|
addr, err := address.NewFromString(cctx.Args().First())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ki, err := api.WalletExport(ctx, addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := json.Marshal(ki)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(hex.EncodeToString(b))
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var walletImport = &cli.Command{
|
||||||
|
Name: "import",
|
||||||
|
Usage: "import keys",
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
api, closer, err := GetFullNodeAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer closer()
|
||||||
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
|
var data []byte
|
||||||
|
if !cctx.Args().Present() || cctx.Args().First() == "-" {
|
||||||
|
indata, err := ioutil.ReadAll(os.Stdin)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dec, err := hex.DecodeString(strings.TrimSpace(string(indata)))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
data = dec
|
||||||
|
} else {
|
||||||
|
fdata, err := ioutil.ReadFile(cctx.Args().First())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
data = fdata
|
||||||
|
}
|
||||||
|
|
||||||
|
var ki types.KeyInfo
|
||||||
|
if err := json.Unmarshal(data, &ki); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
addr, err := api.WalletImport(ctx, &ki)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("imported key %s successfully!", addr)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@ -68,3 +68,11 @@ func (a *WalletAPI) WalletDefaultAddress(ctx context.Context) (address.Address,
|
|||||||
// TODO: store a default address in the config or 'wallet' portion of the repo
|
// TODO: store a default address in the config or 'wallet' portion of the repo
|
||||||
return addrs[0], nil
|
return addrs[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *WalletAPI) WalletExport(ctx context.Context, addr address.Address) (*types.KeyInfo, error) {
|
||||||
|
return a.Wallet.Export(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *WalletAPI) WalletImport(ctx context.Context, ki *types.KeyInfo) (address.Address, error) {
|
||||||
|
return a.Wallet.Import(ki)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user