From 6a9ba51a736e36ffdabed6564664325cc6d9fd5e Mon Sep 17 00:00:00 2001 From: lzx <393768033@qq.com> Date: Wed, 23 Apr 2025 15:47:41 +0800 Subject: [PATCH] add aleo mining code(untested) --- internal/gbt/aleo/aleo.go | 524 ++++++++++++++++++ internal/gbt/coin/coin.go | 13 +- internal/gbt/enx/enx.go | 247 --------- .../enx/templatemanager/templatemanager.go | 49 -- internal/gbt/gbt.go | 37 +- internal/server/enx/enx.go | 272 --------- internal/server/enx/hash_enx.go | 35 -- 7 files changed, 547 insertions(+), 630 deletions(-) create mode 100644 internal/gbt/aleo/aleo.go delete mode 100644 internal/gbt/enx/enx.go delete mode 100644 internal/gbt/enx/templatemanager/templatemanager.go delete mode 100644 internal/server/enx/enx.go delete mode 100644 internal/server/enx/hash_enx.go diff --git a/internal/gbt/aleo/aleo.go b/internal/gbt/aleo/aleo.go new file mode 100644 index 0000000..772ba32 --- /dev/null +++ b/internal/gbt/aleo/aleo.go @@ -0,0 +1,524 @@ +package aleo + +import ( + "bytes" + "crypto/sha256" + "encoding/binary" + "fmt" + "io" + "log" + "net" + "os" + "os/signal" + "runtime" + "sync" + "sync/atomic" + "syscall" + "time" +) + +const ( + // 网络常量 + TcpEndpoint = "127.0.0.1:3030" + RpcEndpoint = "http://127.0.0.1:4133" + + // 消息类型 + MsgHandshake uint16 = 1 + MsgHandshakeResponse uint16 = 2 + MsgPuzzleRequest uint16 = 9 + MsgPuzzleResponse uint16 = 10 + MsgUnconfirmedSolution uint16 = 11 + + // 协议版本 + ProtocolVersion uint32 = 17 + + // 挖矿参数 + MaxPuzzleInstances = 6 // 最大puzzle实例数 +) + +// Prover 挖矿节点结构 +type Prover struct { + conn net.Conn + minerAddress []byte + + // 最新状态 + latestEpochHash []byte + latestBlockHeader *BlockHeader + epochHashMutex sync.RWMutex + headerMutex sync.RWMutex + + // puzzle实例计数 + puzzleInstances atomic.Int32 + maxPuzzleInstances uint32 + + // 停止信号 + shutdown chan struct{} +} + +// BlockHeader 区块头结构 +type BlockHeader struct { + Height uint32 + PreviousHash [32]byte + Timestamp uint64 + CoinbaseTarget uint64 + ProofTarget uint64 + TransactionsRoot [32]byte + StateRoot [32]byte +} + +// Solution 挖矿解结构 +type Solution struct { + ID [32]byte + EpochHash []byte + Nonce uint64 + Address []byte + Proof []byte +} + +func NewProver(minerAddress []byte) (*Prover, error) { + // 计算最大puzzle实例数 + maxInstances := uint32(runtime.NumCPU() - 2) + if maxInstances < 1 { + maxInstances = 1 + } + if maxInstances > MaxPuzzleInstances { + maxInstances = MaxPuzzleInstances + } + + prover := &Prover{ + minerAddress: minerAddress, + maxPuzzleInstances: maxInstances, + shutdown: make(chan struct{}), + } + + // 连接节点 + if err := prover.connect(); err != nil { + return nil, err + } + + return prover, nil +} + +func (p *Prover) connect() error { + conn, err := net.Dial("tcp", TcpEndpoint) + if err != nil { + return fmt.Errorf("连接失败: %v", err) + } + p.conn = conn + + // 执行握手 + if err := p.performHandshake(); err != nil { + conn.Close() + return fmt.Errorf("握手失败: %v", err) + } + + return nil +} + +// mining/message.go +func (p *Prover) sendMessage(msgType uint16, payload []byte) error { + header := make([]byte, 6) + binary.BigEndian.PutUint16(header[0:2], msgType) + binary.BigEndian.PutUint32(header[2:6], ProtocolVersion) + + if _, err := p.conn.Write(header); err != nil { + return err + } + + if payload != nil { + if _, err := p.conn.Write(payload); err != nil { + return err + } + } + + return nil +} + +func (p *Prover) receiveMessage() (uint16, []byte, error) { + header := make([]byte, 6) + if _, err := io.ReadFull(p.conn, header); err != nil { + return 0, nil, err + } + + msgType := binary.BigEndian.Uint16(header[0:2]) + // protocolVersion := binary.BigEndian.Uint32(header[2:6]) + + var payload []byte + if msgType == MsgPuzzleResponse { + // 读取epoch hash + epochHash := make([]byte, 32) + if _, err := io.ReadFull(p.conn, epochHash); err != nil { + return msgType, nil, err + } + + // 读取block header + lenBuf := make([]byte, 4) + if _, err := io.ReadFull(p.conn, lenBuf); err != nil { + return msgType, nil, err + } + headerLen := binary.BigEndian.Uint32(lenBuf) + + blockHeader := make([]byte, headerLen) + if _, err := io.ReadFull(p.conn, blockHeader); err != nil { + return msgType, nil, err + } + + payload = append(epochHash, blockHeader...) + } + + return msgType, payload, nil +} + +func (p *Prover) getPuzzleTask() error { + // 发送请求 + if err := p.sendMessage(MsgPuzzleRequest, nil); err != nil { + return err + } + + // 接收响应 + msgType, data, err := p.receiveMessage() + if err != nil { + return err + } + if msgType != MsgPuzzleResponse { + return fmt.Errorf("unexpected message type: %d", msgType) + } + + // 解析数据 + epochHash := data[0:32] + header, err := parseBlockHeader(data[32:]) + if err != nil { + return err + } + + // 更新状态 + p.epochHashMutex.Lock() + p.latestEpochHash = epochHash + p.epochHashMutex.Unlock() + + p.headerMutex.Lock() + p.latestBlockHeader = header + p.headerMutex.Unlock() + + return nil +} + +func (p *Prover) StartMining() error { + // 启动多个puzzle实例 + for i := uint32(0); i < p.maxPuzzleInstances; i++ { + go p.puzzleLoop() + } + + // 定期获取新任务 + go p.taskLoop() + + return nil +} + +func (p *Prover) puzzleLoop() { + p.puzzleInstances.Add(1) + defer p.puzzleInstances.Add(-1) + + for { + select { + case <-p.shutdown: + return + default: + // 获取当前状态 + p.epochHashMutex.RLock() + epochHash := p.latestEpochHash + p.epochHashMutex.RUnlock() + + p.headerMutex.RLock() + header := p.latestBlockHeader + p.headerMutex.RUnlock() + + if epochHash != nil && header != nil { + // 尝试找到解 + solution, err := p.findSolution(epochHash, header.ProofTarget) + if err == nil { + // 提交解 + if err := p.submitSolution(solution); err != nil { + log.Printf("提交解失败: %v", err) + } + } + } + + time.Sleep(100 * time.Millisecond) + } + } +} + +func (p *Prover) taskLoop() { + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + + for { + select { + case <-p.shutdown: + return + case <-ticker.C: + if err := p.getPuzzleTask(); err != nil { + log.Printf("获取任务失败: %v", err) + } + } + } +} + +func (p *Prover) submitSolution(solution *Solution) error { + // 序列化solution + var buf bytes.Buffer + + buf.Write(solution.ID[:]) + buf.Write(solution.EpochHash) + + nonceBytes := make([]byte, 8) + binary.LittleEndian.PutUint64(nonceBytes, solution.Nonce) + buf.Write(nonceBytes) + + buf.Write(solution.Address) + buf.Write(solution.Proof) + + // 发送消息 + return p.sendMessage(MsgUnconfirmedSolution, buf.Bytes()) +} + +func main() { + // 创建矿工地址 + minerAddress := []byte("your_miner_address_here") + + // 创建Prover + prover, err := NewProver(minerAddress) + if err != nil { + log.Fatalf("创建Prover失败: %v", err) + } + + // 启动挖矿 + if err := prover.StartMining(); err != nil { + log.Fatalf("启动挖矿失败: %v", err) + } + + // 等待中断信号 + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + <-sigChan + + // 优雅关闭 + close(prover.shutdown) +} + +func (p *Prover) findSolution(epochHash []byte, proofTarget uint64) (*Solution, error) { + var nonce uint64 = 0 + maxNonce := ^uint64(0) // 最大uint64值 + + // 将proofTarget转换为字节数组用于比较 + targetBytes := make([]byte, 32) + targetBytes[0] = byte(proofTarget) + + for nonce < maxNonce { + // 计算proof + proof, err := p.computeProof(epochHash, p.minerAddress, nonce) + if err != nil { + return nil, fmt.Errorf("计算proof失败: %v", err) + } + + // 验证proof是否满足难度要求 + if p.verifyProof(proof, targetBytes) { + // 构造解 + solution := &Solution{ + EpochHash: epochHash, + Nonce: nonce, + Address: p.minerAddress, + Proof: proof, + } + + // 计算解的ID + id, err := p.computeSolutionID(solution) + if err != nil { + return nil, fmt.Errorf("计算解ID失败: %v", err) + } + copy(solution.ID[:], id) + + log.Printf("找到有效解 - Nonce: %d, ID: %x", nonce, id) + return solution, nil + } + + // 每处理1000个nonce检查一次是否需要退出 + if nonce%1000 == 0 { + select { + case <-p.shutdown: + return nil, fmt.Errorf("挖矿已停止") + default: + } + } + + nonce++ + } + + return nil, fmt.Errorf("未找到有效解") +} + +// computeProof 计算工作量证明 +func (p *Prover) computeProof(epochHash []byte, address []byte, nonce uint64) ([]byte, error) { + hasher := sha256.New() + + // 写入epoch hash + if _, err := hasher.Write(epochHash); err != nil { + return nil, fmt.Errorf("写入epoch hash失败: %v", err) + } + + // 写入地址 + if _, err := hasher.Write(address); err != nil { + return nil, fmt.Errorf("写入地址失败: %v", err) + } + + // 写入nonce (小端字节序) + nonceBytes := make([]byte, 8) + binary.LittleEndian.PutUint64(nonceBytes, nonce) + if _, err := hasher.Write(nonceBytes); err != nil { + return nil, fmt.Errorf("写入nonce失败: %v", err) + } + + return hasher.Sum(nil), nil +} + +// verifyProof 验证工作量证明是否满足难度要求 +func (p *Prover) verifyProof(proof []byte, target []byte) bool { + // 比较proof和target + // proof必须小于target才是有效的 + for i := 0; i < len(proof) && i < len(target); i++ { + if proof[i] < target[i] { + return true + } + if proof[i] > target[i] { + return false + } + } + return false +} + +// computeSolutionID 计算解的唯一标识符 +func (p *Prover) computeSolutionID(solution *Solution) ([]byte, error) { + hasher := sha256.New() + + // 写入所有字段 + if _, err := hasher.Write(solution.EpochHash); err != nil { + return nil, fmt.Errorf("写入epoch hash失败: %v", err) + } + + if _, err := hasher.Write(solution.Address); err != nil { + return nil, fmt.Errorf("写入地址失败: %v", err) + } + + nonceBytes := make([]byte, 8) + binary.LittleEndian.PutUint64(nonceBytes, solution.Nonce) + if _, err := hasher.Write(nonceBytes); err != nil { + return nil, fmt.Errorf("写入nonce失败: %v", err) + } + + if _, err := hasher.Write(solution.Proof); err != nil { + return nil, fmt.Errorf("写入proof失败: %v", err) + } + + return hasher.Sum(nil), nil +} + +type PuzzleInstances struct { + count uint32 +} + +// Sub 原子减少实例计数 +func (p *PuzzleInstances) Sub(delta uint32) { + atomic.AddUint32(&p.count, ^(delta - 1)) +} + +// Add 原子增加实例计数 +func (p *PuzzleInstances) Add(delta uint32) { + atomic.AddUint32(&p.count, delta) +} + +// Get 获取当前实例数 +func (p *PuzzleInstances) Get() uint32 { + return atomic.LoadUint32(&p.count) +} + +func parseBlockHeader(data []byte) (*BlockHeader, error) { + if len(data) < 96 { // 最小区块头长度 + return nil, fmt.Errorf("区块头数据太短") + } + + reader := bytes.NewReader(data) + header := &BlockHeader{} + + // 读取高度 (4字节) + if err := binary.Read(reader, binary.LittleEndian, &header.Height); err != nil { + return nil, fmt.Errorf("读取区块高度失败: %v", err) + } + + // 读取前一个区块哈希 (32字节) + if _, err := io.ReadFull(reader, header.PreviousHash[:]); err != nil { + return nil, fmt.Errorf("读取前一个区块哈希失败: %v", err) + } + + // 读取时间戳 (8字节) + if err := binary.Read(reader, binary.LittleEndian, &header.Timestamp); err != nil { + return nil, fmt.Errorf("读取时间戳失败: %v", err) + } + + // 读取coinbase目标值 (8字节) + if err := binary.Read(reader, binary.LittleEndian, &header.CoinbaseTarget); err != nil { + return nil, fmt.Errorf("读取coinbase目标值失败: %v", err) + } + + // 读取proof目标值 (8字节) + if err := binary.Read(reader, binary.LittleEndian, &header.ProofTarget); err != nil { + return nil, fmt.Errorf("读取proof目标值失败: %v", err) + } + + // 读取交易根 (32字节) + if _, err := io.ReadFull(reader, header.TransactionsRoot[:]); err != nil { + return nil, fmt.Errorf("读取交易根失败: %v", err) + } + + // 读取状态根 (32字节) + if _, err := io.ReadFull(reader, header.StateRoot[:]); err != nil { + return nil, fmt.Errorf("读取状态根失败: %v", err) + } + + return header, nil +} + +func (p *Prover) performHandshake() error { + // 发送握手消息 + if err := p.sendMessage(MsgHandshake, nil); err != nil { + return fmt.Errorf("发送握手消息失败: %v", err) + } + + // 设置读取超时 + if err := p.conn.SetReadDeadline(time.Now().Add(10 * time.Second)); err != nil { + return fmt.Errorf("设置读取超时失败: %v", err) + } + defer p.conn.SetReadDeadline(time.Time{}) // 清除超时 + + // 接收握手响应 + msgType, payload, err := p.receiveMessage() + if err != nil { + return fmt.Errorf("接收握手响应失败: %v", err) + } + + // 验证消息类型 + if msgType != MsgHandshakeResponse { + return fmt.Errorf("收到意外的消息类型: %d, 期望类型: %d", msgType, MsgHandshakeResponse) + } + + // 验证协议版本 + if len(payload) >= 4 { + version := binary.BigEndian.Uint32(payload[0:4]) + if version != ProtocolVersion { + return fmt.Errorf("协议版本不匹配: 收到 %d, 期望 %d", version, ProtocolVersion) + } + } + + log.Printf("握手成功 - 协议版本: %d", ProtocolVersion) + return nil +} diff --git a/internal/gbt/coin/coin.go b/internal/gbt/coin/coin.go index 12fd6e7..9052ab5 100644 --- a/internal/gbt/coin/coin.go +++ b/internal/gbt/coin/coin.go @@ -9,7 +9,6 @@ import ( "pool/internal/utility" "github.com/btcsuite/btcd/rpcclient" - kaspad "github.com/kaspanet/kaspad/infrastructure/network/rpcclient" "github.com/redis/go-redis/v9" "github.com/zeromq/goczmq" "go.uber.org/zap" @@ -58,12 +57,12 @@ type GbtContext struct { PushCh *goczmq.Sock - Started bool - Config GbtConfig - Client *rpcclient.Client - ClientAlph *net.Conn - ClientAlphApi *http.HttpClient - ClientEnx *kaspad.RPCClient + Started bool + Config GbtConfig + Client *rpcclient.Client + ClientAlph *net.Conn + ClientAlphApi *http.HttpClient + // ClientEnx *kaspad.RPCClient ExitNotifyChan chan bool ExitGbtChan chan bool ExitBlockChan chan bool diff --git a/internal/gbt/enx/enx.go b/internal/gbt/enx/enx.go deleted file mode 100644 index 7f1fa9b..0000000 --- a/internal/gbt/enx/enx.go +++ /dev/null @@ -1,247 +0,0 @@ -package enx - -import ( - "encoding/hex" - "fmt" - "pool/internal/db" - "pool/internal/gbt/coin" - "pool/internal/gbt/enx/templatemanager" - "pool/internal/msg" - "sync" - "sync/atomic" - "time" - - "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" - "github.com/kaspanet/kaspad/domain/consensus/utils/pow" - "github.com/kaspanet/kaspad/util/difficulty" - "go.uber.org/zap" -) - -const GBT_ENX_VERSION string = "enx v1.15.2" - -type EnxAddrConfig struct { - Addr string `json:"addr"` -} - -type EnxConfig struct { - Enx EnxAddrConfig `json:"enx"` -} - -type GbtEnxContext struct { - Config EnxConfig - GbtCtx *coin.GbtContext - - last_time time.Time - last_gbt EnxGbtTemplate - - Submits float64 - - addressIndex int - - new_block_chan chan int - new_block_index int - - last_height uint32 -} - -var logg *zap.Logger -var GbtEnxCtx GbtEnxContext - -// Kaspa GetBlockTemplate 结构体 -type EnxGbtTemplate struct { - Block struct { - Header struct { - Version int `json:"version"` - ParentsByLevel [][]string `json:"parents_by_level"` - HashMerkleRoot string `json:"hash_merkle_root"` - AcceptedIdMerkleRoot string `json:"accepted_id_merkle_root"` - UtxoCommitment string `json:"utxo_commitment"` - Timestamp uint64 `json:"timestamp"` - Bits uint32 `json:"bits"` - Nonce uint64 `json:"nonce"` - DaaScore uint64 `json:"daa_score"` - BlueWork [3]uint64 `json:"blue_work"` // 可改为 big.Int - BlueScore uint64 `json:"blue_score"` - PruningPoint string `json:"pruning_point"` - } `json:"header"` - - Transactions []struct { - Version int `json:"version"` - LockTime uint64 `json:"lock_time"` - SubnetworkId string `json:"subnetwork_id"` - Gas uint64 `json:"gas"` - PayLoad string `json:"payload"` - Mass uint64 `json:"mass"` - - Inputs []struct{} `json:"inputs"` - Outputs []struct{} `json:"outputs"` - - VerboseData interface{} `json:"verbose_data"` - } `json:"transactions"` - } `json:"block"` - - IsSync bool `json:"is_sync"` -} - -type BlockCheckData struct { - Height int - Nonce string - User string - Miner string - MinerId string - Hash string - SubIdx int -} - -type PushBlkNewMsg struct { - Coin string `json:"coin"` - Height int `json:"height"` - Nonce string `json:"nonce"` -} - -type EnxJob struct { - JobID uint32 - Job *externalapi.DomainBlock - State *pow.State -} - -type EnxContext struct { - GbtCtx *coin.GbtContext - - SLock sync.Mutex - JobID uint32 - Jobs []EnxJob - - LastHeight uint64 - - Submits float64 -} - -var enxCtx EnxContext - -func update_block_confirm(gbt *GbtEnxContext) {} - -var hashesTried uint64 - -func get_blocktemplate(gbt *GbtEnxContext, mineWhenNotSynced bool) (*externalapi.DomainBlock, *pow.State) { - tryCount := 0 - const sleepTime = 500 * time.Millisecond - const sleepTimeWhenNotSynced = 5 * time.Second - - for { - tryCount++ - - shouldLog := (tryCount-1)%10 == 0 - template, state, isSynced := templatemanager.Get() - if template == nil { - if shouldLog { - logg.Info("Waiting for the initial template") - } - time.Sleep(sleepTime) - continue - } - if !isSynced && !mineWhenNotSynced { - if shouldLog { - logg.Warn("Kaspad is not synced. Skipping current block template") - } - time.Sleep(sleepTimeWhenNotSynced) - continue - } - - return template, state - } -} - -func get_gbt_msg(gbt *GbtEnxContext) []byte { - // 这里从节点获取区块模版(block template) - dagInfoMsg, err := gbt.GbtCtx.ClientEnx.GetBlockDAGInfo() - if err != nil { - logg.Info("[gbt]", zap.String("GetBlockDAGInfo ", err.Error())) - return nil - } - height := dagInfoMsg.VirtualDAAScore - if err != nil { - logg.Info("[gbt]", zap.String("GetBlockCount ", err.Error())) - return nil - } - height = height + 1 - block, state := getBlockForMining(mineWhenNotSynced) - //state.Nonce = nonce - state.Nonce = 0 - atomic.AddUint64(&hashesTried, 1) - - var job msg.EnxStratumJob - enxCtx.SLock.Lock() - job.Job_id = 0 - job.Gbt_id = enxCtx.JobID - enxCtx.SLock.Unlock() - - job.CurTime = uint64(state.Timestamp) - job.Target = hex.EncodeToString(state.Target.Bytes()) - job.Bits = difficulty.BigToCompact(&(state.Target)) - job.Nonce = "" - job.Extranonce1 = "" - job.Extranonce2_size = 6 - job.Extranonce2 = "" - job.Data = hex.EncodeToString(state.GetPrePowHash()) - job.PrevBlockHash = fmt.Sprint("%s", block.Header.DirectParents()) - job.Height = block.Header.BlueScore() - - return []byte{} -} - -func getBlockForMining(mineWhenNotSynced bool) (*externalapi.DomainBlock, *pow.State) { - tryCount := 0 - - const sleepTime = 500 * time.Millisecond - const sleepTimeWhenNotSynced = 5 * time.Second - - for { - tryCount++ - - shouldLog := (tryCount-1)%10 == 0 - template, state, isSynced := templatemanager.Get() - if template == nil { - if shouldLog { - logg.Info("Waiting for the initial template") - } - time.Sleep(sleepTime) - continue - } - if !isSynced && !mineWhenNotSynced { - if shouldLog { - logg.Warn("Kaspad is not synced. Skipping current block template") - } - time.Sleep(sleepTimeWhenNotSynced) - continue - } - - return template, state - } -} - -func gbt_notify_running(gbt *GbtEnxContext) {} - -func gbt_running(gbt *GbtEnxContext) {} - -func enxInit(config *EnxConfig) {} - -func Init(GbtCtx *coin.GbtContext, DbCtx *db.DbContext) {} - -func Start() { - go gbt_running(&GbtEnxCtx) - go gbt_notify_running(&GbtEnxCtx) - go submit_block_running(&GbtEnxCtx) -} - -func Stop() { - defer close(GbtEnxCtx.new_block_chan) -} - -func new_block_into_db(block *GbtEnxContext, user string, miner string, minerid string, height int64, nonce string, hash string, subidx int64) bool { - return true -} - -func submit_block_running(block *GbtEnxContext) {} - -func new_job_from_gbt(gbt *GbtEnxContext, rxmsg *msg.GbtMsg) []byte { return []byte{} } diff --git a/internal/gbt/enx/templatemanager/templatemanager.go b/internal/gbt/enx/templatemanager/templatemanager.go deleted file mode 100644 index 45a207c..0000000 --- a/internal/gbt/enx/templatemanager/templatemanager.go +++ /dev/null @@ -1,49 +0,0 @@ -package templatemanager - -import ( - "sync" - - "github.com/kaspanet/kaspad/app/appmessage" - "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" - "github.com/kaspanet/kaspad/domain/consensus/utils/pow" -) - -var currentTemplate *externalapi.DomainBlock -var currentState *pow.State -var prevState *pow.State -var isSynced bool -var lock = &sync.Mutex{} - -// Get returns the template to work on -func Get() (*externalapi.DomainBlock, *pow.State, bool) { - lock.Lock() - defer lock.Unlock() - // Shallow copy the block so when the user replaces the header it won't affect the template here. - if currentTemplate == nil { - return nil, nil, false - } - if prevState != nil { - if currentState.Target.Cmp(&(prevState.Target)) == 0 { - return nil, nil, false - } - } - block := *currentTemplate - state := *currentState - prevState = currentState - currentTemplate = nil - return &block, &state, isSynced -} - -// Set sets the current template to work on -func Set(template *appmessage.GetBlockTemplateResponseMessage) error { - block, err := appmessage.RPCBlockToDomainBlock(template.Block) - if err != nil { - return err - } - lock.Lock() - defer lock.Unlock() - currentTemplate = block - currentState = pow.NewState(block.Header.ToMutable()) - isSynced = template.IsSynced - return nil -} diff --git a/internal/gbt/gbt.go b/internal/gbt/gbt.go index a9284f1..a130bd8 100644 --- a/internal/gbt/gbt.go +++ b/internal/gbt/gbt.go @@ -24,7 +24,6 @@ import ( "pool/internal/gbt/alph/http" "pool/internal/gbt/coin" "pool/internal/gbt/dgb" - "pool/internal/gbt/enx" "pool/internal/gbt/grs" "pool/internal/gbt/mona" "pool/internal/gbt/nexa" @@ -37,7 +36,6 @@ import ( "time" "github.com/btcsuite/btcd/rpcclient" - kaspad "github.com/kaspanet/kaspad/infrastructure/network/rpcclient" "github.com/redis/go-redis/v9" "go.uber.org/zap" ) @@ -74,23 +72,23 @@ func InitClient(gbt *coin.GbtContext) error { gbt.ClientAlphApi = apiClient // blockCount := apiClient.GetBlockCount() return nil - case "enx": - host := gbt.Config.Rpc.Host - port := gbt.Config.Rpc.Port - client, err := kaspad.NewRPCClient(host + ":" + port) - if err != nil { - logg.Info("[gbt]", zap.String("rpcclient new ", err.Error())) - return err - } - gbt.ClientEnx = client - dagInfoMsg, err := client.GetBlockDAGInfo() - if err != nil { - logg.Info("[gbt]", zap.String("GetBlockDAGInfo ", err.Error())) - return err - } - blockCount := dagInfoMsg.VirtualDAAScore - logg.Info("[gbt]", zap.Int64("Block count ", int64(blockCount))) - return nil + // case "enx": + // host := gbt.Config.Rpc.Host + // port := gbt.Config.Rpc.Port + // client, err := kaspad.NewRPCClient(host + ":" + port) + // if err != nil { + // logg.Info("[gbt]", zap.String("rpcclient new ", err.Error())) + // return err + // } + // gbt.ClientEnx = client + // dagInfoMsg, err := client.GetBlockDAGInfo() + // if err != nil { + // logg.Info("[gbt]", zap.String("GetBlockDAGInfo ", err.Error())) + // return err + // } + // blockCount := dagInfoMsg.VirtualDAAScore + // logg.Info("[gbt]", zap.Int64("Block count ", int64(blockCount))) + // return nil default: var config rpcclient.ConnConfig if gbt.Config.Rpc.Type == "testnet" { @@ -183,7 +181,6 @@ var coinobjs = []coinobj{ {Coin: "dgbq", Init: dgb.Init, Start: dgb.Start, Stop: dgb.Stop}, {Coin: "dgbs", Init: dgb.Init, Start: dgb.Start, Stop: dgb.Stop}, {Coin: "alph", Init: alph.Init, Start: alph.Start, Stop: alph.Stop}, - {Coin: "enx", Init: enx.Init, Start: enx.Start, Stop: enx.Stop}, } func register_signal(dbctx *db.DbContext) { diff --git a/internal/server/enx/enx.go b/internal/server/enx/enx.go deleted file mode 100644 index a1eaead..0000000 --- a/internal/server/enx/enx.go +++ /dev/null @@ -1,272 +0,0 @@ -package enx - -import ( - "bytes" - "encoding/binary" - "encoding/hex" - "encoding/json" - "fmt" - "pool/internal/msg" - "pool/internal/server/coin" - "pool/internal/stratum" - "pool/internal/utility" - - "github.com/btcsuite/btcd/wire" - "go.uber.org/zap" -) - -const SERVER_ENX_VERSION string = "enx v1.15.2" - -type ServerEnxContext struct { - ServerCtx *coin.ServerContext - logg *zap.Logger - Job msg.StratumJob -} - -var logg *zap.Logger -var ServerEnxCtx ServerEnxContext - -// headerHash:本身的pow计算结果,收到后根据nonce和timestamp重新计算该值,确保该值正确 -// headerHash本身可以通过计算得出难度 -func handle_submit(miner *coin.MinerObj, id float64, miner_user string, job_id string, headerHash string, ntime string, nonce string) (bool, bool, bool) { - var submit_item coin.BlockMsg - /*var user_blk_item coin.UserBlockMsg*/ - var pool_blk_item coin.PoolBlkMsg - - var blk_detail_height int64 - var blk_detail_hash string - var blk_detail_success bool - var blk_detail_miner_diff float64 - var blk_detail_pool_diff float64 - - if miner.Authorized != true { - miner.ErrOthers = miner.ErrOthers + 1 - stratum.Handle_exception(miner, id, stratum.MINER_ERR_UNAUTH_WORKER) - stratum.Send_reconnect_msg(miner) - return false, false, false - } - var new_found bool = false - var ack stratum.Submit_ack - ack.ID = id - ack.Result = true - //logg.Warn("[server]", zap.String("user", miner.User), zap.String("miner", miner.Miner)) - //logg.Debug("[server]", zap.Float64("id", id), zap.String("job_id", job_id)) - //logg.Debug("[server]", zap.String("nonce2", nonce2), zap.String("ntime", ntime), zap.String("nonce", nonce)) - //stratum.UpdateJobs(miner) - v, ok := miner.Jobs.Load(job_id) - if ok { - job := v.(msg.StratumJob) - if job.Height < miner.CurHeight-1 { - ack.Result = false - stratum.Handle_exception(miner, id, stratum.MINER_ERR_STALED_JOB) - miner.ErrStaleds = miner.ErrStaleds + 1 - return false, false, false - } - - if miner.LastNonce != nonce { - miner.LastNonce = nonce - if miner.ZlogInit { - miner.Zlog.Info().Msg("height " + fmt.Sprintf("%d", job.Height) + " target " + job.Target + " extra1 " + job.Extranonce1 + " size " + fmt.Sprintf("%d", job.Extranonce2_size) + " " + miner.User + "." + miner.Miner) - } - } - vb := make([]byte, 4) - binary.LittleEndian.PutUint32(vb, uint32(job.Version)) - vBuffer := bytes.NewBuffer(vb) - binary.Read(vBuffer, binary.BigEndian, &(miner.Version)) - - job.Nonce = nonce - job.Extranonce2 = headerHash - - var calc_hash []byte - var header wire.BlockHeader - - } -} - -// 构造提交至节点的区块 -func Produce_block_submit(miner *coin.MinerObj, header wire.BlockHeader, job *msg.StratumJob, PowHash string, SubIdx int64) { -} - -// server-->miner -func enx_parse_miner_notify(miner *coin.MinerObj, msg msg.StratumJob) int {} - -func Init(server *coin.ServerContext) { - ServerEnxCtx.ServerCtx = server - logg = server.Logg - logg.Info("[server]", zap.String("server_mona_version", SERVER_ENX_VERSION)) - coin.Init_diff_db() -} - -func Start() { - -} - -func Stop() { - coin.DiffStop() -} - -func InitMiner(miner *coin.MinerObj) {} - -func Handle_subscribe_enx(miner *coin.MinerObj, id float64, extranonce1 string) { - stratum.Handle_subscribe(miner, id, extranonce1) -} - -func HandleMinerSubscribe(miner *coin.MinerObj, id float64, extranonce1 string, msg string) { - Handle_subscribe_enx(miner, id, extranonce1) -} - -func HandleMinerAuth(miner *coin.MinerObj) { - -} - -func HandleMinerSubmit(miner *coin.MinerObj, id float64, miner_user string, job_id string, nonce2 string, ntime string, nonce string) (bool, bool, bool) { - - accept_ok, submit_ok, handle_ok := handle_submit(miner, id, miner_user, job_id, nonce2, ntime, nonce) - return accept_ok, submit_ok, handle_ok -} - -func set_difficulty(miner *coin.MinerObj) {} - -func SetDifficulty(miner *coin.MinerObj) { - set_difficulty(miner) -} - -/** -id: int, method: string, params:[string(jobid), string(headerHash, 32 byte serialized header, 8 bytes timestamp)] -*/ -func EnxNotify(miner *coin.MinerObj) { - miner.TxLock.Lock() - if !((miner.Status == coin.MINER_STATUS_AUTHORIZED) || (miner.Status == coin.MINER_STATUS_RUNNING)) { - miner.TxLock.Unlock() - return - } - miner.TxLock.Unlock() - if miner.DifficultyNext > -1 { - ratio := miner.DifficultyNext / miner.Difficulty - if ratio > 1.1 || ratio < 0.9 { - miner.Difficulty = miner.DifficultyNext - miner.DifficultyNext = -1 - //Set_difficulty(miner) - miner.Server.CoinCtx.SetDifficulty(miner) - } else { - miner.DifficultyNext = -1 - } - } - miner.TxLock.Lock() - //log.Println("[server]extra1, id", miner.Job.Extranonce1, miner.Job.Job_id, miner.MinerId) - var params [9]interface{} - var tlist []string = make([]string, 0) - idb := make([]byte, 4) - binary.BigEndian.PutUint32(idb, miner.JobId) - miner.Job.Job_id = hex.EncodeToString(idb) - params[0] = miner.Job.Job_id - if len(miner.Job.PrevblockS) > 0 { - params[1] = miner.Job.PrevblockBig - } else { - p_big := utility.Convert_big_endian(miner.Job.Prevblock.CloneBytes()) - params[1] = hex.EncodeToString(p_big) - } - params[2] = miner.Job.Coinbase1 - params[3] = miner.Job.Coinbase2 - params[4] = tlist - - miner.CurHeight = miner.Job.Height - - if miner.Job.Transactions != nil { - if len(*miner.Job.Transactions) > 0 { - params[4] = miner.Job.Transactions - - /*miner.Server.Logg.Error("[notify]", zap.String("coinbase1", miner.Job.Coinbase1), zap.String("coinbase2", miner.Job.Coinbase2), zap.Uint32("height", miner.Job.Height)) - for i := 0; i < len(*miner.Job.Transactions); i++ { - miner.Server.Logg.Error("[notify]", zap.String("trans", (*miner.Job.Transactions)[i])) - }*/ - - } - } - vb := make([]byte, 4) - binary.LittleEndian.PutUint32(vb, uint32(miner.Job.Version)) - params[5] = hex.EncodeToString(vb) - bb := make([]byte, 4) - binary.LittleEndian.PutUint32(bb, miner.Job.Bits) - params[6] = hex.EncodeToString(bb) - t := miner.Job.Timestamp.Unix() - if t > int64(^uint32(0)) { - tb := make([]byte, 8) - binary.LittleEndian.PutUint64(tb, uint64(t)) - params[7] = hex.EncodeToString(tb) - } else { - tb := make([]byte, 4) - binary.LittleEndian.PutUint32(tb, uint32(t)) - params[7] = hex.EncodeToString(tb) - } - if miner.Reconnect { - params[8] = true - miner.Reconnect = false - } else { - params[8] = miner.Job.IsClean - } - miner.Job.JobDifficulty = miner.Difficulty - - //miner.Jobs[miner.Job.Job_id] = miner.Job - miner.Jobs.LoadOrStore(miner.Job.Job_id, miner.Job) - - /*var entry coin.JobListEntry - entry.Job_id = miner.Job.Job_id - entry.Ts = time.Now() - - miner.LockForJobs.Lock() - miner.JobList.PushFront(entry) - var removes string = "" - if miner.JobList.Len() > int(coin.LOCAL_JOBS_TOTAL_SIZE) { - e := miner.JobList.Back() - entry := e.Value.(coin.JobListEntry) - removes = entry.Job_id - miner.JobList.Remove(e) - } - miner.LockForJobs.Unlock() - if len(removes) > 0 { - miner.Jobs.Delete(removes) - }*/ - stratum.AddAndUpdateJob(miner) - stratum.UpdateJobs(miner) - - //miner.LastJobId = miner.Job.Job_id - miner.JobId++ - - var msg stratum.Notify_msg - msg.ID = nil - msg.Method = "mining.notify" - msg.Params = params - body, err := json.Marshal(msg) - if err != nil { - miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) - miner.TxLock.Unlock() - return - } - var body_string = string(body) + "\n" - err = stratum.Conn_tx(miner.Conn, []byte(body_string)) - if err != nil { - //delete(miner.Server.Miners, miner.MinerId) - //miner.Server.Miners.Delete(miner.MinerId) - } - //miner.Server.Logg.Debug("[server]", zap.String("tx", body_string)) - miner.TxLock.Unlock() - - if miner.ZlogInit { - miner.Zlog.Info().Msg(body_string) - } -} - -func Notify(miner *coin.MinerObj) { - EnxNotify(miner) -} - -func HandleJobMsg(server *coin.ServerContext, Msg []byte) {} - -func IsMhsLow(miner *coin.MinerObj) bool { - return miner.Mhs5M < 1 -} - -func GetBlockInterval() int { - return 30 // 30秒没获取到任务发送退出信号 -} diff --git a/internal/server/enx/hash_enx.go b/internal/server/enx/hash_enx.go deleted file mode 100644 index db52dc3..0000000 --- a/internal/server/enx/hash_enx.go +++ /dev/null @@ -1,35 +0,0 @@ -package enx - -/* -#cgo CFLAGS: -I../include/heavyHash -#cgo LDFLAGS: -L../lib/heavyHash -lheavyhash -#include "heavyhash.h" -*/ -import "C" -import ( - "fmt" - "strings" - "unsafe" -) - -func EnxHash(data []byte) string { - // 初始化 CSHA3_256 结构体 - var sha3 C.CSHA3_256 - - // 调用 C 语言的 Write 方法 - C.CSHA3_256_Write(&sha3, (*C.uchar)(unsafe.Pointer(&data[0])), C.size_t(len(data))) - - // 调用 C 语言的 Finalize 方法来生成哈希 - var hash [C.OUTPUT_SIZE]C.uchar - C.CSHA3_256_Finalize(&sha3, &hash[0]) - - // 使用 strings.Builder 来拼接字符串 - var builder strings.Builder - for i := 0; i < C.OUTPUT_SIZE; i++ { - // 以十六进制方式格式化每个字节 - builder.WriteString(fmt.Sprintf("%02x", hash[i])) - } - - // 返回最终的哈希值 - return builder.String() -}