mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-13 19:37:30 +01:00
Implement missing branch on POW validation for testnet, implement Blo… (#652)
* Implement missing branch on POW validation for testnet, implement BlockHeaderDAO.find * implement second special case for if we are allowing min difficulty blocks, but are at a POW change interval. If we are at a POW change interval, we return that block * Address code review
This commit is contained in:
parent
e960422ff8
commit
2994e82d02
3 changed files with 50 additions and 9 deletions
|
@ -16,7 +16,7 @@ class BlockHeaderDAOTest extends ChainUnitTest {
|
|||
override def withFixture(test: OneArgAsyncTest): FutureOutcome =
|
||||
withBlockHeaderDAO(test)
|
||||
|
||||
override implicit val system: ActorSystem = ActorSystem("BlockHeaderDAOTest")
|
||||
implicit override val system: ActorSystem = ActorSystem("BlockHeaderDAOTest")
|
||||
|
||||
behavior of "BlockHeaderDAO"
|
||||
|
||||
|
@ -172,4 +172,20 @@ class BlockHeaderDAOTest extends ChainUnitTest {
|
|||
assert(headers == Seq(blockHeader, blockHeader1))
|
||||
}
|
||||
}
|
||||
|
||||
it must "find a header with height 1" in { blockHeaderDAO: BlockHeaderDAO =>
|
||||
val blockHeader = BlockHeaderHelper.buildNextHeader(genesisHeaderDb)
|
||||
val createdF = blockHeaderDAO.create(blockHeader)
|
||||
|
||||
val f: BlockHeaderDb => Boolean = { bh =>
|
||||
bh.height == 1
|
||||
}
|
||||
|
||||
val foundF = createdF.flatMap(created => blockHeaderDAO.find(f))
|
||||
|
||||
for {
|
||||
created <- createdF
|
||||
found <- foundF
|
||||
} yield assert(found.get == created)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ case class BlockHeaderDAO()(
|
|||
|
||||
/** Returns competing blockchains that are contained in our BlockHeaderDAO
|
||||
* Each chain returns the last [[org.bitcoins.core.protocol.blockchain.ChainParams.difficultyChangeInterval difficutly interval]]
|
||||
* as defined by the network we are on. For instance, on bitcoin mainnet this will be 2016 block headers.
|
||||
* block headers as defined by the network we are on. For instance, on bitcoin mainnet this will be 2016 block headers.
|
||||
* If no competing tips are found, we only return one [[Blockchain blockchain]], else we
|
||||
* return n chains for the number of competing [[chainTips tips]] we have
|
||||
* @see [[Blockchain]]
|
||||
|
@ -194,4 +194,22 @@ case class BlockHeaderDAO()(
|
|||
Future.sequence(nestedFuture)
|
||||
}
|
||||
}
|
||||
|
||||
/** Finds a [[org.bitcoins.chain.models.BlockHeaderDb block header]] that satisfies the given predicate, else returns None */
|
||||
def find(f: BlockHeaderDb => Boolean)(
|
||||
implicit ec: ExecutionContext): Future[Option[BlockHeaderDb]] = {
|
||||
val chainsF = getBlockchains()
|
||||
chainsF.map { chains =>
|
||||
val headersOpt: Vector[Option[BlockHeaderDb]] =
|
||||
chains.map(_.headers.find(f))
|
||||
//if there are multiple, we just choose the first one for now
|
||||
val result = headersOpt.filter(_.isDefined).flatten
|
||||
if (result.length > 1) {
|
||||
logger.warn(
|
||||
s"Discarding other matching headers for predicate headers=${result
|
||||
.map(_.hashBE.hex)}")
|
||||
}
|
||||
result.headOption
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,13 +40,19 @@ sealed abstract class Pow extends BitcoinSLogger {
|
|||
Future.successful(powLimit)
|
||||
} else {
|
||||
// Return the last non-special-min-difficulty-rules-block
|
||||
//while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit)
|
||||
// pindex = pindex->pprev;
|
||||
val nonMinDiffF = blockHeaderDAO.find { h =>
|
||||
h.nBits != powLimit || h.height % chainParams.difficultyChangeInterval == 0
|
||||
}
|
||||
|
||||
// this is complex to implement and requires walking the
|
||||
//chain until we find a block header that does not have
|
||||
//the minimum difficulty rule on testnet
|
||||
|
||||
//TODO: This is not correctly implemented, come back and fix this when BlockHeaderDAO has a predicate to satisfy
|
||||
Future.successful(powLimit)
|
||||
nonMinDiffF.map {
|
||||
case Some(bh) => bh.nBits
|
||||
case None =>
|
||||
//if we can't find a non min diffulty block, let's just fail
|
||||
throw new RuntimeException(
|
||||
s"Could not find non mindiffulty block in chain! hash=${tip.hashBE.hex} height=${currentHeight}")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Future.successful(tip.blockHeader.nBits)
|
||||
|
@ -54,7 +60,8 @@ sealed abstract class Pow extends BitcoinSLogger {
|
|||
} else {
|
||||
val firstHeight = currentHeight - (chainParams.difficultyChangeInterval - 1)
|
||||
|
||||
require(firstHeight >= 0, s"We must have our first height be postive, got=${firstHeight}")
|
||||
require(firstHeight >= 0,
|
||||
s"We must have our first height be postive, got=${firstHeight}")
|
||||
|
||||
val firstBlockAtIntervalF: Future[Option[BlockHeaderDb]] = {
|
||||
blockHeaderDAO.getAncestorAtHeight(tip, firstHeight)
|
||||
|
|
Loading…
Add table
Reference in a new issue