m2pool-core/internal/server/proxy/randomxT.go

166 lines
4.5 KiB
Go

package proxy
import (
"context"
"crypto/rand"
"encoding/hex"
"fmt"
pb "pool/internal/server/proxy/proto"
block "pool/internal/server/proxy/proto/block"
transaction "pool/internal/server/proxy/proto/transaction"
"sync"
"google.golang.org/grpc"
)
// BaseNode客户端示例
type BaseNodeClient struct {
conn *grpc.ClientConn
client pb.BaseNodeClient
ctx context.Context
}
type NewBlockTemplateResponse struct {
NewBlockTemplate *block.NewBlockTemplate `json:"new_block_template"`
InitialSyncAchieved bool `json:"initial_sync_achieved"`
MinerData *pb.MinerData `json:"miner_data"`
}
type NewBlockTemplate struct {
Header *block.BlockHeader `json:"header"`
Body *transaction.AggregateBody `json:"body"`
}
// 创建BaseNode客户端
func NewBaseNodeClient(address string) (*BaseNodeClient, error) {
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
return nil, fmt.Errorf("failed to connect to base node: %v", err)
}
ctx := context.Background()
return &BaseNodeClient{
conn: conn,
client: pb.NewBaseNodeClient(conn),
ctx: ctx,
}, nil
}
type RandomxTJob struct {
JobID string `json:"job_id"`
SeedHash string `json:"seed_hash"`
Height uint64 `json:"height"`
MiningHash string `json:"mining_hash"`
Blob string `json:"blob"` // hash_blob
Difficulty uint64 `json:"diffculty"`
Header string `json:"header"`
Body string `json:"body"`
}
type MoneroNotify_params_msg struct {
Id string `json:"id"`
JobId string `json:"job_id"`
SeedHash string `json:"seed_hash"`
Blob string `json:"blob"`
Height uint32 `json:"height"`
Target string `json:"target"`
NextSeedHash string `json:"next_seed_hash"`
Algo string `json:"algo"`
}
type Monero_msg struct {
Jsonrpc string `json:"jsonrpc"`
Method string `json:"method"`
Params MoneroNotify_params_msg `json:"params"`
}
type MoneroAuthorize_reply struct {
ID float64 `json:"id"`
Jsonrpc string `json:"jsonrpc"`
Error interface{} `json:"error"`
Result MoneroJob `json:"result"`
}
type MoneroJob struct {
Id string `json:"id"`
Job MoneroNotify_params_msg `json:"job"`
Status string `json:"status"`
}
func randomxJobId() string {
// 生成4个字节
bytes := make([]byte, 4)
_, err := rand.Read(bytes)
if err != nil {
panic(err)
}
// 转成 hex 字符串
hexStr := hex.EncodeToString(bytes)
return hexStr
}
var jobs sync.Map
func (c *BaseNodeClient) get_randomxt_data() {
getblocktemplateReq := &pb.NewBlockTemplateRequest{
Algo: &block.PowAlgo{
PowAlgo: block.PowAlgo_POW_ALGOS_RANDOMXT, // 使用 SHA3X 算法
},
MaxWeight: 0x00ff, // 设置最大权重
}
blocktemplate, err := c.client.GetNewBlockTemplate(c.ctx, getblocktemplateReq)
if err != nil {
fmt.Println("get block template failed:", err)
return
}
synced := blocktemplate.InitialSyncAchieved
if !synced {
fmt.Println("chain doesn`t synced!")
return
}
diff := blocktemplate.MinerData.TargetDifficulty
template := blocktemplate.NewBlockTemplate
newblock, err := c.client.GetNewBlock(c.ctx, template)
if err != nil {
fmt.Println("get new block failed:", err)
return
}
height := newblock.Block.Header.Height
newblockblob, err := c.client.GetNewBlockBlob(c.ctx, template)
if err != nil {
fmt.Println("get new block blob failed:", err)
return
}
mining_hash_byte, vm_key_byte := newblock.BlockHash, newblock.VmKey
header_byte, body_byte := newblockblob.Header, newblockblob.BlockBody
// 构造tari-ranomdxt hashing_blob
// 3字节前导0 + 32字节mining_hash + 8字节nonce + 1字节pow_algo + 32字节pow_data
pilotZero := make([]byte, 3)
pow_algo := []byte{0x20}
pow_data := make([]byte, 32)
initNonce := make([]byte, 8)
hashing_blob := make([]byte, 76)
copy(hashing_blob[0:3], pilotZero) // 3字节
copy(hashing_blob[3:35], mining_hash_byte) // 32字节
copy(hashing_blob[35:43], initNonce) // 8字节
copy(hashing_blob[43:44], pow_algo) // 1字节
copy(hashing_blob[44:76], pow_data) // 32字节
jobId := randomxJobId()
var job RandomxTJob
job.MiningHash = hex.EncodeToString(mining_hash_byte)
job.Blob = hex.EncodeToString(hashing_blob)
job.Header = hex.EncodeToString(header_byte)
job.Body = hex.EncodeToString(body_byte)
job.Height = height
job.Difficulty = diff
job.SeedHash = hex.EncodeToString(vm_key_byte)
job.JobID = jobId
jobs.LoadOrStore(jobId, job)
}