From b35f9b56b42ae7415284f5ced424af21923d693e Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Fri, 9 Oct 2020 20:17:04 -0700 Subject: [PATCH 01/17] WIP: adding in ledger support Signed-off-by: Jakub Sztandera --- chain/messagepool/messagepool.go | 3 + chain/wallet/ledger/ledger.go | 139 +++++++++++++++++++++ cmd/lotus-shed/ledger.go | 205 +++++++++++++++++++++++++++++++ cmd/lotus-shed/main.go | 1 + cmd/lotus-wallet/main.go | 11 +- go.mod | 1 + go.sum | 7 ++ 7 files changed, 366 insertions(+), 1 deletion(-) create mode 100644 chain/wallet/ledger/ledger.go create mode 100644 cmd/lotus-shed/ledger.go diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index d3c638b22..2a4704c3b 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -1249,6 +1249,9 @@ func (mp *MessagePool) Updates(ctx context.Context) (<-chan api.MpoolUpdate, err } func (mp *MessagePool) loadLocal() error { + return nil + // TODO: this causes super slow startup... + res, err := mp.localMsgs.Query(query.Query{}) if err != nil { return xerrors.Errorf("query local messages: %w", err) diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go new file mode 100644 index 000000000..36b0fb040 --- /dev/null +++ b/chain/wallet/ledger/ledger.go @@ -0,0 +1,139 @@ +package ledgerwallet + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/types" + "github.com/ipfs/go-datastore" + "github.com/ipfs/go-datastore/query" + ledgerfil "github.com/whyrusleeping/ledger-filecoin-go" +) + +type LedgerWallet struct { + ds datastore.Datastore +} + +func NewWallet(ds datastore.Datastore) *LedgerWallet { + return &LedgerWallet{ds} +} + +type LedgerKeyInfo struct { + Address address.Address + Path []uint32 +} + +var _ (api.WalletAPI) = (*LedgerWallet)(nil) + +func (lw LedgerWallet) WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta api.MsgMeta) (*crypto.Signature, error) { + ki, err := lw.getKeyInfo(signer) + if err != nil { + return nil, err + } + + fl, err := ledgerfil.FindLedgerFilecoinApp() + if err != nil { + return nil, err + } + defer fl.Close() + if meta.Type != api.MTChainMsg { + return nil, fmt.Errorf("ledger can only sign chain messages") + } + + // TODO: assert meta matches the 'toSign' bits + + sig, err := fl.SignSECP256K1(ki.Path, meta.Extra) + if err != nil { + return nil, err + } + + return &crypto.Signature{ + Type: crypto.SigTypeSecp256k1, + Data: sig.SignatureBytes(), + }, nil +} + +func (lw LedgerWallet) getKeyInfo(addr address.Address) (*LedgerKeyInfo, error) { + kib, err := lw.ds.Get(keyForAddr(addr)) + if err != nil { + return nil, err + } + + var out LedgerKeyInfo + if err := json.Unmarshal(kib, &out); err != nil { + return nil, err + } + + return &out, nil +} + +func (lw LedgerWallet) WalletDelete(ctx context.Context, k address.Address) error { + return lw.ds.Delete(keyForAddr(k)) +} + +func (lw LedgerWallet) WalletExport(ctx context.Context, k address.Address) (*types.KeyInfo, error) { + return nil, fmt.Errorf("cannot export keys from ledger wallets") +} + +func (lw LedgerWallet) WalletHas(ctx context.Context, k address.Address) (bool, error) { + _, err := lw.ds.Get(keyForAddr(k)) + if err == nil { + return true, nil + } + if err == datastore.ErrNotFound { + return false, nil + } + return false, err +} + +func (lw LedgerWallet) WalletImport(ctx context.Context, kinfo *types.KeyInfo) (address.Address, error) { + var ki LedgerKeyInfo + if err := json.Unmarshal(kinfo.PrivateKey, &ki); err != nil { + return address.Undef, err + } + + if ki.Address == address.Undef { + return address.Undef, fmt.Errorf("no address given in imported key info") + } + + if err := lw.ds.Put(keyForAddr(ki.Address), kinfo.PrivateKey); err != nil { + return address.Undef, err + } + + return ki.Address, nil +} + +func (lw LedgerWallet) WalletList(ctx context.Context) ([]address.Address, error) { + res, err := lw.ds.Query(query.Query{Prefix: "ledgerkey/"}) + if err != nil { + return nil, err + } + + var out []address.Address + for { + res, ok := res.NextSync() + if !ok { + break + } + + var ki LedgerKeyInfo + if err := json.Unmarshal(res.Value, &ki); err != nil { + return nil, err + } + + out = append(out, ki.Address) + } + return out, nil +} + +func (lw LedgerWallet) WalletNew(ctx context.Context, t crypto.SigType) (address.Address, error) { + return address.Undef, fmt.Errorf("cannot create new address on ledger") +} + +func keyForAddr(addr address.Address) datastore.Key { + return datastore.NewKey("ledgerkey/" + addr.String()) +} diff --git a/cmd/lotus-shed/ledger.go b/cmd/lotus-shed/ledger.go new file mode 100644 index 000000000..4bb61e5e0 --- /dev/null +++ b/cmd/lotus-shed/ledger.go @@ -0,0 +1,205 @@ +package main + +import ( + "encoding/json" + "fmt" + "strconv" + "strings" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/chain/wallet" + ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" + "github.com/urfave/cli/v2" + ledgerfil "github.com/whyrusleeping/ledger-filecoin-go" +) + +var ledgerCmd = &cli.Command{ + Name: "ledger", + Usage: "Ledger interactions", + Flags: []cli.Flag{}, + Subcommands: []*cli.Command{ + ledgerListAddressesCmd, + ledgerKeyInfoCmd, + ledgerSignTestCmd, + }, +} + +var ledgerListAddressesCmd = &cli.Command{ + Name: "list", + Action: func(cctx *cli.Context) error { + + fl, err := ledgerfil.FindLedgerFilecoinApp() + if err != nil { + return err + } + + for i := 0; i < 20; i++ { + p := []uint32{0x80000000 + 44, 0x80000000 + 461, 0x80000000, 0, uint32(i)} + pubk, err := fl.GetPublicKeySECP256K1(p) + if err != nil { + return err + } + + addr, err := address.NewSecp256k1Address(pubk) + if err != nil { + return err + } + + fmt.Printf("%s: %s\n", addr, printHDPath(p)) + } + + return nil + }, +} + +func parseHDPath(s string) ([]uint32, error) { + parts := strings.Split(s, "/") + if parts[0] != "m" { + return nil, fmt.Errorf("expected HD path to start with 'm'") + } + + var out []uint32 + for _, p := range parts[1:] { + var hard bool + if strings.HasSuffix(p, "'") { + p = p[:len(p)-1] + hard = true + } + + v, err := strconv.ParseUint(p, 10, 32) + if err != nil { + return nil, err + } + if v >= 0x80000000 { + return nil, fmt.Errorf("path element %s too large", p) + } + + if hard { + v += 0x80000000 + } + out = append(out, uint32(v)) + } + return out, nil +} + +func printHDPath(pth []uint32) string { + s := "m/" + for _, p := range pth { + var hard bool + if p >= 0x80000000 { + p -= 0x80000000 + } + s += fmt.Sprint(p) + if hard { + s += "'" + } + s += "/" + } + + return strings.TrimRight(s, "/") +} + +func numlist(p []uint32) string { + var out []string + for _, v := range p { + out = append(out, fmt.Sprint(v)) + } + return strings.Join(out, ",") +} + +var ledgerKeyInfoCmd = &cli.Command{ + Name: "key-info", + Action: func(cctx *cli.Context) error { + if !cctx.Args().Present() { + return cli.ShowCommandHelp(cctx, cctx.Command.Name) + } + + fl, err := ledgerfil.FindLedgerFilecoinApp() + if err != nil { + return err + } + + p, err := parseHDPath(cctx.Args().First()) + if err != nil { + return err + } + + pubk, _, addr, err := fl.GetAddressPubKeySECP256K1(p) + if err != nil { + return err + } + fmt.Println(addr) + fmt.Println(pubk) + + a, err := address.NewFromString(addr) + if err != nil { + return err + } + + var pd ledgerwallet.LedgerKeyInfo + pd.Address = a + pd.Path = p + + b, err := json.Marshal(pd) + if err != nil { + return err + } + + var ki types.KeyInfo + ki.Type = wallet.KTSecp256k1 + ki.PrivateKey = b + + out, err := json.Marshal(ki) + if err != nil { + return err + } + + fmt.Println(string(out)) + + return nil + }, +} + +var ledgerSignTestCmd = &cli.Command{ + Name: "sign", + Action: func(cctx *cli.Context) error { + if !cctx.Args().Present() { + return cli.ShowCommandHelp(cctx, cctx.Command.Name) + } + + fl, err := ledgerfil.FindLedgerFilecoinApp() + if err != nil { + return err + } + + p, err := parseHDPath(cctx.Args().First()) + if err != nil { + return err + } + + addr, err := address.NewFromString("f1xc3hws5n6y5m3m44gzb3gyjzhups6wzmhe663ji") + if err != nil { + return err + } + + m := &types.Message{ + To: addr, + From: addr, + } + + b, err := m.ToStorageBlock() + if err != nil { + return err + } + + sig, err := fl.SignSECP256K1(p, b.RawData()) + if err != nil { + return err + } + + fmt.Println(sig.SignatureBytes()) + + return nil + }, +} diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index 4542551db..29a105355 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -41,6 +41,7 @@ func main() { syncCmd, stateTreePruneCmd, datastoreCmd, + ledgerCmd, } app := &cli.App{ diff --git a/cmd/lotus-wallet/main.go b/cmd/lotus-wallet/main.go index ae3580a59..fbedffed0 100644 --- a/cmd/lotus-wallet/main.go +++ b/cmd/lotus-wallet/main.go @@ -13,6 +13,7 @@ import ( "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/wallet" + ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" lcli "github.com/filecoin-project/lotus/cli" "github.com/filecoin-project/lotus/lib/lotuslog" "github.com/filecoin-project/lotus/node/repo" @@ -98,6 +99,14 @@ var runCmd = &cli.Command{ if err != nil { return err } + _ = w + + ds, err := lr.Datastore("/metadata") + if err != nil { + return err + } + + lw := ledgerwallet.NewWallet(ds) address := cctx.String("listen") mux := mux.NewRouter() @@ -105,7 +114,7 @@ var runCmd = &cli.Command{ log.Info("Setting up API endpoint at " + address) rpcServer := jsonrpc.NewServer() - rpcServer.Register("Filecoin", &LoggedWallet{under: w}) + rpcServer.Register("Filecoin", &LoggedWallet{under: lw}) mux.Handle("/rpc/v0", rpcServer) mux.PathPrefix("/").Handler(http.DefaultServeMux) // pprof diff --git a/go.mod b/go.mod index eb79a496c..d6a4768b7 100644 --- a/go.mod +++ b/go.mod @@ -120,6 +120,7 @@ require ( github.com/urfave/cli/v2 v2.2.0 github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba github.com/whyrusleeping/cbor-gen v0.0.0-20200826160007-0b9f6c5fb163 + github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 github.com/whyrusleeping/pubsub v0.0.0-20131020042734-02de8aa2db3d github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 diff --git a/go.sum b/go.sum index e13359f6c..fe7aacbf9 100644 --- a/go.sum +++ b/go.sum @@ -1422,6 +1422,8 @@ github.com/whyrusleeping/go-smux-multiplex v3.0.16+incompatible/go.mod h1:34LEDb github.com/whyrusleeping/go-smux-multistream v2.0.2+incompatible/go.mod h1:dRWHHvc4HDQSHh9gbKEBbUZ+f2Q8iZTPG3UOGYODxSQ= github.com/whyrusleeping/go-smux-yamux v2.0.8+incompatible/go.mod h1:6qHUzBXUbB9MXmw3AUdB52L8sEb/hScCqOdW2kj/wuI= github.com/whyrusleeping/go-smux-yamux v2.0.9+incompatible/go.mod h1:6qHUzBXUbB9MXmw3AUdB52L8sEb/hScCqOdW2kj/wuI= +github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4 h1:NwiwjQDB3CzQ5XH0rdMh1oQqzJH7O2PSLWxif/w3zsY= +github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4/go.mod h1:K+EVq8d5QcQ2At5VECsA+SNZvWefyBXh8TnIsxo1OvQ= github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= @@ -1443,6 +1445,10 @@ github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 h1:oWgZJmC1DorFZD github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/U6FtvQ= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8= +github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.12.1 h1:hYRcyznPRJp+5mzF2sazTLP2nGvGjYDD2VzhHhFomLU= +github.com/zondax/ledger-go v0.12.1/go.mod h1:KatxXrVDzgWwbssUWsF5+cOJHXPvzQ09YSlzGNuhOEo= go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= @@ -1515,6 +1521,7 @@ golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= From 99791a695373c78ec93d985adb5895358406585b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sat, 10 Oct 2020 13:03:39 +0200 Subject: [PATCH 02/17] lotus-wallet: ledger flag Signed-off-by: Jakub Sztandera --- cmd/lotus-wallet/main.go | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/cmd/lotus-wallet/main.go b/cmd/lotus-wallet/main.go index fbedffed0..2d87998a4 100644 --- a/cmd/lotus-wallet/main.go +++ b/cmd/lotus-wallet/main.go @@ -2,6 +2,7 @@ package main import ( "context" + "github.com/filecoin-project/lotus/api" "net" "net/http" "os" @@ -61,6 +62,10 @@ var runCmd = &cli.Command{ Usage: "host address and port the wallet api will listen on", Value: "0.0.0.0:1777", }, + &cli.BoolFlag{ + Name: "ledger", + Usage: "use a ledger device instead of an on-disk wallet", + }, }, Action: func(cctx *cli.Context) error { log.Info("Starting lotus wallet") @@ -95,18 +100,21 @@ var runCmd = &cli.Command{ return err } - w, err := wallet.NewWallet(ks) - if err != nil { - return err - } - _ = w + var w api.WalletAPI + if !cctx.Bool("ledger") { + w, err = wallet.NewWallet(ks) + if err != nil { + return err + } + } else { + ds, err := lr.Datastore("/metadata") + if err != nil { + return err + } - ds, err := lr.Datastore("/metadata") - if err != nil { - return err + w = ledgerwallet.NewWallet(ds) } - lw := ledgerwallet.NewWallet(ds) address := cctx.String("listen") mux := mux.NewRouter() @@ -114,7 +122,7 @@ var runCmd = &cli.Command{ log.Info("Setting up API endpoint at " + address) rpcServer := jsonrpc.NewServer() - rpcServer.Register("Filecoin", &LoggedWallet{under: lw}) + rpcServer.Register("Filecoin", &LoggedWallet{under: w}) mux.Handle("/rpc/v0", rpcServer) mux.PathPrefix("/").Handler(http.DefaultServeMux) // pprof From 66d6113340e943fe9aca2b0227312ac521b059e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sat, 10 Oct 2020 13:06:02 +0200 Subject: [PATCH 03/17] ledgerwallet: Validate signing bytes Signed-off-by: Jakub Sztandera --- chain/wallet/ledger/ledger.go | 21 +++++++++++++++++++-- cmd/lotus-wallet/main.go | 6 +++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index 36b0fb040..71ec067c8 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -1,9 +1,12 @@ package ledgerwallet import ( + "bytes" "context" "encoding/json" "fmt" + "github.com/ipfs/go-cid" + "golang.org/x/xerrors" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/crypto" @@ -27,7 +30,7 @@ type LedgerKeyInfo struct { Path []uint32 } -var _ (api.WalletAPI) = (*LedgerWallet)(nil) +var _ api.WalletAPI = (*LedgerWallet)(nil) func (lw LedgerWallet) WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta api.MsgMeta) (*crypto.Signature, error) { ki, err := lw.getKeyInfo(signer) @@ -44,7 +47,21 @@ func (lw LedgerWallet) WalletSign(ctx context.Context, signer address.Address, t return nil, fmt.Errorf("ledger can only sign chain messages") } - // TODO: assert meta matches the 'toSign' bits + { + var cmsg types.Message + if err := cmsg.UnmarshalCBOR(bytes.NewReader(meta.Extra)); err != nil { + return nil, xerrors.Errorf("unmarshalling message: %w", err) + } + + _, bc, err := cid.CidFromBytes(toSign) + if err != nil { + return nil, xerrors.Errorf("getting cid from signing bytes: %w", err) + } + + if !cmsg.Cid().Equals(bc) { + return nil, xerrors.Errorf("cid(meta.Extra).bytes() != toSign") + } + } sig, err := fl.SignSECP256K1(ki.Path, meta.Extra) if err != nil { diff --git a/cmd/lotus-wallet/main.go b/cmd/lotus-wallet/main.go index 2d87998a4..ffaddc7e3 100644 --- a/cmd/lotus-wallet/main.go +++ b/cmd/lotus-wallet/main.go @@ -2,7 +2,6 @@ package main import ( "context" - "github.com/filecoin-project/lotus/api" "net" "net/http" "os" @@ -12,6 +11,8 @@ import ( "github.com/urfave/cli/v2" "github.com/filecoin-project/go-jsonrpc" + + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/wallet" ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" @@ -63,7 +64,7 @@ var runCmd = &cli.Command{ Value: "0.0.0.0:1777", }, &cli.BoolFlag{ - Name: "ledger", + Name: "ledger", Usage: "use a ledger device instead of an on-disk wallet", }, }, @@ -115,7 +116,6 @@ var runCmd = &cli.Command{ w = ledgerwallet.NewWallet(ds) } - address := cctx.String("listen") mux := mux.NewRouter() From 2c9215723344c106f9508df7e7c13fde6def76d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sat, 10 Oct 2020 13:41:19 +0200 Subject: [PATCH 04/17] shed ledger: Some UX improvements Signed-off-by: Jakub Sztandera --- cmd/lotus-shed/ledger.go | 55 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/cmd/lotus-shed/ledger.go b/cmd/lotus-shed/ledger.go index 4bb61e5e0..fd7ac1b51 100644 --- a/cmd/lotus-shed/ledger.go +++ b/cmd/lotus-shed/ledger.go @@ -7,11 +7,15 @@ import ( "strings" "github.com/filecoin-project/go-address" + "github.com/urfave/cli/v2" + ledgerfil "github.com/whyrusleeping/ledger-filecoin-go" + "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet" ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" - "github.com/urfave/cli/v2" - ledgerfil "github.com/whyrusleeping/ledger-filecoin-go" + lcli "github.com/filecoin-project/lotus/cli" ) var ledgerCmd = &cli.Command{ @@ -27,7 +31,26 @@ var ledgerCmd = &cli.Command{ var ledgerListAddressesCmd = &cli.Command{ Name: "list", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "print-balances", + Usage: "print balances", + Aliases: []string{"b"}, + }, + }, Action: func(cctx *cli.Context) error { + var api api.FullNode + if cctx.Bool("print-balances") { + a, closer, err := lcli.GetFullNodeAPI(cctx) + if err != nil { + return err + } + + api = a + + defer closer() + } + ctx := lcli.ReqContext(cctx) fl, err := ledgerfil.FindLedgerFilecoinApp() if err != nil { @@ -35,6 +58,10 @@ var ledgerListAddressesCmd = &cli.Command{ } for i := 0; i < 20; i++ { + if err := ctx.Err(); err != nil { + return err + } + p := []uint32{0x80000000 + 44, 0x80000000 + 461, 0x80000000, 0, uint32(i)} pubk, err := fl.GetPublicKeySECP256K1(p) if err != nil { @@ -46,7 +73,17 @@ var ledgerListAddressesCmd = &cli.Command{ return err } - fmt.Printf("%s: %s\n", addr, printHDPath(p)) + if cctx.Bool("print-balances") && api != nil { // api check makes linter happier + b, err := api.WalletBalance(ctx, addr) + if err != nil { + return xerrors.Errorf("getting balance: %w", err) + } + + fmt.Printf("%s %s %s\n", addr, printHDPath(p), types.FIL(b)) + } else { + fmt.Printf("%s %s\n", addr, printHDPath(p)) + } + } return nil @@ -110,6 +147,12 @@ func numlist(p []uint32) string { var ledgerKeyInfoCmd = &cli.Command{ Name: "key-info", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "verbose", + Aliases: []string{"v"}, + }, + }, Action: func(cctx *cli.Context) error { if !cctx.Args().Present() { return cli.ShowCommandHelp(cctx, cctx.Command.Name) @@ -129,8 +172,10 @@ var ledgerKeyInfoCmd = &cli.Command{ if err != nil { return err } - fmt.Println(addr) - fmt.Println(pubk) + if cctx.Bool("verbose") { + fmt.Println(addr) + fmt.Println(pubk) + } a, err := address.NewFromString(addr) if err != nil { From 8ae66d6c6a2aa27105566bbdf41dd569b2e4a109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sat, 10 Oct 2020 14:06:03 +0200 Subject: [PATCH 05/17] Fix lint warnings Signed-off-by: Jakub Sztandera --- chain/wallet/ledger/ledger.go | 12 +++++++----- cmd/lotus-shed/ledger.go | 14 +++----------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index 71ec067c8..94a828603 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -5,16 +5,18 @@ import ( "context" "encoding/json" "fmt" + "github.com/ipfs/go-cid" + "github.com/ipfs/go-datastore" + "github.com/ipfs/go-datastore/query" + ledgerfil "github.com/whyrusleeping/ledger-filecoin-go" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" - "github.com/ipfs/go-datastore" - "github.com/ipfs/go-datastore/query" - ledgerfil "github.com/whyrusleeping/ledger-filecoin-go" ) type LedgerWallet struct { @@ -42,7 +44,7 @@ func (lw LedgerWallet) WalletSign(ctx context.Context, signer address.Address, t if err != nil { return nil, err } - defer fl.Close() + defer fl.Close() // nolint:errcheck if meta.Type != api.MTChainMsg { return nil, fmt.Errorf("ledger can only sign chain messages") } @@ -82,7 +84,7 @@ func (lw LedgerWallet) getKeyInfo(addr address.Address) (*LedgerKeyInfo, error) var out LedgerKeyInfo if err := json.Unmarshal(kib, &out); err != nil { - return nil, err + return nil, xerrors.Errorf("unmarshalling ledger key info: %w", err) } return &out, nil diff --git a/cmd/lotus-shed/ledger.go b/cmd/lotus-shed/ledger.go index fd7ac1b51..8111cc6bf 100644 --- a/cmd/lotus-shed/ledger.go +++ b/cmd/lotus-shed/ledger.go @@ -33,8 +33,8 @@ var ledgerListAddressesCmd = &cli.Command{ Name: "list", Flags: []cli.Flag{ &cli.BoolFlag{ - Name: "print-balances", - Usage: "print balances", + Name: "print-balances", + Usage: "print balances", Aliases: []string{"b"}, }, }, @@ -137,19 +137,11 @@ func printHDPath(pth []uint32) string { return strings.TrimRight(s, "/") } -func numlist(p []uint32) string { - var out []string - for _, v := range p { - out = append(out, fmt.Sprint(v)) - } - return strings.Join(out, ",") -} - var ledgerKeyInfoCmd = &cli.Command{ Name: "key-info", Flags: []cli.Flag{ &cli.BoolFlag{ - Name: "verbose", + Name: "verbose", Aliases: []string{"v"}, }, }, From bb6a354b6269949529bc9791b62ec34c7562d74d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sat, 10 Oct 2020 14:17:44 +0200 Subject: [PATCH 06/17] chain cli: decode params command Signed-off-by: Jakub Sztandera --- cli/chain.go | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/cli/chain.go b/cli/chain.go index 763752f23..4dfcf3f36 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -3,6 +3,7 @@ package cli import ( "bytes" "context" + "encoding/hex" "encoding/json" "fmt" "os" @@ -53,6 +54,7 @@ var chainCmd = &cli.Command{ slashConsensusFault, chainGasPriceCmd, chainInspectUsage, + chainDecodeCmd, }, } @@ -1233,3 +1235,68 @@ var chainGasPriceCmd = &cli.Command{ return nil }, } + +var chainDecodeCmd = &cli.Command{ + Name: "decode", + Usage: "decode various types", + Subcommands: []*cli.Command{ + chainDecodeParamsCmd, + }, +} + +var chainDecodeParamsCmd = &cli.Command{ + Name: "params", + Usage: "Decode message params", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "tipset", + }, + }, + ArgsUsage: "[toAddr method hexParams]", + Action: func(cctx *cli.Context) error { + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + if cctx.Args().Len() != 3 { + return ShowHelp(cctx, fmt.Errorf("incorrect number of arguments")) + } + + to, err := address.NewFromString(cctx.Args().First()) + if err != nil { + return xerrors.Errorf("parsing toAddr: %w", err) + } + + method, err := strconv.ParseInt(cctx.Args().Get(1), 10, 64) + if err != nil { + return xerrors.Errorf("parsing method id: %w", err) + } + + params, err := hex.DecodeString(cctx.Args().Get(2)) + if err != nil { + return xerrors.Errorf("parsing hex params: %w", err) + } + + ts, err := LoadTipSet(ctx, cctx, api) + if err != nil { + return err + } + + act, err := api.StateGetActor(ctx, to, ts.Key()) + if err != nil { + return xerrors.Errorf("getting actor: %w", err) + } + + pstr, err := jsonParams(act.Code, abi.MethodNum(method), params) + if err != nil { + return err + } + + fmt.Println(pstr) + + return nil + }, +} From 753d7b71a9e3ac330ec29fd9c41a9eba824bd8ec Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Sat, 10 Oct 2020 22:59:40 +0200 Subject: [PATCH 07/17] Fix hardened path printing, show 20 addresses after empty Signed-off-by: Jakub Sztandera --- cmd/lotus-shed/ledger.go | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/cmd/lotus-shed/ledger.go b/cmd/lotus-shed/ledger.go index 8111cc6bf..84d582dea 100644 --- a/cmd/lotus-shed/ledger.go +++ b/cmd/lotus-shed/ledger.go @@ -29,6 +29,8 @@ var ledgerCmd = &cli.Command{ }, } +const hdHard = 0x80000000 + var ledgerListAddressesCmd = &cli.Command{ Name: "list", Flags: []cli.Flag{ @@ -57,12 +59,13 @@ var ledgerListAddressesCmd = &cli.Command{ return err } - for i := 0; i < 20; i++ { + end := 20 + for i := 0; i < end; i++ { if err := ctx.Err(); err != nil { return err } - p := []uint32{0x80000000 + 44, 0x80000000 + 461, 0x80000000, 0, uint32(i)} + p := []uint32{hdHard | 44, hdHard | 461, hdHard | 0, 0, uint32(i)} pubk, err := fl.GetPublicKeySECP256K1(p) if err != nil { return err @@ -78,6 +81,9 @@ var ledgerListAddressesCmd = &cli.Command{ if err != nil { return xerrors.Errorf("getting balance: %w", err) } + if !b.IsZero() { + end = i + 21 // BIP32 spec, stop after 20 empty addresses + } fmt.Printf("%s %s %s\n", addr, printHDPath(p), types.FIL(b)) } else { @@ -108,12 +114,12 @@ func parseHDPath(s string) ([]uint32, error) { if err != nil { return nil, err } - if v >= 0x80000000 { + if v >= hdHard { return nil, fmt.Errorf("path element %s too large", p) } if hard { - v += 0x80000000 + v += hdHard } out = append(out, uint32(v)) } @@ -121,20 +127,20 @@ func parseHDPath(s string) ([]uint32, error) { } func printHDPath(pth []uint32) string { - s := "m/" + s := "m" for _, p := range pth { - var hard bool - if p >= 0x80000000 { - p -= 0x80000000 - } + s += "/" + + hard := p&hdHard != 0 + p &^= hdHard // remove hdHard bit + s += fmt.Sprint(p) if hard { s += "'" } - s += "/" } - return strings.TrimRight(s, "/") + return s } var ledgerKeyInfoCmd = &cli.Command{ @@ -164,6 +170,7 @@ var ledgerKeyInfoCmd = &cli.Command{ if err != nil { return err } + if cctx.Bool("verbose") { fmt.Println(addr) fmt.Println(pubk) From 7ee6bafd2312f8894eee66bd2c57fe3015118ede Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Sat, 10 Oct 2020 23:13:22 +0200 Subject: [PATCH 08/17] Fix lint warn Signed-off-by: Jakub Sztandera --- cmd/lotus-shed/ledger.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lotus-shed/ledger.go b/cmd/lotus-shed/ledger.go index 84d582dea..f8267ce12 100644 --- a/cmd/lotus-shed/ledger.go +++ b/cmd/lotus-shed/ledger.go @@ -65,7 +65,7 @@ var ledgerListAddressesCmd = &cli.Command{ return err } - p := []uint32{hdHard | 44, hdHard | 461, hdHard | 0, 0, uint32(i)} + p := []uint32{hdHard | 44, hdHard | 461, hdHard, 0, uint32(i)} pubk, err := fl.GetPublicKeySECP256K1(p) if err != nil { return err From 6a232e7214ae6e21c2b6c7f5ac5735b694cc47a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sun, 11 Oct 2020 00:08:12 +0200 Subject: [PATCH 09/17] Basic multi-wallet support Signed-off-by: Jakub Sztandera --- chain/wallet/ledger/ledger.go | 17 ++- chain/wallet/multi.go | 160 ++++++++++++++++++++++++++++ chain/wallet/remotewallet/remote.go | 8 ++ chain/wallet/wallet.go | 21 ++++ node/builder.go | 13 ++- node/config/def.go | 2 + 6 files changed, 215 insertions(+), 6 deletions(-) create mode 100644 chain/wallet/multi.go diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index 94a828603..231b3faae 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -17,13 +17,14 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/node/modules/dtypes" ) type LedgerWallet struct { ds datastore.Datastore } -func NewWallet(ds datastore.Datastore) *LedgerWallet { +func NewWallet(ds dtypes.MetadataDS) *LedgerWallet { return &LedgerWallet{ds} } @@ -127,7 +128,7 @@ func (lw LedgerWallet) WalletImport(ctx context.Context, kinfo *types.KeyInfo) ( } func (lw LedgerWallet) WalletList(ctx context.Context) ([]address.Address, error) { - res, err := lw.ds.Query(query.Query{Prefix: "ledgerkey/"}) + res, err := lw.ds.Query(query.Query{Prefix: "/ledgerkey/"}) if err != nil { return nil, err } @@ -153,6 +154,14 @@ func (lw LedgerWallet) WalletNew(ctx context.Context, t crypto.SigType) (address return address.Undef, fmt.Errorf("cannot create new address on ledger") } -func keyForAddr(addr address.Address) datastore.Key { - return datastore.NewKey("ledgerkey/" + addr.String()) +func (lw *LedgerWallet) Get() api.WalletAPI { + if lw == nil { + return nil + } + + return lw +} + +func keyForAddr(addr address.Address) datastore.Key { + return datastore.NewKey("/ledgerkey/" + addr.String()) } diff --git a/chain/wallet/multi.go b/chain/wallet/multi.go new file mode 100644 index 000000000..bff8d7003 --- /dev/null +++ b/chain/wallet/multi.go @@ -0,0 +1,160 @@ +package wallet + +import ( + "context" + + "go.uber.org/fx" + "golang.org/x/xerrors" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/crypto" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/types" + ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" + "github.com/filecoin-project/lotus/chain/wallet/remotewallet" +) + +type MultiWallet struct { + fx.In // "constructed" with fx.In instead of normal constructor + + Local *LocalWallet `optional:"true"` + Remote *remotewallet.RemoteWallet `optional:"true"` + Ledger *ledgerwallet.LedgerWallet `optional:"true"` +} + +type getif interface { + api.WalletAPI + + // workaround for the fact that iface(*struct(nil)) != nil + Get() api.WalletAPI +} + +func firstNonNil(wallets ...getif) api.WalletAPI { + for _, w := range wallets { + if w.Get() != nil { + return w + } + } + + return nil +} + +func nonNil(wallets ...getif) []api.WalletAPI { + var out []api.WalletAPI + for _, w := range wallets { + if w.Get() == nil { + continue + } + + out = append(out, w) + } + + return out +} + +func (m MultiWallet) find(ctx context.Context, address address.Address, wallets ...getif) (api.WalletAPI, error) { + ws := nonNil(wallets...) + + for _, w := range ws { + have, err := w.WalletHas(ctx, address) + if err != nil { + return nil, err + } + + if have { + return w, nil + } + } + + return nil, nil +} + +func (m MultiWallet) WalletNew(ctx context.Context, sigType crypto.SigType) (address.Address, error) { + w := firstNonNil(m.Remote, m.Local) + if w == nil { + return address.Undef, xerrors.Errorf("no wallet backends configured") + } + + return w.WalletNew(ctx, sigType) +} + +func (m MultiWallet) WalletHas(ctx context.Context, address address.Address) (bool, error) { + w, err := m.find(ctx, address, m.Remote, m.Ledger, m.Local) + return w != nil, err +} + +func (m MultiWallet) WalletList(ctx context.Context) ([]address.Address, error) { + var out []address.Address + seen := map[address.Address]struct{}{} + + ws := nonNil(m.Remote, m.Ledger, m.Local) + for _, w := range ws { + l, err := w.WalletList(ctx) + if err != nil { + return nil, err + } + + for _, a := range l { + if _, ok := seen[a]; ok { + continue + } + seen[a] = struct{}{} + + out = append(out, a) + } + } + + return out, nil +} + +func (m MultiWallet) WalletSign(ctx context.Context, signer address.Address, toSign []byte, meta api.MsgMeta) (*crypto.Signature, error) { + w, err := m.find(ctx, signer, m.Remote, m.Ledger, m.Local) + if err != nil { + return nil, err + } + if w == nil { + return nil, xerrors.Errorf("key not found") + } + + return w.WalletSign(ctx, signer, toSign, meta) +} + +func (m MultiWallet) WalletExport(ctx context.Context, address address.Address) (*types.KeyInfo, error) { + w, err := m.find(ctx, address, m.Remote, m.Local) + if err != nil { + return nil, err + } + if w == nil { + return nil, xerrors.Errorf("key not found") + } + + return w.WalletExport(ctx, address) +} + +func (m MultiWallet) WalletImport(ctx context.Context, info *types.KeyInfo) (address.Address, error) { + w := firstNonNil(m.Remote, m.Ledger, m.Local) + if w == nil { + return address.Undef, xerrors.Errorf("no wallet backends configured") + } + + return w.WalletImport(ctx, info) +} + +func (m MultiWallet) WalletDelete(ctx context.Context, address address.Address) error { + for { + w, err := m.find(ctx, address, m.Remote, m.Ledger, m.Local) + if err != nil { + return err + } + if w == nil { + return nil + } + + if err := w.WalletDelete(ctx, address); err != nil { + return err + } + } +} + +var _ api.WalletAPI = MultiWallet{} diff --git a/chain/wallet/remotewallet/remote.go b/chain/wallet/remotewallet/remote.go index c7192f496..aa4427132 100644 --- a/chain/wallet/remotewallet/remote.go +++ b/chain/wallet/remotewallet/remote.go @@ -40,3 +40,11 @@ func SetupRemoteWallet(info string) func(mctx helpers.MetricsCtx, lc fx.Lifecycl return &RemoteWallet{wapi}, nil } } + +func (w *RemoteWallet) Get() api.WalletAPI { + if w == nil { + return nil + } + + return w +} diff --git a/chain/wallet/wallet.go b/chain/wallet/wallet.go index 57e63625b..66529d889 100644 --- a/chain/wallet/wallet.go +++ b/chain/wallet/wallet.go @@ -300,6 +300,14 @@ func (w *LocalWallet) WalletDelete(ctx context.Context, addr address.Address) er return nil } +func (w *LocalWallet) Get() api.WalletAPI { + if w == nil { + return nil + } + + return w +} + var _ api.WalletAPI = &LocalWallet{} func swapMainnetForTestnetPrefix(addr string) (string, error) { @@ -312,3 +320,16 @@ func swapMainnetForTestnetPrefix(addr string) (string, error) { aChars[0] = prefixRunes[0] return string(aChars), nil } + +type nilDefault struct{} + +func (n nilDefault) GetDefault() (address.Address, error) { + return address.Undef, nil +} + +func (n nilDefault) SetDefault(a address.Address) error { + return xerrors.Errorf("not supported; local wallet disabled") +} + +var NilDefault nilDefault +var _ Default = NilDefault diff --git a/node/builder.go b/node/builder.go index b91172386..f96505eec 100644 --- a/node/builder.go +++ b/node/builder.go @@ -44,6 +44,7 @@ import ( "github.com/filecoin-project/lotus/chain/metrics" "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" + ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" "github.com/filecoin-project/lotus/chain/wallet/remotewallet" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" @@ -251,8 +252,8 @@ func Online() Option { Override(new(*stmgr.StateManager), stmgr.NewStateManagerWithUpgradeSchedule), Override(new(stmgr.StateManagerAPI), From(new(*stmgr.StateManager))), Override(new(*wallet.LocalWallet), wallet.NewWallet), - Override(new(api.WalletAPI), From(new(*wallet.LocalWallet))), Override(new(wallet.Default), From(new(*wallet.LocalWallet))), + Override(new(api.WalletAPI), From(new(wallet.MultiWallet))), Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner), Override(new(dtypes.ChainGCLocker), blockstore.NewGCLocker), @@ -459,8 +460,16 @@ func ConfigFullNode(c interface{}) Option { If(cfg.Metrics.HeadNotifs, Override(HeadMetricsKey, metrics.SendHeadNotifs(cfg.Metrics.Nickname)), ), + If(cfg.Wallet.RemoteBackend != "", - Override(new(api.WalletAPI), remotewallet.SetupRemoteWallet(cfg.Wallet.RemoteBackend)), + Override(new(*remotewallet.RemoteWallet), remotewallet.SetupRemoteWallet(cfg.Wallet.RemoteBackend)), + ), + If(cfg.Wallet.EnableLedger, + Override(new(*ledgerwallet.LedgerWallet), ledgerwallet.NewWallet), + ), + If(cfg.Wallet.DisableLocal, + Unset(new(*wallet.LocalWallet)), + Override(new(wallet.Default), wallet.NilDefault), ), ) } diff --git a/node/config/def.go b/node/config/def.go index 63340cfd5..7eb7e19f0 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -110,6 +110,8 @@ type Client struct { type Wallet struct { RemoteBackend string + EnableLedger bool + DisableLocal bool } func defCommon() Common { From 2b21fdef3348dcc5799a9ecc21c04cfdd40e9cc1 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Sun, 11 Oct 2020 20:12:01 +0200 Subject: [PATCH 10/17] Refactor from crypto.SigType to types.KeyType Signed-off-by: Jakub Sztandera --- api/api_full.go | 4 +- api/api_wallet.go | 2 +- api/apistruct/struct.go | 8 ++-- api/docgen/docgen.go | 1 + api/test/paych.go | 3 +- chain/gen/gen.go | 4 +- chain/messagepool/messagepool_test.go | 25 ++++++------ chain/messagepool/repub_test.go | 6 +-- chain/messagepool/selection_test.go | 43 +++++++++++---------- chain/messagesigner/messagesigner_test.go | 9 ++--- chain/types/keystore.go | 46 ++++++++++++++++++++++- chain/vectors/gen/main.go | 5 +-- chain/wallet/key.go | 30 ++++++++------- chain/wallet/ledger/ledger.go | 2 +- chain/wallet/multi.go | 11 ++++-- chain/wallet/wallet.go | 4 +- cli/paych_test.go | 3 +- cli/wallet.go | 7 ++-- cmd/chain-noise/main.go | 4 +- cmd/lotus-gateway/endtoend_test.go | 5 +-- cmd/lotus-keygen/main.go | 8 ++-- cmd/lotus-seed/seed/seed.go | 3 +- cmd/lotus-shed/keyinfo.go | 20 +++++----- cmd/lotus-shed/ledger.go | 3 +- cmd/lotus-storage-miner/init.go | 3 +- cmd/lotus-wallet/logged.go | 9 +---- cmd/lotus-wallet/main.go | 19 ++++++---- documentation/en/api-methods.md | 8 ++-- node/modules/lp2p/libp2p.go | 4 +- scripts/dev/api.bash | 4 +- storage/mockstorage/preseal.go | 3 +- 31 files changed, 173 insertions(+), 133 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index a2fe94ee9..f42c8d03f 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -229,7 +229,9 @@ type FullNode interface { // MethodGroup: Wallet // WalletNew creates a new address in the wallet with the given sigType. - WalletNew(context.Context, crypto.SigType) (address.Address, error) + // Available key types: bls, secp256k1, secp256k1-ledger + // Support for numerical types: 1 - secp256k1, 2 - BLS is deprecated + WalletNew(context.Context, types.KeyType) (address.Address, error) // WalletHas indicates whether the given address is in the wallet. WalletHas(context.Context, address.Address) (bool, error) // WalletList lists all the addresses in the wallet. diff --git a/api/api_wallet.go b/api/api_wallet.go index 1213ffc1d..88ad8f43a 100644 --- a/api/api_wallet.go +++ b/api/api_wallet.go @@ -35,7 +35,7 @@ type MsgMeta struct { } type WalletAPI interface { - WalletNew(context.Context, crypto.SigType) (address.Address, error) + WalletNew(context.Context, types.KeyType) (address.Address, error) WalletHas(context.Context, address.Address) (bool, error) WalletList(context.Context) ([]address.Address, error) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 22d50e726..cef335939 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -133,7 +133,7 @@ type FullNodeStruct struct { MinerGetBaseInfo func(context.Context, address.Address, abi.ChainEpoch, types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"` MinerCreateBlock func(context.Context, *api.BlockTemplate) (*types.BlockMsg, error) `perm:"write"` - WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"` + WalletNew func(context.Context, types.KeyType) (address.Address, error) `perm:"write"` WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"` WalletList func(context.Context) ([]address.Address, error) `perm:"write"` WalletBalance func(context.Context, address.Address) (types.BigInt, error) `perm:"read"` @@ -384,7 +384,7 @@ type GatewayStruct struct { type WalletStruct struct { Internal struct { - WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"` + WalletNew func(context.Context, types.KeyType) (address.Address, error) `perm:"write"` WalletHas func(context.Context, address.Address) (bool, error) `perm:"write"` WalletList func(context.Context) ([]address.Address, error) `perm:"write"` WalletSign func(context.Context, address.Address, []byte, api.MsgMeta) (*crypto.Signature, error) `perm:"sign"` @@ -631,7 +631,7 @@ func (c *FullNodeStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.Chain return c.Internal.ChainGetTipSetByHeight(ctx, h, tsk) } -func (c *FullNodeStruct) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) { +func (c *FullNodeStruct) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) { return c.Internal.WalletNew(ctx, typ) } @@ -1465,7 +1465,7 @@ func (g GatewayStruct) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence return g.Internal.StateWaitMsg(ctx, msg, confidence) } -func (c *WalletStruct) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) { +func (c *WalletStruct) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) { return c.Internal.WalletNew(ctx, typ) } diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index ced536cc3..dc6004121 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -87,6 +87,7 @@ func init() { addExample(abi.RegisteredPoStProof_StackedDrgWindow32GiBV1) addExample(abi.ChainEpoch(10101)) addExample(crypto.SigTypeBLS) + addExample(types.KTBLS) addExample(int64(9)) addExample(12.3) addExample(123) diff --git a/api/test/paych.go b/api/test/paych.go index a8ccebdde..43401554d 100644 --- a/api/test/paych.go +++ b/api/test/paych.go @@ -26,7 +26,6 @@ import ( "github.com/filecoin-project/lotus/chain/events" "github.com/filecoin-project/lotus/chain/events/state" "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/chain/wallet" ) func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) { @@ -58,7 +57,7 @@ func TestPaymentChannels(t *testing.T, b APIBuilder, blocktime time.Duration) { bm.MineBlocks() // send some funds to register the receiver - receiverAddr, err := paymentReceiver.WalletNew(ctx, wallet.ActSigType("secp256k1")) + receiverAddr, err := paymentReceiver.WalletNew(ctx, types.KTSecp256k1) if err != nil { t.Fatal(err) } diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 9133f14b4..288c84219 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -155,14 +155,14 @@ func NewGeneratorWithSectors(numSectors int) (*ChainGen, error) { return nil, xerrors.Errorf("creating memrepo wallet failed: %w", err) } - banker, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + banker, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { return nil, xerrors.Errorf("failed to generate banker key: %w", err) } receievers := make([]address.Address, msgsPerBlock) for r := range receievers { - receievers[r], err = w.WalletNew(context.Background(), crypto.SigTypeBLS) + receievers[r], err = w.WalletNew(context.Background(), types.KTBLS) if err != nil { return nil, xerrors.Errorf("failed to generate receiver key: %w", err) } diff --git a/chain/messagepool/messagepool_test.go b/chain/messagepool/messagepool_test.go index 063e0bbab..8f6613cad 100644 --- a/chain/messagepool/messagepool_test.go +++ b/chain/messagepool/messagepool_test.go @@ -8,7 +8,6 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/chain/messagepool/gasguess" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/mock" @@ -232,7 +231,7 @@ func TestMessagePool(t *testing.T) { a := tma.nextBlock() - sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS) + sender, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -273,7 +272,7 @@ func TestMessagePoolMessagesInEachBlock(t *testing.T) { a := tma.nextBlock() - sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS) + sender, err := w.WalletNew(context.Background(), types.KTBLS) if err != nil { t.Fatal(err) } @@ -323,7 +322,7 @@ func TestRevertMessages(t *testing.T) { a := tma.nextBlock() b := tma.nextBlock() - sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS) + sender, err := w.WalletNew(context.Background(), types.KTBLS) if err != nil { t.Fatal(err) } @@ -386,7 +385,7 @@ func TestPruningSimple(t *testing.T) { a := tma.nextBlock() tma.applyBlock(t, a) - sender, err := w.WalletNew(context.Background(), crypto.SigTypeBLS) + sender, err := w.WalletNew(context.Background(), types.KTBLS) if err != nil { t.Fatal(err) } @@ -433,7 +432,7 @@ func TestLoadLocal(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -443,7 +442,7 @@ func TestLoadLocal(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -505,7 +504,7 @@ func TestClearAll(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -515,7 +514,7 @@ func TestClearAll(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -559,7 +558,7 @@ func TestClearNonLocal(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -569,7 +568,7 @@ func TestClearNonLocal(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -620,7 +619,7 @@ func TestUpdates(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -630,7 +629,7 @@ func TestUpdates(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } diff --git a/chain/messagepool/repub_test.go b/chain/messagepool/repub_test.go index 3e1252eec..9cadf24c7 100644 --- a/chain/messagepool/repub_test.go +++ b/chain/messagepool/repub_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" - "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/chain/messagepool/gasguess" + "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/specs-actors/actors/builtin" "github.com/ipfs/go-datastore" @@ -33,7 +33,7 @@ func TestRepubMessages(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -43,7 +43,7 @@ func TestRepubMessages(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } diff --git a/chain/messagepool/selection_test.go b/chain/messagepool/selection_test.go index 9e4fe39e5..37c2f2dc0 100644 --- a/chain/messagepool/selection_test.go +++ b/chain/messagepool/selection_test.go @@ -18,7 +18,6 @@ import ( logging "github.com/ipfs/go-log" "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/messagepool/gasguess" "github.com/filecoin-project/lotus/chain/types" @@ -77,7 +76,7 @@ func TestMessageChains(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -87,7 +86,7 @@ func TestMessageChains(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -315,7 +314,7 @@ func TestMessageChainSkipping(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -325,7 +324,7 @@ func TestMessageChainSkipping(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -391,7 +390,7 @@ func TestBasicMessageSelection(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -401,7 +400,7 @@ func TestBasicMessageSelection(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -535,7 +534,7 @@ func TestMessageSelectionTrimming(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -545,7 +544,7 @@ func TestMessageSelectionTrimming(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -598,7 +597,7 @@ func TestPriorityMessageSelection(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -608,7 +607,7 @@ func TestPriorityMessageSelection(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -677,7 +676,7 @@ func TestPriorityMessageSelection2(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -687,7 +686,7 @@ func TestPriorityMessageSelection2(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -746,7 +745,7 @@ func TestPriorityMessageSelection3(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -756,7 +755,7 @@ func TestPriorityMessageSelection3(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -843,7 +842,7 @@ func TestOptimalMessageSelection1(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -853,7 +852,7 @@ func TestOptimalMessageSelection1(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -910,7 +909,7 @@ func TestOptimalMessageSelection2(t *testing.T) { t.Fatal(err) } - a1, err := w1.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a1, err := w1.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -920,7 +919,7 @@ func TestOptimalMessageSelection2(t *testing.T) { t.Fatal(err) } - a2, err := w2.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a2, err := w2.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -994,7 +993,7 @@ func TestOptimalMessageSelection3(t *testing.T) { t.Fatal(err) } - a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -1074,7 +1073,7 @@ func testCompetitiveMessageSelection(t *testing.T, rng *rand.Rand, getPremium fu t.Fatal(err) } - a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } @@ -1344,7 +1343,7 @@ readLoop: t.Fatal(err) } - a, err := w.WalletNew(context.Background(), crypto.SigTypeSecp256k1) + a, err := w.WalletNew(context.Background(), types.KTSecp256k1) if err != nil { t.Fatal(err) } diff --git a/chain/messagesigner/messagesigner_test.go b/chain/messagesigner/messagesigner_test.go index 0dafce9a1..5eebd36da 100644 --- a/chain/messagesigner/messagesigner_test.go +++ b/chain/messagesigner/messagesigner_test.go @@ -9,7 +9,6 @@ import ( "github.com/filecoin-project/lotus/chain/wallet" - "github.com/filecoin-project/go-state-types/crypto" "github.com/stretchr/testify/require" ds_sync "github.com/ipfs/go-datastore/sync" @@ -47,13 +46,13 @@ func TestMessageSignerSignMessage(t *testing.T) { ctx := context.Background() w, _ := wallet.NewWallet(wallet.NewMemKeyStore()) - from1, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1) + from1, err := w.WalletNew(ctx, types.KTSecp256k1) require.NoError(t, err) - from2, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1) + from2, err := w.WalletNew(ctx, types.KTSecp256k1) require.NoError(t, err) - to1, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1) + to1, err := w.WalletNew(ctx, types.KTSecp256k1) require.NoError(t, err) - to2, err := w.WalletNew(ctx, crypto.SigTypeSecp256k1) + to2, err := w.WalletNew(ctx, types.KTSecp256k1) require.NoError(t, err) type msgSpec struct { diff --git a/chain/types/keystore.go b/chain/types/keystore.go index 76eb5f296..107c1fbe3 100644 --- a/chain/types/keystore.go +++ b/chain/types/keystore.go @@ -1,7 +1,10 @@ package types import ( + "encoding/json" "fmt" + + "github.com/filecoin-project/go-state-types/crypto" ) var ( @@ -9,9 +12,50 @@ var ( ErrKeyExists = fmt.Errorf("key already exists") ) +// KeyType defines a type of a key +type KeyType string + +func (kt *KeyType) UnmarshalJSON(bb []byte) error { + { + // first option, try unmarshaling as string + var s string + err := json.Unmarshal(bb, &s) + if err == nil { + *kt = KeyType(s) + return nil + } + } + + { + var b byte + err := json.Unmarshal(bb, &b) + if err != nil { + return fmt.Errorf("could not unmarshal KeyType either as string nor integer: %w", err) + } + bst := crypto.SigType(b) + + switch bst { + case crypto.SigTypeBLS: + *kt = KTBLS + case crypto.SigTypeSecp256k1: + *kt = KTSecp256k1 + default: + return fmt.Errorf("unknown sigtype: %d", bst) + } + log.Warnf("deprecation: integer style 'KeyType' is deprecated, switch to string style") + return nil + } +} + +const ( + KTBLS KeyType = "bls" + KTSecp256k1 KeyType = "secp256k1" + KTSecp256k1Ledger KeyType = "secp256k1-ledger" +) + // KeyInfo is used for storing keys in KeyStore type KeyInfo struct { - Type string + Type KeyType PrivateKey []byte } diff --git a/chain/vectors/gen/main.go b/chain/vectors/gen/main.go index 096548e04..757227d0d 100644 --- a/chain/vectors/gen/main.go +++ b/chain/vectors/gen/main.go @@ -11,7 +11,6 @@ import ( "golang.org/x/xerrors" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/gen" "github.com/filecoin-project/lotus/chain/types" @@ -62,7 +61,7 @@ func MakeMessageSigningVectors() []vectors.MessageSigningVector { panic(err) } - blsk, err := w.WalletNew(context.Background(), crypto.SigTypeBLS) + blsk, err := w.WalletNew(context.Background(), types.KTBLS) if err != nil { panic(err) } @@ -86,7 +85,7 @@ func MakeMessageSigningVectors() []vectors.MessageSigningVector { Signature: &bmsg.Signature, } - secpk, err := w.WalletNew(context.Background(), crypto.SigTypeBLS) + secpk, err := w.WalletNew(context.Background(), types.KTBLS) if err != nil { panic(err) } diff --git a/chain/wallet/key.go b/chain/wallet/key.go index 4b746a17a..ac9fc436f 100644 --- a/chain/wallet/key.go +++ b/chain/wallet/key.go @@ -10,13 +10,17 @@ import ( "github.com/filecoin-project/lotus/lib/sigs" ) -func GenerateKey(typ crypto.SigType) (*Key, error) { - pk, err := sigs.Generate(typ) +func GenerateKey(typ types.KeyType) (*Key, error) { + ctyp := ActSigType(typ) + if ctyp == crypto.SigTypeUnknown { + return nil, xerrors.Errorf("unknown key type: %s", typ) + } + pk, err := sigs.Generate(ctyp) if err != nil { return nil, err } ki := types.KeyInfo{ - Type: kstoreSigType(typ), + Type: typ, PrivateKey: pk, } return NewKey(ki) @@ -41,41 +45,41 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) { } switch k.Type { - case KTSecp256k1: + case types.KTSecp256k1: k.Address, err = address.NewSecp256k1Address(k.PublicKey) if err != nil { return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err) } - case KTBLS: + case types.KTBLS: k.Address, err = address.NewBLSAddress(k.PublicKey) if err != nil { return nil, xerrors.Errorf("converting BLS to address: %w", err) } default: - return nil, xerrors.Errorf("unknown key type") + return nil, xerrors.Errorf("unknown key type: %s", k.Type) } return k, nil } -func kstoreSigType(typ crypto.SigType) string { +func kstoreSigType(typ crypto.SigType) types.KeyType { switch typ { case crypto.SigTypeBLS: - return KTBLS + return types.KTBLS case crypto.SigTypeSecp256k1: - return KTSecp256k1 + return types.KTSecp256k1 default: return "" } } -func ActSigType(typ string) crypto.SigType { +func ActSigType(typ types.KeyType) crypto.SigType { switch typ { - case KTBLS: + case types.KTBLS: return crypto.SigTypeBLS - case KTSecp256k1: + case types.KTSecp256k1: return crypto.SigTypeSecp256k1 default: - return 0 + return crypto.SigTypeUnknown } } diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index 231b3faae..b6b5683cd 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -150,7 +150,7 @@ func (lw LedgerWallet) WalletList(ctx context.Context) ([]address.Address, error return out, nil } -func (lw LedgerWallet) WalletNew(ctx context.Context, t crypto.SigType) (address.Address, error) { +func (lw LedgerWallet) WalletNew(ctx context.Context, t types.KeyType) (address.Address, error) { return address.Undef, fmt.Errorf("cannot create new address on ledger") } diff --git a/chain/wallet/multi.go b/chain/wallet/multi.go index bff8d7003..6eac03367 100644 --- a/chain/wallet/multi.go +++ b/chain/wallet/multi.go @@ -18,7 +18,7 @@ import ( type MultiWallet struct { fx.In // "constructed" with fx.In instead of normal constructor - Local *LocalWallet `optional:"true"` + Local *LocalWallet `optional:"true"` Remote *remotewallet.RemoteWallet `optional:"true"` Ledger *ledgerwallet.LedgerWallet `optional:"true"` } @@ -70,7 +70,7 @@ func (m MultiWallet) find(ctx context.Context, address address.Address, wallets return nil, nil } -func (m MultiWallet) WalletNew(ctx context.Context, sigType crypto.SigType) (address.Address, error) { +func (m MultiWallet) WalletNew(ctx context.Context, sigType types.KeyType) (address.Address, error) { w := firstNonNil(m.Remote, m.Local) if w == nil { return address.Undef, xerrors.Errorf("no wallet backends configured") @@ -133,7 +133,12 @@ func (m MultiWallet) WalletExport(ctx context.Context, address address.Address) } func (m MultiWallet) WalletImport(ctx context.Context, info *types.KeyInfo) (address.Address, error) { - w := firstNonNil(m.Remote, m.Ledger, m.Local) + var local getif = m.Local + if info.Type == types.KTSecp256k1Ledger { + local = m.Ledger + } + + w := firstNonNil(m.Remote, local) if w == nil { return address.Undef, xerrors.Errorf("no wallet backends configured") } diff --git a/chain/wallet/wallet.go b/chain/wallet/wallet.go index 66529d889..925547ea8 100644 --- a/chain/wallet/wallet.go +++ b/chain/wallet/wallet.go @@ -26,8 +26,6 @@ const ( KNamePrefix = "wallet-" KTrashPrefix = "trash-" KDefault = "default" - KTBLS = "bls" - KTSecp256k1 = "secp256k1" ) type LocalWallet struct { @@ -236,7 +234,7 @@ func (w *LocalWallet) SetDefault(a address.Address) error { return nil } -func (w *LocalWallet) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) { +func (w *LocalWallet) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) { w.lk.Lock() defer w.lk.Unlock() diff --git a/cli/paych_test.go b/cli/paych_test.go index 862ca2e74..b94ba27e7 100644 --- a/cli/paych_test.go +++ b/cli/paych_test.go @@ -29,7 +29,6 @@ import ( "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/events" "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/chain/wallet" builder "github.com/filecoin-project/lotus/node/test" ) @@ -415,7 +414,7 @@ func startTwoNodesOneMiner(ctx context.Context, t *testing.T, blocktime time.Dur bm.MineBlocks() // Send some funds to register the receiver - receiverAddr, err := paymentReceiver.WalletNew(ctx, wallet.ActSigType("secp256k1")) + receiverAddr, err := paymentReceiver.WalletNew(ctx, types.KTSecp256k1) if err != nil { t.Fatal(err) } diff --git a/cli/wallet.go b/cli/wallet.go index aa5b9bed3..3d6abc357 100644 --- a/cli/wallet.go +++ b/cli/wallet.go @@ -17,7 +17,6 @@ import ( "github.com/filecoin-project/go-state-types/crypto" types "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/lib/tablewriter" ) @@ -55,7 +54,7 @@ var walletNew = &cli.Command{ t = "secp256k1" } - nk, err := api.WalletNew(ctx, wallet.ActSigType(t)) + nk, err := api.WalletNew(ctx, types.KeyType(t)) if err != nil { return err } @@ -329,9 +328,9 @@ var walletImport = &cli.Command{ ki.PrivateKey = gk.PrivateKey switch gk.SigType { case 1: - ki.Type = wallet.KTSecp256k1 + ki.Type = types.KTSecp256k1 case 2: - ki.Type = wallet.KTBLS + ki.Type = types.KTBLS default: return fmt.Errorf("unrecognized key type: %d", gk.SigType) } diff --git a/cmd/chain-noise/main.go b/cmd/chain-noise/main.go index 7b9824016..81586e1b2 100644 --- a/cmd/chain-noise/main.go +++ b/cmd/chain-noise/main.go @@ -7,8 +7,6 @@ import ( "os" "time" - "github.com/filecoin-project/go-state-types/crypto" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" @@ -61,7 +59,7 @@ var runCmd = &cli.Command{ func sendSmallFundsTxs(ctx context.Context, api api.FullNode, from address.Address, rate int) error { var sendSet []address.Address for i := 0; i < 20; i++ { - naddr, err := api.WalletNew(ctx, crypto.SigTypeSecp256k1) + naddr, err := api.WalletNew(ctx, types.KTSecp256k1) if err != nil { return err } diff --git a/cmd/lotus-gateway/endtoend_test.go b/cmd/lotus-gateway/endtoend_test.go index 206034968..eebf56a9f 100644 --- a/cmd/lotus-gateway/endtoend_test.go +++ b/cmd/lotus-gateway/endtoend_test.go @@ -22,7 +22,6 @@ import ( "github.com/filecoin-project/lotus/api/test" "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/chain/wallet" "github.com/filecoin-project/lotus/node" builder "github.com/filecoin-project/lotus/node/test" ) @@ -53,7 +52,7 @@ func TestEndToEnd(t *testing.T) { fmt.Println(balance) // Create a wallet on the lite node - liteWalletAddr, err := lite.WalletNew(ctx, wallet.ActSigType("secp256k1")) + liteWalletAddr, err := lite.WalletNew(ctx, types.KTSecp256k1) require.NoError(t, err) // Send some funds from the full node to the lite node @@ -77,7 +76,7 @@ func TestEndToEnd(t *testing.T) { // Create some wallets on the lite node to use for testing multisig var walletAddrs []address.Address for i := 0; i < 4; i++ { - addr, err := lite.WalletNew(ctx, wallet.ActSigType("secp256k1")) + addr, err := lite.WalletNew(ctx, types.KTSecp256k1) require.NoError(t, err) walletAddrs = append(walletAddrs, addr) diff --git a/cmd/lotus-keygen/main.go b/cmd/lotus-keygen/main.go index 4b971cf48..d296cb5da 100644 --- a/cmd/lotus-keygen/main.go +++ b/cmd/lotus-keygen/main.go @@ -5,7 +5,7 @@ import ( "fmt" "os" - "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet" _ "github.com/filecoin-project/lotus/lib/sigs/bls" _ "github.com/filecoin-project/lotus/lib/sigs/secp" @@ -30,12 +30,12 @@ func main() { return err } - var kt crypto.SigType + var kt types.KeyType switch cctx.String("type") { case "bls": - kt = crypto.SigTypeBLS + kt = types.KTBLS case "secp256k1": - kt = crypto.SigTypeSecp256k1 + kt = types.KTSecp256k1 default: return fmt.Errorf("unrecognized key type: %q", cctx.String("type")) } diff --git a/cmd/lotus-seed/seed/seed.go b/cmd/lotus-seed/seed/seed.go index 5e911991d..cd0c4e7ab 100644 --- a/cmd/lotus-seed/seed/seed.go +++ b/cmd/lotus-seed/seed/seed.go @@ -21,7 +21,6 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/extern/sector-storage/zerocomm" "github.com/filecoin-project/specs-actors/actors/builtin/market" @@ -93,7 +92,7 @@ func PreSeal(maddr address.Address, spt abi.RegisteredSealProof, offset abi.Sect return nil, nil, err } } else { - minerAddr, err = wallet.GenerateKey(crypto.SigTypeBLS) + minerAddr, err = wallet.GenerateKey(types.KTBLS) if err != nil { return nil, nil, err } diff --git a/cmd/lotus-shed/keyinfo.go b/cmd/lotus-shed/keyinfo.go index fdd1fcb49..4dcd10cbf 100644 --- a/cmd/lotus-shed/keyinfo.go +++ b/cmd/lotus-shed/keyinfo.go @@ -32,10 +32,10 @@ import ( _ "github.com/filecoin-project/lotus/lib/sigs/secp" ) -var validTypes = []string{wallet.KTBLS, wallet.KTSecp256k1, lp2p.KTLibp2pHost} +var validTypes = []types.KeyType{types.KTBLS, types.KTSecp256k1, lp2p.KTLibp2pHost} type keyInfoOutput struct { - Type string + Type types.KeyType Address string PublicKey string } @@ -86,7 +86,7 @@ var keyinfoVerifyCmd = &cli.Command{ return xerrors.Errorf("decoding key: '%s': %w", fileName, err) } - if string(name) != keyInfo.Type { + if types.KeyType(name) != keyInfo.Type { return fmt.Errorf("%s of type %s is incorrect", fileName, keyInfo.Type) } case modules.KTJwtHmacSecret: @@ -98,7 +98,7 @@ var keyinfoVerifyCmd = &cli.Command{ if string(name) != modules.JWTSecretName { return fmt.Errorf("%s of type %s is incorrect", fileName, keyInfo.Type) } - case wallet.KTSecp256k1, wallet.KTBLS: + case types.KTSecp256k1, types.KTBLS: keystore := wallet.NewMemKeyStore() w, err := wallet.NewWallet(keystore) if err != nil { @@ -214,7 +214,7 @@ var keyinfoImportCmd = &cli.Command{ fmt.Printf("%s\n", peerid.String()) break - case wallet.KTSecp256k1, wallet.KTBLS: + case types.KTSecp256k1, types.KTBLS: w, err := wallet.NewWallet(keystore) if err != nil { return err @@ -317,7 +317,7 @@ var keyinfoInfoCmd = &cli.Command{ kio.PublicKey = base64.StdEncoding.EncodeToString(pkBytes) break - case wallet.KTSecp256k1, wallet.KTBLS: + case types.KTSecp256k1, types.KTBLS: kio.Type = keyInfo.Type key, err := wallet.NewKey(keyInfo) @@ -366,7 +366,7 @@ var keyinfoNewCmd = &cli.Command{ return fmt.Errorf("please specify a type to generate") } - keyType := cctx.Args().First() + keyType := types.KeyType(cctx.Args().First()) flagOutput := cctx.String("output") if i := SliceIndex(len(validTypes), func(i int) bool { @@ -404,8 +404,8 @@ var keyinfoNewCmd = &cli.Command{ keyInfo = ki break - case wallet.KTSecp256k1, wallet.KTBLS: - key, err := wallet.GenerateKey(wallet.ActSigType(keyType)) + case types.KTSecp256k1, types.KTBLS: + key, err := wallet.GenerateKey(keyType) if err != nil { return err } @@ -418,7 +418,7 @@ var keyinfoNewCmd = &cli.Command{ filename := flagOutput filename = strings.ReplaceAll(filename, "", keyAddr) - filename = strings.ReplaceAll(filename, "", keyType) + filename = strings.ReplaceAll(filename, "", string(keyType)) file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { diff --git a/cmd/lotus-shed/ledger.go b/cmd/lotus-shed/ledger.go index f8267ce12..f64916534 100644 --- a/cmd/lotus-shed/ledger.go +++ b/cmd/lotus-shed/ledger.go @@ -13,7 +13,6 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/chain/wallet" ledgerwallet "github.com/filecoin-project/lotus/chain/wallet/ledger" lcli "github.com/filecoin-project/lotus/cli" ) @@ -191,7 +190,7 @@ var ledgerKeyInfoCmd = &cli.Command{ } var ki types.KeyInfo - ki.Type = wallet.KTSecp256k1 + ki.Type = types.KTSecp256k1Ledger ki.PrivateKey = b out, err := json.Marshal(ki) diff --git a/cmd/lotus-storage-miner/init.go b/cmd/lotus-storage-miner/init.go index 0f830023f..ccea707af 100644 --- a/cmd/lotus-storage-miner/init.go +++ b/cmd/lotus-storage-miner/init.go @@ -27,7 +27,6 @@ import ( cborutil "github.com/filecoin-project/go-cbor-util" paramfetch "github.com/filecoin-project/go-paramfetch" "github.com/filecoin-project/go-state-types/abi" - crypto2 "github.com/filecoin-project/go-state-types/crypto" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/sector-storage/stores" @@ -624,7 +623,7 @@ func createStorageMiner(ctx context.Context, api lapi.FullNode, peerid peer.ID, if cctx.String("worker") != "" { worker, err = address.NewFromString(cctx.String("worker")) } else if cctx.Bool("create-worker-key") { // TODO: Do we need to force this if owner is Secpk? - worker, err = api.WalletNew(ctx, crypto2.SigTypeBLS) + worker, err = api.WalletNew(ctx, types.KTBLS) } // TODO: Transfer some initial funds to worker if err != nil { diff --git a/cmd/lotus-wallet/logged.go b/cmd/lotus-wallet/logged.go index 3bcb3f867..272a8d10b 100644 --- a/cmd/lotus-wallet/logged.go +++ b/cmd/lotus-wallet/logged.go @@ -19,13 +19,8 @@ type LoggedWallet struct { under api.WalletAPI } -func (c *LoggedWallet) WalletNew(ctx context.Context, typ crypto.SigType) (address.Address, error) { - n, err := typ.Name() - if err != nil { - return address.Address{}, err - } - - log.Infow("WalletNew", "type", n) +func (c *LoggedWallet) WalletNew(ctx context.Context, typ types.KeyType) (address.Address, error) { + log.Infow("WalletNew", "type", typ) return c.under.WalletNew(ctx, typ) } diff --git a/cmd/lotus-wallet/main.go b/cmd/lotus-wallet/main.go index ffaddc7e3..3285b13e7 100644 --- a/cmd/lotus-wallet/main.go +++ b/cmd/lotus-wallet/main.go @@ -101,19 +101,22 @@ var runCmd = &cli.Command{ return err } - var w api.WalletAPI - if !cctx.Bool("ledger") { - w, err = wallet.NewWallet(ks) - if err != nil { - return err - } - } else { + lw, err := wallet.NewWallet(ks) + if err != nil { + return err + } + + var w api.WalletAPI = lw + if cctx.Bool("ledger") { ds, err := lr.Datastore("/metadata") if err != nil { return err } - w = ledgerwallet.NewWallet(ds) + w = wallet.MultiWallet{ + Local: lw, + Ledger: ledgerwallet.NewWallet(ds), + } } address := cctx.String("listen") diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index ec8071b57..6d201b435 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -4710,7 +4710,7 @@ Inputs: Response: ```json { - "Type": "string value", + "Type": "bls", "PrivateKey": "Ynl0ZSBhcnJheQ==" } ``` @@ -4740,7 +4740,7 @@ Inputs: ```json [ { - "Type": "string value", + "Type": "bls", "PrivateKey": "Ynl0ZSBhcnJheQ==" } ] @@ -4760,6 +4760,8 @@ Response: `null` ### WalletNew WalletNew creates a new address in the wallet with the given sigType. +Available key types: bls, secp256k1, secp256k1-ledger +Support for numerical types: 1 - secp256k1, 2 - BLS is deprecated Perms: write @@ -4767,7 +4769,7 @@ Perms: write Inputs: ```json [ - 2 + "bls" ] ``` diff --git a/node/modules/lp2p/libp2p.go b/node/modules/lp2p/libp2p.go index 5a1666cb6..51749c4d6 100644 --- a/node/modules/lp2p/libp2p.go +++ b/node/modules/lp2p/libp2p.go @@ -20,8 +20,8 @@ import ( var log = logging.Logger("p2pnode") const ( - KLibp2pHost = "libp2p-host" - KTLibp2pHost = KLibp2pHost + KLibp2pHost = "libp2p-host" + KTLibp2pHost types.KeyType = KLibp2pHost ) type Libp2pOpts struct { diff --git a/scripts/dev/api.bash b/scripts/dev/api.bash index 5539e4fef..ac9eb4e66 100644 --- a/scripts/dev/api.bash +++ b/scripts/dev/api.bash @@ -1,11 +1,11 @@ #!/bin/bash # vim: set expandtab ts=2 sw=2: -token=$(lotus auth create-token --perm admin) +_lotus_token=$(./lotus auth create-token --perm admin) runAPI() { curl -X POST \ -H "Content-Type: application/json" \ --data '{"jsonrpc":"2.0","id":2,"method":"Filecoin.'"$1"'","params":'"${2:-null}"'}' \ - 'http://127.0.0.1:1234/rpc/v0?token='"$token" + 'http://127.0.0.1:1234/rpc/v0?token='"$_lotus_token" } diff --git a/storage/mockstorage/preseal.go b/storage/mockstorage/preseal.go index 8ca789ba6..090aacc3c 100644 --- a/storage/mockstorage/preseal.go +++ b/storage/mockstorage/preseal.go @@ -7,7 +7,6 @@ import ( commcid "github.com/filecoin-project/go-fil-commcid" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/lotus/extern/sector-storage/mock" market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" @@ -20,7 +19,7 @@ import ( ) func PreSeal(ssize abi.SectorSize, maddr address.Address, sectors int) (*genesis.Miner, *types.KeyInfo, error) { - k, err := wallet.GenerateKey(crypto.SigTypeBLS) + k, err := wallet.GenerateKey(types.KTBLS) if err != nil { return nil, nil, err } From d6c8276c7a3e76e32484aaae745a0ccb2e6fef53 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Mon, 12 Oct 2020 00:48:23 +0200 Subject: [PATCH 11/17] Add support for WalletNew to ledger Signed-off-by: Jakub Sztandera --- chain/wallet/key.go | 15 +------ chain/wallet/ledger/ledger.go | 76 +++++++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 17 deletions(-) diff --git a/chain/wallet/key.go b/chain/wallet/key.go index ac9fc436f..1b191cc4b 100644 --- a/chain/wallet/key.go +++ b/chain/wallet/key.go @@ -13,7 +13,7 @@ import ( func GenerateKey(typ types.KeyType) (*Key, error) { ctyp := ActSigType(typ) if ctyp == crypto.SigTypeUnknown { - return nil, xerrors.Errorf("unknown key type: %s", typ) + return nil, xerrors.Errorf("unknown sig type: %s", typ) } pk, err := sigs.Generate(ctyp) if err != nil { @@ -56,23 +56,12 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) { return nil, xerrors.Errorf("converting BLS to address: %w", err) } default: - return nil, xerrors.Errorf("unknown key type: %s", k.Type) + return nil, xerrors.Errorf("unsupported key type: %s", k.Type) } return k, nil } -func kstoreSigType(typ crypto.SigType) types.KeyType { - switch typ { - case crypto.SigTypeBLS: - return types.KTBLS - case crypto.SigTypeSecp256k1: - return types.KTSecp256k1 - default: - return "" - } -} - func ActSigType(typ types.KeyType) crypto.SigType { switch typ { case types.KTBLS: diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index b6b5683cd..9a0d13419 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -115,12 +115,22 @@ func (lw LedgerWallet) WalletImport(ctx context.Context, kinfo *types.KeyInfo) ( if err := json.Unmarshal(kinfo.PrivateKey, &ki); err != nil { return address.Undef, err } + return lw.importKey(ki) +} +func (lw LedgerWallet) importKey(ki LedgerKeyInfo) (address.Address, error) { if ki.Address == address.Undef { return address.Undef, fmt.Errorf("no address given in imported key info") } + if len(ki.Path) != filHdPathLen { + return address.Undef, fmt.Errorf("bad hd path len: %d, expected: %d", len(ki.Path), filHdPathLen) + } + bb, err := json.Marshal(ki) + if err != nil { + return address.Undef, xerrors.Errorf("marshaling key info: %w", err) + } - if err := lw.ds.Put(keyForAddr(ki.Address), kinfo.PrivateKey); err != nil { + if err := lw.ds.Put(keyForAddr(ki.Address), bb); err != nil { return address.Undef, err } @@ -128,10 +138,11 @@ func (lw LedgerWallet) WalletImport(ctx context.Context, kinfo *types.KeyInfo) ( } func (lw LedgerWallet) WalletList(ctx context.Context) ([]address.Address, error) { - res, err := lw.ds.Query(query.Query{Prefix: "/ledgerkey/"}) + res, err := lw.ds.Query(query.Query{Prefix: dsLedgerPrefix}) if err != nil { return nil, err } + defer res.Close() var out []address.Address for { @@ -150,8 +161,63 @@ func (lw LedgerWallet) WalletList(ctx context.Context) ([]address.Address, error return out, nil } +const hdHard = 0x80000000 + +var filHDBasePath = []uint32{hdHard | 44, hdHard | 461, hdHard, 0} +var filHdPathLen = 5 + func (lw LedgerWallet) WalletNew(ctx context.Context, t types.KeyType) (address.Address, error) { - return address.Undef, fmt.Errorf("cannot create new address on ledger") + if t != types.KTSecp256k1Ledger { + return address.Undef, fmt.Errorf("unsupported key type: '%s', only '%s' supported", + t, types.KTSecp256k1Ledger) + } + + res, err := lw.ds.Query(query.Query{Prefix: dsLedgerPrefix}) + if err != nil { + return address.Undef, err + } + defer res.Close() + + var maxi int64 = -1 + for { + res, ok := res.NextSync() + if !ok { + break + } + + var ki LedgerKeyInfo + if err := json.Unmarshal(res.Value, &ki); err != nil { + return address.Undef, err + } + if i := ki.Path[filHdPathLen-1]; maxi == -1 || maxi < int64(i) { + maxi = int64(i) + } + } + if maxi == -1 { + maxi = 0 + } + + fl, err := ledgerfil.FindLedgerFilecoinApp() + if err != nil { + return address.Undef, xerrors.Errorf("finding ledger: %w", err) + } + + path := append(append([]uint32(nil), filHDBasePath...), uint32(maxi)) + _, _, addr, err := fl.GetAddressPubKeySECP256K1(path) + if err != nil { + return address.Undef, xerrors.Errorf("getting public key from ledger: %w", err) + } + + a, err := address.NewFromString(addr) + if err != nil { + return address.Undef, fmt.Errorf("parsing address: %w", err) + } + + var lki LedgerKeyInfo + lki.Address = a + lki.Path = path + + return lw.importKey(lki) } func (lw *LedgerWallet) Get() api.WalletAPI { @@ -162,6 +228,8 @@ func (lw *LedgerWallet) Get() api.WalletAPI { return lw } +var dsLedgerPrefix = "/ledgerkey/" + func keyForAddr(addr address.Address) datastore.Key { - return datastore.NewKey("/ledgerkey/" + addr.String()) + return datastore.NewKey(dsLedgerPrefix + addr.String()) } From 7b4a5fc7ca0cd0fd5fd6068c93005adbec3167db Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Mon, 12 Oct 2020 00:50:29 +0200 Subject: [PATCH 12/17] Fixup off by one Signed-off-by: Jakub Sztandera --- chain/wallet/ledger/ledger.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index 9a0d13419..14c75b356 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -193,16 +193,13 @@ func (lw LedgerWallet) WalletNew(ctx context.Context, t types.KeyType) (address. maxi = int64(i) } } - if maxi == -1 { - maxi = 0 - } fl, err := ledgerfil.FindLedgerFilecoinApp() if err != nil { return address.Undef, xerrors.Errorf("finding ledger: %w", err) } - path := append(append([]uint32(nil), filHDBasePath...), uint32(maxi)) + path := append(append([]uint32(nil), filHDBasePath...), uint32(maxi+1)) _, _, addr, err := fl.GetAddressPubKeySECP256K1(path) if err != nil { return address.Undef, xerrors.Errorf("getting public key from ledger: %w", err) From fda8b932bab6899e28089b72ef18ea366408fbf0 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Mon, 12 Oct 2020 01:27:15 +0200 Subject: [PATCH 13/17] Ask for confirmation when creating a key Signed-off-by: Jakub Sztandera --- chain/wallet/ledger/ledger.go | 9 +++++++++ chain/wallet/multi.go | 15 ++++++++++----- go.mod | 3 ++- go.sum | 9 +++++++++ 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index 14c75b356..34307d192 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -9,6 +9,7 @@ import ( "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/query" + logging "github.com/ipfs/go-log" ledgerfil "github.com/whyrusleeping/ledger-filecoin-go" "golang.org/x/xerrors" @@ -20,6 +21,8 @@ import ( "github.com/filecoin-project/lotus/node/modules/dtypes" ) +var log = logging.Logger("wallet-ledger") + type LedgerWallet struct { ds datastore.Datastore } @@ -205,6 +208,12 @@ func (lw LedgerWallet) WalletNew(ctx context.Context, t types.KeyType) (address. return address.Undef, xerrors.Errorf("getting public key from ledger: %w", err) } + log.Warnf("creating key: %s, accept the key in ledger device", addr) + _, _, addr, err = fl.ShowAddressPubKeySECP256K1(path) + if err != nil { + return address.Undef, xerrors.Errorf("verifying public key with ledger: %w", err) + } + a, err := address.NewFromString(addr) if err != nil { return address.Undef, fmt.Errorf("parsing address: %w", err) diff --git a/chain/wallet/multi.go b/chain/wallet/multi.go index 6eac03367..532ad217b 100644 --- a/chain/wallet/multi.go +++ b/chain/wallet/multi.go @@ -70,13 +70,18 @@ func (m MultiWallet) find(ctx context.Context, address address.Address, wallets return nil, nil } -func (m MultiWallet) WalletNew(ctx context.Context, sigType types.KeyType) (address.Address, error) { - w := firstNonNil(m.Remote, m.Local) - if w == nil { - return address.Undef, xerrors.Errorf("no wallet backends configured") +func (m MultiWallet) WalletNew(ctx context.Context, keyType types.KeyType) (address.Address, error) { + var local getif = m.Local + if keyType == types.KTSecp256k1Ledger { + local = m.Ledger } - return w.WalletNew(ctx, sigType) + w := firstNonNil(m.Remote, local) + if w == nil { + return address.Undef, xerrors.Errorf("no wallet backends supporting key type: %s", keyType) + } + + return w.WalletNew(ctx, keyType) } func (m MultiWallet) WalletHas(ctx context.Context, address address.Address) (bool, error) { diff --git a/go.mod b/go.mod index d6a4768b7..922e4b6b5 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/drand/kyber v1.1.2 github.com/dustin/go-humanize v1.0.0 github.com/elastic/go-sysinfo v1.3.0 - github.com/fatih/color v1.8.0 + github.com/fatih/color v1.9.0 github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200716204036-cddc56607e1d github.com/filecoin-project/go-address v0.0.4 github.com/filecoin-project/go-amt-ipld/v2 v2.1.1-0.20201006184820-924ee87a1349 // indirect @@ -104,6 +104,7 @@ require ( github.com/libp2p/go-libp2p-tls v0.1.3 github.com/libp2p/go-libp2p-yamux v0.2.8 github.com/libp2p/go-maddr-filter v0.1.0 + github.com/mattn/go-colorable v0.1.6 // indirect github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 github.com/mitchellh/go-homedir v1.1.0 github.com/multiformats/go-base32 v0.0.3 diff --git a/go.sum b/go.sum index fe7aacbf9..6dfc9aac6 100644 --- a/go.sum +++ b/go.sum @@ -221,6 +221,8 @@ github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:Jp github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.8.0 h1:5bzFgL+oy7JITMTxUPJ00n7VxmYd/PdMp5mHFX40/RY= github.com/fatih/color v1.8.0/go.mod h1:3l45GVGkyrnYNl9HoIjnp2NnNWvh6hLAqD8yTfGjnw8= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E= github.com/filecoin-project/go-address v0.0.3 h1:eVfbdjEbpbzIrbiSa+PiGUY+oDK9HnUn+M1R/ggoHf8= github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= @@ -1045,11 +1047,16 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -1665,11 +1672,13 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From df7ee610cd426bbd20bdf6ccdeae4b9b4e89e3fe Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Mon, 12 Oct 2020 01:29:19 +0200 Subject: [PATCH 14/17] Re-enable repub Signed-off-by: Jakub Sztandera --- chain/messagepool/messagepool.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/chain/messagepool/messagepool.go b/chain/messagepool/messagepool.go index 2a4704c3b..d3c638b22 100644 --- a/chain/messagepool/messagepool.go +++ b/chain/messagepool/messagepool.go @@ -1249,9 +1249,6 @@ func (mp *MessagePool) Updates(ctx context.Context) (<-chan api.MpoolUpdate, err } func (mp *MessagePool) loadLocal() error { - return nil - // TODO: this causes super slow startup... - res, err := mp.localMsgs.Query(query.Query{}) if err != nil { return xerrors.Errorf("query local messages: %w", err) From a2e0832a12f220678ac73bf96542c747814b02bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 12 Oct 2020 06:17:00 +0200 Subject: [PATCH 15/17] Fix lint --- chain/wallet/ledger/ledger.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index 34307d192..c1757fd0a 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -145,7 +145,7 @@ func (lw LedgerWallet) WalletList(ctx context.Context) ([]address.Address, error if err != nil { return nil, err } - defer res.Close() + defer res.Close() // nolint:errcheck var out []address.Address for { @@ -179,7 +179,7 @@ func (lw LedgerWallet) WalletNew(ctx context.Context, t types.KeyType) (address. if err != nil { return address.Undef, err } - defer res.Close() + defer res.Close() // nolint:errcheck var maxi int64 = -1 for { From 4ac2bee81ce92676e966959299a4cd1a18b3a6ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 12 Oct 2020 06:34:45 +0200 Subject: [PATCH 16/17] Update oni --- extern/oni | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/oni b/extern/oni index dbee44e4f..10ed9ef57 160000 --- a/extern/oni +++ b/extern/oni @@ -1 +1 @@ -Subproject commit dbee44e4f940a502971f17116ccbba61ceaf2674 +Subproject commit 10ed9ef576836186de3b8513c03cdc3fb18c44ed From 8b648cf77cba845ae1bf0f0c46a906b51ffd1ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 12 Oct 2020 09:21:42 +0200 Subject: [PATCH 17/17] ledger: Close device in WalletNew --- chain/wallet/ledger/ledger.go | 1 + 1 file changed, 1 insertion(+) diff --git a/chain/wallet/ledger/ledger.go b/chain/wallet/ledger/ledger.go index c1757fd0a..07f92e7ff 100644 --- a/chain/wallet/ledger/ledger.go +++ b/chain/wallet/ledger/ledger.go @@ -201,6 +201,7 @@ func (lw LedgerWallet) WalletNew(ctx context.Context, t types.KeyType) (address. if err != nil { return address.Undef, xerrors.Errorf("finding ledger: %w", err) } + defer fl.Close() // nolint:errcheck path := append(append([]uint32(nil), filHDBasePath...), uint32(maxi+1)) _, _, addr, err := fl.GetAddressPubKeySECP256K1(path)