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{} }