From 15c0898b5173938816b31a894f61710e0d5d6854 Mon Sep 17 00:00:00 2001 From: yuriy0803 Date: Sat, 20 Aug 2022 23:33:46 +0200 Subject: [PATCH] stratum_blacklist wallet --- api.json | 17 ++++++------ policy/policy.go | 62 +++++++++++++++++++++++++++++++++++------- proxy/handlers.go | 21 +++++++++++++- proxy/miner.go | 9 ++++++ stratum_blacklist.json | 1 + 5 files changed, 91 insertions(+), 19 deletions(-) create mode 100644 stratum_blacklist.json diff --git a/api.json b/api.json index f00f6a6..860a645 100644 --- a/api.json +++ b/api.json @@ -2,7 +2,7 @@ "threads": 4, "coin": "etc", "name": "main", - "pplns": 9000, + "pplns": 9000, "network": "classic", "coin-name":"etc", @@ -27,14 +27,15 @@ "timeout": "120s", "maxConn": 8192, "tls": false, - "certFile": "/path/to/cert.pem", - "keyFile": "/path/to/key.pem" + "certFile": "/path/to/cert.pem", + "keyFile": "/path/to/key.pem" }, "policy": { "workers": 8, "resetInterval": "60m", "refreshInterval": "1m", + "blacklist_file" : "/home/pool/open-etc-pool-friends/stratum_blacklist.json", "banning": { "enabled": false, @@ -67,11 +68,11 @@ "poolCharts":"*/20 * * * *", "poolChartsNum":74, "minerCharts":"*/20 * * * *", - "minerChartsNum":74, - "netCharts":"*/20 * * * *", - "netChartsNum":74, - "shareCharts":"*/20 * * * *", - "shareChartsNum":74 + "minerChartsNum":74, + "netCharts":"*/20 * * * *", + "netChartsNum":74, + "shareCharts":"*/20 * * * *", + "shareChartsNum":74 }, "upstreamCheckInterval": "5s", diff --git a/policy/policy.go b/policy/policy.go index 0f5e199..6154d8d 100644 --- a/policy/policy.go +++ b/policy/policy.go @@ -1,9 +1,12 @@ package policy import ( + "encoding/json" "fmt" "log" + "os" "os/exec" + "path/filepath" "strings" "sync" "sync/atomic" @@ -19,6 +22,7 @@ type Config struct { Limits Limits `json:"limits"` ResetInterval string `json:"resetInterval"` RefreshInterval string `json:"refreshInterval"` + Walletblacklist string `json:"blacklist_file"` } type Limits struct { @@ -52,16 +56,17 @@ type Stats struct { type PolicyServer struct { sync.RWMutex - statsMu sync.Mutex - config *Config - stats map[string]*Stats - banChannel chan string - startedAt int64 - grace int64 - timeout int64 - blacklist []string - whitelist []string - storage *storage.RedisClient + statsMu sync.Mutex + config *Config + stats map[string]*Stats + banChannel chan string + startedAt int64 + grace int64 + timeout int64 + blacklist []string + whitelist []string + storage *storage.RedisClient + walletblacklist []string } func Start(cfg *Config, storage *storage.RedisClient) *PolicyServer { @@ -142,6 +147,26 @@ func (s *PolicyServer) resetStats() { log.Printf("Flushed stats for %v IP addresses", total) } +// loads up blacklist of wallets if file is present +func (s *PolicyServer) GetWalletBlacklist() ([]string, error) { + blacklistFileName := s.config.Walletblacklist + blacklistFileName, _ = filepath.Abs(blacklistFileName) + log.Printf("Loading wallet blacklist: %v", blacklistFileName) + blacklistFile, err := os.Open(blacklistFileName) + if err != nil { + log.Printf("File error: %v", err.Error()) + return nil, err + } + defer blacklistFile.Close() + var data []string + jsonParser := json.NewDecoder(blacklistFile) + if err := jsonParser.Decode(&data); err != nil { + log.Printf("Blacklist parsing error: %v", err.Error()) + return nil, err + } + return data, nil +} + func (s *PolicyServer) refreshState() { s.Lock() defer s.Unlock() @@ -155,6 +180,10 @@ func (s *PolicyServer) refreshState() { if err != nil { log.Printf("Failed to get whitelist from backend: %v", err) } + s.walletblacklist, err = s.GetWalletBlacklist() + if err != nil { + log.Printf("Failed to get wallet/login blacklist from json file backend: %v", err) + } log.Println("Policy state refresh complete") } @@ -201,6 +230,13 @@ func (s *PolicyServer) ApplyLimitPolicy(ip string) bool { return true } +func (s *PolicyServer) ApplyLoginWalletPolicy(login string) bool { + if s.InWalletBlackList(login) { + return false + } + return true +} + func (s *PolicyServer) ApplyLoginPolicy(addy, ip string) bool { if s.InBlackList(addy) { x := s.Get(ip) @@ -210,6 +246,12 @@ func (s *PolicyServer) ApplyLoginPolicy(addy, ip string) bool { return true } +func (s *PolicyServer) InWalletBlackList(addy string) bool { + s.RLock() + defer s.RUnlock() + return util.StringInSlice(addy, s.walletblacklist) +} + func (s *PolicyServer) ApplyMalformedPolicy(ip string) bool { x := s.Get(ip) n := x.incrMalformed() diff --git a/proxy/handlers.go b/proxy/handlers.go index 9cc031c..4ab495b 100644 --- a/proxy/handlers.go +++ b/proxy/handlers.go @@ -30,6 +30,11 @@ func (s *ProxyServer) handleLoginRPC(cs *Session, params []string, id string) (b if !s.policy.ApplyLoginPolicy(login, cs.ip) { return false, &ErrorReply{Code: -1, Message: "You are blacklisted"} } + //save for later, too broad right now, bans the ip the wallet comes from, (bad if more then one miner proxies there) + // if !s.policy.ApplyLoginWalletPolicy(login) { + // // check to see if this wallet login is blocked in json file + // return false, &ErrorReply{Code: -1, Message: "You are blacklisted"} + // } cs.login = login s.registerSession(cs) log.Printf("Stratum miner connected %v@%v", login, cs.ip) @@ -71,24 +76,38 @@ func (s *ProxyServer) handleSubmitRPC(cs *Session, login, id string, params []st log.Printf("Malformed PoW result from %s@%s %v", login, cs.ip, params) return false, &ErrorReply{Code: -1, Message: "Malformed PoW result"} } + go func(s *ProxyServer, cs *Session, login, id string, params []string) { t := s.currentBlockTemplate() + + //MFO: This function (s.processShare) will process a share as per hasher.Verify function of github.com/ethereum/ethash + // output of this function is either: + // true,true (Exists) which means share already exists and it is validShare + // true,false (Exists & invalid)which means share already exists and it is invalidShare or it is a block <-- should not ever happen + // false,false (stale/invalid)which means share is new, and it is not a block, might be a stale share or invalidShare + // false,true (valid)which means share is new, and it is a block or accepted share + // false,false,false (blacklisted wallet attached to share) see json file + // When this function finishes, the results is already recorded in the db for valid shares or blocks. exist, validShare := s.processShare(login, id, cs.ip, t, params) ok := s.policy.ApplySharePolicy(cs.ip, !exist && validShare) + // if true,true or true,false if exist { log.Printf("Duplicate share from %s@%s %v", login, cs.ip, params) cs.lastErr = errors.New("Duplicate share") } + // if false, false if !validShare { + //MFO: Here we have an invalid share log.Printf("Invalid share from %s@%s", login, cs.ip) // Bad shares limit reached, return error and close if !ok { cs.lastErr = errors.New("Invalid share") } } - + //MFO: Here we have a valid share and it is already recorded in DB by miner.go + // if false, true if s.config.Proxy.Debug { log.Printf("Valid share from %s@%s", login, cs.ip) } diff --git a/proxy/miner.go b/proxy/miner.go index 2096a68..50ecc5f 100644 --- a/proxy/miner.go +++ b/proxy/miner.go @@ -65,6 +65,15 @@ func (s *ProxyServer) processShare(login, id, ip string, t *BlockTemplate, param mixDigest: common.HexToHash(mixDigest), } + //this is to stop people in wallet blacklist, from getting shares into the db. + //rare instances of hacks require letting the hacks waste thier money on occassion + if !s.policy.ApplyLoginWalletPolicy(login) { + // check to see if this wallet login is blocked + log.Printf("Blacklisted wallet share, skipped from %v", login) + return false, false + //return codes need work here, a lot of it. + } + if !hasher.Verify(share) { s.backend.WriteWorkerShareStatus(login, id, false, false, true) return false, false diff --git a/stratum_blacklist.json b/stratum_blacklist.json new file mode 100644 index 0000000..c540d38 --- /dev/null +++ b/stratum_blacklist.json @@ -0,0 +1 @@ +[ "0x0835290fe660379faefe63a533c6cb96e10770cd", "0x4bc7b9d69d6454c5666ecad87e5699c1ec02d533" ] \ No newline at end of file