@@ -30,8 +30,9 @@ use std::kinds::marker;
30
30
31
31
use blockdata:: block:: { Block , BlockHeader } ;
32
32
use blockdata:: transaction:: Transaction ;
33
- use blockdata:: constants:: { DIFFCHANGE_INTERVAL , DIFFCHANGE_TIMESPAN , max_target, genesis_block} ;
34
- use network:: constants:: Network ;
33
+ use blockdata:: constants:: { DIFFCHANGE_INTERVAL , DIFFCHANGE_TIMESPAN ,
34
+ TARGET_BLOCK_SPACING , max_target, genesis_block} ;
35
+ use network:: constants:: { Network , BitcoinTestnet } ;
35
36
use network:: serialize:: { Serializable , SerializeIter } ;
36
37
use util:: BitArray ;
37
38
use util:: error:: { BitcoinResult , BlockNotFound , DuplicateHash , PrevHashNotFound } ;
@@ -491,9 +492,25 @@ impl Blockchain {
491
492
if target > max { target = max } ;
492
493
// Compactify (make expressible in the 8+24 nBits float format
493
494
satoshi_the_precision ( & target)
494
- } else {
495
+ // On non-diffchange blocks, Testnet has a rule that any 20-minute-long
496
+ // block intervals result the difficulty
497
+ } else if self . network == BitcoinTestnet &&
498
+ block. header . time > prev. block . header . time + 2 * TARGET_BLOCK_SPACING {
499
+ max_target ( self . network )
500
+ // On the other hand, if we are in Testnet and the block interval is less
501
+ // than 20 minutes, we need to scan backward to find a block for which the
502
+ // previous rule did not apply, to find the "real" difficulty.
503
+ } else if self . network == BitcoinTestnet {
504
+ // Scan back DIFFCHANGE_INTERVAL blocks
505
+ let mut scan = prev. clone ( ) ;
506
+ while scan. height % DIFFCHANGE_INTERVAL != 0 &&
507
+ scan. required_difficulty == max_target ( self . network ) {
508
+ scan = scan. prev ( & self . tree ) . unwrap ( ) ;
509
+ }
510
+ scan. required_difficulty
495
511
// Otherwise just use the last block's difficulty
496
- prev. required_difficulty
512
+ } else {
513
+ prev. required_difficulty
497
514
} ;
498
515
// Create node
499
516
let ret = Rc :: new ( BlockchainNode {
0 commit comments