Attempt to sync with sendheaders (#537)

* Attempt to sync with sendheaders

Fix sync with headers by generating one block in regtest to get out of IBD

Fix comment

Add more comments

Add missing actor system import

more clean up

* refactor test case to avoid sleeping the thread
This commit is contained in:
Chris Stewart 2019-06-20 05:58:25 -05:00 committed by GitHub
parent 67fb821b00
commit a716d374ca
3 changed files with 65 additions and 8 deletions

View File

@ -1,6 +1,8 @@
package org.bitcoins.node
import akka.actor.ActorSystem
import org.bitcoins.core.crypto.DoubleSha256DigestBE
import org.bitcoins.rpc.client.common.BitcoindRpcClient
import org.bitcoins.rpc.util.RpcUtil
import org.bitcoins.testkit.node.NodeUnitTest
import org.bitcoins.testkit.node.fixture.SpvNodeConnectedWithBitcoind
@ -9,6 +11,8 @@ import org.scalatest.FutureOutcome
import scala.concurrent.Future
import org.bitcoins.testkit.node.NodeTestUtil
import scala.concurrent.duration.DurationInt
class SpvNodeTest extends NodeUnitTest {
override type FixtureParam = SpvNodeConnectedWithBitcoind
@ -31,7 +35,7 @@ class SpvNodeTest extends NodeUnitTest {
bitcoind.generate(1).map(_.head)
}
//check we have that hash inside of our chain project!
//sync our spv node expecting to get that generated hash
val spvSyncF = for {
_ <- hashF
sync <- spvNode.sync()
@ -42,6 +46,62 @@ class SpvNodeTest extends NodeUnitTest {
.awaitSync(spvNode, bitcoind)
.map(_ => succeed)
}
}
it must "stay in sync with a bitcoind instance" in {
spvNodeConnectedWithBitcoind: SpvNodeConnectedWithBitcoind =>
val spvNode = spvNodeConnectedWithBitcoind.spvNode
val bitcoind = spvNodeConnectedWithBitcoind.bitcoind
//we need to generate 1 block for bitcoind to consider
//itself out of IBD. bitcoind will not sendheaders
//when it believes itself, or it's peer is in IBD
val gen1F = bitcoind.generate(1)
//this needs to be called to get our peer to send us headers
//as they happen with the 'sendheaders' message
//both our spv node and our bitcoind node _should_ both be at the genesis block (regtest)
//at this point so no actual syncing is happening
val initSyncF = gen1F.flatMap(_ => spvNode.sync())
//start generating a block every 10 seconds with bitcoind
//this should result in 5 blocks
val startGenF = initSyncF.map { _ =>
//generate a block every 5 seconds
//until we have generated 5 total blocks
genBlockInterval(bitcoind)
}
startGenF.flatMap { _ =>
//we should expect 5 headers have been announced to us via
//the send headers message.
val has6BlocksF = RpcUtil.retryUntilSatisfiedF(
conditionF = () => spvNode.chainApi.getBlockCount.map(_ == 6),
duration = 1.seconds)
has6BlocksF.map(_ => succeed)
}
}
/** Helper method to generate blocks every interval */
private def genBlockInterval(bitcoind: BitcoindRpcClient)(
implicit system: ActorSystem): Unit = {
var counter = 0
val desiredBlocks = 5
val interval = 500.millis
val genBlock = new Runnable {
override def run(): Unit = {
if (counter < desiredBlocks) {
bitcoind.generate(1)
counter = counter + 1
} else {
//do nothing
}
}
}
system.scheduler.schedule(interval, interval, genBlock)
}
}

View File

@ -1,7 +1,6 @@
package org.bitcoins.node.networking
import akka.actor.{Actor, ActorRef, ActorRefFactory, Props}
import akka.event.LoggingReceive
import akka.io.{IO, Tcp}
import akka.util.ByteString
import org.bitcoins.core.config.NetworkParameters
@ -71,7 +70,7 @@ sealed abstract class ClientActor extends Actor with BitcoinSLogger {
*/
private def awaitNetworkRequest(
peer: ActorRef,
unalignedBytes: ByteVector): Receive = LoggingReceive {
unalignedBytes: ByteVector): Receive = {
case message: NetworkMessage => sendNetworkMessage(message, peer)
case payload: NetworkPayload =>
val networkMsg = NetworkMessage(network, payload)
@ -83,7 +82,7 @@ sealed abstract class ClientActor extends Actor with BitcoinSLogger {
}
/** This context is responsible for initializing a tcp connection with a peer on the bitcoin p2p network */
def receive = LoggingReceive {
def receive: Receive = {
case cmd: Tcp.Command =>
//we only accept a Tcp.Connect/Tcp.Connected
//message to the default receive on this actor

View File

@ -4,7 +4,6 @@ import java.net.InetSocketAddress
import akka.actor.ActorSystem
import org.bitcoins.core.config.NetworkParameters
import org.bitcoins.core.p2p.NetworkIpAddress
import org.bitcoins.core.util.BitcoinSLogger
import org.bitcoins.db.AppConfig
import org.bitcoins.node.SpvNode
@ -15,6 +14,8 @@ import org.bitcoins.node.networking.peer.{
PeerMessageSender
}
import org.bitcoins.rpc.client.common.BitcoindRpcClient
import org.bitcoins.testkit.BitcoinSAppConfig
import org.bitcoins.testkit.BitcoinSAppConfig._
import org.bitcoins.testkit.chain.ChainUnitTest
import org.bitcoins.testkit.fixtures.BitcoinSFixture
import org.bitcoins.testkit.node.fixture.SpvNodeConnectedWithBitcoind
@ -29,9 +30,6 @@ import org.scalatest.{
import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext, Future}
import org.bitcoins.testkit.BitcoinSAppConfig
import org.bitcoins.testkit.BitcoinSAppConfig._
trait NodeUnitTest
extends BitcoinSFixture
with MustMatchers