public async Task <Share> SubmitShareAsync(StratumClient worker, MoneroSubmitShareRequest request, MoneroWorkerJob workerJob, double stratumDifficultyBase) { Contract.RequiresNonNull(worker, nameof(worker)); Contract.RequiresNonNull(request, nameof(request)); logger.LogInvoke(LogCat, new[] { worker.ConnectionId }); var context = worker.GetContextAs <MoneroWorkerContext>(); var job = currentJob; if (workerJob.Height != job?.BlockTemplate.Height) { throw new StratumException(StratumError.MinusOne, "block expired"); } // validate & process var(share, blobHex, blobHash) = job.ProcessShare(request.Nonce, workerJob.ExtraNonce, request.Hash, worker); // enrich share with common data share.PoolId = poolConfig.Id; share.IpAddress = worker.RemoteEndpoint.Address.ToString(); share.Miner = context.MinerName; share.Worker = context.WorkerName; share.PayoutInfo = context.PaymentId; share.UserAgent = context.UserAgent; share.Source = clusterConfig.ClusterName; share.NetworkDifficulty = job.BlockTemplate.Difficulty; share.Created = clock.Now; // if block candidate, submit & check if accepted by network if (share.IsBlockCandidate) { logger.Info(() => $"[{LogCat}] Submitting block {share.BlockHeight} [{blobHash.Substring(0, 6)}]"); share.IsBlockCandidate = await SubmitBlockAsync(share, blobHex, blobHash); if (share.IsBlockCandidate) { logger.Info(() => $"[{LogCat}] Daemon accepted block {share.BlockHeight} [{blobHash.Substring(0, 6)}] submitted by {context.MinerName}"); blockSubmissionSubject.OnNext(Unit.Default); share.TransactionConfirmationData = blobHash; } else { // clear fields that no longer apply share.TransactionConfirmationData = null; } } return(share); }
public async Task <IShare> SubmitShareAsync(StratumClient <MoneroWorkerContext> worker, MoneroSubmitShareRequest request, MoneroWorkerJob workerJob, double stratumDifficulty, double stratumDifficultyBase) { MoneroJob job; lock (jobLock) { if (workerJob.Height != currentJob.BlockTemplate.Height) { throw new StratumException(StratumError.MinusOne, "block expired"); } job = currentJob; } // validate & process var share = job?.ProcessShare(request.Nonce, workerJob.ExtraNonce, request.Hash, stratumDifficulty); // if block candidate, submit & check if accepted by network if (share.IsBlockCandidate) { logger.Info(() => $"[{LogCat}] Submitting block {share.BlockHeight} [{share.BlobHash.Substring(0, 6)}]"); share.IsBlockCandidate = await SubmitBlockAsync(share); if (share.IsBlockCandidate) { logger.Info(() => $"[{LogCat}] Daemon accepted block {share.BlockHeight} [{share.BlobHash.Substring(0, 6)}]"); share.TransactionConfirmationData = share.BlobHash; } else { // clear fields that no longer apply share.TransactionConfirmationData = null; } } // enrich share with common data share.PoolId = poolConfig.Id; share.IpAddress = worker.RemoteEndpoint.Address.ToString(); share.Miner = worker.Context.MinerName; share.Worker = worker.Context.WorkerName; share.PayoutInfo = worker.Context.PaymentId; share.UserAgent = worker.Context.UserAgent; share.NetworkDifficulty = BlockchainStats.NetworkDifficulty; share.StratumDifficulty = stratumDifficulty; share.StratumDifficultyBase = stratumDifficultyBase; share.Created = DateTime.UtcNow; return(share); }