Pool mining support

- pool mining support added (not for stratum pools)
- fixed an issue that caused a crash when miners connect at a certain point
This commit is contained in:
8lecramm 2022-08-19 22:04:41 +02:00 committed by GitHub
parent 52b82854cb
commit 80c9995ea4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 111 additions and 39 deletions

View File

@ -8,13 +8,15 @@ Long To-Do list, but this is a working release.
- muliple wallets are supported
- notification of incoming and lost connections / submitted results / stats
- user-defined logging interval
- pool mining support (not stratum)
**Usage**
```derohe-proxy [--listen-address=<127.0.0.1:11111>] [--log-interval=<60>] [--minimal] [--nonce] --daemon-address=<1.2.3.4:10100>```
```derohe-proxy [--listen-address=<127.0.0.1:11111>] [--log-interval=<60>] [--minimal] [--nonce] [--pool] --daemon-address=<1.2.3.4:10100>```
```--listen-address (optional): bind to address:port for incoming miner connections. By default, proxy listens on 0.0.0.0:10200
--daemon-address: address:port of daemon
--log-interval (optional): logging every X seconds, where X >= 60. Default is 60 seconds
--minimal (optional): forward only 2 jobs per block (1 for first 9 miniblocks, 1 for final miniblock)
--nonce (optional): enable random nonces, disabled by default```
--pool (optional): enable pool mining, disable keyhash replacement

36
config/config.go Normal file
View File

@ -0,0 +1,36 @@
package config
var Command_line string = `derohe-proxy
Proxy to combine all miners and to reduce network load
Usage:
derohe-proxy [--listen-address=<127.0.0.1:10100>] [--log-interval=<60>] [--minimal] [--nonce] [--pool] --daemon-address=<1.2.3.4:10100>
Options:
--listen-address=<127.0.0.1:10100> bind to specific address:port, default is 0.0.0.0:10200
--daemon-address=<1.2.3.4:10100> connect to this daemon
--log-interval=<60> set logging interval in seconds (range 60 - 3600), default is 60 seconds
--minimal forward only 2 jobs per block (1 for miniblocks and 1 for final miniblock), by default all jobs are forwarded
--nonce enable nonce editing, default is off
--pool use this option for pool mining; this option avoids changing the keyhash
Example Mainnet: ./derohe-proxy --daemon-address=minernode1.dero.io:10100
`
// program arguments
var Arguments = map[string]interface{}{}
var Listen_addr string = "0.0.0.0:10200"
var Daemon_address string = "minernode1.dero.io:10100"
// logging interval in seconds
var Log_intervall int = 60
// send only 2 jobs per block
var Minimal bool = false
// edit nonce
var Nonce bool = false
// pool mining
var Pool_mode bool = false

View File

@ -1,10 +1,12 @@
package main
import (
"derohe-proxy/config"
"derohe-proxy/proxy"
"fmt"
"net"
"strconv"
"sync"
"time"
"github.com/docopt/docopt-go"
@ -12,68 +14,75 @@ import (
func main() {
var err error
var rwmutex sync.RWMutex
Arguments, err = docopt.Parse(command_line, nil, true, "pre-alpha", false)
config.Arguments, err = docopt.Parse(config.Command_line, nil, true, "pre-alpha", false)
if err != nil {
return
}
if Arguments["--listen-address"] != nil {
addr, err := net.ResolveTCPAddr("tcp", Arguments["--listen-address"].(string))
if config.Arguments["--listen-address"] != nil {
addr, err := net.ResolveTCPAddr("tcp", config.Arguments["--listen-address"].(string))
if err != nil {
return
} else {
if addr.Port == 0 {
return
} else {
listen_addr = addr.String()
config.Listen_addr = addr.String()
}
}
}
if Arguments["--daemon-address"] == nil {
if config.Arguments["--daemon-address"] == nil {
return
} else {
daemon_address = Arguments["--daemon-address"].(string)
config.Daemon_address = config.Arguments["--daemon-address"].(string)
}
if Arguments["--log-interval"] != nil {
interval, err := strconv.ParseInt(Arguments["--log-interval"].(string), 10, 32)
if config.Arguments["--log-interval"] != nil {
interval, err := strconv.ParseInt(config.Arguments["--log-interval"].(string), 10, 32)
if err != nil {
return
} else {
if interval < 60 || interval > 3600 {
log_intervall = 60
config.Log_intervall = 60
} else {
log_intervall = int(interval)
config.Log_intervall = int(interval)
}
}
}
if Arguments["--minimal"].(bool) {
minimal = true
if config.Arguments["--minimal"].(bool) {
config.Minimal = true
fmt.Printf("%v Forward only 2 jobs per block\n", time.Now().Format(time.Stamp))
}
if Arguments["--nonce"].(bool) {
nonce = true
if config.Arguments["--nonce"].(bool) {
config.Nonce = true
fmt.Printf("%v Nonce editing is enabled\n", time.Now().Format(time.Stamp))
}
fmt.Printf("%v Logging every %d seconds\n", time.Now().Format(time.Stamp), log_intervall)
if config.Arguments["--pool"].(bool) {
config.Pool_mode = true
config.Minimal = false
fmt.Printf("%v Pool mode is enabled\n", time.Now().Format(time.Stamp))
}
go proxy.Start_server(listen_addr)
fmt.Printf("%v Logging every %d seconds\n", time.Now().Format(time.Stamp), config.Log_intervall)
go proxy.Start_server()
// Wait for first miner connection to grab wallet address
for proxy.CountMiners() < 1 {
time.Sleep(time.Second * 1)
}
go proxy.Start_client(daemon_address, proxy.Address, minimal, nonce)
go proxy.Start_client(proxy.Address)
go proxy.SendUpdateToDaemon()
for {
time.Sleep(time.Second * time.Duration(log_intervall))
time.Sleep(time.Second * time.Duration(config.Log_intervall))
hash_rate_string := ""
@ -90,11 +99,17 @@ func main() {
hash_rate_string = fmt.Sprintf("%d H/s", int(proxy.Hashrate))
}
if !config.Pool_mode {
fmt.Printf("%v %d miners connected, IB:%d MB:%d MBR:%d MBO:%d - MINING @ %s\n", time.Now().Format(time.Stamp), proxy.CountMiners(), proxy.Blocks, proxy.Minis, proxy.Rejected, proxy.Orphans, hash_rate_string)
} else {
fmt.Printf("%v %d miners connected, Pool stats: IB:%d MB:%d MBR:%d MBO:%d - MINING @ %s\n", time.Now().Format(time.Stamp), proxy.CountMiners(), proxy.Blocks, proxy.Minis, proxy.Rejected, proxy.Orphans, hash_rate_string)
}
rwmutex.RLock()
for i := range proxy.Wallet_count {
if proxy.Wallet_count[i] > 1 {
fmt.Printf("%v Wallet %v, %d miners\n", time.Now().Format(time.Stamp), i, proxy.Wallet_count[i])
}
}
rwmutex.RUnlock()
}
}

View File

@ -8,6 +8,8 @@ import (
"net/url"
"time"
"derohe-proxy/config"
"github.com/gorilla/websocket"
)
@ -45,7 +47,7 @@ var ModdedNode bool = false
var Hashrate float64
// proxy-client
func Start_client(v string, w string, min_jobs bool, nonce bool) {
func Start_client(w string) {
var err error
var last_diff uint64
var last_height uint64
@ -54,14 +56,18 @@ func Start_client(v string, w string, min_jobs bool, nonce bool) {
for {
u := url.URL{Scheme: "wss", Host: v, Path: "/ws/" + w}
u := url.URL{Scheme: "wss", Host: config.Daemon_address, Path: "/ws/" + w}
dialer := websocket.DefaultDialer
dialer.TLSClientConfig = &tls.Config{
InsecureSkipVerify: true,
}
fmt.Println(time.Now().Format(time.Stamp), "Connected to node", v)
if !config.Pool_mode {
fmt.Printf("%v Connected to node %v\n", time.Now().Format(time.Stamp), config.Daemon_address)
} else {
fmt.Printf("%v Connected to node %v using wallet %v\n", time.Now().Format(time.Stamp), config.Daemon_address, w)
}
connection, _, err = websocket.DefaultDialer.Dial(u.String(), nil)
if err != nil {
time.Sleep(5 * time.Second)
@ -92,22 +98,22 @@ func Start_client(v string, w string, min_jobs bool, nonce bool) {
if ModdedNode != params.Hansen33Mod {
if params.Hansen33Mod {
fmt.Print("Hansen33 Mod Mining Node Detected - Happy Mining\n")
fmt.Printf("%v Hansen33 Mod Mining Node Detected - Happy Mining\n", time.Now().Format(time.Stamp))
}
}
ModdedNode = params.Hansen33Mod
if !ModdedNode {
fmt.Print("Official Mining Node Detected - Happy Mining\n")
fmt.Printf("%v Official Mining Node Detected - Happy Mining\n", time.Now().Format(time.Stamp))
}
if min_jobs {
if config.Minimal {
if params.Height != last_height || params.Difficultyuint64 != last_diff {
last_height = params.Height
last_diff = params.Difficultyuint64
go SendTemplateToNodes(recv_data, nonce)
go SendTemplateToNodes(recv_data)
}
} else {
go SendTemplateToNodes(recv_data, nonce)
go SendTemplateToNodes(recv_data)
}
}
}

View File

@ -15,6 +15,8 @@ import (
"sync"
"time"
"derohe-proxy/config"
"github.com/deroproject/derohe/globals"
"github.com/deroproject/derohe/rpc"
"github.com/deroproject/graviton"
@ -57,10 +59,11 @@ var client_list_mutex sync.Mutex
var client_list = map[*websocket.Conn]*user_session{}
var miners_count int
var shares uint64
var Wallet_count map[string]uint
var Address string
func Start_server(listen string) {
func Start_server() {
var err error
tlsConfig := &tls.Config{
@ -74,7 +77,7 @@ func Start_server(listen string) {
server = nbhttp.NewServer(nbhttp.Config{
Name: "GETWORK",
Network: "tcp",
AddrsTLS: []string{listen},
AddrsTLS: []string{config.Listen_addr},
TLSConfig: tlsConfig,
Handler: mux,
MaxLoad: 10 * 1024,
@ -110,7 +113,7 @@ func CountMiners() int {
}
// forward all incoming templates from daemon to all miners
func SendTemplateToNodes(data []byte, nonce bool) {
func SendTemplateToNodes(data []byte) {
client_list_mutex.Lock()
defer client_list_mutex.Unlock()
@ -121,13 +124,15 @@ func SendTemplateToNodes(data []byte, nonce bool) {
break
}
if !config.Pool_mode {
miner_address := rv.address_sum
if result := edit_blob(data, miner_address, nonce); result != nil {
if result := edit_blob(data, miner_address, config.Nonce); result != nil {
data = result
} else {
fmt.Println(time.Now().Format(time.Stamp), "Failed to change nonce / miner keyhash")
}
}
go func(k *websocket.Conn, v *user_session) {
defer globals.Recover(2)
@ -137,7 +142,6 @@ func SendTemplateToNodes(data []byte, nonce bool) {
}(rk, rv)
}
}
// handling for incoming miner connections
@ -172,7 +176,11 @@ func onWebsocket(w http.ResponseWriter, r *http.Request) {
client_list[wsConn] = &session
Wallet_count[client_list[wsConn].address.String()]++
Address = address
if !config.Pool_mode {
fmt.Printf("%v Incoming connection: %v, Wallet: %v\n", time.Now().Format(time.Stamp), wsConn.RemoteAddr().String(), address)
} else {
fmt.Printf("%v Incoming connection: %v\n", time.Now().Format(time.Stamp), wsConn.RemoteAddr().String())
}
}
// forward results to daemon
@ -207,7 +215,12 @@ func newUpgrader() *websocket.Upgrader {
return
} else {
go SendToDaemon(data)
if !config.Pool_mode {
fmt.Printf("%v Submitting result from miner: %v, Wallet: %v\n", time.Now().Format(time.Stamp), c.RemoteAddr().String(), client_list[c].address.String())
} else {
shares++
fmt.Printf("%v Shares submitted: %d\n", time.Now().Format(time.Stamp), shares)
}
}
})