diff --git a/cmd/lncli/walletrpc_active.go b/cmd/lncli/walletrpc_active.go index 96d3f9fe..ad2561e2 100644 --- a/cmd/lncli/walletrpc_active.go +++ b/cmd/lncli/walletrpc_active.go @@ -4,7 +4,6 @@ package main import ( "encoding/base64" - "encoding/binary" "encoding/hex" "encoding/json" "errors" @@ -988,13 +987,14 @@ func importAccount(ctx *cli.Context) error { return err } - var masterKeyFingerprint uint32 + var mkfpBytes []byte if ctx.IsSet("master_key_fingerprint") { - mkfp, err := hex.DecodeString(ctx.String("master_key_fingerprint")) + mkfpBytes, err = hex.DecodeString( + ctx.String("master_key_fingerprint"), + ) if err != nil { return fmt.Errorf("invalid master key fingerprint: %v", err) } - masterKeyFingerprint = binary.LittleEndian.Uint32(mkfp) } walletClient, cleanUp := getWalletClient(ctx) @@ -1004,7 +1004,7 @@ func importAccount(ctx *cli.Context) error { req := &walletrpc.ImportAccountRequest{ Name: ctx.Args().Get(1), ExtendedPublicKey: ctx.Args().Get(0), - MasterKeyFingerprint: masterKeyFingerprint, + MasterKeyFingerprint: mkfpBytes, AddressType: addrType, DryRun: dryRun, } diff --git a/lnrpc/walletrpc/walletkit.pb.go b/lnrpc/walletrpc/walletkit.pb.go index 840bde9c..9786d656 100644 --- a/lnrpc/walletrpc/walletkit.pb.go +++ b/lnrpc/walletrpc/walletkit.pb.go @@ -723,8 +723,9 @@ type Account struct { // //The fingerprint of the root key from which the account public key was //derived from. This will always be zero for the default imported account in - //which single public keys are imported into. - MasterKeyFingerprint uint32 `protobuf:"varint,4,opt,name=master_key_fingerprint,json=masterKeyFingerprint,proto3" json:"master_key_fingerprint,omitempty"` + //which single public keys are imported into. The bytes are in big-endian + //order. + MasterKeyFingerprint []byte `protobuf:"bytes,4,opt,name=master_key_fingerprint,json=masterKeyFingerprint,proto3" json:"master_key_fingerprint,omitempty"` // //The derivation path corresponding to the account public key. This will //always be empty for the default imported account in which single public keys @@ -797,11 +798,11 @@ func (x *Account) GetExtendedPublicKey() string { return "" } -func (x *Account) GetMasterKeyFingerprint() uint32 { +func (x *Account) GetMasterKeyFingerprint() []byte { if x != nil { return x.MasterKeyFingerprint } - return 0 + return nil } func (x *Account) GetDerivationPath() string { @@ -951,8 +952,9 @@ type ImportAccountRequest struct { // //The fingerprint of the root key (also known as the key with derivation path //m/) from which the account public key was derived from. This may be required - //by some hardware wallets for proper identification and signing. - MasterKeyFingerprint uint32 `protobuf:"varint,3,opt,name=master_key_fingerprint,json=masterKeyFingerprint,proto3" json:"master_key_fingerprint,omitempty"` + //by some hardware wallets for proper identification and signing. The bytes + //must be in big-endian order. + MasterKeyFingerprint []byte `protobuf:"bytes,3,opt,name=master_key_fingerprint,json=masterKeyFingerprint,proto3" json:"master_key_fingerprint,omitempty"` // //An address type is only required when the extended account public key has a //legacy version (xpub, tpub, etc.), such that the wallet cannot detect what @@ -1013,11 +1015,11 @@ func (x *ImportAccountRequest) GetExtendedPublicKey() string { return "" } -func (x *ImportAccountRequest) GetMasterKeyFingerprint() uint32 { +func (x *ImportAccountRequest) GetMasterKeyFingerprint() []byte { if x != nil { return x.MasterKeyFingerprint } - return 0 + return nil } func (x *ImportAccountRequest) GetAddressType() AddressType { @@ -2841,7 +2843,7 @@ var file_walletrpc_walletkit_proto_rawDesc = []byte{ 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x34, 0x0a, 0x16, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x69, 0x6e, - 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, + 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x14, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x64, @@ -2872,7 +2874,7 @@ var file_walletrpc_walletkit_proto_rawDesc = []byte{ 0x52, 0x11, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x34, 0x0a, 0x16, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x14, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x46, 0x69, + 0x01, 0x28, 0x0c, 0x52, 0x14, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0c, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72, diff --git a/lnrpc/walletrpc/walletkit.proto b/lnrpc/walletrpc/walletkit.proto index a556654f..8aecbf28 100644 --- a/lnrpc/walletrpc/walletkit.proto +++ b/lnrpc/walletrpc/walletkit.proto @@ -324,9 +324,10 @@ message Account { /* The fingerprint of the root key from which the account public key was derived from. This will always be zero for the default imported account in - which single public keys are imported into. + which single public keys are imported into. The bytes are in big-endian + order. */ - uint32 master_key_fingerprint = 4; + bytes master_key_fingerprint = 4; /* The derivation path corresponding to the account public key. This will @@ -377,9 +378,10 @@ message ImportAccountRequest { /* The fingerprint of the root key (also known as the key with derivation path m/) from which the account public key was derived from. This may be required - by some hardware wallets for proper identification and signing. + by some hardware wallets for proper identification and signing. The bytes + must be in big-endian order. */ - uint32 master_key_fingerprint = 3; + bytes master_key_fingerprint = 3; /* An address type is only required when the extended account public key has a diff --git a/lnrpc/walletrpc/walletkit.swagger.json b/lnrpc/walletrpc/walletkit.swagger.json index 3489de38..f87fd4b9 100644 --- a/lnrpc/walletrpc/walletkit.swagger.json +++ b/lnrpc/walletrpc/walletkit.swagger.json @@ -861,9 +861,9 @@ "description": "The public key backing the account that all keys are derived from\nrepresented as an extended key. This will always be empty for the default\nimported account in which single public keys are imported into." }, "master_key_fingerprint": { - "type": "integer", - "format": "int64", - "description": "The fingerprint of the root key from which the account public key was\nderived from. This will always be zero for the default imported account in\nwhich single public keys are imported into." + "type": "string", + "format": "byte", + "description": "The fingerprint of the root key from which the account public key was\nderived from. This will always be zero for the default imported account in\nwhich single public keys are imported into. The bytes are in big-endian\norder." }, "derivation_path": { "type": "string", @@ -1057,9 +1057,9 @@ "description": "A public key that corresponds to a wallet account represented as an extended\nkey. It must conform to a derivation path of the form\nm/purpose'/coin_type'/account'." }, "master_key_fingerprint": { - "type": "integer", - "format": "int64", - "description": "The fingerprint of the root key (also known as the key with derivation path\nm/) from which the account public key was derived from. This may be required\nby some hardware wallets for proper identification and signing." + "type": "string", + "format": "byte", + "description": "The fingerprint of the root key (also known as the key with derivation path\nm/) from which the account public key was derived from. This may be required\nby some hardware wallets for proper identification and signing. The bytes\nmust be in big-endian order." }, "address_type": { "$ref": "#/definitions/walletrpcAddressType", diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index 820cc581..002a620f 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -5,6 +5,7 @@ package walletrpc import ( "bytes" "context" + "encoding/binary" "errors" "fmt" "io/ioutil" @@ -1253,8 +1254,8 @@ func marshalWalletAccount(account *waddrmgr.AccountProperties) (*Account, error) break } - switch account.AddrSchema { - case &waddrmgr.KeyScopeBIP0049AddrSchema: + switch *account.AddrSchema { + case waddrmgr.KeyScopeBIP0049AddrSchema: addrType = AddressType_NESTED_WITNESS_PUBKEY_HASH default: return nil, fmt.Errorf("unsupported address schema %v", @@ -1283,7 +1284,13 @@ func marshalWalletAccount(account *waddrmgr.AccountProperties) (*Account, error) nonHardenedIndex := account.AccountPubKey.ChildIndex() - hdkeychain.HardenedKeyStart rpcAccount.ExtendedPublicKey = account.AccountPubKey.String() - rpcAccount.MasterKeyFingerprint = account.MasterKeyFingerprint + if account.MasterKeyFingerprint != 0 { + var mkfp [4]byte + binary.BigEndian.PutUint32( + mkfp[:], account.MasterKeyFingerprint, + ) + rpcAccount.MasterKeyFingerprint = mkfp[:] + } rpcAccount.DerivationPath = fmt.Sprintf("%v/%v'", account.KeyScope, nonHardenedIndex) } @@ -1396,14 +1403,27 @@ func (w *WalletKit) ImportAccount(ctx context.Context, if err != nil { return nil, err } + + var mkfp uint32 + switch len(req.MasterKeyFingerprint) { + // No master key fingerprint provided, which is fine as it's not + // required. + case 0: + // Expected length. + case 4: + mkfp = binary.BigEndian.Uint32(req.MasterKeyFingerprint) + default: + return nil, errors.New("invalid length for master key " + + "fingerprint, expected 4 bytes in big-endian") + } + addrType, err := parseAddrType(req.AddressType, false) if err != nil { return nil, err } accountProps, extAddrs, intAddrs, err := w.cfg.Wallet.ImportAccount( - req.Name, accountPubKey, req.MasterKeyFingerprint, addrType, - req.DryRun, + req.Name, accountPubKey, mkfp, addrType, req.DryRun, ) if err != nil { return nil, err