package proxy import ( "crypto/tls" "net" "sync/atomic" "time" ) var minerIDSequence atomic.Int64 // NewMiner creates a Miner for an accepted net.Conn. Does not start reading yet. // // m := proxy.NewMiner(conn, 3333, nil) func NewMiner(conn net.Conn, localPort uint16, tlsCfg *tls.Config) *Miner { miner := &Miner{ id: minerIDSequence.Add(1), state: MinerStateWaitLogin, localPort: localPort, mapperID: -1, routeID: -1, conn: conn, connectedAt: time.Now().UTC(), lastActivityAt: time.Now().UTC(), } if tlsCfg != nil { if tlsConnection, ok := conn.(*tls.Conn); ok { miner.tlsConn = tlsConnection } } if conn != nil && conn.RemoteAddr() != nil { miner.ip = remoteHost(conn.RemoteAddr().String()) } return miner } func (m *Miner) ID() int64 { return m.id } func (m *Miner) RPCID() string { return m.rpcID } func (m *Miner) User() string { return m.user } func (m *Miner) Password() string { return m.password } func (m *Miner) Agent() string { return m.agent } func (m *Miner) RigID() string { return m.rigID } func (m *Miner) IP() string { return m.ip } func (m *Miner) State() MinerState { if m == nil { return MinerStateClosing } m.stateMu.RLock() state := m.state m.stateMu.RUnlock() return state } func (m *Miner) Diff() uint64 { return m.diff } func (m *Miner) FixedByte() uint8 { return m.fixedByte } func (m *Miner) MapperID() int64 { return m.mapperID } func (m *Miner) RouteID() int64 { return m.routeID } func (m *Miner) CustomDiff() uint64 { return m.customDiff } func (m *Miner) TX() uint64 { return m.tx } func (m *Miner) RX() uint64 { return m.rx } func (m *Miner) LastActivityAt() time.Time { return m.lastActivityAt } func (m *Miner) SetRPCID(value string) { m.rpcID = value } func (m *Miner) SetUser(value string) { m.user = value } func (m *Miner) SetPassword(value string) { m.password = value } func (m *Miner) SetAgent(value string) { m.agent = value } func (m *Miner) SetRigID(value string) { m.rigID = value } func (m *Miner) SetState(value MinerState) { if m == nil { return } m.stateMu.Lock() m.state = value m.stateMu.Unlock() } func (m *Miner) SetDiff(value uint64) { m.diff = value } func (m *Miner) SetFixedByte(value uint8) { m.fixedByte = value } func (m *Miner) SetMapperID(value int64) { m.mapperID = value } func (m *Miner) SetRouteID(value int64) { m.routeID = value } func (m *Miner) SetCustomDiff(value uint64) { m.customDiff = value } func (m *Miner) SetNiceHashEnabled(value bool) { m.extNH = value } func (m *Miner) PrimeJob(job Job) { if m == nil || !job.IsValid() { return } m.currentJob = &job m.diff = m.effectiveDifficulty(job) } func (m *Miner) Touch() { m.lastActivityAt = time.Now().UTC() } func remoteHost(address string) string { host, _, errorValue := net.SplitHostPort(address) if errorValue != nil { return address } return host } func (m *Miner) effectiveDifficulty(job Job) uint64 { difficulty := job.DifficultyFromTarget() if m == nil || m.customDiff == 0 { return difficulty } if difficulty == 0 || difficulty <= m.customDiff { return difficulty } return m.customDiff } func (m *Miner) effectiveTarget(job Job) string { difficulty := m.effectiveDifficulty(job) if difficulty == 0 { return job.Target } return TargetForDifficulty(difficulty) }