Browse Source

Supported CN varaint 4.

Validated pool address.
master
Jianping Wu 5 years ago
parent
commit
267c5a7927
  1. 19
      cnutil/cnutil.go
  2. 7
      cnutil/src/cnutil.cpp
  3. 3
      cnutil/src/cnutil.h
  4. 12
      cnutil/src/main.cc
  5. 9
      rpc/rpc.go
  6. 17
      stratum/handlers.go
  7. 15
      stratum/miner.go
  8. 8
      stratum/proto.go
  9. 5
      stratum/stratum.go
  10. 25
      util/util.go

19
cnutil/cnutil.go

@ -5,7 +5,9 @@ package cnutil @@ -5,7 +5,9 @@ package cnutil
// #include <stdlib.h>
// #include "src/cnutil.h"
import "C"
import "unsafe"
import (
"unsafe"
)
func ConvertBlob(blob []byte) []byte {
output := make([]byte, 76)
@ -18,25 +20,16 @@ func ConvertBlob(blob []byte) []byte { @@ -18,25 +20,16 @@ func ConvertBlob(blob []byte) []byte {
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)
}
func Hash(blob []byte, fast bool) []byte {
func Hash(blob []byte, fast bool, height int) []byte {
output := make([]byte, 32)
if fast {
C.cryptonight_fast_hash((*C.char)(unsafe.Pointer(&blob[0])), (*C.char)(unsafe.Pointer(&output[0])), (C.uint32_t)(len(blob)))
} else {
C.cryptonight_hash((*C.char)(unsafe.Pointer(&blob[0])), (*C.char)(unsafe.Pointer(&output[0])), (C.uint32_t)(len(blob)))
C.cryptonight_hash((*C.char)(unsafe.Pointer(&blob[0])), (*C.char)(unsafe.Pointer(&output[0])), (C.uint32_t)(len(blob)), (C.int)(height))
}
return output
}
func FastHash(blob []byte) []byte {
return Hash(append([]byte{byte(len(blob))}, blob...), true)
return Hash(append([]byte{byte(len(blob))}, blob...), true, 0)
}

7
cnutil/src/cnutil.cpp

@ -18,10 +18,3 @@ extern "C" uint32_t convert_blob(const char *blob, size_t len, char *out) { @@ -18,10 +18,3 @@ extern "C" uint32_t convert_blob(const char *blob, size_t len, char *out) {
output.copy(out, output.length(), 0);
return output.length();
}
extern "C" bool 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);
}

3
cnutil/src/cnutil.h

@ -6,9 +6,8 @@ extern "C" { @@ -6,9 +6,8 @@ extern "C" {
#endif
uint32_t convert_blob(const char *blob, uint32_t len, char *out);
bool validate_address(const char *addr, uint32_t len);
void cryptonight_hash(const char* input, char* output, uint32_t len);
void cryptonight_hash(const char* input, char* output, uint32_t len, int height);
void cryptonight_fast_hash(const char* input, char* output, uint32_t len);
#ifdef __cplusplus

12
cnutil/src/main.cc

@ -26,17 +26,9 @@ extern "C" uint32_t convert_blob(const char *blob, size_t len, char *out) { @@ -26,17 +26,9 @@ extern "C" uint32_t convert_blob(const char *blob, size_t len, char *out) {
return output.length();
}
extern "C" bool 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);
}
extern "C" void cryptonight_hash(const char* input, char* output, uint32_t len) {
extern "C" void cryptonight_hash(const char* input, char* output, uint32_t len, int height) {
const int variant = input[0] >= 7 ? input[0] - 6 : 0;
crypto::cn_slow_hash(input, len, output, variant, 0, 0);
crypto::cn_slow_hash(input, len, output, variant, 0, height);
}
extern "C" void cryptonight_fast_hash(const char* input, char* output, uint32_t len) {

9
rpc/rpc.go

@ -47,6 +47,11 @@ type GetInfoReply struct { @@ -47,6 +47,11 @@ type GetInfoReply struct {
Status string `json:"status"`
}
type ValidateAddressReply struct {
IsValid bool `json:"isvalid"`
IsMine bool `json:"ismine"`
}
type JSONRpcResp struct {
Id *json.RawMessage `json:"id"`
Result *json.RawMessage `json:"result"`
@ -97,6 +102,10 @@ func (r *RPCClient) SubmitBlock(hash string) (*JSONRpcResp, error) { @@ -97,6 +102,10 @@ func (r *RPCClient) SubmitBlock(hash string) (*JSONRpcResp, error) {
return r.doPost(r.Url.String(), "submitblock", []string{hash})
}
func (r *RPCClient) ValidateAddress(addr string) (*JSONRpcResp, error) {
return r.doPost(r.Url.String(), "validateaddress", []string{addr})
}
func (r *RPCClient) doPost(url, method string, params interface{}) (*JSONRpcResp, error) {
jsonReq := map[string]interface{}{"jsonrpc": "2.0", "id": 0, "method": method, "params": params}
data, _ := json.Marshal(jsonReq)

17
stratum/handlers.go

@ -5,8 +5,6 @@ import ( @@ -5,8 +5,6 @@ import (
"regexp"
"strings"
"sync/atomic"
"../util"
)
var noncePattern *regexp.Regexp
@ -18,11 +16,16 @@ func init() { @@ -18,11 +16,16 @@ func init() {
}
func (s *StratumServer) handleLoginRPC(cs *Session, params *LoginParams) (*JobReply, *ErrorReply) {
address, id := extractWorkerId(params.Login)
if !s.config.BypassAddressValidation && !util.ValidateAddress(address, s.config.Address) {
log.Printf("Invalid address %s used for login by %s", address, cs.ip)
return nil, &ErrorReply{Code: -1, Message: "Invalid address used for login"}
}
_, id := extractWorkerId(params.Login)
/*
r := s.rpc()
if !s.config.BypassAddressValidation && !util.ValidateAddress(r, address, false) {
log.Printf("Invalid address %s used for login by %s", address, cs.ip)
return nil, &ErrorReply{Code: -1, Message: "Invalid address used for login"}
}
*/
t := s.currentBlockTemplate()
if t == nil {

15
stratum/miner.go

@ -68,7 +68,18 @@ func (cs *Session) getJob(t *BlockTemplate) *JobReplyData { @@ -68,7 +68,18 @@ func (cs *Session) getJob(t *BlockTemplate) *JobReplyData {
}
job.submissions = make(map[string]struct{})
cs.pushJob(job)
reply := &JobReplyData{JobId: job.id, Blob: blob, Target: cs.endpoint.targetHex}
majorVersion, err := strconv.ParseInt(blob[0:2], 16, 32)
if err != nil {
panic("Failed to get major version")
}
variant := majorVersion - 6
reply := &JobReplyData{
JobId: job.id,
Blob: blob,
Target: cs.endpoint.targetHex,
Height: t.height,
Variant: variant,
}
return reply
}
@ -151,7 +162,7 @@ func (m *Miner) processShare(s *StratumServer, cs *Session, job *Job, t *BlockTe @@ -151,7 +162,7 @@ func (m *Miner) processShare(s *StratumServer, cs *Session, job *Job, t *BlockTe
hashBytes, _ = hex.DecodeString(result)
} else {
convertedBlob = cnutil.ConvertBlob(shareBuff)
hashBytes = cnutil.Hash(convertedBlob, false)
hashBytes = cnutil.Hash(convertedBlob, false, int(t.height))
}
if !s.config.BypassShareValidation && hex.EncodeToString(hashBytes) != result {

8
stratum/proto.go

@ -45,9 +45,11 @@ type JobReply struct { @@ -45,9 +45,11 @@ type JobReply struct {
}
type JobReplyData struct {
Blob string `json:"blob"`
JobId string `json:"job_id"`
Target string `json:"target"`
Blob string `json:"blob"`
JobId string `json:"job_id"`
Target string `json:"target"`
Height int64 `json:"height"`
Variant int64 `json:"variant"`
}
type StatusReply struct {

5
stratum/stratum.go

@ -79,6 +79,11 @@ func NewStratum(cfg *pool.Config) *StratumServer { @@ -79,6 +79,11 @@ func NewStratum(cfg *pool.Config) *StratumServer {
}
log.Printf("Default upstream: %s => %s", stratum.rpc().Name, stratum.rpc().Url)
r := stratum.rpc()
if !cfg.BypassAddressValidation && !util.ValidateAddress(r, cfg.Address, true) {
log.Fatal(cfg.Address + " is either not a valid address or not owned by upstream server")
}
stratum.miners = NewMinersMap()
stratum.sessions = make(map[*Session]struct{})

25
util/util.go

@ -2,11 +2,11 @@ package util @@ -2,11 +2,11 @@ package util
import (
"encoding/hex"
"encoding/json"
"math/big"
"time"
"unicode/utf8"
"../cnutil"
"../rpc"
)
var Diff1 = StringToBig("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
@ -42,16 +42,23 @@ func GetHashDifficulty(hashBytes []byte) (*big.Int, bool) { @@ -42,16 +42,23 @@ func GetHashDifficulty(hashBytes []byte) (*big.Int, bool) {
return diff.Div(Diff1, diff), true
}
func ValidateAddress(addy string, poolAddy string) bool {
if len(addy) != len(poolAddy) {
func ValidateAddress(r *rpc.RPCClient, addr string, checkIsMine bool) bool {
rpcResp, err := r.ValidateAddress(addr)
if err != nil {
return false
}
prefix, _ := utf8.DecodeRuneInString(addy)
poolPrefix, _ := utf8.DecodeRuneInString(poolAddy)
if prefix != poolPrefix {
return false
var reply *rpc.ValidateAddressReply
if rpcResp.Result != nil {
err = json.Unmarshal(*rpcResp.Result, &reply)
if err != nil {
return false
}
if checkIsMine {
return reply.IsMine
}
return reply.IsValid
}
return cnutil.ValidateAddress(addy)
return false
}
func reverse(src []byte) []byte {

Loading…
Cancel
Save