forked from kaspanet/kaspad
/
server.go
143 lines (116 loc) · 3.88 KB
/
server.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
131
132
133
134
135
136
137
138
139
140
141
142
143
package server
import (
"fmt"
"net"
"os"
"sync"
"time"
"github.com/Kash-Protocol/kashd/domain/consensus/model/externalapi"
"github.com/Kash-Protocol/kashd/util/txmass"
"github.com/Kash-Protocol/kashd/util/profiling"
"github.com/Kash-Protocol/kashd/cmd/kashwallet/daemon/pb"
"github.com/Kash-Protocol/kashd/cmd/kashwallet/keys"
"github.com/Kash-Protocol/kashd/domain/dagconfig"
"github.com/Kash-Protocol/kashd/infrastructure/network/rpcclient"
"github.com/Kash-Protocol/kashd/infrastructure/os/signal"
"github.com/Kash-Protocol/kashd/util/panics"
"github.com/pkg/errors"
"google.golang.org/grpc"
)
type server struct {
pb.UnimplementedKashwalletdServer
rpcClient *rpcclient.RPCClient
params *dagconfig.Params
lock sync.RWMutex
utxosSortedByAmount []*walletUTXO
nextSyncStartIndex uint32
keysFile *keys.File
shutdown chan struct{}
addressSet walletAddressSet
txMassCalculator *txmass.Calculator
usedOutpoints map[externalapi.DomainOutpoint]time.Time
isLogFinalProgressLineShown bool
maxUsedAddressesForLog uint32
maxProcessedAddressesForLog uint32
}
// MaxDaemonSendMsgSize is the max send message size used for the daemon server.
// Currently, set to 100MB
const MaxDaemonSendMsgSize = 100_000_000
// Start starts the kashwalletd server
func Start(params *dagconfig.Params, listen, rpcServer string, keysFilePath string, profile string, timeout uint32) error {
initLog(defaultLogFile, defaultErrLogFile)
defer panics.HandlePanic(log, "MAIN", nil)
interrupt := signal.InterruptListener()
if profile != "" {
profiling.Start(profile, log)
}
listener, err := net.Listen("tcp", listen)
if err != nil {
return (errors.Wrapf(err, "Error listening to TCP on %s", listen))
}
log.Infof("Listening to TCP on %s", listen)
log.Infof("Connecting to a node at %s...", rpcServer)
rpcClient, err := connectToRPC(params, rpcServer, timeout)
if err != nil {
return (errors.Wrapf(err, "Error connecting to RPC server %s", rpcServer))
}
log.Infof("Connected, reading keys file %s...", keysFilePath)
keysFile, err := keys.ReadKeysFile(params, keysFilePath)
if err != nil {
return (errors.Wrapf(err, "Error reading keys file %s", keysFilePath))
}
err = keysFile.TryLock()
if err != nil {
return err
}
serverInstance := &server{
rpcClient: rpcClient,
params: params,
utxosSortedByAmount: []*walletUTXO{},
nextSyncStartIndex: 0,
keysFile: keysFile,
shutdown: make(chan struct{}),
addressSet: make(walletAddressSet),
txMassCalculator: txmass.NewCalculator(params.MassPerTxByte, params.MassPerScriptPubKeyByte, params.MassPerSigOp),
usedOutpoints: map[externalapi.DomainOutpoint]time.Time{},
isLogFinalProgressLineShown: false,
maxUsedAddressesForLog: 0,
maxProcessedAddressesForLog: 0,
}
log.Infof("Read, syncing the wallet...")
spawn("serverInstance.sync", func() {
err := serverInstance.sync()
if err != nil {
printErrorAndExit(errors.Wrap(err, "error syncing the wallet"))
}
})
grpcServer := grpc.NewServer(grpc.MaxSendMsgSize(MaxDaemonSendMsgSize))
pb.RegisterKashwalletdServer(grpcServer, serverInstance)
spawn("grpcServer.Serve", func() {
err := grpcServer.Serve(listener)
if err != nil {
printErrorAndExit(errors.Wrap(err, "Error serving gRPC"))
}
})
select {
case <-serverInstance.shutdown:
case <-interrupt:
const stopTimeout = 2 * time.Second
stopChan := make(chan interface{})
spawn("gRPCServer.Stop", func() {
grpcServer.GracefulStop()
close(stopChan)
})
select {
case <-stopChan:
case <-time.After(stopTimeout):
log.Warnf("Could not gracefully stop: timed out after %s", stopTimeout)
grpcServer.Stop()
}
}
return nil
}
func printErrorAndExit(err error) {
fmt.Fprintf(os.Stderr, "%+v\n", err)
os.Exit(1)
}