Skip to content

Commit

Permalink
Initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
sammy007 committed Jul 5, 2015
0 parents commit 7f07ef9
Show file tree
Hide file tree
Showing 37 changed files with 2,664 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.DS_Store

# CMake
CMakeCache.txt
CMakeFiles
cmake_install.cmake
install_manifest.txt
*.cmake
Makefile

# Object files
*.a
*.so
*.dylib

# Configs
config.json
aeon.json
13 changes: 13 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
cmake_minimum_required (VERSION 2.8.11)
project (pool)

if (DEFINED ENV{MONERO_DIR})
get_filename_component(MONERO_DIR $ENV{MONERO_DIR} ABSOLUTE)
message("Using Monero source from env ${MONERO_DIR}")
else()
get_filename_component(MONERO_DIR "${CMAKE_SOURCE_DIR}/../bitmonero" ABSOLUTE)
message("Monero surce directory is not defined, using default ${MONERO_DIR}")
endif()

add_subdirectory(hashing)
add_subdirectory(cnutil)
340 changes: 340 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

106 changes: 106 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# go-cryptonote-pool

High performance CryptoNote mining stratum written in Golang backed by Redis.

**Stratum feature list:**

* Full [node-cryptonote-pool](https://github.com/zone117x/node-cryptonote-pool) database compatibility
* Concurrent shares processing, each connection is handled in a lightweight thread of execution
* Several configurable stratum policies to prevent basic attacks
* Banning policy using [**ipset**s](http://ipset.netfilter.org/) on Linux for high performance banning
* Whitelist for trusted miners and blacklist for unwelcome guests
* AES-NI enabled share validation code with fallback to slow implementation provided by linking with [**Monero**](https://github.com/monero-project/bitmonero) libraries
* Integrated NewRelic performance monitoring plugin

### Installation

Dependencies:

* go-1.4
* boost-1.55+
* cmake

Install required packages:

go get gopkg.in/redis.v3
go get github.com/yvasiyarov/gorelic

#### Mac OS X

Download and compile [Monero](https://github.com/monero-project/bitmonero) daemon.

Now clone stratum repo and compile it:

git clone https://github.com/sammy007/go-cryptonote-pool.git
cmake .
make

Notice that for share validation stratum requires bitmonero source tree where .a libs already compiled. By default stratum will use <code>../bitmonero</code> directory. You can override this behaviour by passing <code>MONERO_DIR</code> env variable:

MONERO_DIR=/path/to/bitmonero cmake .
make

#### Linux

Installation on linux is similar to OS X installation and currently the only dfference is that you should copy *.so* libs from *hashing* and *cnutil* directories to */usr/local/lib* or similar dir in order to make CGO happy. I would recommend you to use Ubuntu 14.04 LTS.

In order to successfully link with bitmonero libs, recompile bitmonero with:

CXXFLAGS="-fPIC" CFLAGS="-fPIC" make release

Build stratum:

MONERO_DIR=/opt/src/bitmonero cmake .
make

Run it:

LD_LIBRARY_PATH="/usr/local/lib/" GOPATH=/path/to/go go run main.go

More info on *GOPATH* you can find in a [wiki](https://github.com/golang/go/wiki/GOPATH).

### Configuration

Configuration is self-describing, just copy *config.example.json* to *config.json* and run stratum with path to config file as 1st argument. There is default XMR address of monero core team in config example and open monero rpc node from [moneroclub.com](https://www.moneroclub.com/node).

#### Redis

Leave Redis password blank if you have local setup in a trusted environment. Don't rely on Redis password, it's easily bruteforceable. Password option is only for some clouds. There is a connection pool, use some reasonable value. Remember, that each valid share submission will lease one connection from a pool due to <code>multi</code> exec and instantly release it, this is how go-redis works.

#### Policies

Stratum policy server collecting several stats on per IP basis.

Banning enabled by default. Specify <code>ipset</code> name for banning. Timeout argument will be passed to this ipset. For ipset usage refer to [this article](https://wiki.archlinux.org/index.php/Ipset). Stratum will use os/exec command like <code>sudo ipset ...</code> for banning, so you have to configure sudo properly and make sure that your system will never ask for password:

*/etc/sudoers.d/stratum*

stratum ALL=NOPASSWD: /sbin/ipset

Use limits to prevent connection flood to your stratum, there is initial <code>limit</code> and <code>limitJump</code>. Policy server will increase number of allowed connections on each valid share submission. Stratum will bypass this policy regarding <code>grace</code> time specified on start.

#### Payouts and Block Unlocking

This is just stratum yet. Use corresponding [node-cryptonote-pool](https://github.com/zone117x/node-cryptonote-pool) modules for block unlocking and payout processing. Database is 100% compatible.

### Private Pool Guidelines

For personal private pool you can use [DigitalOcean](https://www.digitalocean.com/?refcode=2a6767e6285f) droplet. With recent blockchain-db merged into Monero it's ok to run it even on 5 USD plan. You will receive 10 USD free credit there.

### TODO

Still in early stage, despite that I am using it for private setups, stratum requires a lot of stability tests. Please run it with <code>-race</code> flag with <code>GORACE="log_path=/path/to/race.log"</code> in private setup and send contents of this file to me if you are "lucky" and found race. It will make stratum ~20x slower, but it does not hit performance if you are soloing with a dozen of GPUs. Look at *-debug.fish* script for example.

Cool stuff will be added after excessive testing, I always have ideas for improvement and new features.

### Donations

* **BTC**: [16bBz4wZPh7kV53nFMf8LmtJHE2rHsADB2](https://blockchain.info/address/16bBz4wZPh7kV53nFMf8LmtJHE2rHsADB2)
* **XMR**: 4Aag5kkRHmCFHM5aRUtfB2RF3c5NDmk5CVbGdg6fefszEhhFdXhnjiTCr81YxQ9bsi73CSHT3ZN3p82qyakHwZ2GHYqeaUr
* **XMR openalias**: wallet.hashinvest.net

### License

Released under the GNU General Public License v2.

http://www.gnu.org/licenses/gpl-2.0.html
7 changes: 7 additions & 0 deletions cnutil/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Makefile
CmakeCache.txt
cmake_install.cmake
CMakeFiles
*.a
*.so
*.dylib
36 changes: 36 additions & 0 deletions cnutil/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
set(CXXLIB "cnutilxx")

find_package(Boost COMPONENTS thread system program_options date_time filesystem REQUIRED)

# Flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE")

include_directories(${Boost_INCLUDE_DIRS})
include_directories("${MONERO_DIR}/contrib/epee/include")
include_directories("${MONERO_DIR}/src")

# Build library
add_library(${CXXLIB} SHARED cnutilxx/main.cpp)

target_link_libraries(${CXXLIB}
${MONERO_DIR}/build/release/src/cryptonote_core/libcryptonote_core.a
${MONERO_DIR}/build/release/src/crypto/libcrypto.a
${MONERO_DIR}/build/release/src/common/libcommon.a
)

target_link_libraries(${CXXLIB}
${Boost_THREAD_LIBRARY}
${Boost_SYSTEM_LIBRARY}
${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_DATE_TIME_LIBRARY}
${Boost_FILESYSTEM_LIBRARY}
)

set(LIB "cnutil")

# Flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE")

# Build library
add_library(${LIB} SHARED cnutil.c)
target_link_libraries(${LIB} ${CXXLIB})
13 changes: 13 additions & 0 deletions cnutil/cnutil.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <stdint.h>
#include "stdbool.h"
#include <stdio.h>
#include <stdlib.h>
#include "cnutilxx/main.h"

uint32_t convert_blob(const char *blob, size_t len, char *out) {
return cn_convert_blob(blob, len, out);
}

bool validate_address(const char *addr, size_t len) {
return cn_validate_address(addr, len);
}
28 changes: 28 additions & 0 deletions cnutil/cnutil.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package cnutil

// #cgo CFLAGS: -std=c11 -D_GNU_SOURCE
// #cgo LDFLAGS: -L. -lcnutil -lcnutilxx -lstdc++
// #include "cnutil.h"
import "C"
import "unsafe"

func ConvertBlob(blob []byte) []byte {
output := make([]byte, 76)
out := (*C.char)(unsafe.Pointer(&output[0]))

input := C.CString(string(blob))
defer C.free(unsafe.Pointer(input))

size := (C.uint32_t)(len(blob))
C.convert_blob(input, size, out)
return output
}

func ValidateAddress(addr string) bool {
input := C.CString(addr)
defer C.free(unsafe.Pointer(input))

size := (C.uint32_t)(len(addr))
result := C.validate_address(input, size)
return (bool)(result)
}
7 changes: 7 additions & 0 deletions cnutil/cnutil.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "stdbool.h"

uint32_t convert_blob(const char *blob, uint32_t len, char *out);
bool validate_address(const char *addr, uint32_t len);
58 changes: 58 additions & 0 deletions cnutil/cnutil_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package cnutil

import (
"encoding/hex"
"log"
"testing"
)

func TestConvertBlob(t *testing.T) {
hashBytes, _ := hex.DecodeString("0100a5d1fca9057dff46d140d453a672437ba0ec7d6a74bc5fa0391f8a918e41fd7ba2cf6fc1af000000000183811401ffc7801405889ec5dc2402e0fe0db63a8e532a7b988e0c32a764e5e8d64d7efac9bc9d24ce32b0984ab93980b09dc2df0102ccd38432501a9182ccc5b44cb47abdddbc9a6321cd581f5f07a7a9195795d5c68080dd9da41702f6e944ee4c6e1eeaed1fa6a3c2480a410e959c6e823b96dad54d31fe223cc0fd80c0a8ca9a3a0286d0e3411670e4c2abe8492c695c66d8262660ee88a0b14a2b03c9180fb6f0d480c0caf384a30202aec5c9b7efe841dd821476e0e06217be13a4c85a83efcf9576314d60130e02e72b0150526f7a381cec33e5827c1848dd80e6eac4b262304ea06b3a43303a4631df28020800000000018ba82000")
expectedResult, _ := hex.DecodeString("0100a5d1fca9057dff46d140d453a672437ba0ec7d6a74bc5fa0391f8a918e41fd7ba2cf6fc1af00000000e81cb2bf0d2c5054a49bda094c39cb263a9565b9b81cf4c4f848292040419f4a01")
output := ConvertBlob(hashBytes)

if len(output) != 76 {
t.Error("Invalid result length")
}
ok := true
for i := range output {
if expectedResult[i] != output[i] {
ok = false
break
}
}
if !ok {
log.Printf("Got: %v %v", output, len(output))
log.Printf("Expected: %v %v", expectedResult, len(expectedResult))
t.Error("Invalid result")
}
}

func TestDecodeAddress(t *testing.T) {
addy := "45pyCXYn2UBVUmCFjgKr7LF8hCTeGwucWJ2xni7qrbj6GgAZBFY6tANarozZx9DaQqHyuR1AL8HJbRmqwLhUaDpKJW4hqS1"
if !ValidateAddress(addy) {
t.Error("Valid address")
}

addy = "46BeWrHpwXmHDpDEUmZBWZfoQpdc6HaERCNmx1pEYL2rAcuwufPN9rXHHtyUA4QVy66qeFQkn6sfK8aHYjA3jk3o1Bv16em"
if !ValidateAddress(addy) {
t.Error("Valid address")
}

if ValidateAddress("OMG") {
t.Error("Invalid address")
}
}

func BenchmarkConvertBlob(b *testing.B) {
for i := 0; i < b.N; i++ {
hashBytes, _ := hex.DecodeString("0100a5d1fca9057dff46d140d453a672437ba0ec7d6a74bc5fa0391f8a918e41fd7ba2cf6fc1af000000000183811401ffc7801405889ec5dc2402e0fe0db63a8e532a7b988e0c32a764e5e8d64d7efac9bc9d24ce32b0984ab93980b09dc2df0102ccd38432501a9182ccc5b44cb47abdddbc9a6321cd581f5f07a7a9195795d5c68080dd9da41702f6e944ee4c6e1eeaed1fa6a3c2480a410e959c6e823b96dad54d31fe223cc0fd80c0a8ca9a3a0286d0e3411670e4c2abe8492c695c66d8262660ee88a0b14a2b03c9180fb6f0d480c0caf384a30202aec5c9b7efe841dd821476e0e06217be13a4c85a83efcf9576314d60130e02e72b0150526f7a381cec33e5827c1848dd80e6eac4b262304ea06b3a43303a4631df28020800000000018ba82000")
ConvertBlob(hashBytes)
}
}

func BenchmarkDecodeAddress(b *testing.B) {
for i := 0; i < b.N; i++ {
ValidateAddress("45pyCXYn2UBVUmCFjgKr7LF8hCTeGwucWJ2xni7qrbj6GgAZBFY6tANarozZx9DaQqHyuR1AL8HJbRmqwLhUaDpKJW4hqS1")
}
}
30 changes: 30 additions & 0 deletions cnutil/cnutilxx/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include <stdint.h>
#include <string>
#include "cryptonote_core/cryptonote_format_utils.h"
#include "common/base58.h"

using namespace cryptonote;

// Well, it's dirty and useless, but without it I can't link to bitmonero's /build/release/src/**/*.a libs
unsigned int epee::g_test_dbg_lock_sleep = 0;

extern "C" uint32_t cn_convert_blob(const char *blob, size_t len, char *out) {
std::string input = std::string(blob, len);
std::string output = "";

block b = AUTO_VAL_INIT(b);
if (!parse_and_validate_block_from_blob(input, b)) {
return 0;
}

output = get_block_hashing_blob(b);
output.copy(out, output.length(), 0);
return output.length();
}

extern "C" bool cn_validate_address(const char *addr, size_t len) {
std::string input = std::string(addr, len);
std::string output = "";
uint64_t prefix;
return tools::base58::decode_addr(addr, prefix, output);
}
12 changes: 12 additions & 0 deletions cnutil/cnutilxx/main.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

uint32_t cn_convert_blob(const char *blob, uint32_t len, char *out);
bool cn_validate_address(const char *addr, uint32_t len);

#ifdef __cplusplus
}
#endif
Loading

3 comments on commit 7f07ef9

@viregis
Copy link

@viregis viregis commented on 7f07ef9 Jul 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello Sammy!

Could you please help me?

I'm using your stratum now, but I've mined for some hours and then my pool server restarted, so after that all the information on the website (the pool's website) was 0 (zero). Every single Accepted disapperead.

Is it normal? I will need to keep the server alive all the time?

About the payments in the wallet, when it happens? When a block is found?

Thanks in advance.
monero-stratum

@viregis
Copy link

@viregis viregis commented on 7f07ef9 Jul 30, 2017 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sammy007
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WTF you are commenting here?

Please sign in to comment.