-
Notifications
You must be signed in to change notification settings - Fork 3
/
rpcserver.go
130 lines (107 loc) · 3.64 KB
/
rpcserver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright (C) 2013-2017 The btcsuite developers
// Copyright (C) 2015-2016 The Decred developers
// Copyright (C) 2015-2022 Lightning Labs and The Lightning Network Developers
// Copyright (C) 2022 Bottlepay and The Lightning Network Developers
package lndsigner
import (
"context"
"fmt"
"github.com/hashicorp/vault/api"
"github.com/nydig/lndsigner/keyring"
"github.com/nydig/lndsigner/proto"
"github.com/tv42/zbase32"
"google.golang.org/grpc"
)
// keyRingKeyStruct is a struct used to look up a keyring passed in a context.
type keyRingKeyStruct struct{}
var (
keyRingKey = keyRingKeyStruct{}
)
// rpcServer is a gRPC front end to the signer daemon.
type rpcServer struct {
// Required by the grpc-gateway/v2 library for forward compatibility.
// Must be after the atomically used variables to not break struct
// alignment.
proto.UnimplementedLightningServer
client *api.Logical
cfg *Config
keyRing *keyring.KeyRing
}
// A compile time check to ensure that rpcServer fully implements the
// LightningServer gRPC service.
var _ proto.LightningServer = (*rpcServer)(nil)
// newRPCServer creates and returns a new instance of the rpcServer. Before
// dependencies are added, this will be an non-functioning RPC server only to
// be used to register the LightningService with the gRPC server.
func newRPCServer(cfg *Config, c *api.Logical) *rpcServer {
return &rpcServer{
cfg: cfg,
client: c,
keyRing: keyring.NewKeyRing(
c,
cfg.NodePubKey,
cfg.ActiveNetParams.HDCoinType,
),
}
}
// intercept allows the RPC server to intercept requests to ensure that they're
// authorized by a macaroon signed by the macaroon root key.
func (r *rpcServer) intercept(ctx context.Context, req interface{},
info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (
interface{}, error) {
return handler(
context.WithValue(ctx, keyRingKey, r.keyRing),
req,
)
}
// RegisterWithGrpcServer registers the rpcServer and any subservers with the
// root gRPC server.
func (r *rpcServer) RegisterWithGrpcServer(grpcServer *grpc.Server) error {
// Register the main RPC server.
lnDesc := proto.Lightning_ServiceDesc
lnDesc.ServiceName = "lnrpc.Lightning"
grpcServer.RegisterService(&lnDesc, r)
// Register the wallet subserver.
walletDesc := proto.WalletKit_ServiceDesc
walletDesc.ServiceName = "walletrpc.WalletKit"
grpcServer.RegisterService(&walletDesc, &walletKit{
server: r,
})
// Register the signer subserver.
signerDesc := proto.Signer_ServiceDesc
signerDesc.ServiceName = "signrpc.Signer"
grpcServer.RegisterService(&signerDesc, &signerServer{
server: r,
})
return nil
}
var (
// signedMsgPrefix is a special prefix that we'll prepend to any
// messages we sign/verify. We do this to ensure that we don't
// accidentally sign a sighash, or other sensitive material. By
// prepending this fragment, we mind message signing to our particular
// context.
signedMsgPrefix = []byte("Lightning Signed Message:")
)
// SignMessage signs a message with the resident node's private key. The
// returned signature string is zbase32 encoded and pubkey recoverable, meaning
// that only the message digest and signature are needed for verification.
func (r *rpcServer) SignMessage(_ context.Context,
in *proto.SignMessageRequest) (*proto.SignMessageResponse, error) {
if in.Msg == nil {
return nil, fmt.Errorf("need a message to sign")
}
in.Msg = append(signedMsgPrefix, in.Msg...)
keyLoc := keyring.KeyLocator{
Family: 6,
Index: 0,
}
sig, err := r.keyRing.SignMessage(
keyLoc, in.Msg, !in.SingleHash, true,
)
if err != nil {
return nil, err
}
sigStr := zbase32.EncodeToString(sig)
return &proto.SignMessageResponse{Signature: sigStr}, nil
}