func (jm *JobManager) CreateNewJob(rpcData *daemons.GetBlockTemplate) {
	tmpBlockTemplate := NewJob(
		utils.RandHexUint64(),
		rpcData,
		jm.PoolAddress.GetScript(),
		jm.ExtraNoncePlaceholder,
		jm.Options.Coin.Reward,
		jm.Options.Coin.TxMessages,
		jm.Options.RewardRecipients,
	)
	jm.CurrentJob = tmpBlockTemplate
	jm.ValidJobs[tmpBlockTemplate.JobId] = tmpBlockTemplate
	log.Info("New Job (Block) from block template")
}
CreateNewJob creates a new job when mining new height
package jobs
import (
	"encoding/hex"
	"math/big"
	"net"
	"strconv"
	"strings"
	"time"
	logging "github.com/ipfs/go-log/v2"
	"github.com/mining-pool/not-only-mining-pool/algorithm"
	"github.com/mining-pool/not-only-mining-pool/config"
	"github.com/mining-pool/not-only-mining-pool/daemons"
	"github.com/mining-pool/not-only-mining-pool/storage"
	"github.com/mining-pool/not-only-mining-pool/types"
	"github.com/mining-pool/not-only-mining-pool/utils"
)
var log = logging.Logger("jobMgr")
type JobCounter struct {
	Counter *big.Int
}
type JobManager struct {
	PoolAddress *config.Recipient
	Storage               *storage.DB
	Options               *config.Options
	JobCounter            *JobCounter
	ExtraNonce1Generator  *ExtraNonce1Generator
	ExtraNoncePlaceholder []byte
	ExtraNonce2Size       int
	CurrentJob *Job
	ValidJobs  map[string]*Job
	CoinbaseHasher func([]byte) []byte
	DaemonManager *daemons.DaemonManager
	NewBlockEvent chan *Job
}
func NewJobManager(options *config.Options, dm *daemons.DaemonManager, storage *storage.DB) *JobManager {
	placeholder, _ := hex.DecodeString("f000000ff111111f")
	extraNonce1Generator := NewExtraNonce1Generator()
	return &JobManager{
		PoolAddress: options.PoolAddress,
		Options:               options,
		ExtraNonce1Generator:  extraNonce1Generator,
		ExtraNoncePlaceholder: placeholder,
		ExtraNonce2Size:       len(placeholder) - extraNonce1Generator.Size,
		CurrentJob:            nil,
		ValidJobs:             make(map[string]*Job),
		CoinbaseHasher:        utils.Sha256d,
		Storage:               storage,
		DaemonManager:         dm,
	}
}
func (jm *JobManager) Init(gbt *daemons.GetBlockTemplate) {
	jm.ProcessTemplate(gbt)
}
func (jm *JobManager) ProcessShare(share *types.Share) {
	var isAccepted bool
	var tx string
	if share.BlockHex != "" {
		log.Info("submitting new Block: ", share.BlockHex)
		jm.DaemonManager.SubmitBlock(share.BlockHex)
		isAccepted, tx = jm.CheckBlockAccepted(share.BlockHash)
		share.TxHash = tx
		if isAccepted {
			log.Info("Block ", share.BlockHash, " Accepted! generation tx: ", share.TxHash, ". Wait for pendding!")
		}
		gbt, err := jm.DaemonManager.GetBlockTemplate()
		if err != nil {
			log.Panic("failed fetching GBT: ", err)
		}
		jm.ProcessTemplate(gbt)
	}
	go jm.Storage.PutShare(share, isAccepted)
}
func (jm *JobManager) CheckBlockAccepted(blockHash string) (isAccepted bool, tx string) {
	_, results := jm.DaemonManager.CmdAll("getblock", []interface{}{blockHash})
	isAccepted = true
	for i := range results {
		isAccepted = isAccepted && results[i] != nil && results[i].Error == nil
	}
	for i := range results {
		if results[i] == nil {
			continue
		}
		gb := daemons.BytesToGetBlock(results[i].Result)
		if gb.Tx != nil {
			return isAccepted, gb.Tx[0]
		}
	}
	return isAccepted, ""
}
func (jm *JobManager) UpdateCurrentJob(rpcData *daemons.GetBlockTemplate) {
	tmpBlockTemplate := NewJob(
		jm.CurrentJob.JobId,
		rpcData,
		jm.PoolAddress.GetScript(),
		jm.ExtraNoncePlaceholder,
		jm.Options.Coin.Reward,
		jm.Options.Coin.TxMessages,
		jm.Options.RewardRecipients,
	)
	jm.CurrentJob = tmpBlockTemplate
	jm.ValidJobs[tmpBlockTemplate.JobId] = tmpBlockTemplate
	log.Debug("Job updated")
}