Reshuffle package location of P2P messages (#495)

* Reshuffle package location of P2P messages

Previously the companion objects for P2P messages
and the actual messages were in different pacakges.
This made them more awkward to use than necessary.

We also clean up some Scaladocs in this commit.

* Move all P2P messages to core
This commit is contained in:
Torkel Rogstad 2019-06-06 16:13:32 +02:00 committed by Chris Stewart
parent bd10f1c35e
commit 1ff0dee934
76 changed files with 827 additions and 469 deletions

View file

@ -1,4 +1,4 @@
package org.bitcoins.node.messages.control
package org.bitcoins.core.p2p
import org.bitcoins.testkit.gen.ControlMessageGenerator
import org.bitcoins.testkit.util.BitcoinSUnitTest

View file

@ -1,4 +1,4 @@
package org.bitcoins.node.messages.data
package org.bitcoins.core.p2p
import org.bitcoins.testkit.gen.DataMessageGenerator
import org.bitcoins.testkit.util.BitcoinSUnitTest

View file

@ -1,11 +1,8 @@
package org.bitcoins.node.messages.data
package org.bitcoins.core.p2p
import org.bitcoins.testkit.gen.DataMessageGenerator
import org.bitcoins.testkit.util.BitcoinSUnitTest
/**
* Created by chris on 7/8/16.
*/
class InventoryMessageSpec extends BitcoinSUnitTest {
it must " have serialization symmetry" in {

View file

@ -1,11 +1,8 @@
package org.bitcoins.node.messages.data
package org.bitcoins.core.p2p
import org.bitcoins.testkit.gen.DataMessageGenerator
import org.bitcoins.testkit.util.BitcoinSUnitTest
/**
* Created by chris on 7/8/16.
*/
class InventorySpec extends BitcoinSUnitTest {
it must "have serialization symmetry" in {

View file

@ -1,4 +1,4 @@
package org.bitcoins.node.messages.data
package org.bitcoins.core.p2p
import org.bitcoins.testkit.gen.DataMessageGenerator
import org.bitcoins.testkit.util.BitcoinSUnitTest

View file

@ -1,9 +1,8 @@
package org.bitcoins.node.headers
package org.bitcoins.core.p2p
import org.bitcoins.core.config.TestNet3
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.util.{BitcoinSUtil, CryptoUtil}
import org.bitcoins.node.messages.VerAckMessage
import org.bitcoins.testkit.node.NodeTestUtil
import org.scalatest.{FlatSpec, MustMatchers}

View file

@ -1,11 +1,8 @@
package org.bitcoins.node
package org.bitcoins.core.p2p
import org.bitcoins.testkit.node.NodeTestUtil
import org.bitcoins.testkit.util.BitcoinSUnitTest
/**
* Created by chris on 6/28/16.
*/
class NetworkMessageTest extends BitcoinSUnitTest {
"NetworkMessage" must "be able to serialize then deserialize a message and get the original hex back" in {

View file

@ -1,6 +1,5 @@
package org.bitcoins.node.messages
package org.bitcoins.core.p2p
import org.bitcoins.node.headers.NetworkHeader
import org.bitcoins.testkit.node.NodeTestUtil
import org.bitcoins.testkit.util.BitcoinSUnitTest

View file

@ -1,4 +1,4 @@
package org.bitcoins.node.messages.control
package org.bitcoins.core.p2p
import org.bitcoins.testkit.gen.ControlMessageGenerator
import org.bitcoins.testkit.util.BitcoinSUnitTest

View file

@ -1,4 +1,4 @@
package org.bitcoins.node.messages.control
package org.bitcoins.core.p2p
import org.bitcoins.testkit.gen.ControlMessageGenerator
import org.bitcoins.testkit.util.BitcoinSUnitTest

View file

@ -1,4 +1,4 @@
package org.bitcoins.node.versions
package org.bitcoins.core.p2p
import org.bitcoins.testkit.util.BitcoinSUnitTest

View file

@ -1,4 +1,4 @@
package org.bitcoins.node.messages.control
package org.bitcoins.core.p2p
import org.bitcoins.testkit.gen.ControlMessageGenerator
import org.bitcoins.testkit.util.BitcoinSUnitTest

View file

@ -1,4 +1,4 @@
package org.bitcoins.node.messages.data
package org.bitcoins.core.p2p
import org.bitcoins.testkit.gen.DataMessageGenerator
import org.bitcoins.testkit.util.BitcoinSUnitTest

View file

@ -1,10 +1,6 @@
package org.bitcoins.node.messages
package org.bitcoins.core.p2p
import org.bitcoins.node.messages.TypeIdentifier.{
MsgBlock,
MsgFilteredBlock,
MsgTx
}
import org.bitcoins.core.p2p.TypeIdentifier.{MsgBlock, MsgFilteredBlock, MsgTx}
import org.bitcoins.testkit.util.BitcoinSUnitTest
class TypeIdentifierTest extends BitcoinSUnitTest {

View file

@ -1,10 +1,10 @@
package org.bitcoins.node.messages.control
package org.bitcoins.core.p2p
import java.net.InetAddress
import org.bitcoins.testkit.util.BitcoinSUnitTest
import org.bitcoins.core.config.MainNet
import org.bitcoins.core.number.{Int32, UInt64}
import org.bitcoins.testkit.util.BitcoinSUnitTest
import org.joda.time.DateTime
class VersionMessageTest extends BitcoinSUnitTest {

View file

@ -1,8 +1,8 @@
package org.bitcoins.node.serializers.headers
package org.bitcoins.core.serializers.p2p.headers
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.util.BitcoinSUtil
import org.bitcoins.node.messages.NetworkPayload
import org.bitcoins.core.p2p.NetworkPayload
import org.bitcoins.testkit.node.NodeTestUtil
import org.bitcoins.testkit.util.BitcoinSUnitTest

View file

@ -1,12 +1,9 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.number.UInt64
import org.bitcoins.core.protocol.CompactSizeUInt
import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 6/3/16.
*/
class RawAddrMessageSerializerTest extends FlatSpec with MustMatchers {
//from this bitcoin developer guide example

View file

@ -1,11 +1,8 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.util.BitcoinSUtil
import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 8/26/16.
*/
class RawFilterAddMessageSerializerTest extends FlatSpec with MustMatchers {
//https://bitcoin.org/en/developer-reference#filteradd

View file

@ -1,4 +1,4 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.bloom.BloomUpdateNone
import org.bitcoins.core.number.{UInt32, UInt64}

View file

@ -1,13 +1,10 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.number.UInt64
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.util.BitcoinSUtil
import org.bitcoins.node.messages.GetBlocksMessage
import org.bitcoins.node.versions.ProtocolVersion70001
import org.bitcoins.node.messages.GetBlocksMessage
import org.bitcoins.node.versions.ProtocolVersion70001
import org.bitcoins.core.p2p._
import org.scalatest.{FlatSpec, MustMatchers}
/**

View file

@ -1,10 +1,10 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.number.UInt64
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.node.messages.TypeIdentifier.MsgTx
import org.bitcoins.node.messages.data.Inventory
import org.bitcoins.core.p2p.Inventory
import org.bitcoins.core.p2p.TypeIdentifier.MsgTx
import org.scalatest.{FlatSpec, MustMatchers}
/**

View file

@ -1,9 +1,9 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.p2p._
import org.bitcoins.core.number.UInt64
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.node.versions.ProtocolVersion70002
import org.bitcoins.testkit.node.NodeTestUtil
import org.scalatest.{FlatSpec, MustMatchers}

View file

@ -1,4 +1,4 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.number.{UInt32, UInt64}

View file

@ -1,4 +1,4 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.number.UInt64
import org.bitcoins.core.protocol.CompactSizeUInt

View file

@ -1,8 +1,8 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.util.BitcoinSUtil
import org.bitcoins.node.messages.TypeIdentifier.MsgTx
import org.bitcoins.core.p2p.TypeIdentifier.MsgTx
import org.scalatest.{FlatSpec, MustMatchers}
/**

View file

@ -1,4 +1,4 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.number.{UInt32, UInt64}
@ -7,9 +7,6 @@ import org.bitcoins.core.util.BitcoinSUtil
import org.scalatest.{FlatSpec, MustMatchers}
import scodec.bits.BitVector
/**
* Created by chris on 6/2/16.
*/
class RawMerkleBlockMessageSerializerTest extends FlatSpec with MustMatchers {
//from bitcoin developer reference

View file

@ -1,13 +1,9 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.number.UInt32
import org.bitcoins.node.messages.control.NodeNetwork
import org.bitcoins.node.messages.control.NodeNetwork
import org.bitcoins.core.p2p.NodeNetwork
import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 6/2/16.
*/
class RawNetworkIpAddressSerializerTest extends FlatSpec with MustMatchers {
//from this bitcoin developer guide example

View file

@ -1,12 +1,9 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.number.UInt64
import org.bitcoins.core.protocol.CompactSizeUInt
import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 6/2/16.
*/
class RawNotFoundMessageSerializerTest extends FlatSpec with MustMatchers {
//according to the developer reference, the format for inventory messages and

View file

@ -1,7 +1,7 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.number.UInt64
import org.bitcoins.node.messages.control.PingMessage
import org.bitcoins.core.p2p.PingMessage
import org.scalatest.{FlatSpec, MustMatchers}
/**

View file

@ -1,4 +1,4 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.number.UInt64
import org.bitcoins.core.protocol.CompactSizeUInt

View file

@ -1,7 +1,6 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.node.messages.control.{NodeNetwork, UnnamedService}
import org.bitcoins.node.messages.control.{NodeNetwork, UnnamedService}
import org.bitcoins.core.p2p.{NodeNetwork, UnnamedService}
import org.scalatest.{FlatSpec, MustMatchers}
/**

View file

@ -1,12 +1,9 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.util.BitcoinSUtil
import org.bitcoins.testkit.node.NodeTestUtil
import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 6/2/16.
*/
class RawTransactionMessageSerializerTest extends FlatSpec with MustMatchers {
"RawTransactionMessageSerializer" must "read a TransactionMessage from a sequence of bytes" in {

View file

@ -1,10 +1,6 @@
package org.bitcoins.node.serializers.messages
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.node.messages.TypeIdentifier.{
MsgBlock,
MsgFilteredBlock,
MsgTx
}
import org.bitcoins.core.p2p.TypeIdentifier.{MsgBlock, MsgFilteredBlock, MsgTx}
import org.scalatest.{FlatSpec, MustMatchers}
/**

View file

@ -1,25 +1,14 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.serializers.p2p.messages
import java.net.InetSocketAddress
import org.bitcoins.core.number.{Int32, Int64, UInt64}
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.util.BitcoinSUtil
import org.bitcoins.node.messages.control.{NodeNetwork, UnnamedService}
import org.bitcoins.core.p2p._
import org.bitcoins.node.util.BitcoinSpvNodeUtil
import org.bitcoins.node.versions.{ProtocolVersion, ProtocolVersion70002}
import org.bitcoins.node.messages.control.{NodeNetwork, UnnamedService}
import org.bitcoins.node.util.BitcoinSpvNodeUtil
import org.bitcoins.node.versions.{
ProtocolVersion,
ProtocolVersion70002,
ProtocolVersion70012
}
import org.scalatest.{FlatSpec, MustMatchers}
/**
* Created by chris on 6/3/16.
*/
class RawVersionMessageSerializerTest extends FlatSpec with MustMatchers {
//take from the bitcoin developer reference underneath this seciton
@ -54,13 +43,13 @@ class RawVersionMessageSerializerTest extends FlatSpec with MustMatchers {
versionMessage.timestamp must be(Int64(1415483324))
versionMessage.addressReceiveServices must be(NodeNetwork)
BitcoinSpvNodeUtil
NetworkIpAddress
.writeAddress(versionMessage.addressReceiveIpAddress)
.toHex must be(receivingNodeIpAddress)
versionMessage.addressReceivePort must be(8333)
versionMessage.addressTransServices must be(NodeNetwork)
BitcoinSpvNodeUtil
NetworkIpAddress
.writeAddress(versionMessage.addressTransIpAddress)
.toHex must be(transNodeIpAddress)
versionMessage.addressTransPort must be(8333)

View file

@ -1,18 +1,14 @@
package org.bitcoins.node.messages.data
package org.bitcoins.core.p2p
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.protocol.NetworkElement
import org.bitcoins.core.util.Factory
import org.bitcoins.node.messages.TypeIdentifier
import org.bitcoins.node.serializers.messages.data.RawInventorySerializer
import org.bitcoins.node.messages.TypeIdentifier
import org.bitcoins.node.serializers.messages.data.RawInventorySerializer
import org.bitcoins.core.serializers.p2p.messages.RawInventorySerializer
import scodec.bits.ByteVector
/**
* Created by chris on 5/31/16.
* These are used as unique identifiers inside the peer-to-peer network
* [[https://bitcoin.org/en/developer-reference#term-inventory]]
* @see [[https://bitcoin.org/en/developer-reference#term-inventory]]
*/
trait Inventory extends NetworkElement {
@ -47,3 +43,6 @@ object Inventory extends Factory[Inventory] {
InventoryImpl(typeIdentifier, hash)
}
}

View file

@ -1,19 +1,15 @@
package org.bitcoins.node.headers
package org.bitcoins.core.p2p
import org.bitcoins.core.config.NetworkParameters
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.NetworkElement
import org.bitcoins.core.serializers.p2p.headers.RawNetworkHeaderSerializer
import org.bitcoins.core.util.{CryptoUtil, Factory}
import org.bitcoins.node.messages.NetworkPayload
import org.bitcoins.node.serializers.headers.RawNetworkHeaderSerializer
import org.bitcoins.node.messages.NetworkPayload
import org.bitcoins.node.serializers.headers.RawNetworkHeaderSerializer
import scodec.bits.ByteVector
/**
* Created by chris on 5/31/16.
* Represents a message header on the peer-to-peer network
* https://bitcoin.org/en/developer-reference#message-headers
* @see https://bitcoin.org/en/developer-reference#message-headers
*/
sealed trait NetworkHeader extends NetworkElement {
@ -22,23 +18,18 @@ sealed trait NetworkHeader extends NetworkElement {
/**
* Magic bytes indicating the originating network;
* used to seek to next message when stream state is unknown.
* @return
*/
def network: ByteVector
/**
* ASCII string which identifies what message type is contained in the payload.
* Followed by nulls (0x00) to pad out byte count; for example: version\0\0\0\0\0.
*
* @return
*/
def commandName: String
/**
* Number of bytes in payload. The current maximum number of bytes (MAX_SIZE) allowed in the payload
* by Bitcoin Core is 32 MiBmessages with a payload size larger than this will be dropped or rejected.
*
* @return
*/
def payloadSize: UInt32
@ -47,8 +38,6 @@ sealed trait NetworkHeader extends NetworkElement {
* First 4 bytes of SHA256(SHA256(payload)) in internal byte order.
* If payload is empty, as in verack and getaddr messages,
* the checksum is always 0x5df6e0e2 (SHA256(SHA256(""))).
*
* @return
*/
def checksum: ByteVector
@ -74,7 +63,6 @@ object NetworkHeader extends Factory[NetworkHeader] {
* @param commandName the name of the command being sent in the header
* @param payloadSize the size of the payload being sent by this header
* @param checksum the checksum of the payload to ensure that the entire payload was sent
* @return
*/
def apply(
network: ByteVector,
@ -88,7 +76,6 @@ object NetworkHeader extends Factory[NetworkHeader] {
* Creates a [[NetworkHeader]] from it's [[NetworkParameters]] and [[NetworkPayload]]
* @param network the [[NetworkParameters]] object that indicates what network the payload needs to be sent on
* @param payload the [[NetworkPayload]] object that needs to be sent on the network
* @return
*/
def apply(
network: NetworkParameters,

View file

@ -1,19 +1,16 @@
package org.bitcoins.node.util
package org.bitcoins.core.p2p
import java.net.{InetAddress, InetSocketAddress}
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.NetworkElement
import org.bitcoins.core.serializers.p2p.messages.RawNetworkIpAddressSerializer
import org.bitcoins.core.util.Factory
import org.bitcoins.node.messages.control.{NodeNetwork, ServiceIdentifier}
import org.bitcoins.node.messages.control.ServiceIdentifier
import org.bitcoins.node.serializers.messages.control.RawNetworkIpAddressSerializer
import scodec.bits.ByteVector
import scodec.bits._
/**
* Created by chris on 5/31/16.
* Encapsulated network IP address currently uses the following structure
* https://bitcoin.org/en/developer-reference#addr
* @see https://bitcoin.org/en/developer-reference#addr
*/
sealed abstract class NetworkIpAddress extends NetworkElement {
@ -24,23 +21,17 @@ sealed abstract class NetworkIpAddress extends NetworkElement {
* Other nodes just relaying the IP address should not change the time.
* Nodes can use the time field to avoid relaying old addr messages.
* Malicious nodes may change times or even set them in the future.
*
* @return
*/
def time: UInt32
/**
* The services the node advertised in its version message.
*
* @return
*/
def services: ServiceIdentifier
/**
* IPv6 address in big endian byte order.
* IPv4 addresses can be provided as IPv4-mapped IPv6 addresses
*
* @return
*/
def address: InetAddress
@ -49,8 +40,6 @@ sealed abstract class NetworkIpAddress extends NetworkElement {
* Note that Bitcoin Core will only connect to nodes with non-standard port numbers as
* a last resort for finding peers. This is to prevent anyone from trying to use the
* network to disrupt non-Bitcoin services that run on other ports.
*
* @return
*/
def port: Int
@ -58,6 +47,30 @@ sealed abstract class NetworkIpAddress extends NetworkElement {
}
object NetworkIpAddress extends Factory[NetworkIpAddress] {
/**
* Writes an IP address to the representation that the p2p network requires.
* An IPv6 address is in big endian byte order.
* An IPv4 address has to be mapped to an IPv6 address.
*
* @see https://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses
*/
def writeAddress(iNetAddress: InetAddress): ByteVector = {
if (iNetAddress.getAddress.size == 4) {
//this means we need to convert the IPv4 address to an IPv6 address
//first we have an 80 bit prefix of zeros
val zeroBytes = ByteVector.fill(10)(0)
//the next 16 bits are ones
val oneBytes = hex"ffff"
val prefix: ByteVector = zeroBytes ++ oneBytes
val addr = prefix ++ ByteVector(iNetAddress.getAddress)
addr
} else {
ByteVector(iNetAddress.getAddress)
}
}
private case class NetworkIpAddressImpl(
time: UInt32,
services: ServiceIdentifier,

View file

@ -1,14 +1,9 @@
package org.bitcoins.node
package org.bitcoins.core.p2p
import org.bitcoins.core.config.NetworkParameters
import org.bitcoins.core.protocol.NetworkElement
import org.bitcoins.core.serializers.p2p.RawNetworkMessageSerializer
import org.bitcoins.core.util.Factory
import org.bitcoins.node.headers.NetworkHeader
import org.bitcoins.node.messages.NetworkPayload
import org.bitcoins.node.serializers.RawNetworkMessageSerializer
import org.bitcoins.node.headers.NetworkHeader
import org.bitcoins.node.messages.NetworkPayload
import org.bitcoins.node.serializers.RawNetworkMessageSerializer
import scodec.bits.ByteVector
/**

View file

@ -1,4 +1,4 @@
package org.bitcoins.node.messages
package org.bitcoins.core.p2p
import java.net.InetAddress
@ -10,19 +10,17 @@ import org.bitcoins.core.protocol.transaction.Transaction
import org.bitcoins.core.protocol.{CompactSizeUInt, NetworkElement}
import org.bitcoins.core.util.BitcoinSUtil
import org.bitcoins.core.wallet.fee.{SatoshisPerByte, SatoshisPerKiloByte}
import org.bitcoins.node.headers.NetworkHeader
import org.bitcoins.node.messages.control.ServiceIdentifier
import org.bitcoins.node.messages.data.Inventory
import org.bitcoins.node.serializers.messages.control._
import org.bitcoins.node.serializers.messages.data._
import org.bitcoins.node.util.NetworkIpAddress
import org.bitcoins.node.versions.ProtocolVersion
import org.bitcoins.core.serializers.p2p.messages._
import scodec.bits.ByteVector
import org.bitcoins.core.util.Factory
import org.bitcoins.core.config.NetworkParameters
import java.net.InetSocketAddress
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.bloom.BloomFlag
/**
* Created by chris on 5/31/16.
* Trait that represents a payload for a message on the Bitcoin p2p network
* [[https://bitcoin.org/en/developer-reference#p2p-network]]
* @see [[https://bitcoin.org/en/developer-reference#p2p-network]]
*/
sealed trait NetworkPayload extends NetworkElement {
@ -30,8 +28,7 @@ sealed trait NetworkPayload extends NetworkElement {
* ASCII string which identifies what message type is contained in the payload.
* Followed by nulls (0x00) to pad out byte count; for example: version\0\0\0\0\0.
* Command names need to be 12 bytes long
* This is generally used to build a [[org.bitcoins.node.headers.NetworkHeader]]
* @return
* This is generally used to build a [[org.bitcoins.core.p2p.NetworkHeader]]
*/
def commandName: String
}
@ -50,7 +47,6 @@ trait BlockMessage extends DataPayload {
/**
* The block being transmitted inside of this [[BlockMessage]]
* @return
*/
def block: Block
@ -59,18 +55,28 @@ trait BlockMessage extends DataPayload {
override def bytes: ByteVector = RawBlockMessageSerializer.write(this)
}
object BlockMessage extends Factory[BlockMessage] {
private case class BlockMessageImpl(block: Block) extends BlockMessage
def fromBytes(bytes: ByteVector): BlockMessage =
RawBlockMessageSerializer.read(bytes)
def apply(block: Block): BlockMessage = BlockMessageImpl(block)
}
/**
* The getblocks message requests an inv message that provides block header hashes
* The `getblocks` message requests an inv message that provides block header hashes
* starting from a particular point in the block chain.
* It allows a peer which has been disconnected or started for the first time to get the data
* it needs to request the blocks it hasnt seen.
* [[https://bitcoin.org/en/developer-reference#getblocks]]
* @see [https://bitcoin.org/en/developer-reference#getblocks]]
*/
trait GetBlocksMessage extends DataPayload {
/**
* The protocol version number; the same as sent in the version message.
* @return
*/
def protocolVersion: ProtocolVersion
@ -78,7 +84,6 @@ trait GetBlocksMessage extends DataPayload {
* The number of header hashes provided not including the stop hash.
* There is no limit except that the byte size of the entire message
* must be below the MAX_SIZE limit; typically from 1 to 200 hashes are sent.
* @return
*/
def hashCount: CompactSizeUInt
@ -86,7 +91,6 @@ trait GetBlocksMessage extends DataPayload {
* One or more block header hashes (32 bytes each) in internal byte order.
* Hashes should be provided in reverse order of block height,
* so highest-height hashes are listed first and lowest-height hashes are listed last.
* @return
*/
def blockHeaderHashes: Seq[DoubleSha256Digest]
@ -96,7 +100,6 @@ trait GetBlocksMessage extends DataPayload {
* header hashes (a maximum of 500 will be sent as a reply to this message;
* if you need more than 500, you will need to send another getblocks message
* with a higher-height header hash as the first entry in block header hash field).
* @return
*/
def stopHash: DoubleSha256Digest
@ -105,23 +108,54 @@ trait GetBlocksMessage extends DataPayload {
override def bytes: ByteVector = RawGetBlocksMessageSerializer.write(this)
}
/**
* This is the companion object for the GetBlocks network message on the p2p network
* @see https://bitcoin.org/en/developer-reference#getblocks
*/
object GetBlocksMessage extends Factory[GetBlocksMessage] {
private case class GetBlocksMessageImpl(
protocolVersion: ProtocolVersion,
hashCount: CompactSizeUInt,
blockHeaderHashes: Seq[DoubleSha256Digest],
stopHash: DoubleSha256Digest)
extends GetBlocksMessage
def apply(
version: ProtocolVersion,
hashCount: CompactSizeUInt,
blockHeaderHashes: Seq[DoubleSha256Digest],
stopHash: DoubleSha256Digest): GetBlocksMessage = {
GetBlocksMessageImpl(version, hashCount, blockHeaderHashes, stopHash)
}
def apply(
version: ProtocolVersion,
blockHeaderHashes: Seq[DoubleSha256Digest],
stopHash: DoubleSha256Digest): GetBlocksMessage = {
val hashCount = CompactSizeUInt(UInt64(blockHeaderHashes.length))
GetBlocksMessage(version, hashCount, blockHeaderHashes, stopHash)
}
def fromBytes(bytes: ByteVector): GetBlocksMessage =
RawGetBlocksMessageSerializer.read(bytes)
}
/**
* The getdata message requests one or more data objects from another node.
* The objects are requested by an inventory,
* which the requesting node typically previously received by way of an inv message.
* [[https://bitcoin.org/en/developer-reference#getdata]]
* @see [[https://bitcoin.org/en/developer-reference#getdata]]
*/
trait GetDataMessage extends DataPayload {
/**
* The number of inventory enteries
* @return
*/
def inventoryCount: CompactSizeUInt
/**
* One or more inventory entries up to a maximum of 50,000 entries.
* @return
*/
def inventories: Seq[Inventory]
@ -130,6 +164,31 @@ trait GetDataMessage extends DataPayload {
override def bytes: ByteVector = RawGetDataMessageSerializer.write(this)
}
object GetDataMessage extends Factory[GetDataMessage] {
private case class GetDataMessageImpl(
inventoryCount: CompactSizeUInt,
inventories: Seq[Inventory])
extends GetDataMessage
override def fromBytes(bytes: ByteVector): GetDataMessage = {
RawGetDataMessageSerializer.read(bytes)
}
def apply(
inventoryCount: CompactSizeUInt,
inventories: Seq[Inventory]): GetDataMessage = {
GetDataMessageImpl(inventoryCount, inventories)
}
def apply(inventories: Seq[Inventory]): GetDataMessage = {
val inventoryCount = CompactSizeUInt(UInt64(inventories.length))
GetDataMessage(inventoryCount, inventories)
}
def apply(inventory: Inventory): GetDataMessage =
GetDataMessage(Seq(inventory))
}
/**
* The getheaders message requests a headers message that provides block headers starting
* from a particular point in the block chain.
@ -147,10 +206,61 @@ trait GetHeadersMessage extends DataPayload {
override def bytes: ByteVector = RawGetHeadersMessageSerializer.write(this)
}
object GetHeadersMessage extends Factory[GetHeadersMessage] {
private case class GetHeadersMessageImpl(
version: ProtocolVersion,
hashCount: CompactSizeUInt,
hashes: Seq[DoubleSha256Digest],
hashStop: DoubleSha256Digest)
extends GetHeadersMessage
override def fromBytes(bytes: ByteVector): GetHeadersMessage =
RawGetHeadersMessageSerializer.read(bytes)
def apply(
version: ProtocolVersion,
hashCount: CompactSizeUInt,
hashes: Seq[DoubleSha256Digest],
hashStop: DoubleSha256Digest): GetHeadersMessage = {
GetHeadersMessageImpl(version, hashCount, hashes, hashStop)
}
def apply(
version: ProtocolVersion,
hashes: Seq[DoubleSha256Digest],
hashStop: DoubleSha256Digest): GetHeadersMessage = {
val hashCount = CompactSizeUInt(UInt64(hashes.length))
GetHeadersMessage(version, hashCount, hashes, hashStop)
}
/** Creates a [[GetHeadersMessage]] with the default protocol version */
def apply(
hashes: Seq[DoubleSha256Digest],
hashStop: DoubleSha256Digest): GetHeadersMessage = {
GetHeadersMessage(ProtocolVersion.default, hashes, hashStop)
}
/** Creates a [[GetHeadersMessage]] with no hash stop set, this requests all possible blocks
* if we need more than 2000 block headers, we will have to send another [[GetHeadersMessage]]
*
* @see [[https://bitcoin.org/en/developer-reference#getheaders]]
*/
def apply(hashes: Seq[DoubleSha256Digest]): GetHeadersMessage = {
//The header hash of the last header hash being requested; set to all zeroes to request an inv message with all
//subsequent header hashes (a maximum of 2000 will be sent as a reply to this message
val hashStop = DoubleSha256Digest.empty
GetHeadersMessage(hashes, hashStop)
}
def apply(hashes: DoubleSha256Digest): GetHeadersMessage = {
GetHeadersMessage(Vector(hashes))
}
}
/**
* The headers message sends one or more block headers to a node
* which previously requested certain headers with a getheaders message.
* [[https://bitcoin.org/en/developer-reference#headers]]
* @see [[https://bitcoin.org/en/developer-reference#headers]]
*/
trait HeadersMessage extends DataPayload {
@ -158,7 +268,6 @@ trait HeadersMessage extends DataPayload {
* Number of block headers up to a maximum of 2,000.
* Note: headers-first sync assumes the sending node
* will send the maximum number of headers whenever possible.
* @return
*/
def count: CompactSizeUInt
@ -167,7 +276,6 @@ trait HeadersMessage extends DataPayload {
* block headers section with an additional 0x00 suffixed.
* This 0x00 is called the transaction count, but because the headers message
* doesnt include any transactions, the transaction count is always zero.
* @return
*/
def headers: Vector[BlockHeader]
@ -176,23 +284,41 @@ trait HeadersMessage extends DataPayload {
override def bytes: ByteVector = RawHeadersMessageSerializer.write(this)
}
object HeadersMessage extends Factory[HeadersMessage] {
private case class HeadersMessageImpl(
count: CompactSizeUInt,
headers: Vector[BlockHeader])
extends HeadersMessage
def fromBytes(bytes: ByteVector): HeadersMessage =
RawHeadersMessageSerializer.read(bytes)
def apply(
count: CompactSizeUInt,
headers: Vector[BlockHeader]): HeadersMessage =
HeadersMessageImpl(count, headers)
def apply(headers: Vector[BlockHeader]): HeadersMessage = {
val count = CompactSizeUInt(UInt64(headers.length))
HeadersMessageImpl(count, headers)
}
}
/**
* The inv message (inventory message) transmits one or more inventories of objects known to the transmitting peer.
* It can be sent unsolicited to announce new transactions or blocks,
* or it can be sent in reply to a getblocks message or mempool message.
* [[https://bitcoin.org/en/developer-reference#inv]]
* @see [[https://bitcoin.org/en/developer-reference#inv]]
*/
trait InventoryMessage extends DataPayload {
/**
* The number of inventory enteries
* @return
*/
def inventoryCount: CompactSizeUInt
/**
* One or more inventory entries up to a maximum of 50,000 entries.
* @return
*/
def inventories: Seq[Inventory]
@ -201,6 +327,31 @@ trait InventoryMessage extends DataPayload {
override def bytes: ByteVector = RawInventoryMessageSerializer.write(this)
}
/**
* Creates an scala object that represents the inventory type on the p2p network
* @see https://bitcoin.org/en/developer-reference#inv
*/
object InventoryMessage extends Factory[InventoryMessage] {
private case class InventoryMessageImpl(
inventoryCount: CompactSizeUInt,
inventories: Seq[Inventory])
extends InventoryMessage
override def fromBytes(bytes: ByteVector): InventoryMessage =
RawInventoryMessageSerializer.read(bytes)
def apply(
inventoryCount: CompactSizeUInt,
inventories: Seq[Inventory]): InventoryMessage = {
InventoryMessageImpl(inventoryCount, inventories)
}
def apply(inventories: Seq[Inventory]): InventoryMessage = {
val count = CompactSizeUInt(UInt64(inventories.length))
InventoryMessage(count, inventories)
}
}
/**
* The mempool message requests the TXIDs of transactions that the receiving node has verified
* as valid but which have not yet appeared in a block.
@ -218,7 +369,8 @@ case object MemPoolMessage extends DataPayload {
* block using the inventory type MSG_MERKLEBLOCK.
* It is only part of the reply: if any matching transactions are found,
* they will be sent separately as tx messages.
* [[https://bitcoin.org/en/developer-reference#merkleblock]]
*
* @see [[https://bitcoin.org/en/developer-reference#merkleblock]]
*/
trait MerkleBlockMessage extends DataPayload {
@ -231,34 +383,86 @@ trait MerkleBlockMessage extends DataPayload {
}
/**
* @see https://bitcoin.org/en/developer-reference#merkleblock
*/
object MerkleBlockMessage extends Factory[MerkleBlockMessage] {
private case class MerkleBlockMessageImpl(merkleBlock: MerkleBlock)
extends MerkleBlockMessage
def fromBytes(bytes: ByteVector): MerkleBlockMessage =
RawMerkleBlockMessageSerializer.read(bytes)
def apply(merkleBlock: MerkleBlock): MerkleBlockMessage = {
MerkleBlockMessageImpl(merkleBlock)
}
}
/**
* The notfound message is a reply to a getdata message which requested an object the receiving
* node does not have available for relay. (Nodes are not expected to relay historic transactions
* which are no longer in the memory pool or relay set.
* Nodes may also have pruned spent transactions from older blocks, making them unable to send those blocks.)
* [[https://bitcoin.org/en/developer-reference#notfound]]
* @see [[https://bitcoin.org/en/developer-reference#notfound]]
*/
trait NotFoundMessage extends DataPayload with InventoryMessage {
override def commandName = NetworkPayload.notFoundCommandName
override def bytes: ByteVector = RawNotFoundMessageSerializer.write(this)
}
/**
* The companion object factory used to create NotFoundMessages on the p2p network
* @see https://bitcoin.org/en/developer-reference#notfound
*/
object NotFoundMessage extends Factory[NotFoundMessage] {
private case class NotFoundMessageImpl(
inventoryCount: CompactSizeUInt,
inventories: Seq[Inventory])
extends NotFoundMessage
def fromBytes(bytes: ByteVector): NotFoundMessage =
RawNotFoundMessageSerializer.read(bytes)
def apply(
inventoryCount: CompactSizeUInt,
inventories: Seq[Inventory]): NotFoundMessage = {
NotFoundMessageImpl(inventoryCount, inventories)
}
}
/**
* The tx message transmits a single transaction in the raw transaction format.
* It can be sent in a variety of situations;
* [[https://bitcoin.org/en/developer-reference#tx]]
* @see [[https://bitcoin.org/en/developer-reference#tx]]
*/
trait TransactionMessage extends DataPayload {
/**
* The transaction being sent over the wire
* @return
*/
def transaction: Transaction
override def commandName = NetworkPayload.transactionCommandName
override def bytes: ByteVector = RawTransactionMessageSerializer.write(this)
}
/**
* Companion factory object for the TransactionMessage on the p2p network
* @see https://bitcoin.org/en/developer-reference#tx
*/
object TransactionMessage extends Factory[TransactionMessage] {
private case class TransactionMessageImpl(transaction: Transaction)
extends TransactionMessage
def fromBytes(bytes: ByteVector): TransactionMessage =
RawTransactionMessageSerializer.read(bytes)
def apply(transaction: Transaction): TransactionMessage =
TransactionMessageImpl(transaction)
}
/**
* Represents a control message on this network
* [[https://bitcoin.org/en/developer-reference#control-messages]]
@ -272,7 +476,7 @@ sealed trait ControlPayload extends NetworkPayload
* Some of its peers send that information to their peers (also unsolicited),
* some of which further distribute it, allowing decentralized peer discovery for
* any program already on the network.
* [[https://bitcoin.org/en/developer-reference#addr]]
* @see [[https://bitcoin.org/en/developer-reference#addr]]
*/
trait AddrMessage extends ControlPayload {
def ipCount: CompactSizeUInt
@ -281,6 +485,27 @@ trait AddrMessage extends ControlPayload {
override def bytes: ByteVector = RawAddrMessageSerializer.write(this)
}
/**
* The companion object for an AddrMessage
* @see https://bitcoin.org/en/developer-reference#addr
*/
object AddrMessage extends Factory[AddrMessage] {
private case class AddrMessageImpl(
ipCount: CompactSizeUInt,
addresses: Seq[NetworkIpAddress])
extends AddrMessage
def fromBytes(bytes: ByteVector): AddrMessage =
RawAddrMessageSerializer.read(bytes)
def apply(
ipCount: CompactSizeUInt,
addresses: Seq[NetworkIpAddress]): AddrMessage =
AddrMessageImpl(ipCount, addresses)
}
/**
* The feefilter message is a request to the receiving peer to not relay any transaction inv messages
* to the sending peer where the fee rate for the transaction is below the fee rate specified in the
@ -309,18 +534,35 @@ trait FeeFilterMessage extends ControlPayload {
}
}
object FeeFilterMessage extends Factory[FeeFilterMessage] {
private case class FeeFilterMessageImpl(feeRate: SatoshisPerKiloByte)
extends FeeFilterMessage
override def fromBytes(bytes: ByteVector): FeeFilterMessage = {
RawFeeFilterMessageSerializer.read(bytes)
}
def apply(satoshisPerKiloByte: SatoshisPerKiloByte): FeeFilterMessage = {
FeeFilterMessageImpl(satoshisPerKiloByte)
}
def apply(satPerByte: SatoshisPerByte): FeeFilterMessage = {
FeeFilterMessage(satPerByte.toSatPerKb)
}
}
/**
* The filteradd message tells the receiving peer to add a single element to a
* previously-set bloom filter, such as a new public key.
* The element is sent directly to the receiving peer; the peer then uses the parameters
* set in the filterload message to add the element to the bloom filter.
* [[https://bitcoin.org/en/developer-reference#filteradd]]
* @see [[https://bitcoin.org/en/developer-reference#filteradd]]
*/
trait FilterAddMessage extends ControlPayload {
/**
* The number of bytes in the following element field.
* @return
*/
def elementSize: CompactSizeUInt
@ -330,7 +572,6 @@ trait FilterAddMessage extends ControlPayload {
* onto the stack in a pubkey or signature script.
* Elements must be sent in the byte order they would use when appearing in a raw transaction;
* for example, hashes should be sent in internal byte order.
* @return
*/
def element: ByteVector
@ -339,11 +580,30 @@ trait FilterAddMessage extends ControlPayload {
override def bytes: ByteVector = RawFilterAddMessageSerializer.write(this)
}
/**
* @see [[https://bitcoin.org/en/developer-reference#filteradd]]
*/
object FilterAddMessage extends Factory[FilterAddMessage] {
private case class FilterAddMessageImpl(
elementSize: CompactSizeUInt,
element: ByteVector)
extends FilterAddMessage
override def fromBytes(bytes: ByteVector): FilterAddMessage =
RawFilterAddMessageSerializer.read(bytes)
def apply(
elementSize: CompactSizeUInt,
element: ByteVector): FilterAddMessage = {
FilterAddMessageImpl(elementSize, element)
}
}
/**
* The filterclear message tells the receiving peer to remove a previously-set bloom filter.
* This also undoes the effect of setting the relay field in the version message to 0,
* allowing unfiltered access to inv messages announcing new transactions.
* [[https://bitcoin.org/en/developer-reference#filterclear]]
* @see [[https://bitcoin.org/en/developer-reference#filterclear]]
*/
case object FilterClearMessage extends ControlPayload {
override val commandName = NetworkPayload.filterClearCommandName
@ -355,7 +615,7 @@ case object FilterClearMessage extends ControlPayload {
* requested merkle blocks through the provided filter.
* This allows clients to receive transactions relevant to their wallet plus a configurable
* rate of false positive transactions which can provide plausible-deniability privacy.
* [[https://bitcoin.org/en/developer-reference#filterload]]
* @see [[https://bitcoin.org/en/developer-reference#filterload]]
*/
trait FilterLoadMessage extends ControlPayload {
@ -367,12 +627,58 @@ trait FilterLoadMessage extends ControlPayload {
override def bytes: ByteVector = RawFilterLoadMessageSerializer.write(this)
}
/**
* @see [[https://bitcoin.org/en/developer-reference#filterload]]
*/
object FilterLoadMessage extends Factory[FilterLoadMessage] {
private case class FilterLoadMessageImpl(bloomFilter: BloomFilter)
extends FilterLoadMessage {
require(
bloomFilter.filterSize.num.toLong <= BloomFilter.maxSize.toLong,
"Can only have a maximum of 36,000 bytes in our filter, got: " + bloomFilter.data.size)
require(
bloomFilter.hashFuncs <= BloomFilter.maxHashFuncs,
"Can only have a maximum of 50 hashFuncs inside FilterLoadMessage, got: " + bloomFilter.hashFuncs)
require(
bloomFilter.filterSize.num.toLong == bloomFilter.data.size,
"Filter Size compactSizeUInt and actual filter size were different, " +
"filterSize: " + bloomFilter.filterSize.num + " actual filter size: " + bloomFilter.data.length
)
}
override def fromBytes(bytes: ByteVector): FilterLoadMessage =
RawFilterLoadMessageSerializer.read(bytes)
def apply(
filterSize: CompactSizeUInt,
filter: ByteVector,
hashFuncs: UInt32,
tweak: UInt32,
flags: BloomFlag): FilterLoadMessage = {
val bloomFilter = BloomFilter(filterSize, filter, hashFuncs, tweak, flags)
FilterLoadMessage(bloomFilter)
}
def apply(
filter: ByteVector,
hashFuncs: UInt32,
tweak: UInt32,
flags: BloomFlag): FilterLoadMessage = {
val filterSize = CompactSizeUInt(UInt64(filter.length))
FilterLoadMessage(filterSize, filter, hashFuncs, tweak, flags)
}
def apply(bloomFilter: BloomFilter): FilterLoadMessage = {
FilterLoadMessageImpl(bloomFilter)
}
}
/**
* The getaddr message requests an addr message from the receiving node,
* preferably one with lots of IP addresses of other receiving nodes.
* The transmitting node can use those IP addresses to quickly update its
* database of available nodes rather than waiting for unsolicited addr messages to arrive over time.
* [[https://bitcoin.org/en/developer-reference#getaddr]]
* @see [[https://bitcoin.org/en/developer-reference#getaddr]]
*/
case object GetAddrMessage extends ControlPayload {
override val commandName = NetworkPayload.getAddrCommandName
@ -384,7 +690,7 @@ case object GetAddrMessage extends ControlPayload {
* If a TCP/IP error is encountered when sending the ping message (such as a connection timeout),
* the transmitting node can assume that the receiving node is disconnected.
* The response to a ping message is the pong message.
* [[https://bitcoin.org/en/developer-reference#ping]]
* @see [[https://bitcoin.org/en/developer-reference#ping]]
*/
trait PingMessage extends ControlPayload {
@ -392,7 +698,6 @@ trait PingMessage extends ControlPayload {
* Random nonce assigned to this ping message.
* The responding pong message will include this nonce
* to identify the ping message to which it is replying.
* @return
*/
def nonce: UInt64
@ -401,17 +706,26 @@ trait PingMessage extends ControlPayload {
override def bytes: ByteVector = RawPingMessageSerializer.write(this)
}
object PingMessage extends Factory[PingMessage] {
private case class PingMessageImpl(nonce: UInt64) extends PingMessage
override def fromBytes(bytes: ByteVector): PingMessage = {
val pingMsg = RawPingMessageSerializer.read(bytes)
PingMessageImpl(pingMsg.nonce)
}
def apply(nonce: UInt64): PingMessage = PingMessageImpl(nonce)
}
/**
* The pong message replies to a ping message, proving to the pinging node that the ponging node is still alive.
* Bitcoin Core will, by default, disconnect from any clients which have not responded
* to a ping message within 20 minutes.
* [[https://bitcoin.org/en/developer-reference#pong]]
* @see [[https://bitcoin.org/en/developer-reference#pong]]
*/
trait PongMessage extends ControlPayload {
/**
* The nonce which is the nonce in the ping message the peer is responding too
* @return
*/
def nonce: UInt64
@ -421,42 +735,48 @@ trait PongMessage extends ControlPayload {
}
object PongMessage extends Factory[PongMessage] {
private case class PongMessageImpl(nonce: UInt64) extends PongMessage
def fromBytes(bytes: ByteVector): PongMessage = {
val pongMsg = RawPongMessageSerializer.read(bytes)
PongMessageImpl(pongMsg.nonce)
}
def apply(nonce: UInt64): PongMessage = PongMessageImpl(nonce)
}
/**
* The reject message informs the receiving node that one of its previous messages has been rejected.
* [[https://bitcoin.org/en/developer-reference#reject]]
* @see [[https://bitcoin.org/en/developer-reference#reject]]
*/
trait RejectMessage extends ControlPayload {
/**
* The number of bytes in the following message field.
* @return
*/
def messageSize: CompactSizeUInt
/**
* The type of message rejected as ASCII text without null padding.
* For example: tx, block, or version.
* @return
*/
def message: String
/**
* The reject message code.
* @return
*/
def code: Char
/**
* The number of bytes in the following reason field.
* May be 0x00 if a text reason isnt provided.
* @return
*/
def reasonSize: CompactSizeUInt
/**
* The reason for the rejection in ASCII text.
* This should not be displayed to the user; it is only for debugging purposes.
* @return
*/
def reason: String
@ -464,7 +784,6 @@ trait RejectMessage extends ControlPayload {
* Optional additional data provided with the rejection.
* For example, most rejections of tx messages or block messages include
* the hash of the rejected transaction or block header. See the code table below.
* @return
*/
def extra: ByteVector
@ -473,6 +792,43 @@ trait RejectMessage extends ControlPayload {
override def bytes: ByteVector = RawRejectMessageSerializer.write(this)
}
/**
* @see [[https://bitcoin.org/en/developer-reference#reject]]
*/
object RejectMessage extends Factory[RejectMessage] {
private case class RejectMessageImpl(
messageSize: CompactSizeUInt,
message: String,
code: Char,
reasonSize: CompactSizeUInt,
reason: String,
extra: ByteVector)
extends RejectMessage
def apply(
messageSize: CompactSizeUInt,
message: String,
code: Char,
reasonSize: CompactSizeUInt,
reason: String,
extra: ByteVector): RejectMessage = {
RejectMessageImpl(messageSize, message, code, reasonSize, reason, extra)
}
def fromBytes(bytes: ByteVector): RejectMessage =
RawRejectMessageSerializer.read(bytes)
def apply(
message: String,
code: Char,
reason: String,
extra: ByteVector): RejectMessage = {
val messageSize: CompactSizeUInt = CompactSizeUInt(UInt64(message.size))
val reasonSize: CompactSizeUInt = CompactSizeUInt(UInt64(reason.size))
RejectMessage(messageSize, message, code, reasonSize, reason, extra)
}
}
/**
* The sendheaders message tells the receiving peer to send new block announcements
* using a headers message rather than an inv message.
@ -510,13 +866,11 @@ trait VersionMessage extends ControlPayload {
/**
* The highest protocol version understood by the transmitting node. See the protocol version section.
* @return
*/
def version: ProtocolVersion
/**
* The services supported by the transmitting node encoded as a bitfield. See the list of service codes below.
* @return
*/
def services: ServiceIdentifier
@ -524,7 +878,6 @@ trait VersionMessage extends ControlPayload {
* The current Unix epoch time according to the transmitting nodes clock.
* Because nodes will reject blocks with timestamps more than two hours in the future,
* this field can help other nodes to determine that their clock is wrong.
* @return
*/
def timestamp: Int64
@ -532,7 +885,6 @@ trait VersionMessage extends ControlPayload {
* The services supported by the receiving node as perceived by the transmitting node.
* Same format as the services field above.
* Bitcoin Core will attempt to provide accurate information. BitcoinJ will, by default, always send 0.
* @return
*/
def addressReceiveServices: ServiceIdentifier
@ -547,13 +899,11 @@ trait VersionMessage extends ControlPayload {
/**
* The port number of the receiving node as perceived by the transmitting node in big endian byte order.
* @return
*/
def addressReceivePort: Int
/**
* The services supported by the transmitting node. Should be identical to the services field above.
* @return
*/
def addressTransServices: ServiceIdentifier
@ -562,13 +912,11 @@ trait VersionMessage extends ControlPayload {
* IPv4 addresses can be provided as IPv4-mapped IPv6 addresses.
* Set to ::ffff:127.0.0.1 if unknown.
* This is the network address of the node emitting this message
* @return
*/
def addressTransIpAddress: InetAddress
/**
* The port number of the transmitting node in big endian byte order.
* @return
*/
def addressTransPort: Int
@ -577,26 +925,22 @@ trait VersionMessage extends ControlPayload {
* If the nonce is 0, the nonce field is ignored.
* If the nonce is anything else, a node should terminate the connection on receipt
* of a version message with a nonce it previously sent.
* @return
*/
def nonce: UInt64
/**
* Number of bytes in following user_agent field. If 0x00, no user agent field is sent.
* @return
*/
def userAgentSize: CompactSizeUInt
/**
* User agent as defined by BIP14. Previously called subVer.
* @return
*/
def userAgent: String
/**
* The height of the transmitting nodes best block chain or,
* in the case of an SPV client, best block header chain.
* @return
*/
def startHeight: Int32
@ -604,7 +948,6 @@ trait VersionMessage extends ControlPayload {
* Transaction relay flag. If 0x00, no inv messages or tx messages announcing new transactions
* should be sent to this client until it sends a filterload message or filterclear message.
* If 0x01, this node wants inv messages and tx messages announcing new transactions.
* @return
*/
def relay: Boolean
@ -613,6 +956,110 @@ trait VersionMessage extends ControlPayload {
override def bytes: ByteVector = RawVersionMessageSerializer.write(this)
}
/**
* @see https://bitcoin.org/en/developer-reference#version
*/
object VersionMessage extends Factory[VersionMessage] {
private case class VersionMessageImpl(
version: ProtocolVersion,
services: ServiceIdentifier,
timestamp: Int64,
addressReceiveServices: ServiceIdentifier,
addressReceiveIpAddress: InetAddress,
addressReceivePort: Int,
addressTransServices: ServiceIdentifier,
addressTransIpAddress: InetAddress,
addressTransPort: Int,
nonce: UInt64,
userAgentSize: CompactSizeUInt,
userAgent: String,
startHeight: Int32,
relay: Boolean)
extends VersionMessage
override def fromBytes(bytes: ByteVector): VersionMessage =
RawVersionMessageSerializer.read(bytes)
def apply(
version: ProtocolVersion,
services: ServiceIdentifier,
timestamp: Int64,
addressReceiveServices: ServiceIdentifier,
addressReceiveIpAddress: InetAddress,
addressReceivePort: Int,
addressTransServices: ServiceIdentifier,
addressTransIpAddress: InetAddress,
addressTransPort: Int,
nonce: UInt64,
userAgent: String,
startHeight: Int32,
relay: Boolean): VersionMessage = {
val userAgentSize: CompactSizeUInt =
CompactSizeUInt.calculateCompactSizeUInt(ByteVector(userAgent.getBytes))
VersionMessageImpl(
version = version,
services = services,
timestamp = timestamp,
addressReceiveServices = addressReceiveServices,
addressReceiveIpAddress = addressReceiveIpAddress,
addressReceivePort = addressReceivePort,
addressTransServices = addressTransServices,
addressTransIpAddress = addressTransIpAddress,
addressTransPort = addressTransPort,
nonce = nonce,
userAgentSize = userAgentSize,
userAgent = userAgent,
startHeight = startHeight,
relay = relay
)
}
def apply(
network: NetworkParameters,
receivingIpAddress: InetAddress): VersionMessage = {
val transmittingIpAddress = InetAddress.getLocalHost
VersionMessage(network, receivingIpAddress, transmittingIpAddress)
}
def apply(
network: NetworkParameters,
receivingIpAddress: InetAddress,
transmittingIpAddress: InetAddress): VersionMessage = {
val nonce = UInt64.zero
val userAgent = ProtocolVersion.userAgent
val startHeight = Int32.zero
val relay = false
VersionMessage(
version = ProtocolVersion.default,
services = UnnamedService,
timestamp = Int64(java.time.Instant.now.toEpochMilli),
addressReceiveServices = UnnamedService,
addressReceiveIpAddress = receivingIpAddress,
addressReceivePort = network.port,
addressTransServices = NodeNetwork,
addressTransIpAddress = transmittingIpAddress,
addressTransPort = network.port,
nonce = nonce,
userAgent = userAgent,
startHeight = startHeight,
relay = relay
)
}
def apply(host: String, network: NetworkParameters): VersionMessage = {
//network.dnsSeeds(0)
val transmittingIpAddress = InetAddress.getByName(host)
VersionMessage(network, transmittingIpAddress)
}
def apply(
socket: InetSocketAddress,
network: NetworkParameters): VersionMessage = {
VersionMessage(network, socket.getAddress)
}
}
object NetworkPayload {
val alertCommandName = "alert"
val blockCommandName = "block"
@ -644,7 +1091,6 @@ object NetworkPayload {
* required in [[NetworkHeader]]
* [[https://bitcoin.org/en/developer-reference#message-headers]]
*
* @return
*/
val commandNames: Map[String, ByteVector => NetworkPayload] = Map(
blockCommandName -> { RawBlockMessageSerializer.read(_) },
@ -688,7 +1134,6 @@ object NetworkPayload {
* to determine what type of [[NetworkPayload]] this is
* @param networkHeader the header for the message on the p2p network
* @param payloadBytes the payload corresponding to the header on the p2p network
* @return
*/
def apply(
networkHeader: NetworkHeader,
@ -704,7 +1149,6 @@ object NetworkPayload {
* to determine what type of [[NetworkPayload]] this is
* @param networkHeader the header for the message on the p2p network
* @param payloadHex the hexadecimal representation of the payload
* @return
*/
def apply(
networkHeader: NetworkHeader,

View file

@ -1,19 +1,24 @@
package org.bitcoins.node.versions
package org.bitcoins.core.p2p
import org.bitcoins.core.protocol.NetworkElement
import org.bitcoins.core.util.Factory
import scodec.bits.ByteVector
import scodec.bits._
/**
* Created by chris on 6/1/16.
* The peer to peer network has versions to allow for new operations
* Here are the currently protocol versions in the network
* [[https://bitcoin.org/en/developer-reference#protocol-versions]]
* @see [[https://bitcoin.org/en/developer-reference#protocol-versions]]
*/
sealed trait ProtocolVersion extends NetworkElement
object ProtocolVersion extends Factory[ProtocolVersion] {
/** The default protocol version */
val default: ProtocolVersion = ProtocolVersion70013
/** The Bitcoin-S node useragent */
val userAgent = "/bitcoins-spv-node/0.0.1"
val versions: Seq[ProtocolVersion] = List(
ProtocolVersion106,
ProtocolVersion209,
@ -39,7 +44,7 @@ object ProtocolVersion extends Factory[ProtocolVersion] {
* Bitcoin Core 0.1.6 (Oct 2009)
*/
case object ProtocolVersion106 extends ProtocolVersion {
override val bytes: ByteVector = ByteVector.fromHex("6a000000").get
override val bytes: ByteVector = hex"6a000000"
}
/**
@ -47,7 +52,7 @@ case object ProtocolVersion106 extends ProtocolVersion {
* Bitcoin Core 0.2.9 (May 2010)
*/
case object ProtocolVersion209 extends ProtocolVersion {
override val bytes: ByteVector = ByteVector.fromHex("d1000000").get
override val bytes: ByteVector = hex"d1000000"
}
/**
@ -55,7 +60,7 @@ case object ProtocolVersion209 extends ProtocolVersion {
* Bitcion Core 0.3.11 (Aug 2010)
*/
case object ProtocolVersion311 extends ProtocolVersion {
override val bytes: ByteVector = ByteVector.fromHex("37010000").get
override val bytes: ByteVector = hex"37010000"
}
/**
@ -63,7 +68,7 @@ case object ProtocolVersion311 extends ProtocolVersion {
* Bitcoin Core 0.3.15 (Oct 2010)
*/
case object ProtocolVersion31402 extends ProtocolVersion {
override val bytes: ByteVector = ByteVector.fromHex("aa7a0000").get
override val bytes: ByteVector = hex"aa7a0000"
}
/**
@ -71,7 +76,7 @@ case object ProtocolVersion31402 extends ProtocolVersion {
* Bitcoin Core 0.3.18 (Dec 2010)
*/
case object ProtocolVersion31800 extends ProtocolVersion {
override val bytes: ByteVector = ByteVector.fromHex("387c0000").get
override val bytes: ByteVector = hex"387c0000"
}
/**
@ -79,7 +84,7 @@ case object ProtocolVersion31800 extends ProtocolVersion {
* Bitcoin Core 0.6.0 (Mar 2012)
*/
case object ProtocolVersion60000 extends ProtocolVersion {
override val bytes: ByteVector = ByteVector.fromHex("60ea0000").get
override val bytes: ByteVector = hex"60ea0000"
}
/**
@ -87,7 +92,7 @@ case object ProtocolVersion60000 extends ProtocolVersion {
* Bitcoin Core 0.6.1 (May 2012)
*/
case object ProtocolVersion60001 extends ProtocolVersion {
override val bytes: ByteVector = ByteVector.fromHex("61ea0000").get
override val bytes: ByteVector = hex"61ea0000"
}
/**
@ -96,7 +101,7 @@ case object ProtocolVersion60001 extends ProtocolVersion {
* Bitcoin Core 0.7.0 (Sep 2012)
*/
case object ProtocolVersion60002 extends ProtocolVersion {
override val bytes: ByteVector = ByteVector.fromHex("62ea0000").get
override val bytes: ByteVector = hex"62ea0000"
}
/**
@ -111,7 +116,7 @@ case object ProtocolVersion60002 extends ProtocolVersion {
* Bitcoin Core 0.8.0 (Feb 2013)
*/
case object ProtocolVersion70001 extends ProtocolVersion {
override val bytes: ByteVector = ByteVector.fromHex("71110100").get
override val bytes: ByteVector = hex"71110100"
}
/**
@ -120,7 +125,7 @@ case object ProtocolVersion70001 extends ProtocolVersion {
* Bitcoin Core 0.9.0 (Mar 2014)
*/
case object ProtocolVersion70002 extends ProtocolVersion {
override val bytes: ByteVector = ByteVector.fromHex("72110100").get
override val bytes: ByteVector = hex"72110100"
}
/**
@ -128,7 +133,7 @@ case object ProtocolVersion70002 extends ProtocolVersion {
* Bitcoin Core 0.12.0
*/
case object ProtocolVersion70012 extends ProtocolVersion {
override val bytes: ByteVector = ByteVector.fromHex("7c110100").get
override val bytes: ByteVector = hex"7c110100"
}
/**
@ -137,7 +142,7 @@ case object ProtocolVersion70012 extends ProtocolVersion {
* Bitcoin Core 0.13.0 (August 2016)
*/
case object ProtocolVersion70013 extends ProtocolVersion {
override val bytes: ByteVector = ByteVector.fromHex("7d110100").get
override val bytes: ByteVector = hex"7d110100"
}
/**
@ -147,7 +152,7 @@ case object ProtocolVersion70013 extends ProtocolVersion {
* Bitcoin Core 0.13.0 (August 2016)
*/
case object ProtocolVersion70014 extends ProtocolVersion {
override val bytes: ByteVector = ByteVector.fromHex("7e110100").get
override val bytes: ByteVector = hex"7e110100"
}
/**
@ -155,9 +160,5 @@ case object ProtocolVersion70014 extends ProtocolVersion {
* Bitcoin Core 0.13.2 (January 2017)
*/
case object ProtocolVersion70015 extends ProtocolVersion {
override val bytes: ByteVector = ByteVector.fromHex("7f110100").get
override val bytes: ByteVector = hex"7f110100"
}

View file

@ -1,15 +1,14 @@
package org.bitcoins.node.messages.control
package org.bitcoins.core.p2p
import org.bitcoins.core.number.UInt64
import org.bitcoins.core.protocol.NetworkElement
import org.bitcoins.core.serializers.p2p.messages.RawServiceIdentifierSerializer
import org.bitcoins.core.util.Factory
import org.bitcoins.node.serializers.messages.control.RawServiceIdentifierSerializer
import scodec.bits.ByteVector
/**
* Created by chris on 6/2/16.
* Indicates the services that are provided by this spv node
* [[https://bitcoin.org/en/developer-reference#version]]
* @see [[https://bitcoin.org/en/developer-reference#version]]
*/
sealed trait ServiceIdentifier extends NetworkElement {
def num: UInt64

View file

@ -1,16 +1,15 @@
package org.bitcoins.node.messages
package org.bitcoins.core.p2p
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.NetworkElement
import org.bitcoins.core.serializers.p2p.messages.RawTypeIdentifierSerializer
import org.bitcoins.core.util.Factory
import org.bitcoins.node.serializers.messages.RawTypeIdentifierSerializer
import org.bitcoins.node.serializers.messages.RawTypeIdentifierSerializer
import scodec.bits.ByteVector
/**
* Created by chris on 5/31/16.
* This indicates the type of the object that has been hashed for an inventory
* https://bitcoin.org/en/developer-reference#data-messages
*
* @see https://bitcoin.org/en/developer-reference#data-messages
*/
sealed trait TypeIdentifier extends NetworkElement {
def num: UInt32

View file

@ -1,19 +1,16 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.p2p.serializers.messages
import java.net.InetAddress
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.core.util.{BitcoinSLogger, NumberUtil}
import org.bitcoins.node.messages.control.ServiceIdentifier
import org.bitcoins.node.util.{BitcoinSpvNodeUtil, NetworkIpAddress}
import org.bitcoins.node.util.{BitcoinSpvNodeUtil, NetworkIpAddress}
import org.bitcoins.core.p2p._
import scodec.bits.ByteVector
/**
* Created by chris on 6/2/16.
* Responsible for serializing and deserializing network ip address objects on the p2p network
* https://bitcoin.org/en/developer-reference#addr
* @see https://bitcoin.org/en/developer-reference#addr
*/
trait RawNetworkIpAddressSerializer
extends RawBitcoinSerializer[NetworkIpAddress]
@ -31,7 +28,7 @@ trait RawNetworkIpAddressSerializer
def write(networkIpAddress: NetworkIpAddress): ByteVector = {
val time = networkIpAddress.time.bytes.reverse
val services = networkIpAddress.services.bytes
val ipAddress = BitcoinSpvNodeUtil.writeAddress(networkIpAddress.address)
val ipAddress = NetworkIpAddress.writeAddress(networkIpAddress.address)
//uint16s are only 4 hex characters
val port = ByteVector.fromShort(networkIpAddress.port.toShort)
time ++ services ++ ipAddress ++ port

View file

@ -1,16 +1,9 @@
package org.bitcoins.node.serializers
package org.bitcoins.core.serializers.p2p
import org.bitcoins.core.p2p._
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.node.NetworkMessage
import org.bitcoins.node.headers.NetworkHeader
import org.bitcoins.node.messages.NetworkPayload
import org.bitcoins.node.NetworkMessage
import org.bitcoins.node.headers.NetworkHeader
import scodec.bits.ByteVector
/**
* Created by chris on 6/11/16.
*/
trait RawNetworkMessageSerializer extends RawBitcoinSerializer[NetworkMessage] {
def read(bytes: ByteVector): NetworkMessage = {

View file

@ -1,15 +1,14 @@
package org.bitcoins.node.serializers.headers
package org.bitcoins.core.serializers.p2p.headers
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.p2p.NetworkHeader
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.core.util.BitcoinSLogger
import org.bitcoins.node.headers.NetworkHeader
import scodec.bits.ByteVector
/**
* Created by chris on 5/31/16.
* Reads and writes a message header on the peer-to-peer network
* https://bitcoin.org/en/developer-reference#message-headers
* @see https://bitcoin.org/en/developer-reference#message-headers
*/
trait RawNetworkHeaderSerializer
extends RawBitcoinSerializer[NetworkHeader]

View file

@ -1,18 +1,15 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.serializers.{RawBitcoinSerializer, RawSerializerHelper}
import org.bitcoins.node.messages.AddrMessage
import org.bitcoins.node.messages.control.AddrMessage
import org.bitcoins.node.util.NetworkIpAddress
import org.bitcoins.core.p2p._
import scodec.bits.ByteVector
import scala.annotation.tailrec
/**
* Created by chris on 6/3/16.
* Responsible for the serialization and deserialization of AddrMessages
* https://bitcoin.org/en/developer-reference#addr
* @see https://bitcoin.org/en/developer-reference#addr
*/
trait RawAddrMessageSerializer extends RawBitcoinSerializer[AddrMessage] {

View file

@ -1,16 +1,10 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.protocol.blockchain.Block
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.node.messages.BlockMessage
import org.bitcoins.node.messages.data.BlockMessage
import org.bitcoins.node.messages.BlockMessage
import org.bitcoins.node.messages.data.BlockMessage
import org.bitcoins.core.p2p.BlockMessage
import scodec.bits.ByteVector
/**
* Created by chris on 7/8/16.
*/
trait RawBlockMessageSerializer extends RawBitcoinSerializer[BlockMessage] {
def read(bytes: ByteVector): BlockMessage = {

View file

@ -1,14 +1,14 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.currency.Satoshis
import org.bitcoins.core.number.Int64
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.core.wallet.fee.SatoshisPerKiloByte
import org.bitcoins.node.messages.FeeFilterMessage
import org.bitcoins.node.messages.control.FeeFilterMessage
import org.bitcoins.core.p2p._
import scodec.bits.ByteVector
sealed abstract class RawFeeFilterMessageSerializer extends RawBitcoinSerializer[FeeFilterMessage] {
sealed abstract class RawFeeFilterMessageSerializer
extends RawBitcoinSerializer[FeeFilterMessage] {
override def read(bytes: ByteVector): FeeFilterMessage = {
val i64 = Int64.fromBytes(bytes.take(8).reverse)
@ -22,4 +22,4 @@ sealed abstract class RawFeeFilterMessageSerializer extends RawBitcoinSerializer
}
}
object RawFeeFilterMessageSerializer extends RawFeeFilterMessageSerializer
object RawFeeFilterMessageSerializer extends RawFeeFilterMessageSerializer

View file

@ -1,17 +1,13 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.node.messages.FilterAddMessage
import org.bitcoins.node.messages.control.FilterAddMessage
import org.bitcoins.node.messages.FilterAddMessage
import org.bitcoins.node.messages.control.FilterAddMessage
import org.bitcoins.core.p2p._
import scodec.bits.ByteVector
/**
* Created by chris on 8/26/16.
* Responsible for serializing and deserializing a [[FilterAddMessage]]
* [[https://bitcoin.org/en/developer-reference#filteradd]]
* @see [[https://bitcoin.org/en/developer-reference#filteradd]]
*/
trait RawFilterAddMessageSerializer
extends RawBitcoinSerializer[FilterAddMessage] {

View file

@ -1,15 +1,13 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.core.serializers.bloom.RawBloomFilterSerializer
import org.bitcoins.node.messages.FilterLoadMessage
import org.bitcoins.node.messages.control.FilterLoadMessage
import org.bitcoins.core.p2p.FilterLoadMessage
import scodec.bits.ByteVector
/**
* Created by chris on 7/19/16.
* Serializes and deserializes a [[FilterLoadMessage]]
* https://bitcoin.org/en/developer-reference#filterload
* @see https://bitcoin.org/en/developer-reference#filterload
*/
trait RawFilterLoadMessageSerializer
extends RawBitcoinSerializer[FilterLoadMessage] {

View file

@ -1,23 +1,17 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.serializers.{RawBitcoinSerializer, RawSerializerHelper}
import org.bitcoins.node.messages.GetBlocksMessage
import org.bitcoins.node.messages.data.GetBlocksMessage
import org.bitcoins.node.versions.ProtocolVersion
import org.bitcoins.node.messages.GetBlocksMessage
import org.bitcoins.node.messages.data.GetBlocksMessage
import org.bitcoins.node.versions.ProtocolVersion
import org.bitcoins.core.p2p._
import scodec.bits.ByteVector
import scala.annotation.tailrec
/**
* Created by chris on 6/1/16.
* This trait is responsible for the serialization and deserialization of
* getblocks messages in on the p2p network
* https://bitcoin.org/en/developer-reference#getblocks
* @see https://bitcoin.org/en/developer-reference#getblocks
*/
trait RawGetBlocksMessageSerializer
extends RawBitcoinSerializer[GetBlocksMessage] {

View file

@ -1,14 +1,11 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.node.messages.GetDataMessage
import org.bitcoins.node.messages.data.{GetDataMessage, InventoryMessage}
import org.bitcoins.node.messages.data.{GetDataMessage, InventoryMessage}
import org.bitcoins.core.p2p.{GetDataMessage, InventoryMessage}
import scodec.bits.ByteVector
/**
* Created by chris on 7/8/16.
* https://bitcoin.org/en/developer-reference#getdata
* @see https://bitcoin.org/en/developer-reference#getdata
*/
trait RawGetDataMessageSerializer extends RawBitcoinSerializer[GetDataMessage] {
//InventoryMessages & GetDataMessages have the same structure and are serialized the same

View file

@ -1,21 +1,13 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.serializers.{RawBitcoinSerializer, RawSerializerHelper}
import org.bitcoins.node.messages.GetHeadersMessage
import org.bitcoins.node.messages.data.GetHeadersMessage
import org.bitcoins.node.versions.ProtocolVersion
import org.bitcoins.node.messages.GetHeadersMessage
import org.bitcoins.node.messages.data.GetHeadersMessage
import org.bitcoins.node.versions.ProtocolVersion
import org.bitcoins.core.p2p._
import scodec.bits.ByteVector
import scala.annotation.tailrec
/**
* Created by chris on 6/29/16.
*/
trait RawGetHeadersMessageSerializer
extends RawBitcoinSerializer[GetHeadersMessage] {

View file

@ -1,19 +1,13 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.protocol.blockchain.BlockHeader
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.node.messages.HeadersMessage
import org.bitcoins.node.messages.data.HeadersMessage
import org.bitcoins.node.messages.HeadersMessage
import org.bitcoins.node.messages.data.HeadersMessage
import org.bitcoins.core.p2p.HeadersMessage
import scodec.bits.ByteVector
import scala.annotation.tailrec
/**
* Created by chris on 7/5/16.
*/
trait RawHeadersMessageSerializer extends RawBitcoinSerializer[HeadersMessage] {
def read(bytes: ByteVector): HeadersMessage = {

View file

@ -1,26 +1,21 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.serializers.{RawBitcoinSerializer, RawSerializerHelper}
import org.bitcoins.node.messages.InventoryMessage
import org.bitcoins.node.messages.data.{Inventory, InventoryMessage}
import org.bitcoins.node.messages.data.{Inventory, InventoryMessage}
import org.bitcoins.core.p2p.{Inventory, InventoryMessage}
import scodec.bits.ByteVector
import scala.annotation.tailrec
/**
* Created by chris on 5/31/16.
* Serializes and deserializes inventory objects on the peer-to-peer network
* https://bitcoin.org/en/developer-reference#inv
* @see https://bitcoin.org/en/developer-reference#inv
*/
trait RawInventoryMessageSerializer
extends RawBitcoinSerializer[InventoryMessage] {
/**
* Transforms a sequence of bytes into a Inventory object
* @param bytes
* @return
*/
override def read(bytes: ByteVector): InventoryMessage = {
val inventoryCount = CompactSizeUInt.parseCompactSizeUInt(bytes)
@ -32,8 +27,6 @@ trait RawInventoryMessageSerializer
/**
* Tranforms an inventory object into a hexadecimal string
* @param inventoryMessage
* @return
*/
override def write(inventoryMessage: InventoryMessage): ByteVector = {
val msgBytes =

View file

@ -1,17 +1,14 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.node.messages.TypeIdentifier
import org.bitcoins.node.messages.data.Inventory
import org.bitcoins.node.messages.TypeIdentifier
import org.bitcoins.node.messages.data.Inventory
import org.bitcoins.core.p2p.TypeIdentifier
import org.bitcoins.core.p2p.Inventory
import scodec.bits.ByteVector
/**
* Created by chris on 6/1/16.
* Serializes/deserializes a inventory
* https://bitcoin.org/en/developer-reference#term-inventory
* @see https://bitcoin.org/en/developer-reference#term-inventory
*/
trait RawInventorySerializer extends RawBitcoinSerializer[Inventory] {

View file

@ -1,17 +1,14 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.protocol.blockchain.MerkleBlock
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.core.util.BitcoinSLogger
import org.bitcoins.node.messages.MerkleBlockMessage
import org.bitcoins.node.messages.data.MerkleBlockMessage
import org.bitcoins.node.messages.MerkleBlockMessage
import org.bitcoins.core.p2p.MerkleBlockMessage
import scodec.bits.ByteVector
/**
* Created by chris on 6/2/16.
* Responsible for serialization and deserialization of MerkleBlockMessages
* https://bitcoin.org/en/developer-reference#merkleblock
* @see https://bitcoin.org/en/developer-reference#merkleblock
*/
trait RawMerkleBlockMessageSerializer
extends RawBitcoinSerializer[MerkleBlockMessage]

View file

@ -1,16 +1,12 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.node.messages.NotFoundMessage
import org.bitcoins.node.messages.data.{InventoryMessage, NotFoundMessage}
import org.bitcoins.node.messages.NotFoundMessage
import org.bitcoins.node.messages.data.{InventoryMessage, NotFoundMessage}
import org.bitcoins.core.p2p.{InventoryMessage, NotFoundMessage}
import scodec.bits.ByteVector
/**
* Created by chris on 6/2/16.
* Responsible for the serialization and deserialization of a NotFound message on the p2p network
* https://bitcoin.org/en/developer-reference#notfound
* @see https://bitcoin.org/en/developer-reference#notfound
*/
trait RawNotFoundMessageSerializer
extends RawBitcoinSerializer[NotFoundMessage] {

View file

@ -1,16 +1,13 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.number.UInt64
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.node.messages.PingMessage
import org.bitcoins.node.messages.control.PingMessage
import org.bitcoins.node.messages.PingMessage
import org.bitcoins.node.messages.control.PingMessage
import org.bitcoins.core.p2p.PingMessage
import org.bitcoins.core.p2p.PingMessage
import scodec.bits.ByteVector
/**
* Created by chris on 6/29/16.
* https://bitcoin.org/en/developer-reference#ping
* @see https://bitcoin.org/en/developer-reference#ping
*/
trait RawPingMessageSerializer extends RawBitcoinSerializer[PingMessage] {

View file

@ -1,16 +1,11 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.number.UInt64
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.node.messages.PongMessage
import org.bitcoins.node.messages.control.PongMessage
import org.bitcoins.node.messages.PongMessage
import org.bitcoins.node.messages.control.PongMessage
import org.bitcoins.core.p2p.PongMessage
import org.bitcoins.core.p2p.PongMessage
import scodec.bits.ByteVector
/**
* Created by chris on 7/5/16.
*/
trait RawPongMessageSerializer extends RawBitcoinSerializer[PongMessage] {
override def read(bytes: ByteVector): PongMessage = {

View file

@ -1,16 +1,11 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.node.messages.RejectMessage
import org.bitcoins.node.messages.control.RejectMessage
import org.bitcoins.node.messages.RejectMessage
import org.bitcoins.node.messages.control.RejectMessage
import org.bitcoins.core.p2p.RejectMessage
import org.bitcoins.core.p2p.RejectMessage
import scodec.bits.ByteVector
/**
* Created by chris on 8/31/16.
*/
trait RawRejectMessageSerializer extends RawBitcoinSerializer[RejectMessage] {
def read(bytes: ByteVector): RejectMessage = {

View file

@ -1,16 +1,14 @@
package org.bitcoins.node.serializers.messages.control
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.number.UInt64
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.node.messages.control.ServiceIdentifier
import org.bitcoins.node.messages.control.ServiceIdentifier
import org.bitcoins.core.p2p.ServiceIdentifier
import scodec.bits.ByteVector
/**
* Created by chris on 6/2/16.
* Responsible for serializing and deserializing the
* service identifier in a network message
* https://bitcoin.org/en/developer-reference#version
* @see https://bitcoin.org/en/developer-reference#version
*/
trait RawServiceIdentifierSerializer
extends RawBitcoinSerializer[ServiceIdentifier] {

View file

@ -1,16 +1,13 @@
package org.bitcoins.node.serializers.messages.data
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.protocol.transaction.Transaction
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.node.messages.TransactionMessage
import org.bitcoins.node.messages.data.TransactionMessage
import org.bitcoins.node.messages.TransactionMessage
import org.bitcoins.core.p2p.TransactionMessage
import scodec.bits.ByteVector
/**
* Created by chris on 6/2/16.
* Responsible for serializing and deserializing TransactionMessage network objects
* https://bitcoin.org/en/developer-reference#tx
* @see https://bitcoin.org/en/developer-reference#tx
*/
trait RawTransactionMessageSerializer
extends RawBitcoinSerializer[TransactionMessage] {

View file

@ -1,8 +1,8 @@
package org.bitcoins.node.serializers.messages
package org.bitcoins.core.serializers.p2p.messages
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.node.messages.TypeIdentifier
import org.bitcoins.core.p2p.TypeIdentifier
import scodec.bits.ByteVector
/**

View file

@ -0,0 +1,102 @@
package org.bitcoins.core.serializers.p2p.messages
import java.net.InetAddress
import org.bitcoins.core.number.{Int32, Int64, UInt32, UInt64}
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.core.util.BitcoinSLogger
import org.bitcoins.core.p2p._
import scodec.bits.ByteVector
/**
* Responsible for serialization and deserialization of VersionMessages on the p2p network
* @see https://bitcoin.org/en/developer-reference#version
*/
trait RawVersionMessageSerializer
extends RawBitcoinSerializer[VersionMessage]
with BitcoinSLogger {
def read(bytes: ByteVector): VersionMessage = {
val version = ProtocolVersion(bytes.take(4))
val services = ServiceIdentifier(bytes.slice(4, 12))
val timestamp = Int64(bytes.slice(12, 20).reverse)
val addressReceiveServices = ServiceIdentifier(bytes.slice(20, 28))
val addressReceiveIpAddress =
InetAddress.getByAddress(bytes.slice(28, 44).toArray)
val addressReceivePort = UInt32(bytes.slice(44, 46)).toInt
val addressTransServices = ServiceIdentifier(bytes.slice(46, 54))
val addressTransIpAddress =
InetAddress.getByAddress(bytes.slice(54, 70).toArray)
val addressTransPort = UInt32(bytes.slice(70, 72)).toInt
val nonce = UInt64(bytes.slice(72, 80))
val userAgentSize =
CompactSizeUInt.parseCompactSizeUInt(bytes.slice(80, bytes.size))
val userAgentBytesStartIndex = 80 + userAgentSize.size.toInt
val userAgentBytes = bytes.slice(
userAgentBytesStartIndex,
userAgentBytesStartIndex + userAgentSize.num.toInt)
val userAgent = userAgentBytes.toArray.map(_.toChar).mkString
val startHeightStartIndex = (userAgentBytesStartIndex + userAgentSize.num.toInt)
val startHeight = Int32(
bytes.slice(startHeightStartIndex, startHeightStartIndex + 4).reverse)
val relay = bytes(startHeightStartIndex + 4) != 0
VersionMessage(
version = version,
services = services,
timestamp = timestamp,
addressReceiveServices = addressReceiveServices,
addressReceiveIpAddress = addressReceiveIpAddress,
addressReceivePort = addressReceivePort,
addressTransServices = addressTransServices,
addressTransIpAddress = addressTransIpAddress,
addressTransPort = addressTransPort,
nonce = nonce,
userAgent = userAgent,
startHeight = startHeight,
relay = relay
)
}
def write(versionMessage: VersionMessage): ByteVector = {
versionMessage.version.bytes ++
versionMessage.services.bytes ++
versionMessage.timestamp.bytes.reverse ++
versionMessage.addressReceiveServices.bytes ++
NetworkIpAddress.writeAddress(versionMessage.addressReceiveIpAddress) ++
//encode hex returns 8 characters, but we only need the last 4 since port number is a uint16
//check for precision loss here?
ByteVector.fromShort(versionMessage.addressReceivePort.toShort) ++
versionMessage.addressTransServices.bytes ++
NetworkIpAddress.writeAddress(versionMessage.addressTransIpAddress) ++
//encode hex returns 8 characters, but we only need the last 4 since port number is a uint16
//check for precision loss here?
ByteVector.fromShort(versionMessage.addressTransPort.toShort) ++
versionMessage.nonce.bytes ++
versionMessage.userAgentSize.bytes ++
ByteVector(versionMessage.userAgent.getBytes) ++
versionMessage.startHeight.bytes.reverse ++
(if (versionMessage.relay) ByteVector.fromByte(1.toByte)
else ByteVector.fromByte(0.toByte))
}
}
object RawVersionMessageSerializer extends RawVersionMessageSerializer

View file

@ -1,20 +1,13 @@
package org.bitcoins.node.constant
import akka.actor.ActorSystem
import org.bitcoins.node.versions.ProtocolVersion70013
import scala.concurrent.duration.DurationInt
import com.typesafe.config.ConfigFactory
case object Constants {
val emptyConfig = ConfigFactory.parseString("")
lazy val actorSystem = ActorSystem("BitcoinSpvNode", emptyConfig)
def version = ProtocolVersion70013
lazy val actorSystem = ActorSystem("BitcoinSpvNode")
def timeout = 5.seconds
def userAgent = "/bitcoins-spv-node/0.0.1"
/** This is the file where our block headers are stored */
def blockHeaderFile = new java.io.File("src/main/resources/block_headers.dat")
}

View file

@ -2,8 +2,8 @@ package org.bitcoins.node.models
import java.net.InetSocketAddress
import org.bitcoins.core.p2p.NetworkIpAddress
import org.bitcoins.db.DbRowAutoInc
import org.bitcoins.node.util.NetworkIpAddress
case class Peer(networkIpAddress: NetworkIpAddress, id: Option[Long] = None)
extends DbRowAutoInc[Peer] {

View file

@ -5,15 +5,15 @@ import akka.event.LoggingReceive
import akka.io.{IO, Tcp}
import akka.util.ByteString
import org.bitcoins.core.config.NetworkParameters
import org.bitcoins.core.p2p.NetworkMessage
import org.bitcoins.core.util.BitcoinSLogger
import org.bitcoins.node.NetworkMessage
import org.bitcoins.node.config.NodeAppConfig
import org.bitcoins.node.messages.NetworkPayload
import org.bitcoins.core.p2p.NetworkPayload
import org.bitcoins.node.models.Peer
import org.bitcoins.node.networking.peer.PeerMessageReceiver
import org.bitcoins.node.networking.peer.PeerMessageReceiver.NetworkMessageReceived
import org.bitcoins.node.util.BitcoinSpvNodeUtil
import scodec.bits.ByteVector
import org.bitcoins.node.config.NodeAppConfig
/**
* Created by chris on 6/6/16.

View file

@ -5,7 +5,7 @@ import org.bitcoins.chain.blockchain.ChainHandler
import org.bitcoins.chain.config.ChainAppConfig
import org.bitcoins.chain.models.BlockHeaderDAO
import org.bitcoins.core.util.{BitcoinSLogger, FutureUtil}
import org.bitcoins.node.messages.{
import org.bitcoins.core.p2p.{
DataPayload,
HeadersMessage,
InventoryMessage

View file

@ -2,18 +2,13 @@ package org.bitcoins.node.networking.peer
import akka.actor.ActorRefFactory
import org.bitcoins.chain.config.ChainAppConfig
import org.bitcoins.core.p2p.NetworkMessage
import org.bitcoins.core.util.BitcoinSLogger
import org.bitcoins.node.NetworkMessage
import org.bitcoins.node.config.NodeAppConfig
import org.bitcoins.node.messages._
import org.bitcoins.core.p2p._
import org.bitcoins.node.models.Peer
import org.bitcoins.node.networking.Client
import org.bitcoins.node.networking.peer.PeerMessageReceiverState.{
Disconnected,
Initializing,
Normal,
Preconnection
}
import org.bitcoins.node.networking.peer.PeerMessageReceiverState.{Disconnected, Initializing, Normal, Preconnection}
import scala.util.{Failure, Success, Try}

View file

@ -1,8 +1,8 @@
package org.bitcoins.node.networking.peer
import org.bitcoins.core.p2p.NetworkMessage
import org.bitcoins.core.util.BitcoinSLogger
import org.bitcoins.node.NetworkMessage
import org.bitcoins.node.messages.{VerAckMessage, VersionMessage}
import org.bitcoins.core.p2p.{VerAckMessage, VersionMessage}
import org.bitcoins.node.networking.Client
import scala.concurrent.{Future, Promise}

View file

@ -4,12 +4,9 @@ import akka.actor.ActorRef
import akka.io.Tcp
import org.bitcoins.core.config.NetworkParameters
import org.bitcoins.core.crypto.DoubleSha256Digest
import org.bitcoins.core.p2p.NetworkMessage
import org.bitcoins.core.util.BitcoinSLogger
import org.bitcoins.node.NetworkMessage
import org.bitcoins.node.messages._
import org.bitcoins.node.messages.control.{PongMessage, VersionMessage}
import org.bitcoins.node.messages.data.GetHeadersMessage
import org.bitcoins.node.models.Peer
import org.bitcoins.core.p2p._
import org.bitcoins.node.networking.Client
/**

View file

@ -3,22 +3,14 @@ package org.bitcoins.testkit.gen
import java.net.{InetAddress, InetSocketAddress}
import org.bitcoins.core.number.{UInt32, UInt64}
import org.bitcoins.core.p2p.ProtocolVersion
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.node.messages._
import org.bitcoins.node.messages.control._
import org.bitcoins.node.versions.ProtocolVersion
import org.bitcoins.testkit.core.gen.{
BloomFilterGenerator,
CryptoGenerators,
NumberGenerator,
StringGenerators
}
import org.bitcoins.core.p2p._
import org.bitcoins.core.p2p._
import org.bitcoins.testkit.core.gen.{BloomFilterGenerator, CryptoGenerators, NumberGenerator, StringGenerators}
import org.scalacheck.Gen
import scodec.bits.ByteVector
/**
* Created by chris on 6/27/16.
*/
trait ControlMessageGenerator {
/**

View file

@ -1,8 +1,7 @@
package org.bitcoins.testkit.gen
import org.bitcoins.core.number.UInt32
import org.bitcoins.node.messages._
import org.bitcoins.node.messages.data._
import org.bitcoins.core.p2p._
import org.bitcoins.testkit.core.gen.{
BlockchainElementsGenerator,
CryptoGenerators,
@ -12,17 +11,14 @@ import org.bitcoins.testkit.core.gen.{
import org.scalacheck.Gen
/**
* Created by chris on 6/29/16.
* Responsible for generating random [[DataMessage]]
* [[https://bitcoin.org/en/developer-reference#data-messages]]
* @see [[https://bitcoin.org/en/developer-reference#data-messages]]
*/
trait DataMessageGenerator {
/**
* Generates a random [[GetHeadersMessage]]
* [[https://bitcoin.org/en/developer-reference#getheaders]]
*
* @return
* @see [[https://bitcoin.org/en/developer-reference#getheaders]]
*/
def getHeaderMessages: Gen[GetHeadersMessage] =
for {
@ -44,8 +40,6 @@ trait DataMessageGenerator {
/**
* Generates a random [[TypeIdentifier]]
* [[https://bitcoin.org/en/developer-reference#data-messages]]
*
* @return
*/
def typeIdentifier: Gen[TypeIdentifier] =
for {
@ -54,9 +48,7 @@ trait DataMessageGenerator {
/**
* Generates a random [[Inventory]]
* [[https://bitcoin.org/en/developer-reference#term-inventory]]
*
* @return
* @see [[https://bitcoin.org/en/developer-reference#term-inventory]]
*/
def inventory: Gen[Inventory] =
for {
@ -66,8 +58,7 @@ trait DataMessageGenerator {
/**
* Generates a random [[InventoryMessage]]
* [[https://bitcoin.org/en/developer-reference#inv]]
* @return
* @see [[https://bitcoin.org/en/developer-reference#inv]]
*/
def inventoryMessages: Gen[InventoryMessage] =
for {
@ -77,8 +68,7 @@ trait DataMessageGenerator {
/**
* Generate a random [[GetDataMessage]]
* [[https://bitcoin.org/en/developer-reference#getdata]]
* @return
* @see [[https://bitcoin.org/en/developer-reference#getdata]]
*/
def getDataMessages: Gen[GetDataMessage] =
for {
@ -87,8 +77,7 @@ trait DataMessageGenerator {
/**
* Generates a random [[MerkleBlockMessage]]
* [[https://bitcoin.org/en/developer-reference#merkleblock]]
* @return
* @see [[https://bitcoin.org/en/developer-reference#merkleblock]]
*/
def merkleBlockMessage: Gen[MerkleBlockMessage] =
for {
@ -96,7 +85,7 @@ trait DataMessageGenerator {
} yield MerkleBlockMessage(merkleBlock)
/** Generates a [[TransactionMessage]]
* [[https://bitcoin.org/en/developer-reference#tx]]
* @see [[https://bitcoin.org/en/developer-reference#tx]]
* */
def transactionMessage: Gen[TransactionMessage] =
for {

View file

@ -3,16 +3,15 @@ package org.bitcoins.testkit.node
import java.net.InetSocketAddress
import akka.actor.ActorRefFactory
import org.bitcoins.core.p2p.{NetworkIpAddress, NetworkMessage}
import org.bitcoins.core.protocol.blockchain.BlockHeader
import org.bitcoins.core.protocol.transaction.Transaction
import org.bitcoins.node.NetworkMessage
import org.bitcoins.node.config.NodeAppConfig
import org.bitcoins.node.messages.control.VersionMessage
import org.bitcoins.node.messages.data.GetHeadersMessage
import org.bitcoins.core.p2p.VersionMessage
import org.bitcoins.core.p2p.GetHeadersMessage
import org.bitcoins.node.models.Peer
import org.bitcoins.node.networking.Client
import org.bitcoins.node.networking.peer.PeerMessageReceiver
import org.bitcoins.node.util.NetworkIpAddress
import org.bitcoins.rpc.client.common.BitcoindRpcClient
/**

View file

@ -4,27 +4,18 @@ 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
import org.bitcoins.node.models.Peer
import org.bitcoins.node.networking.peer.{
PeerHandler,
PeerMessageReceiver,
PeerMessageSender
}
import org.bitcoins.node.util.NetworkIpAddress
import org.bitcoins.node.networking.peer.{PeerHandler, PeerMessageReceiver, PeerMessageSender}
import org.bitcoins.rpc.client.common.BitcoindRpcClient
import org.bitcoins.testkit.chain.ChainUnitTest
import org.bitcoins.testkit.fixtures.BitcoinSFixture
import org.bitcoins.testkit.node.fixture.SpvNodeConnectedWithBitcoind
import org.bitcoins.testkit.rpc.BitcoindRpcTestUtil
import org.scalatest.{
BeforeAndAfter,
BeforeAndAfterAll,
FutureOutcome,
MustMatchers
}
import org.scalatest.{BeforeAndAfter, BeforeAndAfterAll, FutureOutcome, MustMatchers}
import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext, Future}