diff --git a/src/models/MiningJob.ts b/src/models/MiningJob.ts index 6b5124e..62c5c07 100644 --- a/src/models/MiningJob.ts +++ b/src/models/MiningJob.ts @@ -25,7 +25,6 @@ export class MiningJob { public jobTemplateId: string; public networkDifficulty: number; public creation: number; - public retiredAt?: number; constructor( private network: bitcoinjs.networks.Network, diff --git a/src/models/StratumV1Client.ts b/src/models/StratumV1Client.ts index 11925cf..0f026cc 100644 --- a/src/models/StratumV1Client.ts +++ b/src/models/StratumV1Client.ts @@ -550,19 +550,6 @@ export class StratumV1Client { return false; } - const classification = this.stratumV1JobsService.classifyJobForShare(job); - if (classification === 'stale-rejected') { - const err = new StratumErrorMessage( - submission.id, - eStratumErrorCode.JobNotFound, - 'stale').response(); - const success = await this.write(err); - if (!success) { - return false; - } - return false; - } - const submissionHash = [ submission.jobId, submission.extraNonce2, diff --git a/src/services/stratum-v1-jobs.service.spec.ts b/src/services/stratum-v1-jobs.service.spec.ts index d5a78c9..279f235 100644 --- a/src/services/stratum-v1-jobs.service.spec.ts +++ b/src/services/stratum-v1-jobs.service.spec.ts @@ -47,7 +47,7 @@ describe('StratumV1JobsService', () => { expect(service.getJobTemplateById('1')).toBe(jobTemplate); }); - it('should retire jobs when the block height changes', async () => { + it('should clear jobs when the block height changes', async () => { const firstTemplate = await firstValueFrom(service.newMiningJob$); service.addJob({ jobId: 'old-job', creation: Date.now() } as any); @@ -57,27 +57,18 @@ describe('StratumV1JobsService', () => { const jobTemplate = await nextTemplate; expect(jobTemplate.blockData.clearJobs).toBe(true); - expect(service.getJobById('old-job')).toEqual(expect.objectContaining({ - jobId: 'old-job', - retiredAt: Date.now() - })); - expect(service.getJobTemplateById(firstTemplate.blockData.id).blockData.retiredAt).toBe(Date.now()); + expect(service.getJobById('old-job')).toBeUndefined(); + expect(service.getJobTemplateById(firstTemplate.blockData.id)).toBeUndefined(); expect(service.getJobTemplateById(jobTemplate.blockData.id)).toBe(jobTemplate); }); - it('should age retired jobs and templates after the retention window', async () => { - const firstTemplate = await firstValueFrom(service.newMiningJob$); + it('should age old jobs and templates after five minutes', async () => { + await firstValueFrom(service.newMiningJob$); const oldCreation = Date.now() - (1000 * 60 * 11); - const retiredAt = Date.now() - (1000 * 60 * 11); - firstTemplate.blockData.retiredAt = retiredAt; - for (let i = 4; i >= 0; i--) { - service.jobs[`old-job-${i}`] = { jobId: `old-job-${i}`, creation: oldCreation - i, retiredAt } as any; - (service as any).trackJob(`old-job-${i}`); - service.blocks[`old-template-${i}`] = { - blockData: { creation: oldCreation - i, retiredAt } - } as any; - (service as any).trackBlock(`old-template-${i}`); - } + service.jobs['old-job'] = { jobId: 'old-job', creation: oldCreation } as any; + service.blocks['old-template'] = { + blockData: { creation: oldCreation } + } as any; bitcoinRpcService.miningInfo.blocks = MockRecording1.BLOCK_TEMPLATE.height; const nextTemplate = firstValueFrom(service.newMiningJob$.pipe(skip(1))); @@ -85,22 +76,11 @@ describe('StratumV1JobsService', () => { const jobTemplate = await nextTemplate; expect(jobTemplate.blockData.clearJobs).toBe(false); - expect(service.getJobById('old-job-4')).toBeUndefined(); - expect(service.getJobTemplateById('old-template-4')).toBeUndefined(); + expect(service.getJobById('old-job')).toBeUndefined(); + expect(service.getJobTemplateById('old-template')).toBeUndefined(); expect(service.getJobTemplateById(jobTemplate.blockData.id)).toBe(jobTemplate); }); - it('should classify retired jobs inside and outside the stale grace window', () => { - const job = { jobId: '1', creation: Date.now(), retiredAt: Date.now() - 1000 } as any; - - expect(service.classifyJobForShare(job, Date.now())).toBe('stale-creditable'); - - job.retiredAt = Date.now() - 6000; - - expect(service.classifyJobForShare(job, Date.now())).toBe('stale-rejected'); - expect(service.classifyJobForShare({ jobId: '2', creation: Date.now() } as any, Date.now())).toBe('active'); - }); - it('should increment job ids when jobs are added', () => { expect(service.getNextId()).toBe('1'); diff --git a/src/services/stratum-v1-jobs.service.ts b/src/services/stratum-v1-jobs.service.ts index b073d0d..61b9634 100644 --- a/src/services/stratum-v1-jobs.service.ts +++ b/src/services/stratum-v1-jobs.service.ts @@ -18,14 +18,9 @@ export interface IJobTemplate { networkDifficulty: number; height: number; clearJobs: boolean; - retiredAt?: number; }; } -const STALE_GRACE_MS = parseInt(process.env.STRATUM_STALE_GRACE_MS) || 5000; -const MIN_RETAINED = 3; -export { STALE_GRACE_MS }; - @Injectable() export class StratumV1JobsService { @@ -36,11 +31,6 @@ export class StratumV1JobsService { public blocks: { [id: number]: IJobTemplate } = {}; private lastBlockHeight = 0; - private jobRetentionMs = parseInt(process.env.JOB_RETENTION_MS) || 600000; - private jobOrder: string[] = []; - private blockOrder: string[] = []; - private jobOrderSet = new Set(); - private blockOrderSet = new Set(); constructor( private readonly bitcoinRpcService: BitcoinRpcService @@ -121,7 +111,6 @@ export class StratumV1JobsService { tap((data) => { this.cleanup(data.blockData.clearJobs); this.blocks[data.blockData.id] = data; - this.trackBlock(data.blockData.id); }), shareReplay({ refCount: true, bufferSize: 1 }) ) @@ -153,78 +142,32 @@ export class StratumV1JobsService { public cleanup(clearJobs: boolean, now: number = Date.now()) { if (clearJobs) { - for (const id of this.blockOrder) { - const block = this.blocks[id]; - if (block != null && block.blockData.retiredAt === undefined) { - block.blockData.retiredAt = now; - } - } - for (const jobId of this.jobOrder) { - const job = this.jobs[jobId]; - if (job != null && job.retiredAt === undefined) { - job.retiredAt = now; - } + this.blocks = {}; + this.jobs = {}; + return; + } + + let templatesDeleted = 0; + let jobsDeleted = 0; + + for (const templateId in this.blocks) { + if (now - this.blocks[templateId].blockData.creation > (1000 * 60 * 5)) { + delete this.blocks[templateId]; + templatesDeleted++; } } - this.ageEntries( - this.blocks, - this.blockOrder, - this.blockOrderSet, - now, - entry => entry.blockData.creation, - entry => entry.blockData.retiredAt, - ); - this.ageEntries( - this.jobs, - this.jobOrder, - this.jobOrderSet, - now, - entry => entry.creation, - entry => entry.retiredAt, - ); - } - - private ageEntries( - map: Record, - order: string[], - orderSet: Set, - now: number, - getCreation: (entry: T) => number, - getRetiredAt: (entry: T) => number | undefined, - ): void { - while (order.length > MIN_RETAINED) { - const id = order[0]; - const entry = map[id]; - if (entry == null) { - order.shift(); - orderSet.delete(id); - continue; + for (const jobId in this.jobs) { + if (now - this.jobs[jobId].creation > (1000 * 60 * 5)) { + delete this.jobs[jobId]; + jobsDeleted++; } - - const retiredAt = getRetiredAt(entry); - - if (retiredAt !== undefined && now - retiredAt > this.jobRetentionMs) { - delete map[id]; - order.shift(); - orderSet.delete(id); - continue; - } - - if (retiredAt === undefined && now - getCreation(entry) > this.jobRetentionMs * 2) { - delete map[id]; - order.shift(); - orderSet.delete(id); - continue; - } - - break; } + //console.log(`Deleted ${templatesDeleted} templates and ${jobsDeleted} jobs.`) } public addJob(job: MiningJob) { this.jobs[job.jobId] = job; - this.trackJob(job.jobId); this.latestJobId++; } @@ -232,13 +175,6 @@ export class StratumV1JobsService { return this.jobs[jobId]; } - public classifyJobForShare(job: MiningJob, now: number = Date.now()): 'active' | 'stale-creditable' | 'stale-rejected' { - if (job.retiredAt === undefined) { - return 'active'; - } - return (now - job.retiredAt) <= STALE_GRACE_MS ? 'stale-creditable' : 'stale-rejected'; - } - public getNextTemplateId() { return this.latestJobTemplateId.toString(16); } @@ -246,20 +182,4 @@ export class StratumV1JobsService { return this.latestJobId.toString(16); } - private trackJob(jobId: string): void { - if (this.jobOrderSet.has(jobId)) { - return; - } - this.jobOrderSet.add(jobId); - this.jobOrder.push(jobId); - } - - private trackBlock(blockId: string): void { - if (this.blockOrderSet.has(blockId)) { - return; - } - this.blockOrderSet.add(blockId); - this.blockOrder.push(blockId); - } - }