|
|
|
@ -21,7 +21,6 @@ var hashPattern = regexp.MustCompile("^0x[0-9a-f]{64}$") |
|
|
|
// characters, each of which is a digit, a letter (upper or lower case), a hyphen, or an underscore
|
|
|
|
// 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
|
|
|
|
// Check if params are valid
|
|
|
|
@ -94,10 +93,11 @@ func (s *ProxyServer) handleSubmitRPC(cs *Session, login, id string, params []st |
|
|
|
return false, &ErrorReply{Code: -1, Message: "Invalid params"} |
|
|
|
return false, &ErrorReply{Code: -1, Message: "Invalid params"} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Add "0x" prefix to params if the stratum mode is NiceHash
|
|
|
|
stratumMode := cs.stratumMode() |
|
|
|
stratumMode := cs.stratumMode() |
|
|
|
if stratumMode == NiceHash { |
|
|
|
if stratumMode == NiceHash { |
|
|
|
for i := 0; i <= 2; i++ { |
|
|
|
for i := 0; i < len(params); i++ { |
|
|
|
if params[i][0:2] != "0x" { |
|
|
|
if !strings.HasPrefix(params[i], "0x") { |
|
|
|
params[i] = "0x" + params[i] |
|
|
|
params[i] = "0x" + params[i] |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -109,37 +109,59 @@ func (s *ProxyServer) handleSubmitRPC(cs *Session, login, id string, params []st |
|
|
|
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) |
|
|
|
return false, &ErrorReply{Code: -1, Message: "Malformed PoW result"} |
|
|
|
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 { |
|
|
|
// Process the share in a separate goroutine
|
|
|
|
log.Printf("Duplicate share from %s@%s %v", login, cs.ip, params) |
|
|
|
go func(s *ProxyServer, cs *Session, login, id string, params []string) { |
|
|
|
// see https://github.com/sammy007/open-ethereum-pool/compare/master...nicehashdev:patch-1
|
|
|
|
// Get the current block template
|
|
|
|
if !ok { |
|
|
|
t := s.currentBlockTemplate() |
|
|
|
return false, &ErrorReply{Code: 23, Message: "Invalid share"} |
|
|
|
|
|
|
|
|
|
|
|
// Check if the share already exists and if it's valid
|
|
|
|
|
|
|
|
exist, validShare := s.processShare(login, id, cs.ip, t, params, stratumMode != EthProxy) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Apply the share policy to determine if the share should be accepted
|
|
|
|
|
|
|
|
ok := s.policy.ApplySharePolicy(cs.ip, !exist && validShare) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Handle duplicate share
|
|
|
|
|
|
|
|
if exist { |
|
|
|
|
|
|
|
log.Printf("Duplicate share from %s@%s %v", login, cs.ip, params) |
|
|
|
|
|
|
|
if !ok { |
|
|
|
|
|
|
|
cs.disconnect() |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
return false, nil |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !validShare { |
|
|
|
// Handle invalid share
|
|
|
|
log.Printf("Invalid share from %s@%s", login, cs.ip) |
|
|
|
if !validShare { |
|
|
|
// Bad shares limit reached, return error and close
|
|
|
|
log.Printf("Invalid share from %s@%s", login, cs.ip) |
|
|
|
|
|
|
|
s.backend.WriteWorkerShareStatus(login, id, false, true, false) |
|
|
|
|
|
|
|
// Bad shares limit reached, disconnect the session
|
|
|
|
|
|
|
|
if !ok { |
|
|
|
|
|
|
|
cs.disconnect() |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Handle valid share
|
|
|
|
|
|
|
|
if s.config.Proxy.Debug { |
|
|
|
|
|
|
|
log.Printf("Valid share from %s@%s", login, cs.ip) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Apply the policy to determine if the session should be disconnected
|
|
|
|
if !ok { |
|
|
|
if !ok { |
|
|
|
return false, &ErrorReply{Code: 23, Message: "Invalid share"} |
|
|
|
cs.disconnect() |
|
|
|
|
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
return false, nil |
|
|
|
}(s, cs, login, id, params) |
|
|
|
} |
|
|
|
|
|
|
|
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 |
|
|
|
return true, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (cs *Session) disconnect() { |
|
|
|
|
|
|
|
cs.conn.Close() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// handleGetBlockByNumberRPC returns the pending block cache for the current block template.
|
|
|
|
// handleGetBlockByNumberRPC returns the pending block cache for the current block template.
|
|
|
|
// If there is no template available, it returns nil.
|
|
|
|
// If there is no template available, it returns nil.
|
|
|
|
func (s *ProxyServer) handleGetBlockByNumberRPC() *rpc.GetBlockReplyPart { |
|
|
|
func (s *ProxyServer) handleGetBlockByNumberRPC() *rpc.GetBlockReplyPart { |
|
|
|
|