-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
executable file
·185 lines (144 loc) · 5.67 KB
/
Copy pathmain.go
File metadata and controls
executable file
·185 lines (144 loc) · 5.67 KB
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package main
import (
"context"
"fmt"
"net"
"net/http"
"time"
"blvchain/core/config"
"blvchain/core/db"
"blvchain/core/logger"
"blvchain/core/protos"
"blvchain/core/ws"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"google.golang.org/grpc"
)
func main() {
// Init BVM internal functions
// bvm.InitBVMInternalFunctions()
// // Run BVM
// bvm_err := bvm.RunBVM(config.SMART_CONTRACT_PATH)
// if bvm_err != nil {
// fmt.Println(bvm_err)
// }
fmt.Println("===== Starting core =====")
syncDone := make(chan bool)
client, client_err := db.ConnectToMongoDB()
if client_err != nil {
logger.INTERNAL_LOGGER.Fatal(client_err)
fmt.Println("Error: see log/internal folder for details.")
}
defer func() {
if client_err = client.Disconnect(context.TODO()); client_err != nil {
logger.INTERNAL_LOGGER.Fatal(client_err)
fmt.Println("Error: see log/internal folder for details.")
}
}()
dataBase := client.Database(config.DATABASE_NAME)
config.BLOCK_COLL = dataBase.Collection(config.BLOCK_COLLECTION_NAME)
// create Mongo indexes for Block collection
{
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Single-field index for timestamp (used for sorting and range queries)
tsIndexModel := mongo.IndexModel{
Keys: bson.D{{Key: "blockMeta.timeStamp", Value: -1}},
Options: options.Index().SetName("idx_blockmeta_timestamp_desc"),
}
// Compound indexes to support common query patterns: filter by sender/receiver and sort by timestamp
senderUidTsIndex := mongo.IndexModel{
Keys: bson.D{{Key: "blockData.senderUid", Value: 1}, {Key: "blockMeta.timeStamp", Value: -1}},
Options: options.Index().SetName("idx_blockdata_senderuid_ts"),
}
receiverUidTsIndex := mongo.IndexModel{
Keys: bson.D{{Key: "blockData.receiverUid", Value: 1}, {Key: "blockMeta.timeStamp", Value: -1}},
Options: options.Index().SetName("idx_blockdata_receiveruid_ts"),
}
// Indexes for equality filters used in several places
useContractIndex := mongo.IndexModel{
Keys: bson.D{{Key: "blockData.useContract", Value: 1}},
Options: options.Index().SetName("idx_blockdata_usecontract"),
}
idxs := []mongo.IndexModel{tsIndexModel, senderUidTsIndex, receiverUidTsIndex, useContractIndex}
if _, idxErr := config.BLOCK_COLL.Indexes().CreateMany(ctx, idxs); idxErr != nil {
logger.INTERNAL_LOGGER.Printf("Warning: failed to create indexes: %v", idxErr)
fmt.Println("Error: see log/internal folder for details.")
}
}
// Genesis makers
check_genesis, check_genesis_err := db.Genesis_check()
// Check genesis block and dns seed in DB in first run of Node
if check_genesis {
//* WebSocket
go func() {
//* Connect to other servers
ws.ClientManagerVar.ConnectToServers(config.DNS_SEED_LIST)
//* Local server gateways
http.HandleFunc("/", ws.WS_Server_Handler)
logger.WS_S_LOGGER.Println("Success: WebSocket Server is running on port", config.WEBSOCKET_PORT)
websocketListener_err := http.ListenAndServe(config.WEBSOCKET_PORT, nil)
if websocketListener_err != nil {
logger.WS_F_LOGGER.Fatalf("Failed to listen WebSocket: %v", websocketListener_err)
fmt.Println("Error: see log/websocket/fail folder for details.")
}
}()
// Monitor and reconnect to missed nodes
go func() {
ws.MonitorAndReconnectToServers(&ws.ClientManagerVar)
}()
go func() {
genesis_sync_result := ws.FirstTimeSyncData(&ws.ClientManagerVar)
syncDone <- genesis_sync_result
}()
// Wait for sync to complete before starting gRPC server
if <-syncDone {
logger.INTERNAL_LOGGER.Println("Success: Data sync completed, running gRPC server")
fmt.Println("Success: Data sync completed, running gRPC server")
//* gRPC
go func() {
grpcListener, grpcListener_err := net.Listen("tcp", config.GRPC_PORT)
if grpcListener_err != nil {
logger.GRPC_F_LOGGER.Fatalf("Error: Failed to listen gRPC: %v", grpcListener_err)
fmt.Println("Error: see log/gRPC/fail folder for details.")
}
// Per-method configuration
methodCfg := map[string]protos.MethodLimit{
"/gate.AddData/addData": {R: config.ADD_DATA_R, Burst: config.ADD_DATA_BURST},
"/gate.ReadData/readData": {R: config.READ_DATA_R, Burst: config.READ_DATA_BURST},
}
// default used for other RPCs (if any)
defaultCfg := protos.MethodLimit{R: 5, Burst: 10}
// create rate limiter with TTL for idle entries
rl := protos.NewRateLimiter(methodCfg, defaultCfg, 5*time.Minute)
grpcServer := grpc.NewServer(
grpc.UnaryInterceptor(rl.UnaryServerInterceptor()),
grpc.StreamInterceptor(rl.StreamServerInterceptor()),
)
// Register the services
protos.RegisterAddDataServer(grpcServer, &protos.AddDataService{})
protos.RegisterReadDataServer(grpcServer, &protos.ReadDataService{})
logger.GRPC_S_LOGGER.Println("Success: gRPC server is running on port", config.GRPC_PORT)
fmt.Println("Success: gRPC server is running on port", config.GRPC_PORT)
if grpcServer_err := grpcServer.Serve(grpcListener); grpcServer_err != nil {
logger.GRPC_F_LOGGER.Fatalf("Error: Failed to serve: %v", grpcServer_err)
fmt.Println("Error: see log/gRPC/fail folder for details.")
}
}()
// Sync missed data
go func() {
ws.SyncData(&ws.ClientManagerVar)
}()
} else {
logger.INTERNAL_LOGGER.Fatal("Error: Data sync failed")
fmt.Println("Error: see log/internal folder for details.")
}
// Prevent main from exiting
select {}
} else {
// Print error if genesis conditions fail
logger.INTERNAL_LOGGER.Printf("Error: %v", check_genesis_err)
fmt.Println("Error: see log/internal folder for details.")
}
}