@@ -53,7 +53,8 @@ public EthereumJobManager(
5353 private EthashFull ethash ;
5454 private readonly IMasterClock clock ;
5555 private readonly IExtraNonceProvider extraNonceProvider ;
56-
56+ private const int MaxBlockBacklog = 8 ;
57+ protected readonly Dictionary < string , EthereumJob > validJobs = new ( ) ;
5758 private EthereumPoolConfigExtra extraPoolConfig ;
5859
5960 protected async Task < bool > UpdateJob ( CancellationToken ct , string via = null )
@@ -93,7 +94,24 @@ protected bool UpdateJob(EthereumBlockTemplate blockTemplate, string via = null)
9394 {
9495 messageBus . NotifyChainHeight ( poolConfig . Id , blockTemplate . Height , poolConfig . Template ) ;
9596
96- job = new EthereumJob ( NextJobId ( "x8" ) , blockTemplate , logger ) ;
97+ var jobId = NextJobId ( "x8" ) ;
98+
99+ // update template
100+ job = new EthereumJob ( jobId , blockTemplate , logger ) ;
101+
102+ lock ( jobLock )
103+ {
104+ // add jobs
105+ validJobs [ jobId ] = job ;
106+
107+ // remove old ones
108+ var obsoleteKeys = validJobs . Keys
109+ . Where ( key => validJobs [ key ] . BlockTemplate . Height < job . BlockTemplate . Height - MaxBlockBacklog ) . ToArray ( ) ;
110+
111+ foreach ( var key in obsoleteKeys )
112+ validJobs . Remove ( key ) ;
113+ }
114+
97115 currentJob = job ;
98116
99117 logger . Info ( ( ) => $ "New work at height { currentJob . BlockTemplate . Height } and header { currentJob . BlockTemplate . Header } via [{ ( via ?? "Unknown" ) } ]") ;
@@ -355,8 +373,20 @@ public async Task<Share> SubmitShareV1Async(StratumConnection worker, string[] r
355373
356374 var context = worker . ContextAs < EthereumWorkerContext > ( ) ;
357375 var nonce = request [ 0 ] ;
376+ var header = request [ 1 ] ;
377+
378+ EthereumJob job ;
358379
359- return await SubmitShareAsync ( worker , context , workerName , currentJob , nonce . StripHexPrefix ( ) , ct ) ;
380+ // stale?
381+ lock ( jobLock )
382+ {
383+ job = validJobs . Values . FirstOrDefault ( x => x . BlockTemplate . Header . Equals ( header ) ) ;
384+
385+ if ( job == null )
386+ throw new StratumException ( StratumError . MinusOne , "stale share" ) ;
387+ }
388+
389+ return await SubmitShareAsync ( worker , context , workerName , job , nonce . StripHexPrefix ( ) , ct ) ;
360390 }
361391
362392 public async Task < Share > SubmitShareV2Async ( StratumConnection worker , string [ ] request , CancellationToken ct )
@@ -368,14 +398,20 @@ public async Task<Share> SubmitShareV2Async(StratumConnection worker, string[] r
368398 var jobId = request [ 1 ] ;
369399 var nonce = request [ 2 ] ;
370400
401+ EthereumJob job ;
402+
371403 // stale?
372- if ( jobId != currentJob . Id )
373- throw new StratumException ( StratumError . MinusOne , "stale share" ) ;
404+ lock ( jobLock )
405+ {
406+ // look up job by id
407+ if ( ! validJobs . TryGetValue ( jobId , out job ) )
408+ throw new StratumException ( StratumError . MinusOne , "stale share" ) ;
409+ }
374410
375411 // assemble full-nonce
376412 var fullNonceHex = context . ExtraNonce1 + nonce ;
377413
378- return await SubmitShareAsync ( worker , context , context . Worker , currentJob , fullNonceHex , ct ) ;
414+ return await SubmitShareAsync ( worker , context , context . Worker , job , fullNonceHex , ct ) ;
379415 }
380416
381417 private async Task < Share > SubmitShareAsync ( StratumConnection worker ,
0 commit comments