Delete files from the last iteration of our spv node (#656)

This commit is contained in:
Chris Stewart 2019-07-22 08:39:12 -05:00 committed by GitHub
parent 2994e82d02
commit aef741adf7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 0 additions and 699 deletions

View file

@ -1,61 +0,0 @@
/*
package org.bitcoins.node.networking
import akka.actor.ActorSystem
import akka.testkit.{ImplicitSender, TestActorRef, TestKit, TestProbe}
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.protocol.blockchain.BlockHeader
import org.bitcoins.core.util.{BitcoinSLogger, BitcoinSUtil}
import org.bitcoins.node.db.UnitTestDbConfig
import org.bitcoins.core.p2p.BlockMessage
import org.bitcoins.core.p2p.BlockMessage
import org.bitcoins.node.util.TestUtil
import org.scalatest.{BeforeAndAfter, BeforeAndAfterAll, FlatSpecLike, MustMatchers}
import scala.concurrent.duration.DurationInt
/**
* Created by chris on 7/10/16.
*/
class BlockActorTest
extends TestKit(ActorSystem("BlockActorTest"))
with FlatSpecLike
with MustMatchers
with ImplicitSender
with BeforeAndAfter
with BeforeAndAfterAll
with BitcoinSLogger {
def blockActor = {
val peerMsgHandler = TestUtil.peer(self)
TestActorRef(
props = BlockActor.props(peerMsgHandler = peerMsgHandler,
dbConfig = TestUtil.dbConfig),
supervisor = self
)
}
val blockHash = DoubleSha256Digest.fromHex(
BitcoinSUtil.flipEndianness(
"00000000b873e79784647a6c82962c70d228557d24a747ea4d1b8bbe878e1206"))
"BlockActor" must "be able to send a GetBlocksMessage then receive that block back" in {
blockActor ! blockHash
val blockMsg = expectMsgType[BlockMessage](10.seconds)
blockMsg.block.blockHeader.hash must be(blockHash)
}
it must "be able to request a block from it's block header" in {
val blockHeader = BlockHeader(
"0100000043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea330900000000bac8b0fa927c0ac8234287e33c5f74d38d354820e24756ad709d7038fc5f31f020e7494dffff001d03e4b672")
blockActor ! blockHeader
val blockMsg = expectMsgType[BlockMessage](10.seconds)
blockMsg.block.blockHeader.hash must be(blockHash)
}
override def afterAll = {
TestKit.shutdownActorSystem(system)
}
}
*/

View file

@ -1,118 +0,0 @@
/*
package org.bitcoins.node.networking
import akka.actor.ActorSystem
import akka.testkit.{ImplicitSender, TestActorRef, TestKit}
import org.bitcoins.core.crypto.{DoubleSha256Digest, Sha256Hash160Digest}
import org.bitcoins.core.number.{Int32, UInt32}
import org.bitcoins.core.protocol.P2PKHAddress
import org.bitcoins.core.protocol.blockchain.{BlockHeader, MerkleBlock, PartialMerkleTree}
import org.bitcoins.core.protocol.transaction.Transaction
import org.bitcoins.node.constant.Constants
import org.bitcoins.core.p2p.data.{Inventory, InventoryMessage, MerkleBlockMessage, TransactionMessage}
import org.bitcoins.core.p2p.{MsgBlock, MsgTx}
import org.bitcoins.node.constant.Constants
import org.bitcoins.node.db.UnitTestDbConfig
import org.bitcoins.core.p2p.data.{Inventory, InventoryMessage, MerkleBlockMessage, TransactionMessage}
import org.bitcoins.core.p2p.{MsgBlock, MsgTx}
import org.bitcoins.node.util.TestUtil
import org.scalatest._
import scodec.bits.BitVector
import scala.concurrent.duration.DurationInt
/**
* Created by chris on 9/1/16.
*/
class PaymentActorTest
extends TestKit(ActorSystem("PaymentActorTest"))
with ImplicitSender
with FlatSpecLike
with MustMatchers
with BeforeAndAfterAll {
val txId = DoubleSha256Digest.fromHex(
"0d507a29efb362ce93687f524e7e3a668689e335ba20374c93710efdf7597c5f")
val transaction = Transaction.fromHex(
"0100000001f78d02e5d2e37319a4cec31331babea9f0c6b9efb75060e27cf23997c6e560b3010000006a47304402207f6d19701c0e58bdedbc5073c17ac36e3493326c8c916db7dd224961fa8c8c9f02201ba78149c12a9754f7ceab1bcfe4c6afb8fb5ee38078f47065d316cddaa932b40121023de7008d781aa60ed8b0cdf92ece1d3e6eca2a0fd958d883114129a450ab05f2feffffff02bf9fb700000000001976a914a82d2cefa38fe32eb90c5d31d2063dde716c90df88ac009f2400000000001976a914415a05d63df2c212e1c750a70eba49d6d8af196d88accb210e00")
"PaymentActor" must "monitor an address, then send SuccessfulPayment or FailedPayment message if that address is not paid in the next block" in {
val paymentActor = paymentActorRef
val pubKeyHash =
Sha256Hash160Digest("415a05d63df2c212e1c750a70eba49d6d8af196d")
val addr = P2PKHAddress(pubKeyHash, Constants.networkParameters)
paymentActor ! addr
//TODO: Remove this thread.sleep call
//wait for connection to be made so we have the right context
Thread.sleep(3000)
//build an inventory message, then send it to the payment actor
val inventory = Inventory(MsgTx, txId)
val txIdInvMsg = InventoryMessage(Seq(inventory))
paymentActor ! txIdInvMsg
//now the payment actor switches to waiting for the full transaction
//so send the actor the full transaction
val txMsg = TransactionMessage(transaction)
paymentActor ! txMsg
//after seeing the tx message, our payment actor waits for a block to be announced on the network
val blockMsg = Inventory(
MsgBlock,
DoubleSha256Digest(
"62862488a791bf863ea840f8b9e4ded91ef5625e73b4f56940d6050000000000"))
val blockInvMsg = InventoryMessage(Seq(blockMsg))
paymentActor ! blockInvMsg
val partialMerkleTree = PartialMerkleTree(
transactionCount = UInt32(36),
hashes = List(
DoubleSha256Digest(
"27f706c39b2ea48d9316d85f513080da35329f3629ecf5f22869e191d38f3553"),
DoubleSha256Digest(
"0d507a29efb362ce93687f524e7e3a668689e335ba20374c93710efdf7597c5f"),
DoubleSha256Digest(
"b80117bee395e816a26e807dcb5858403142dcb8d5edfc3eaa6dde700a9198a2"),
DoubleSha256Digest(
"d297f7e4e712967f77f87c65fc698fc6ff8fc0fb056b07ebd459567d0a1c36f8"),
DoubleSha256Digest(
"114b915455ad5cb314e77c648e243f71d9b4895ab96c38cc3c7e27fd151d112b"),
DoubleSha256Digest(
"c83ce4bd870c2d791d73d1ce3fd7b96f61c94d3ce3af270af22938c0d15b683a"),
DoubleSha256Digest(
"ec89457fd619020e11727f01d7f5518b7c3114aaa70376611efe9efd41c5c099")
),
bits = BitVector.fromValidBin("11011111" + "00000000")
)
//after seeing a new block announcement on the network we request a merkle block message from the peer on the network
//this merkle block message is taken from a node on the network
val header = BlockHeader(
version = Int32(805306368),
previousBlockHash = DoubleSha256Digest(
"1d73fa2ffbdf79c2e78e3312066833c4a264a19b958faf450100000000000000"),
merkleRootHash = DoubleSha256Digest(
"9b47cf5d64aa52d7536e2b469891a79ea8488092dc3c2e0ed26dbe9b508cce16"),
time = UInt32(1472661981),
nBits = UInt32(486604799),
nonce = UInt32(4219144207L)
)
val merkleBlockMsg = MerkleBlockMessage(
merkleBlock = MerkleBlock(blockHeader = header,
txCount = UInt32(36),
partialMerkleTree = partialMerkleTree))
paymentActor ! merkleBlockMsg
expectMsgType[PaymentActor.SuccessfulPayment](10.seconds)
}
def paymentActorRef: TestActorRef[PaymentActor] = {
val peerMsgHandler = TestUtil.peer(self)
val paymentProps = PaymentActor.props(
peerMsgHandler = peerMsgHandler,
dbConfig = TestUtil.dbConfig)
TestActorRef(paymentProps, self)
}
}
*/

View file

@ -1,242 +0,0 @@
/*
package org.bitcoins.node.networking.sync
import akka.actor.{ActorSystem, PoisonPill}
import akka.testkit.{ImplicitSender, TestActorRef, TestKit, TestProbe}
import org.bitcoins.core.config.{MainNet, TestNet3}
import org.bitcoins.core.gen.BlockchainElementsGenerator
import org.bitcoins.core.protocol.blockchain.{
BlockHeader,
MainNetChainParams,
TestNetChainParams
}
import org.bitcoins.node.constant.{Constants, TestConstants}
import org.bitcoins.node.db.NodeDbManagement
import org.bitcoins.core.p2p.data.HeadersMessage
import org.bitcoins.node.models.BlockHeaderTable
import org.bitcoins.node.util.TestUtil
import org.scalatest.{
BeforeAndAfter,
BeforeAndAfterAll,
FlatSpecLike,
MustMatchers
}
import slick.jdbc.PostgresProfile.api._
import scala.concurrent.{Await, ExecutionContext}
import scala.concurrent.duration.DurationInt
/**
* Created by chris on 9/13/16.
*/
class BlockHeaderSyncActorTest
extends TestKit(ActorSystem("BlockHeaderSyncActorSpec"))
with ImplicitSender
with FlatSpecLike
with MustMatchers
with BeforeAndAfter
with BeforeAndAfterAll {
implicit val ec: ExecutionContext =
scala.concurrent.ExecutionContext.Implicits.global
val timeout = 10.seconds
val genesisBlockHash = TestNetChainParams.genesisBlock.blockHeader.hash
before {
Await.result(
NodeDbManagement.createBlockHeaderTable(TestConstants.dbConfig),
timeout)
}
"BlockHeaderSyncActor" must "send us an error if we receive two block headers that are not connected" in {
val (b, probe) = blockHeaderSyncActor
val blockHeader1 = BlockchainElementsGenerator.blockHeader.sample.get
val blockHeader2 = BlockchainElementsGenerator.blockHeader.sample.get
val headersMsg = HeadersMessage(List(blockHeader2))
b ! BlockHeaderSyncActor.StartHeaders(List(blockHeader1))
b ! headersMsg
val errorMsg =
probe.expectMsgType[BlockHeaderSyncActor.BlockHeadersDoNotConnect]
errorMsg must be(
BlockHeaderSyncActor.BlockHeadersDoNotConnect(blockHeader1.hash,
blockHeader2.hash))
b ! PoisonPill
}
it must "sync the first 5 headers on testnet" in {
//genesis block hash is 43497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea330900000000
val genesisBlockHash = TestNetChainParams.genesisBlock.blockHeader.hash
val firstBlockHash = TestUtil.firstFiveTestNetBlockHeaders.head.hash
val secondBlockHash = TestUtil.firstFiveTestNetBlockHeaders(1).hash
val thirdBlockHash = TestUtil.firstFiveTestNetBlockHeaders(2).hash
val fourthBlockHash = TestUtil.firstFiveTestNetBlockHeaders(3).hash
//5th block hash on testnet
val fifthBlockHash = TestUtil.firstFiveTestNetBlockHeaders.last.hash
val (b, probe) = blockHeaderSyncActor
b ! BlockHeaderSyncActor.GetHeaders(genesisBlockHash, fifthBlockHash)
val headersReply =
probe.expectMsgType[BlockHeaderSyncActor.GetHeadersReply](5.seconds)
//note the hash we started the sync at is not included in the expected blockheaders we recevie from our peer
val expectedHashes = List(firstBlockHash,
secondBlockHash,
thirdBlockHash,
fourthBlockHash,
fifthBlockHash)
val actualHashes = headersReply.headers.map(_.hash)
actualHashes.size must be(expectedHashes.size)
actualHashes must be(expectedHashes)
b ! PoisonPill
}
it must "fail to sync with a GetHeaders message if they are not connected" in {
val (b, probe) = blockHeaderSyncActor
val fifthBlockHash = TestUtil.firstFiveTestNetBlockHeaders.last.hash
b ! BlockHeaderSyncActor.GetHeaders(genesisBlockHash, fifthBlockHash)
val headers = TestUtil.firstFiveTestNetBlockHeaders
.slice(0, 2) ++ TestUtil.firstFiveTestNetBlockHeaders
.slice(3, TestUtil.firstFiveTestNetBlockHeaders.size)
val headersMsgMissingHeader = HeadersMessage(headers)
b ! headersMsgMissingHeader
probe.expectMsgType[BlockHeaderSyncActor.BlockHeadersDoNotConnect]
b ! PoisonPill
}
it must "stop syncing when we do not receive 2000 block headers from our peer" in {
val (b, probe) = blockHeaderSyncActor
b ! BlockHeaderSyncActor.StartHeaders(
List(TestNetChainParams.genesisBlock.blockHeader))
val headersMsg = HeadersMessage(TestUtil.firstFiveTestNetBlockHeaders)
b ! headersMsg
val reply =
probe.expectMsgType[BlockHeaderSyncActor.SuccessfulSyncReply](7.seconds)
reply.lastHeader must be(TestUtil.firstFiveTestNetBlockHeaders.last)
b ! PoisonPill
}
it must "start syncing at the genesis block when there are no headers in the database" in {
val (b, probe) = blockHeaderSyncActor
b ! BlockHeaderSyncActor.StartAtLastSavedHeader
val lastSavedHeaderReply =
probe.expectMsgType[BlockHeaderSyncActor.StartAtLastSavedHeaderReply]
lastSavedHeaderReply.header must be(
Constants.chainParams.genesisBlock.blockHeader)
b ! PoisonPill
}
it must "successfully check two block headers if their difficulty is the same" in {
val firstHeader = BlockchainElementsGenerator.blockHeader.sample.get
//note that this header properly references the previous header, but nBits are different
val secondHeader = BlockchainElementsGenerator
.blockHeader(firstHeader.hash, firstHeader.nBits)
.sample
.get
val checkHeaderResult =
BlockHeaderSyncActor.checkHeaders(Some(firstHeader),
List(secondHeader),
0,
MainNet)
checkHeaderResult.error.isDefined must be(false)
checkHeaderResult.headers must be(List(secondHeader))
}
it must "successfully check the header of ONLY the genesis block" in {
val genesisBlockHeader = MainNetChainParams.genesisBlock.blockHeader
val checkHeaderResult =
BlockHeaderSyncActor.checkHeaders(None,
List(genesisBlockHeader),
0,
MainNet)
checkHeaderResult.error.isDefined must be(false)
checkHeaderResult.headers must be(List(genesisBlockHeader))
}
it must "successfully check a sequence of headers if their is a difficulty change on the 2016 block" in {
val firstHeaders = genValidHeaderChain(2015)
val lastHeader =
BlockchainElementsGenerator.blockHeader(firstHeaders.last.hash).sample.get
val headers = firstHeaders ++ List(lastHeader)
val checkHeaderResult =
BlockHeaderSyncActor.checkHeaders(None, headers, 0, MainNet)
checkHeaderResult.error must be(None)
checkHeaderResult.headers must be(headers)
}
it must "fail a checkHeader on a sequence of headers if their is a difficulty change on the 2015 or 2017 block" in {
val firstHeaders = genValidHeaderChain(2014)
val lastHeader =
BlockchainElementsGenerator.blockHeader(firstHeaders.last.hash).sample.get
val headers = firstHeaders ++ List(lastHeader)
val checkHeaderResult =
BlockHeaderSyncActor.checkHeaders(None, headers, 0, MainNet)
checkHeaderResult.error.isDefined must be(true)
checkHeaderResult.headers must be(headers)
val firstHeaders2 =
BlockchainElementsGenerator.validHeaderChain(2016).sample.get
val lastHeader2 = BlockchainElementsGenerator
.blockHeader(firstHeaders2.last.hash)
.sample
.get
val headers2 = firstHeaders ++ List(lastHeader2)
val checkHeaderResult2 =
BlockHeaderSyncActor.checkHeaders(None, headers2, 0, MainNet)
checkHeaderResult2.error.isDefined must be(true)
checkHeaderResult2.headers must be(headers2)
}
it must "fail to check two block headers if the network difficulty isn't correct" in {
val firstHeader = BlockchainElementsGenerator.blockHeader.sample.get
//note that this header properly references the previous header, but nBits are different
val secondHeader =
BlockchainElementsGenerator.blockHeader(firstHeader.hash).sample.get
val checkHeaderResult =
BlockHeaderSyncActor.checkHeaders(Some(firstHeader),
List(secondHeader),
0,
MainNet)
val errorMsg = checkHeaderResult.error.get
.asInstanceOf[BlockHeaderSyncActor.BlockHeaderDifficultyFailure]
errorMsg.previousBlockHeader must be(firstHeader)
errorMsg.blockHeader must be(secondHeader)
}
/** The [[TestActorRef]] for a [[BlockHeaderSyncActor]] we use for testing */
private def blockHeaderSyncActor: (
TestActorRef[BlockHeaderSyncActor],
TestProbe) = {
val probe = TestProbe()
val peerMsgHandler = TestUtil.peer(self)
val syncActorProps = BlockHeaderSyncActor.props(
peerMsgHandler = peerMsgHandler,
dbConfig = TestConstants.dbConfig,
networkParameters = TestNet3)
val blockHeaderSyncActor: TestActorRef[BlockHeaderSyncActor] = {
TestActorRef(syncActorProps, probe.ref)
}
(blockHeaderSyncActor, probe)
}
private def genValidHeaderChain(num: Long): List[BlockHeader] = {
BlockchainElementsGenerator.validHeaderChain(num).sample.get.toList
}
after {
Await.result(NodeDbManagement.dropBlockHeaderTable(TestConstants.dbConfig),
timeout)
}
override def afterAll = {
TestKit.shutdownActorSystem(system)
}
}
*/

View file

@ -1,51 +0,0 @@
package org.bitcoins.node.networking
import akka.actor.{Actor, ActorContext, ActorRef, Props}
import akka.event.LoggingReceive
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.p2p.NetworkMessage
import org.bitcoins.core.protocol.blockchain.BlockHeader
import org.bitcoins.core.util.BitcoinSLogger
import org.bitcoins.core.p2p._
/**
* Created by chris on 7/10/16.
*/
sealed abstract class BlockActor extends Actor with BitcoinSLogger {
def peerMsgHandler: ActorRef
def receive: Receive = LoggingReceive {
case hash: DoubleSha256Digest =>
val inv = Inventory(TypeIdentifier.MsgBlock, hash)
val getDataMessage = GetDataMessage(inv)
val networkMessage =
NetworkMessage(network = ???, getDataMessage)
peerMsgHandler ! networkMessage
context.become(awaitBlockMsg)
case blockHeader: BlockHeader =>
self.forward(blockHeader.hash)
}
def awaitBlockMsg: Receive = LoggingReceive {
case blockMsg: BlockMessage =>
context.parent ! blockMsg
context.stop(self)
}
}
object BlockActor {
private case class BlockActorImpl(
peerMsgHandler: ActorRef
) extends BlockActor
def props(peerMsgHandler: ActorRef): Props = {
Props(classOf[BlockActorImpl], peerMsgHandler)
}
def apply(peerMsgHandler: ActorRef)(
implicit context: ActorContext): ActorRef = {
context.actorOf(props(peerMsgHandler))
}
}

View file

@ -1,175 +0,0 @@
package org.bitcoins.node.networking
import akka.actor.{Actor, ActorRef, ActorRefFactory, Props}
import akka.event.LoggingReceive
import akka.io.Tcp
import org.bitcoins.core.bloom.{BloomFilter, BloomUpdateNone}
import org.bitcoins.core.crypto.{DoubleSha256Digest, Sha256Hash160Digest}
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.p2p.NetworkMessage
import org.bitcoins.core.protocol.Address
import org.bitcoins.core.protocol.blockchain.MerkleBlock
import org.bitcoins.core.util.BitcoinSLogger
import org.bitcoins.core.p2p._
import org.bitcoins.node.util.BitcoinSpvNodeUtil
/**
* Created by chris on 8/30/16.
* Responsible for checking if a payment to a address was made
* Verifying that the transaction that made the payment was included
* inside of a block on the blockchain
*
* 1.) Creates a bloom filter
* 2.) Sends the bloom filter to a node on the network
* 3.) Nodes matches the bloom filter, sends a txid that matched the filter back to us
* 4.) We request the full transaction using a [[GetDataMessage]]
* 5.) We verify the transaction given to us has an output that matches the address we expected a payment to
* 6.) When another block is announced on the network, we send a MsgMerkleBlock
* to our peer on the network to see if the tx was included on that block
* 7.) If it was, send the actor that that requested this message back
*/
sealed abstract class PaymentActor extends Actor with BitcoinSLogger {
def peerMsgHandler: ActorRef
def receive = LoggingReceive {
case hash: Sha256Hash160Digest =>
paymentToHash(hash)
case address: Address =>
self.forward(address.hash)
}
/** Constructs a bloom filter that matches the given hash,
* then sends that bloom filter to a peer on the network */
def paymentToHash(hash: Sha256Hash160Digest) = {
val bloomFilter =
BloomFilter(10, 0.0001, UInt32.zero, BloomUpdateNone).insert(hash)
val filterLoadMsg = FilterLoadMessage(bloomFilter)
val bloomFilterNetworkMsg =
NetworkMessage(network = ???, filterLoadMsg)
peerMsgHandler ! bloomFilterNetworkMsg
}
/** Awaits for a [[GetDataMessage]] that requested a transaction. We can also fire off more [[GetDataMessage]] inside of this context */
def awaitTransactionGetDataMessage(
hash: Sha256Hash160Digest,
peerMessageHandler: ActorRef): Receive = LoggingReceive {
case txMsg: TransactionMessage =>
//check to see if any of the outputs on this tx match our hash
val outputs = txMsg.transaction.outputs.filter(o =>
o.scriptPubKey.asm.filter(_.bytes == hash.bytes).nonEmpty)
if (outputs.nonEmpty) {
logger.debug(
"matched transaction inside of awaitTransactionGetDataMsg: " + txMsg.transaction.hex)
logger.debug("Matched txid: " + txMsg.transaction.txId.hex)
logger.debug("Switching to awaitBlockAnnouncement")
context.become(
awaitBlockAnnouncement(hash,
txMsg.transaction.txId,
peerMessageHandler))
}
//otherwise we do nothing and wait for another transaction message
case invMsg: InventoryMessage =>
//txs are broadcast by nodes on the network when they are seen by a node
//filter out the txs we do not care about
val txInventories =
invMsg.inventories.filter(_.typeIdentifier == TypeIdentifier.MsgTx)
handleTransactionInventoryMessages(txInventories, peerMessageHandler)
}
/** Sends a [[GetDataMessage]] to get the full transaction for a transaction inventory message */
private def handleTransactionInventoryMessages(
inventory: Seq[Inventory],
peerMessageHandler: ActorRef): Unit = {
for {
txInv <- inventory
inventory = GetDataMessage(txInv)
} yield peerMessageHandler ! inventory
()
}
/** This context waits for a block announcement on the network,
* then constructs a [[MerkleBlockMessage]] to check
* if the txid was included in that block */
def awaitBlockAnnouncement(
hash: Sha256Hash160Digest,
txId: DoubleSha256Digest,
peerMessageHandler: ActorRef): Receive = LoggingReceive {
case invMsg: InventoryMessage =>
val blockHashes =
invMsg.inventories
.filter(_.typeIdentifier == TypeIdentifier.MsgBlock)
.map(_.hash)
if (blockHashes.nonEmpty) {
//construct a merkle block message to verify that the txIds was in the block
val merkleBlockInventory =
Inventory(TypeIdentifier.MsgFilteredBlock, blockHashes.head)
val getDataMsg = GetDataMessage(merkleBlockInventory)
val getDataNetworkMessage =
NetworkMessage(network = ???, getDataMsg)
peerMessageHandler ! getDataNetworkMessage
logger.debug("Switching to awaitMerkleBlockMessage")
context.become(
awaitMerkleBlockMessage(hash, txId, blockHashes, peerMessageHandler))
}
//else do nothing and wait for another block announcement
}
/** This context waits for a [[MerkleBlockMessage]] from our peer on the network, then checks
* if the given txid is contained inside of the block. If it is included, send a [[PaymentActor.SuccessfulPayment]]
* message back to the actor that created this actor, else send a [[PaymentActor.FailedPayment]] message back to
* the actor that created this actor
* @param hash
* @param txId
* @param blockHashes
* @param peerMessageHandler
* @return
*/
def awaitMerkleBlockMessage(
hash: Sha256Hash160Digest,
txId: DoubleSha256Digest,
blockHashes: Seq[DoubleSha256Digest],
peerMessageHandler: ActorRef): Receive = LoggingReceive {
case merkleBlockMsg: MerkleBlockMessage =>
val result = merkleBlockMsg.merkleBlock.partialMerkleTree.extractMatches
.contains(txId)
if (result) {
val successfulPayment =
PaymentActor.SuccessfulPayment(hash,
txId,
blockHashes,
merkleBlockMsg.merkleBlock)
logger.info("Received successful payment: " + successfulPayment)
context.parent ! successfulPayment
} else context.parent ! PaymentActor.FailedPayment(hash)
peerMessageHandler ! Tcp.Close
context.stop(self)
}
}
object PaymentActor {
private case class PaymentActorImpl(peerMsgHandler: ActorRef)
extends PaymentActor
def props(peerMsgHandler: ActorRef): Props =
Props(classOf[PaymentActorImpl], peerMsgHandler)
def apply(peerMsgHandler: ActorRef)(
implicit context: ActorRefFactory): ActorRef =
context.actorOf(props(peerMsgHandler),
BitcoinSpvNodeUtil.createActorName(this.getClass))
sealed trait PaymentActorMessage
case class SuccessfulPayment(
hash: Sha256Hash160Digest,
txId: DoubleSha256Digest,
blockHash: Seq[DoubleSha256Digest],
merkleBlock: MerkleBlock)
extends PaymentActorMessage
case class FailedPayment(hash: Sha256Hash160Digest)
extends PaymentActorMessage
}

View file

@ -1,52 +0,0 @@
package org.bitcoins.node.store
import java.io.FileOutputStream
import org.bitcoins.core.protocol.blockchain.BlockHeader
import org.bitcoins.node.constant.Constants
import org.bitcoins.node.constant.Constants
import scala.io.Source
/**
* Created by chris on 9/5/16.
*/
trait BlockHeaderStore {
/** Appends block headers to the given file */
def append(headers: Seq[BlockHeader], file: java.io.File): Unit = {
printToFile(file) { p =>
headers.map(_.hex).foreach(p.println)
}
}
/** Appends block headers to the default blockheader file */
def append(headers: Seq[BlockHeader]): Unit =
append(headers, Constants.blockHeaderFile)
/** Reads block headers from the given file */
def read(file: java.io.File): Seq[BlockHeader] =
(for {
line <- Source.fromFile(file).getLines()
} yield BlockHeader(line)).toSeq
/** Reads block headers from the default [[BlockHeader]] file */
def read: Seq[BlockHeader] = read(Constants.blockHeaderFile)
/** Returns the last [[BlockHeader]] in the block header store */
def lastHeader: Option[BlockHeader] = lastHeader(Constants.blockHeaderFile)
/** Returns the last [[BlockHeader]] in the block header store */
def lastHeader(file: java.io.File): Option[BlockHeader] = {
val headers = read(file)
if (headers.isEmpty) None else Some(headers.last)
}
private def printToFile(f: java.io.File)(
op: java.io.PrintWriter => Unit): Unit = {
val p = new java.io.PrintWriter(new FileOutputStream(f, true))
try { op(p) } finally { p.close() }
}
}
object BlockHeaderStore extends BlockHeaderStore