Make ChainApi.processHeaders() return a failed future in the case we … (#2436)

* Rename NodeUnitTest.confg -> NodeUnitTest.getFreshConfig()

* Rename CachedBitcoinSAppConfig.config -> CachedBitcoinSAppConfig.cachedConfig

* Make CachedChainAppConfig extend CachedBitcoinSAppConfig

* Make ChainApi.processHeaders() return a failed future in the case we have no valid headers

* Run scalafmt

* Fix test case to check if promise is completed yet

* WIP: Get something working that isn't network specific

Start putting things back in place

Add comment

Revert logback file

Remove BitcoinSLogger object

* Fix unused import

* Get rid of annoying diff

* Fix spacing nit
This commit is contained in:
Chris Stewart 2021-01-12 06:11:19 -06:00 committed by GitHub
parent 93dae6c239
commit 4e285e6746
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 27 deletions

View file

@ -94,6 +94,16 @@ class ChainHandlerTest extends ChainDbUnitTest {
} yield succeed
}
it must "fail if we give a header that cannot be connected to anything" in {
chainHandler: ChainHandler =>
val newHeader = BlockHeaderHelper.badPrevHash
recoverToSucceededIf[RuntimeException] {
for {
result <- chainHandler.processHeader(newHeader)
} yield result
}
}
// B
// C -> D
it must "handle a very basic reorg where one chain is one block behind the best chain" in {

View file

@ -135,35 +135,44 @@ class ChainHandler(
successfullyValidatedHeaders.distinct
}
val chains = blockchainUpdates.map(_.blockchain)
if (headersToBeCreated.isEmpty) {
//this means we are given zero headers that were valid.
//Return a failure in this case to avoid issue 2365
//https://github.com/bitcoin-s/bitcoin-s/issues/2365
Future.failed(new RuntimeException(
s"Failed to connect any headers to our internal chain state, failures=$blockchainUpdates"))
} else {
val chains = blockchainUpdates.map(_.blockchain)
val createdF = blockHeaderDAO.createAll(headersToBeCreated)
val createdF = blockHeaderDAO.createAll(headersToBeCreated)
val newChainHandler = ChainHandler(blockHeaderDAO,
filterHeaderDAO,
filterDAO,
blockFilterCheckpoints =
blockFilterCheckpoints)
val newChainHandler = ChainHandler(blockHeaderDAO,
filterHeaderDAO,
filterDAO,
blockFilterCheckpoints =
blockFilterCheckpoints)
createdF.map { headers =>
if (chainConfig.chainCallbacks.onBlockHeaderConnected.nonEmpty) {
headersToBeCreated.reverseIterator.foldLeft(FutureUtil.unit) {
(acc, header) =>
for {
_ <- acc
_ <-
chainConfig.chainCallbacks
.executeOnBlockHeaderConnectedCallbacks(logger,
header.height,
header.blockHeader)
} yield ()
createdF.map { headers =>
if (chainConfig.chainCallbacks.onBlockHeaderConnected.nonEmpty) {
headersToBeCreated.reverseIterator.foldLeft(FutureUtil.unit) {
(acc, header) =>
for {
_ <- acc
_ <-
chainConfig.chainCallbacks
.executeOnBlockHeaderConnectedCallbacks(
logger,
header.height,
header.blockHeader)
} yield ()
}
}
chains.foreach { c =>
logger.info(
s"Processed headers from height=${c.height - headers.length} to ${c.height}. Best hash=${c.tip.hashBE.hex}")
}
newChainHandler
}
chains.foreach { c =>
logger.info(
s"Processed headers from height=${c.height - headers.length} to ${c.height}. Best hash=${c.tip.hashBE.hex}")
}
newChainHandler
}
}
}

View file

@ -19,7 +19,9 @@ import scala.concurrent.Future
trait ChainApi extends ChainQueryApi {
/**
* Adds a block header to our chain project
* Adds a block header to our chain project.
* This will return a failed future when the
* given header is invalid.
* @param header
* @return
*/
@ -29,7 +31,9 @@ trait ChainApi extends ChainQueryApi {
/** Process all of the given headers and returns a new [[ChainApi chain api]]
* that contains these headers. This method processes headers in the order
* that they are given. If the headers are out of order, this method will fail
* that they are given. If the headers are out of order, this method will fail.
*
* This method will also fail when there are zero headers given that are valid.
* @param headers
* @return
*/

View file

@ -105,7 +105,9 @@ class DataMessageHandlerTest extends NodeUnitTest {
val callback: OnBlockHeadersReceived = (headers: Vector[BlockHeader]) => {
Future {
resultP.success(headers)
if (!resultP.isCompleted) {
resultP.success(headers)
}
()
}
}