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 26ad524605
commit 91633375a3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 65 additions and 8 deletions

View file

@ -1,6 +1,8 @@
package org.bitcoins.node package org.bitcoins.node
import akka.actor.ActorSystem
import org.bitcoins.core.crypto.DoubleSha256DigestBE import org.bitcoins.core.crypto.DoubleSha256DigestBE
import org.bitcoins.rpc.client.common.BitcoindRpcClient
import org.bitcoins.rpc.util.RpcUtil import org.bitcoins.rpc.util.RpcUtil
import org.bitcoins.testkit.node.NodeUnitTest import org.bitcoins.testkit.node.NodeUnitTest
import org.bitcoins.testkit.node.fixture.SpvNodeConnectedWithBitcoind import org.bitcoins.testkit.node.fixture.SpvNodeConnectedWithBitcoind
@ -9,6 +11,8 @@ import org.scalatest.FutureOutcome
import scala.concurrent.Future import scala.concurrent.Future
import org.bitcoins.testkit.node.NodeTestUtil import org.bitcoins.testkit.node.NodeTestUtil
import scala.concurrent.duration.DurationInt
class SpvNodeTest extends NodeUnitTest { class SpvNodeTest extends NodeUnitTest {
override type FixtureParam = SpvNodeConnectedWithBitcoind override type FixtureParam = SpvNodeConnectedWithBitcoind
@ -31,7 +35,7 @@ class SpvNodeTest extends NodeUnitTest {
bitcoind.generate(1).map(_.head) 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 { val spvSyncF = for {
_ <- hashF _ <- hashF
sync <- spvNode.sync() sync <- spvNode.sync()
@ -42,6 +46,62 @@ class SpvNodeTest extends NodeUnitTest {
.awaitSync(spvNode, bitcoind) .awaitSync(spvNode, bitcoind)
.map(_ => succeed) .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 package org.bitcoins.node.networking
import akka.actor.{Actor, ActorRef, ActorRefFactory, Props} import akka.actor.{Actor, ActorRef, ActorRefFactory, Props}
import akka.event.LoggingReceive
import akka.io.{IO, Tcp} import akka.io.{IO, Tcp}
import akka.util.ByteString import akka.util.ByteString
import org.bitcoins.core.config.NetworkParameters import org.bitcoins.core.config.NetworkParameters
@ -71,7 +70,7 @@ sealed abstract class ClientActor extends Actor with BitcoinSLogger {
*/ */
private def awaitNetworkRequest( private def awaitNetworkRequest(
peer: ActorRef, peer: ActorRef,
unalignedBytes: ByteVector): Receive = LoggingReceive { unalignedBytes: ByteVector): Receive = {
case message: NetworkMessage => sendNetworkMessage(message, peer) case message: NetworkMessage => sendNetworkMessage(message, peer)
case payload: NetworkPayload => case payload: NetworkPayload =>
val networkMsg = NetworkMessage(network, payload) 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 */ /** 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 => case cmd: Tcp.Command =>
//we only accept a Tcp.Connect/Tcp.Connected //we only accept a Tcp.Connect/Tcp.Connected
//message to the default receive on this actor //message to the default receive on this actor

View file

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