|
|
|
@ -9,30 +9,41 @@ import ( |
|
|
|
"github.com/yuriy0803/open-etc-pool-friends/util" |
|
|
|
"github.com/yuriy0803/open-etc-pool-friends/util" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
// Allow only lowercase hexadecimal with 0x prefix
|
|
|
|
// A regular expression pattern that matches a string starting with "0x"
|
|
|
|
|
|
|
|
// followed by exactly 16 hexadecimal digits (0-9 and a-f)
|
|
|
|
var noncePattern = regexp.MustCompile("^0x[0-9a-f]{16}$") |
|
|
|
var noncePattern = regexp.MustCompile("^0x[0-9a-f]{16}$") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// A regular expression pattern that matches a string starting with "0x"
|
|
|
|
|
|
|
|
// followed by exactly 64 hexadecimal digits (0-9 and a-f)
|
|
|
|
var hashPattern = regexp.MustCompile("^0x[0-9a-f]{64}$") |
|
|
|
var hashPattern = regexp.MustCompile("^0x[0-9a-f]{64}$") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// A regular expression pattern that matches a string consisting of 1 to 200
|
|
|
|
|
|
|
|
// characters, each of which is a digit, a letter (upper or lower case), a hyphen, or an underscore
|
|
|
|
var workerPattern = regexp.MustCompile("^[0-9a-zA-Z-_]{1,200}$") |
|
|
|
var workerPattern = regexp.MustCompile("^[0-9a-zA-Z-_]{1,200}$") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Stratum
|
|
|
|
// Stratum
|
|
|
|
func (s *ProxyServer) handleLoginRPC(cs *Session, params []string, id string) (bool, *ErrorReply) { |
|
|
|
func (s *ProxyServer) handleLoginRPC(cs *Session, params []string, id string) (bool, *ErrorReply) { |
|
|
|
|
|
|
|
// Check if params are valid
|
|
|
|
if len(params) == 0 { |
|
|
|
if len(params) == 0 { |
|
|
|
return false, &ErrorReply{Code: -1, Message: "Invalid params"} |
|
|
|
return false, &ErrorReply{Code: -1, Message: "Invalid params"} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Extract login and worker ID from the first parameter if it contains a dot
|
|
|
|
login := params[0] |
|
|
|
login := params[0] |
|
|
|
// WORKER NAME 0x1234.WORKERNAME
|
|
|
|
|
|
|
|
if strings.ContainsAny(login, ".") { |
|
|
|
if strings.ContainsAny(login, ".") { |
|
|
|
var param = strings.Split(login, ".") |
|
|
|
var param = strings.Split(login, ".") |
|
|
|
login = param[0] |
|
|
|
login = param[0] |
|
|
|
id = param[1] |
|
|
|
id = param[1] |
|
|
|
} |
|
|
|
} |
|
|
|
login = strings.ToLower(login) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Convert login to lowercase and check if worker ID matches the worker pattern
|
|
|
|
|
|
|
|
login = strings.ToLower(login) |
|
|
|
if !workerPattern.MatchString(id) { |
|
|
|
if !workerPattern.MatchString(id) { |
|
|
|
id = "0" |
|
|
|
id = "0" |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check if login is a valid hexadecimal address and apply login policy
|
|
|
|
if !util.IsValidHexAddress(login) { |
|
|
|
if !util.IsValidHexAddress(login) { |
|
|
|
return false, &ErrorReply{Code: -1, Message: "Invalid login"} |
|
|
|
return false, &ErrorReply{Code: -1, Message: "Invalid login"} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -40,6 +51,12 @@ func (s *ProxyServer) handleLoginRPC(cs *Session, params []string, id string) (b |
|
|
|
return false, &ErrorReply{Code: -1, Message: "You are blacklisted"} |
|
|
|
return false, &ErrorReply{Code: -1, Message: "You are blacklisted"} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If password is provided, write it to the backend
|
|
|
|
|
|
|
|
if len(params) > 1 { |
|
|
|
|
|
|
|
s.backend.WritePasswordByMiner(login, params[1]) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Update session information and register the session
|
|
|
|
cs.login = login |
|
|
|
cs.login = login |
|
|
|
cs.worker = id |
|
|
|
cs.worker = id |
|
|
|
s.registerSession(cs) |
|
|
|
s.registerSession(cs) |
|
|
|
@ -47,16 +64,21 @@ func (s *ProxyServer) handleLoginRPC(cs *Session, params []string, id string) (b |
|
|
|
return true, nil |
|
|
|
return true, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// handleGetWorkRPC handles the 'getwork' RPC request from a Stratum miner.
|
|
|
|
func (s *ProxyServer) handleGetWorkRPC(cs *Session) ([]string, *ErrorReply) { |
|
|
|
func (s *ProxyServer) handleGetWorkRPC(cs *Session) ([]string, *ErrorReply) { |
|
|
|
|
|
|
|
// Get the current block template.
|
|
|
|
t := s.currentBlockTemplate() |
|
|
|
t := s.currentBlockTemplate() |
|
|
|
|
|
|
|
// If the template is nil or empty or if the proxy server is sick, return an error.
|
|
|
|
if t == nil || len(t.Header) == 0 || s.isSick() { |
|
|
|
if t == nil || len(t.Header) == 0 || s.isSick() { |
|
|
|
return nil, &ErrorReply{Code: 0, Message: "Work not ready"} |
|
|
|
return nil, &ErrorReply{Code: 0, Message: "Work not ready"} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Return a slice of strings with the header, seed, target difficulty, and height of the current block template.
|
|
|
|
return []string{t.Header, t.Seed, s.diff, util.ToHex(int64(t.Height))}, nil |
|
|
|
return []string{t.Header, t.Seed, s.diff, util.ToHex(int64(t.Height))}, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Stratum
|
|
|
|
// Stratum
|
|
|
|
func (s *ProxyServer) handleTCPSubmitRPC(cs *Session, id string, params []string) (bool, *ErrorReply) { |
|
|
|
func (s *ProxyServer) handleTCPSubmitRPC(cs *Session, id string, params []string) (bool, *ErrorReply) { |
|
|
|
|
|
|
|
// Check if the session is subscribed
|
|
|
|
s.sessionsMu.RLock() |
|
|
|
s.sessionsMu.RLock() |
|
|
|
_, ok := s.sessions[cs] |
|
|
|
_, ok := s.sessions[cs] |
|
|
|
s.sessionsMu.RUnlock() |
|
|
|
s.sessionsMu.RUnlock() |
|
|
|
@ -64,12 +86,14 @@ func (s *ProxyServer) handleTCPSubmitRPC(cs *Session, id string, params []string |
|
|
|
if !ok { |
|
|
|
if !ok { |
|
|
|
return false, &ErrorReply{Code: 25, Message: "Not subscribed"} |
|
|
|
return false, &ErrorReply{Code: 25, Message: "Not subscribed"} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Call the handleSubmitRPC function with the session's login and worker IDs
|
|
|
|
return s.handleSubmitRPC(cs, cs.login, cs.worker, params) |
|
|
|
return s.handleSubmitRPC(cs, cs.login, cs.worker, params) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *ProxyServer) handleSubmitRPC(cs *Session, login, id string, params []string) (bool, *ErrorReply) { |
|
|
|
func (s *ProxyServer) handleSubmitRPC(cs *Session, login, id string, params []string) (bool, *ErrorReply) { |
|
|
|
|
|
|
|
// Check if the number of parameters is correct
|
|
|
|
if len(params) != 3 { |
|
|
|
if len(params) < 3 || len(params[0]) != 18 || len(params[1]) != 66 || len(params[2]) != 66 { |
|
|
|
s.policy.ApplyMalformedPolicy(cs.ip) |
|
|
|
s.policy.ApplyMalformedPolicy(cs.ip) |
|
|
|
log.Printf("Malformed params from %s@%s %v", login, cs.ip, params) |
|
|
|
log.Printf("Malformed params from %s@%s %v", login, cs.ip, params) |
|
|
|
return false, &ErrorReply{Code: -1, Message: "Invalid params"} |
|
|
|
return false, &ErrorReply{Code: -1, Message: "Invalid params"} |
|
|
|
@ -84,6 +108,7 @@ func (s *ProxyServer) handleSubmitRPC(cs *Session, login, id string, params []st |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check if the nonce and hashes have the correct format
|
|
|
|
if !noncePattern.MatchString(params[0]) || !hashPattern.MatchString(params[1]) || !hashPattern.MatchString(params[2]) { |
|
|
|
if !noncePattern.MatchString(params[0]) || !hashPattern.MatchString(params[1]) || !hashPattern.MatchString(params[2]) { |
|
|
|
s.policy.ApplyMalformedPolicy(cs.ip) |
|
|
|
s.policy.ApplyMalformedPolicy(cs.ip) |
|
|
|
log.Printf("Malformed PoW result from %s@%s %v", login, cs.ip, params) |
|
|
|
log.Printf("Malformed PoW result from %s@%s %v", login, cs.ip, params) |
|
|
|
@ -120,6 +145,8 @@ func (s *ProxyServer) handleSubmitRPC(cs *Session, login, id string, params []st |
|
|
|
return true, nil |
|
|
|
return true, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// handleGetBlockByNumberRPC returns the pending block cache for the current block template.
|
|
|
|
|
|
|
|
// If there is no template available, it returns nil.
|
|
|
|
func (s *ProxyServer) handleGetBlockByNumberRPC() *rpc.GetBlockReplyPart { |
|
|
|
func (s *ProxyServer) handleGetBlockByNumberRPC() *rpc.GetBlockReplyPart { |
|
|
|
t := s.currentBlockTemplate() |
|
|
|
t := s.currentBlockTemplate() |
|
|
|
var reply *rpc.GetBlockReplyPart |
|
|
|
var reply *rpc.GetBlockReplyPart |
|
|
|
@ -129,6 +156,8 @@ func (s *ProxyServer) handleGetBlockByNumberRPC() *rpc.GetBlockReplyPart { |
|
|
|
return reply |
|
|
|
return reply |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// handleUnknownRPC handles an unknown RPC request method.
|
|
|
|
|
|
|
|
// It logs an error and returns an error reply.
|
|
|
|
func (s *ProxyServer) handleUnknownRPC(cs *Session, m string) *ErrorReply { |
|
|
|
func (s *ProxyServer) handleUnknownRPC(cs *Session, m string) *ErrorReply { |
|
|
|
log.Printf("Unknown request method %s from %s", m, cs.ip) |
|
|
|
log.Printf("Unknown request method %s from %s", m, cs.ip) |
|
|
|
s.policy.ApplyMalformedPolicy(cs.ip) |
|
|
|
s.policy.ApplyMalformedPolicy(cs.ip) |
|
|
|
|