diff --git a/config.go b/config.go new file mode 100644 index 0000000..85e80a3 --- /dev/null +++ b/config.go @@ -0,0 +1,20 @@ +package main + +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>] --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 + +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" diff --git a/derohe-proxy.go b/derohe-proxy.go new file mode 100644 index 0000000..5ad081f --- /dev/null +++ b/derohe-proxy.go @@ -0,0 +1,52 @@ +package main + +import ( + "derohe-proxy/proxy" + "fmt" + "net" + "time" + + "github.com/docopt/docopt-go" +) + +func main() { + var err error + + Arguments, err = docopt.Parse(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 err != nil { + return + } else { + if addr.Port == 0 { + return + } else { + listen_addr = addr.String() + } + } + } + + if Arguments["--daemon-address"] == nil { + return + } else { + daemon_address = Arguments["--daemon-address"].(string) + } + + go proxy.Start_server(listen_addr) + + // 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) + + for { + time.Sleep(time.Minute * 5) + fmt.Printf("%v %4d miners connected\t\tBlocks:%4d\tMiniblocks:%4d\tRejected:%4d\n", time.Now().Format(time.Stamp), proxy.CountMiners(), proxy.Blocks, proxy.Minis, proxy.Rejected) + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..e2f008f --- /dev/null +++ b/go.mod @@ -0,0 +1,35 @@ +module derohe-proxy + +go 1.18 + +require ( + github.com/chzyer/readline v1.5.0 + github.com/deroproject/derohe v0.0.0-20220502125456-607af6dfdc9a + github.com/deroproject/graviton v0.0.0-20220130070622-2c248a53b2e1 + github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 + github.com/gorilla/websocket v1.5.0 + github.com/lesismal/llib v1.1.6 + github.com/lesismal/nbio v1.2.18 +) + +require ( + github.com/blang/semver/v4 v4.0.0 // indirect + github.com/caarlos0/env/v6 v6.9.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fxamacker/cbor/v2 v2.4.0 // indirect + github.com/go-logr/logr v1.2.3 // indirect + github.com/go-logr/zapr v1.2.3 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/robfig/cron/v3 v3.0.1 // indirect + github.com/satori/go.uuid v1.2.0 // indirect + github.com/stretchr/testify v1.7.1 // indirect + github.com/x448/float16 v0.8.4 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/zap v1.21.0 // indirect + golang.org/x/crypto v0.0.0-20210513122933-cd7d49e622d5 // indirect + golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect + golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..d06de40 --- /dev/null +++ b/go.sum @@ -0,0 +1,116 @@ +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/caarlos0/env/v6 v6.9.1 h1:zOkkjM0F6ltnQ5eBX6IPI41UP/KDGEK7rRPwGCNos8k= +github.com/caarlos0/env/v6 v6.9.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/chzyer/logex v1.2.0 h1:+eqR0HfOetur4tgnC8ftU5imRnhi4te+BadWS95c5AM= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= +github.com/chzyer/readline v1.5.0 h1:lSwwFrbNviGePhkewF1az4oLmcwqCZijQ2/Wi3BGHAI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23 h1:dZ0/VyGgQdVGAss6Ju0dt5P0QltE0SFY5Woh6hbIfiQ= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deroproject/derohe v0.0.0-20220502125456-607af6dfdc9a h1:hl0OLefIqk4AlonnM/0IBbff+ZvkGEB4fFrmzAgXLk8= +github.com/deroproject/derohe v0.0.0-20220502125456-607af6dfdc9a/go.mod h1:EWHh1VkXRnCHvyGML98kXhngDFYebmOhk/9kZ1ATJ1c= +github.com/deroproject/graviton v0.0.0-20220130070622-2c248a53b2e1 h1:nsiNx83HYmRmYpYO37pUzSTmB7p9PFtGBl4FyD+a0jg= +github.com/deroproject/graviton v0.0.0-20220130070622-2c248a53b2e1/go.mod h1:a4u6QJtGGIADg1JwujD77UtaAyhIxg14+I0C7xjyQcc= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88= +github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= +github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lesismal/llib v1.1.6 h1:/mtiOFShydKSEsO/cajK8benGD1OHgP51GrBni7rGEY= +github.com/lesismal/llib v1.1.6/go.mod h1:3vmCrIMrpkaoA3bDu/sI+J7EyEUMPbOvmAxb7PlzilM= +github.com/lesismal/nbio v1.2.18 h1:0xo501NqzQLqYuvOBm4hgYoi6tX+qPI6f/fO8koXXbQ= +github.com/lesismal/nbio v1.2.18/go.mod h1:11bIzMFWwJJ5WurkTKIJejOw5JPCfPP+siptchxeSr8= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= +go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210513122933-cd7d49e622d5 h1:N6Jp/LCiEoIBX56BZSR2bepK5GtbSC2DDOYT742mMfE= +golang.org/x/crypto v0.0.0-20210513122933-cd7d49e622d5/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I= +golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/proxy/client.go b/proxy/client.go new file mode 100644 index 0000000..0586514 --- /dev/null +++ b/proxy/client.go @@ -0,0 +1,70 @@ +package proxy + +import ( + "crypto/tls" + "encoding/json" + "fmt" + "math/rand" + "net/url" + "time" + + "github.com/deroproject/derohe/rpc" + "github.com/gorilla/websocket" +) + +var connection *websocket.Conn +var Blocks uint64 +var Minis uint64 +var Rejected uint64 + +// proxy-client +func Start_client(v string, w string) { + var err error + + rand.Seed(time.Now().UnixMilli()) + + for { + + u := url.URL{Scheme: "wss", Host: v, Path: "/ws/" + w} + + dialer := websocket.DefaultDialer + dialer.TLSClientConfig = &tls.Config{ + InsecureSkipVerify: true, + } + + fmt.Println(time.Now().Format(time.Stamp), "Connected to node", v, "using wallet address", w) + connection, _, err = websocket.DefaultDialer.Dial(u.String(), nil) + if err != nil { + time.Sleep(5 * time.Second) + fmt.Println(err) + continue + } + + var params rpc.GetBlockTemplate_Result + + for { + msg_type, recv_data, err := connection.ReadMessage() + if err != nil { + break + } + + if msg_type != websocket.TextMessage { + continue + } + + if err = json.Unmarshal(recv_data, ¶ms); err != nil { + continue + } + + Blocks = params.Blocks + Minis = params.MiniBlocks + Rejected = params.Rejected + + go SendTemplateToNodes(recv_data) + } + } +} + +func SendToDaemon(buffer []byte) { + connection.WriteMessage(websocket.TextMessage, buffer) +} diff --git a/proxy/feature.go b/proxy/feature.go new file mode 100644 index 0000000..8613da5 --- /dev/null +++ b/proxy/feature.go @@ -0,0 +1,48 @@ +package proxy + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "fmt" + "math/rand" + + "github.com/deroproject/derohe/block" + "github.com/deroproject/derohe/rpc" +) + +func edit_blob(input []byte) (output []byte) { + var err error + var params rpc.GetBlockTemplate_Result + var mbl block.MiniBlock + var raw_hex []byte + var out bytes.Buffer + + if err = json.Unmarshal(input, ¶ms); err != nil { + return + } + + if raw_hex, err = hex.DecodeString(params.Blockhashing_blob); err != nil { + return + } + + if mbl.Deserialize(raw_hex); err != nil { + return + } + + for i := range mbl.Nonce { + mbl.Nonce[i] = rand.Uint32() + } + mbl.Flags = rand.Uint32() + + params.Blockhashing_blob = fmt.Sprintf("%x", mbl.Serialize()) + encoder := json.NewEncoder(&out) + + if err = encoder.Encode(params); err != nil { + return + } + + output = out.Bytes() + + return +} diff --git a/proxy/server.go b/proxy/server.go new file mode 100644 index 0000000..19148dc --- /dev/null +++ b/proxy/server.go @@ -0,0 +1,241 @@ +package proxy + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/x509" + "encoding/pem" + "fmt" + "math/big" + "net/http" + "runtime" + "strings" + "sync" + "time" + + "github.com/deroproject/derohe/globals" + "github.com/deroproject/derohe/rpc" + "github.com/deroproject/graviton" + "github.com/lesismal/llib/std/crypto/tls" + "github.com/lesismal/nbio" + "github.com/lesismal/nbio/nbhttp" + "github.com/lesismal/nbio/nbhttp/websocket" +) + +var server *nbhttp.Server + +var memPool = sync.Pool{ + New: func() interface{} { + return make([]byte, 16*1024) + }, +} + +type user_session struct { + blocks uint64 + miniblocks uint64 + lasterr string + address rpc.Address + valid_address bool + address_sum [32]byte +} + +var client_list_mutex sync.Mutex +var client_list = map[*websocket.Conn]*user_session{} + +var miners_count int +var Address string + +func Start_server(listen string) { + var err error + + tlsConfig := &tls.Config{ + Certificates: []tls.Certificate{generate_random_tls_cert()}, + InsecureSkipVerify: true, + } + + mux := &http.ServeMux{} + mux.HandleFunc("/", onWebsocket) // handle everything + + server = nbhttp.NewServer(nbhttp.Config{ + Name: "GETWORK", + Network: "tcp", + AddrsTLS: []string{listen}, + TLSConfig: tlsConfig, + Handler: mux, + MaxLoad: 10 * 1024, + MaxWriteBufferSize: 32 * 1024, + ReleaseWebsocketPayload: true, + KeepaliveTime: 240 * time.Hour, // we expects all miners to find a block every 10 days, + NPoller: runtime.NumCPU(), + }) + + server.OnReadBufferAlloc(func(c *nbio.Conn) []byte { + return memPool.Get().([]byte) + }) + server.OnReadBufferFree(func(c *nbio.Conn, b []byte) { + memPool.Put(b) + }) + + if err = server.Start(); err != nil { + return + } + + server.Wait() + defer server.Stop() + +} + +func CountMiners() int { + client_list_mutex.Lock() + defer client_list_mutex.Unlock() + miners_count = len(client_list) + return miners_count +} + +// forward all incoming templates from daemon to all miners +func SendTemplateToNodes(input []byte) { + var data []byte + + for rk, rv := range client_list { + + if client_list == nil { + break + } + + if nonce := edit_blob(input); nonce != nil { + data = nonce + } else { + fmt.Println(time.Now().Format(time.Stamp), "Failed to change nonce") + data = input + } + + go func(k *websocket.Conn, v *user_session) { + defer globals.Recover(2) + k.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)) + k.WriteMessage(websocket.TextMessage, data) + + }(rk, rv) + + } + +} + +// handling for incoming miner connections +func onWebsocket(w http.ResponseWriter, r *http.Request) { + if !strings.HasPrefix(r.URL.Path, "/ws/") { + http.NotFound(w, r) + return + } + address := strings.TrimPrefix(r.URL.Path, "/ws/") + + addr, err := globals.ParseValidateAddress(address) + if err != nil { + fmt.Fprintf(w, "err: %s\n", err) + return + } + + upgrader := newUpgrader() + conn, err := upgrader.Upgrade(w, r, nil) + if err != nil { + //panic(err) + return + } + + addr_raw := addr.PublicKey.EncodeCompressed() + wsConn := conn.(*websocket.Conn) + + session := user_session{address: *addr, address_sum: graviton.Sum(addr_raw)} + wsConn.SetSession(&session) + + client_list_mutex.Lock() + defer client_list_mutex.Unlock() + client_list[wsConn] = &session + Address = address + fmt.Println(time.Now().Format(time.Stamp), "Incoming connection from IP:", wsConn.RemoteAddr().String()) +} + +// forward results to daemon +func newUpgrader() *websocket.Upgrader { + u := websocket.NewUpgrader() + + u.OnMessage(func(c *websocket.Conn, messageType websocket.MessageType, data []byte) { + + if messageType != websocket.TextMessage { + return + } + + client_list_mutex.Lock() + defer client_list_mutex.Unlock() + + SendToDaemon(data) + fmt.Println(time.Now().Format(time.Stamp), "Submitting result from miner IP:", c.RemoteAddr().String()) + }) + + u.OnClose(func(c *websocket.Conn, err error) { + client_list_mutex.Lock() + defer client_list_mutex.Unlock() + delete(client_list, c) + fmt.Println(time.Now().Format(time.Stamp), "Interrupted or lost connection:", c.RemoteAddr().String()) + }) + + return u +} + +// taken unmodified from derohe repo +// cert handling +func generate_random_tls_cert() tls.Certificate { + + /* RSA can do only 500 exchange per second, we need to be faster + * reference https://github.com/golang/go/issues/20058 + key, err := rsa.GenerateKey(rand.Reader, 512) // current using minimum size + if err != nil { + log.Fatal("Private key cannot be created.", err.Error()) + } + + // Generate a pem block with the private key + keyPem := pem.EncodeToMemory(&pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: x509.MarshalPKCS1PrivateKey(key), + }) + */ + // EC256 does roughly 20000 exchanges per second + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + b, err := x509.MarshalECPrivateKey(key) + if err != nil { + panic(err) + } + // Generate a pem block with the private key + keyPem := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: b}) + + tml := x509.Certificate{ + SerialNumber: big.NewInt(int64(time.Now().UnixNano())), + + // TODO do we need to add more parameters to make our certificate more authentic + // and thwart traffic identification as a mass scale + + // you can add any attr that you need + NotBefore: time.Now().AddDate(0, -1, 0), + NotAfter: time.Now().AddDate(1, 0, 0), + // you have to generate a different serial number each execution + /* + Subject: pkix.Name{ + CommonName: "New Name", + Organization: []string{"New Org."}, + }, + BasicConstraintsValid: true, // even basic constraints are not required + */ + } + cert, err := x509.CreateCertificate(rand.Reader, &tml, &tml, &key.PublicKey, key) + if err != nil { + panic(err) + } + + // Generate a pem block with the certificate + certPem := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert}) + tlsCert, err := tls.X509KeyPair(certPem, keyPem) + if err != nil { + panic(err) + } + return tlsCert +}