You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
3.9 KiB
136 lines
3.9 KiB
package proxy |
|
|
|
import ( |
|
"log" |
|
"regexp" |
|
"strings" |
|
|
|
"github.com/yuriy0803/open-etc-pool-friends/rpc" |
|
"github.com/yuriy0803/open-etc-pool-friends/util" |
|
) |
|
|
|
// Allow only lowercase hexadecimal with 0x prefix |
|
var noncePattern = regexp.MustCompile("^0x[0-9a-f]{16}$") |
|
var hashPattern = regexp.MustCompile("^0x[0-9a-f]{64}$") |
|
var workerPattern = regexp.MustCompile("^[0-9a-zA-Z-_]{1,200}$") |
|
|
|
// Stratum |
|
func (s *ProxyServer) handleLoginRPC(cs *Session, params []string, id string) (bool, *ErrorReply) { |
|
if len(params) == 0 { |
|
return false, &ErrorReply{Code: -1, Message: "Invalid params"} |
|
} |
|
|
|
login := params[0] |
|
// WORKER NAME 0x1234.WORKERNAME |
|
if strings.ContainsAny(login, ".") { |
|
var param = strings.Split(login, ".") |
|
login = param[0] |
|
id = param[1] |
|
} |
|
login = strings.ToLower(login) |
|
|
|
if !workerPattern.MatchString(id) { |
|
id = "0" |
|
} |
|
|
|
if !util.IsValidHexAddress(login) { |
|
return false, &ErrorReply{Code: -1, Message: "Invalid login"} |
|
} |
|
if !s.policy.ApplyLoginPolicy(login, cs.ip) { |
|
return false, &ErrorReply{Code: -1, Message: "You are blacklisted"} |
|
} |
|
|
|
cs.login = login |
|
cs.worker = id |
|
s.registerSession(cs) |
|
log.Printf("Stratum miner connected %v@%v", login, cs.ip) |
|
return true, nil |
|
} |
|
|
|
func (s *ProxyServer) handleGetWorkRPC(cs *Session) ([]string, *ErrorReply) { |
|
t := s.currentBlockTemplate() |
|
if t == nil || len(t.Header) == 0 || s.isSick() { |
|
return nil, &ErrorReply{Code: 0, Message: "Work not ready"} |
|
} |
|
return []string{t.Header, t.Seed, s.diff, util.ToHex(int64(t.Height))}, nil |
|
} |
|
|
|
// Stratum |
|
func (s *ProxyServer) handleTCPSubmitRPC(cs *Session, id string, params []string) (bool, *ErrorReply) { |
|
s.sessionsMu.RLock() |
|
_, ok := s.sessions[cs] |
|
s.sessionsMu.RUnlock() |
|
|
|
if !ok { |
|
return false, &ErrorReply{Code: 25, Message: "Not subscribed"} |
|
} |
|
return s.handleSubmitRPC(cs, cs.login, cs.worker, params) |
|
} |
|
|
|
func (s *ProxyServer) handleSubmitRPC(cs *Session, login, id string, params []string) (bool, *ErrorReply) { |
|
|
|
if len(params) != 3 { |
|
s.policy.ApplyMalformedPolicy(cs.ip) |
|
log.Printf("Malformed params from %s@%s %v", login, cs.ip, params) |
|
return false, &ErrorReply{Code: -1, Message: "Invalid params"} |
|
} |
|
|
|
stratumMode := cs.stratumMode() |
|
if stratumMode == NiceHash { |
|
for i := 0; i <= 2; i++ { |
|
if params[i][0:2] != "0x" { |
|
params[i] = "0x" + params[i] |
|
} |
|
} |
|
} |
|
|
|
if !noncePattern.MatchString(params[0]) || !hashPattern.MatchString(params[1]) || !hashPattern.MatchString(params[2]) { |
|
s.policy.ApplyMalformedPolicy(cs.ip) |
|
log.Printf("Malformed PoW result from %s@%s %v", login, cs.ip, params) |
|
return false, &ErrorReply{Code: -1, Message: "Malformed PoW result"} |
|
} |
|
t := s.currentBlockTemplate() |
|
exist, validShare := s.processShare(login, id, cs.ip, t, params, stratumMode != EthProxy) |
|
ok := s.policy.ApplySharePolicy(cs.ip, !exist && validShare) |
|
|
|
if exist { |
|
log.Printf("Duplicate share from %s@%s %v", login, cs.ip, params) |
|
// see https://github.com/sammy007/open-ethereum-pool/compare/master...nicehashdev:patch-1 |
|
if !ok { |
|
return false, &ErrorReply{Code: 23, Message: "Invalid share"} |
|
} |
|
return false, nil |
|
} |
|
|
|
if !validShare { |
|
log.Printf("Invalid share from %s@%s", login, cs.ip) |
|
// Bad shares limit reached, return error and close |
|
if !ok { |
|
return false, &ErrorReply{Code: 23, Message: "Invalid share"} |
|
} |
|
return false, nil |
|
} |
|
if s.config.Proxy.Debug { |
|
log.Printf("Valid share from %s@%s", login, cs.ip) |
|
} |
|
|
|
if !ok { |
|
return true, &ErrorReply{Code: -1, Message: "High rate of invalid shares"} |
|
} |
|
return true, nil |
|
} |
|
|
|
func (s *ProxyServer) handleGetBlockByNumberRPC() *rpc.GetBlockReplyPart { |
|
t := s.currentBlockTemplate() |
|
var reply *rpc.GetBlockReplyPart |
|
if t != nil { |
|
reply = t.GetPendingBlockCache |
|
} |
|
return reply |
|
} |
|
|
|
func (s *ProxyServer) handleUnknownRPC(cs *Session, m string) *ErrorReply { |
|
log.Printf("Unknown request method %s from %s", m, cs.ip) |
|
s.policy.ApplyMalformedPolicy(cs.ip) |
|
return &ErrorReply{Code: -3, Message: "Method not found"} |
|
}
|
|
|