166 lines
4.5 KiB
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)
|
|
}
|