forked from maran/electrum-sync-server
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathsync_master.go
More file actions
152 lines (134 loc) · 4.53 KB
/
Copy pathsync_master.go
File metadata and controls
152 lines (134 loc) · 4.53 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
package main
import (
"fmt"
"github.com/ant0ine/go-json-rest/rest"
"github.com/jcelliott/lumber"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/postgres"
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/mattn/go-sqlite3"
"log"
"net/http"
"os"
"path"
)
type SyncMaster struct {
db gorm.DB
logger *lumber.ConsoleLogger
}
func newSyncMaster(opts DbOpts) SyncMaster {
sync := SyncMaster{}
sync.logger = lumber.NewConsoleLogger(lumber.DEBUG)
sync.logger.Info("Starting Electrum Sync Server v%s", Version)
var err error
if opts.DbType == "sqlite3" {
dbPath := opts.DbPath + "/sync.db"
sync.logger.Info("Opening database at %s", dbPath)
err = os.MkdirAll(opts.DbPath, 0700) // read, write and dir search for user
if err != nil {
log.Fatal("Error creating database folder", err)
}
newdb, err := gorm.Open("sqlite3", dbPath)
if err != nil {
log.Fatal("Error opening sqlite3 database:", err)
}
sync.db = *newdb
} else if opts.DbType == "postgres" {
optss := fmt.Sprintf("postgresql://%s:%s@%s:%d/%s", opts.User, opts.Password, opts.Host, opts.Port, opts.Dbname)
sync.logger.Info("Connecting to postgres database")
newdb, err := gorm.Open("postgres", optss)
if err != nil {
log.Fatal("Error connecting to Postgres database: ", err)
}
sync.db = *newdb
} else if opts.DbType == "mysql" {
optss := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", opts.User, opts.Password, opts.Host, opts.Port, opts.Dbname)
sync.logger.Info("Connecting to mysql database")
newdb, err := gorm.Open("mysql", optss)
if err != nil {
log.Fatal("Error connecting to mysql database: ", err)
}
sync.db = *newdb
} else {
log.Fatal("Unknown database type. Please supply sqlite3 or postgres")
}
sync.db.AutoMigrate(&Label{})
return sync
}
func (self *SyncMaster) makeLabel(labelRequest LabelRequest, w rest.ResponseWriter) Label {
var label Label
search := Label{WalletId: labelRequest.WalletId, ExternalId: labelRequest.ExternalId}
self.db.Where(search).FirstOrInit(&label)
self.logger.Debug("current label nonce: %d got a request nonce to overwrite it with %d", label.Nonce, labelRequest.WalletNonce)
if label.Nonce > labelRequest.WalletNonce {
rest.Error(w, "serverNonce is larger then walletNonce please sync first.", 400)
}
label.EncryptedLabel = labelRequest.EncryptedLabel
label.Nonce = labelRequest.WalletNonce
self.db.Save(&label)
return label
}
func (self *SyncMaster) CreateLabels(w rest.ResponseWriter, r *rest.Request) {
labelsRequest := LabelsRequest{}
err := r.DecodeJsonPayload(&labelsRequest)
if err != nil {
rest.Error(w, err.Error(), http.StatusInternalServerError)
return
}
var labelsResponse LabelsResponse
for _, batchLabel := range labelsRequest.Labels {
labelRequest := LabelRequest{batchLabel.EncryptedLabel, batchLabel.ExternalId, labelsRequest.WalletId, labelsRequest.WalletNonce}
labelsResponse.Labels = append(labelsResponse.Labels, self.makeLabel(labelRequest, w))
}
labelsResponse.Nonce = highestNonce(labelsResponse.Labels)
w.WriteJson(labelsResponse)
}
func (self *SyncMaster) CreateLabel(w rest.ResponseWriter, r *rest.Request) {
labelRequest := LabelRequest{}
err := r.DecodeJsonPayload(&labelRequest)
if err != nil {
rest.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if labelRequest.WalletId == "" {
rest.Error(w, "walletId required", 400)
}
if labelRequest.EncryptedLabel == "" {
rest.Error(w, "encryptedLabel required", 400)
}
if labelRequest.ExternalId == "" {
rest.Error(w, "externalId required", 400)
}
if labelRequest.WalletNonce == 0 {
rest.Error(w, "walletNonce required", 400)
}
self.logger.Debug("Got request:", labelRequest)
label := self.makeLabel(labelRequest, w)
w.WriteJson(label)
}
func (self *SyncMaster) GetLabels(w rest.ResponseWriter, r *rest.Request) {
var labels []Label
mpk := r.PathParam("mpk")
nonce := r.PathParam("nonce")
if mpk == "" {
rest.Error(w, "walletId required", 400)
}
if nonce == "" {
rest.Error(w, "nonce required", 400)
}
self.db.Where("wallet_id = ? AND nonce > ?", mpk, nonce).Find(&labels)
highestNonce := highestNonce(labels)
w.WriteJson(LabelsResponse{Nonce: highestNonce, Labels: labels})
}
func highestNonce(labels []Label) int {
var highestNonce int
for _, label := range labels {
if label.Nonce > highestNonce {
highestNonce = label.Nonce
}
}
return highestNonce
}
func defaultDbDir() string {
return path.Join(os.Getenv("HOME"), "/.electrum-sync-server/")
}